import { type ClientId } from './paths.js'; import { type LinkRecord } from './fan-out.manifest.js'; export { getLinkManifestPath, loadManifest, saveManifest } from './fan-out.manifest.js'; export type { LinkKind, LinkManifest, LinkRecord } from './fan-out.manifest.js'; export interface AddLinkOptions { /** Skill identifier (e.g. `author/name`). Used as the directory name on disk. */ skillId: string; /** Source-of-truth client (almost always `claude-code`). */ fromClient: ClientId; /** Destination client (must differ from `fromClient`). */ toClient: ClientId; /** Try `fs.symlink` first; fall back to copy on EPERM. Default: false (copy). */ preferSymlink?: boolean; /** * Overwrite if destination already contains an entry of the same name. * Without `--force`, addLink refuses to clobber a different on-disk skill. */ force?: boolean; } export interface AddLinkResult { record: LinkRecord; /** True if `preferSymlink` was set but EPERM forced a fallback to copy. */ fellBackToCopy: boolean; /** * Things to tell the user: hidden backups left by an interrupted refresh * (SMI-6529 round 7), or a corrupt link manifest moved aside (round 9). * Omitted when none. */ warnings?: string[]; } /** * Create a fan-out link from one client's skill directory into another's. * * - Default kind is `'copy'` (recursive directory copy). `preferSymlink` * opts into a relative symlink and falls back to copy on EPERM (Windows * non-developer-mode users). * - Refuses on cycle. Refuses on conflict unless `force: true`. * - Appends a `LinkRecord` to the manifest at * `~/.skillsmith/links/manifest.json` so uninstall can tear it down. */ export declare function addLink(opts: AddLinkOptions): Promise; /** Result of {@link removeLinks} — see N6's doc comment on `removeRecordedLink`. */ export interface RemoveLinksResult { /** Count of destinations actually removed from disk. */ removed: number; /** * Destinations refused (left in place, e.g. N6's `.git`-at-root guard, or * a removal error) — each entry stays in the manifest so a future * `removeLinks` call retries it, and callers should surface `reason` to * the user rather than silently discarding it. */ refused: Array<{ to: string; reason: string; }>; /** * Things to tell the user: hidden backups left by an interrupted refresh * (SMI-6529 round 7), a corrupt link manifest moved aside (round 9), or a * manifest this uninstall couldn't use (round 11). Omitted when none. */ warnings?: string[]; } /** * Remove every fan-out link recorded for `skillId`. Safe to call when no * manifest exists (returns `{ removed: 0, refused: [] }`). * * Uninstall callers should invoke this BEFORE removing the canonical * directory so symlinks resolve cleanly during their lstat checks. * * SMI-6529 N6 (round 4): a destination `removeRecordedLink` refuses (a * recorded copy that now contains `.git` at its root, or a removal error) * keeps its manifest entry instead of being unconditionally dropped — the * old unconditional `manifest.links = manifest.links.filter(...)` discarded * the record for EVERY matching link regardless of whether the on-disk * removal actually succeeded, so a refused destination could never be * retried and its refusal was never reported anywhere. */ export declare function removeLinks(skillId: string): Promise; /** * List all fan-out links for a skill (or all skills when `skillId` is * undefined). Read-only — for `skillsmith list --client X` and the * cross-client `getInstalledSkills` consolidator. */ export declare function listLinks(skillId?: string): Promise; /** * Convenience: derive the default `fromClient` for fan-out (the canonical * client). Exists so callers don't have to import `CANONICAL_CLIENT` * separately when they only need the fan-out helpers. */ export declare function getDefaultFromClient(): ClientId; //# sourceMappingURL=fan-out.d.ts.map