agentln 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,11 +1,12 @@
1
1
  # agentln
2
2
 
3
- Cross-platform CLI that keeps `CLAUDE.md` and `AGENTS.md` in sync across an
4
- entire repository by managing **relative symlinks** between them.
3
+ Cross-platform CLI that keeps `CLAUDE.md` and `AGENTS.md` (and
4
+ `.claude/skills/` and `.agents/skills/`) in sync across an entire repository
5
+ by managing **relative symlinks** between them.
5
6
 
6
7
  You make **one decision at the repository root** — which filename is the source
7
8
  of truth — and `agentln` applies that decision recursively to every directory
8
- in the repo.
9
+ in the repo, for both the markdown pair and the skills directory pair.
9
10
 
10
11
  - Works on macOS, Linux, and Windows (PowerShell, Git Bash, WSL).
11
12
  - Uses Node's native `fs` symlink APIs. Never shells out to `ln`, `bash`, or
@@ -50,10 +51,27 @@ that contains either file is reconciled to the same convention:
50
51
 
51
52
  `agentln` is idempotent. Running it twice in a row will say "already in sync."
52
53
 
54
+ ### Skills directories
55
+
56
+ The same source-of-truth decision is applied to `.claude/skills/` and
57
+ `.agents/skills/` if either exists in a directory. With `CLAUDE.md` chosen as
58
+ source, `.claude/skills/` becomes the source-of-truth directory and
59
+ `.agents/skills/` is reconciled to a symlink pointing at `../.claude/skills`
60
+ (and vice versa). The parent `.claude/` or `.agents/` directory is created
61
+ automatically when needed.
62
+
63
+ Replacing a non-empty skills directory with a symlink requires `--force`, so
64
+ agentln will not silently delete a populated skills tree.
65
+
66
+ Only the `skills/` subdirectory is managed — other things under `.claude/` or
67
+ `.agents/` (e.g. `commands/`, `hooks/`, `settings.json`) are left alone
68
+ because they don't share a portable convention across agents.
69
+
53
70
  ### Symlink format
54
71
 
55
- Symlinks are always **relative** (`AGENTS.md → CLAUDE.md`), never absolute.
56
- This keeps the repo portable across machines and clones.
72
+ Symlinks are always **relative** (`AGENTS.md → CLAUDE.md`,
73
+ `.agents/skills ../.claude/skills`), never absolute. This keeps the repo
74
+ portable across machines and clones.
57
75
 
58
76
  ### Ignored directories
59
77
 
@@ -72,7 +90,8 @@ agentln [options]
72
90
  --source <name> Use CLAUDE.md or AGENTS.md as source of truth (skips prompt).
73
91
  -y, --yes Non-interactive mode. Accepts defaults for every prompt.
74
92
  --dry-run Show planned changes without writing anything.
75
- --force Overwrite divergent regular files when replacing with a symlink.
93
+ --force Overwrite divergent regular files or non-empty skills directories
94
+ when replacing with a symlink.
76
95
  --copy-fallback On Windows, copy the file instead of failing when symlink
77
96
  creation is denied.
78
97
  --no-copy-fallback Disable the copy fallback (default).
@@ -122,16 +141,6 @@ source of truth" guarantee.
122
141
  - Monorepos with multiple workspaces, each having their own per-package
123
142
  instructions: `agentln` reconciles every workspace in one pass.
124
143
 
125
- ## Publishing
126
-
127
- ```bash
128
- npm run build
129
- npm publish --access public
130
- ```
131
-
132
- The `prepublishOnly` script rebuilds `dist/` and ships only `dist/` plus the
133
- README and license.
134
-
135
144
  ## License
136
145
 
137
146
  MIT
@@ -1 +1 @@
1
- {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,UAAU,EAEhB,MAAM,YAAY,CAAC;AAqBpB,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAoEpD;AAsBD,wBAAgB,QAAQ,IAAI,MAAM,CAEjC"}
1
+ {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,UAAU,EAEhB,MAAM,YAAY,CAAC;AAuBpB,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAoEpD;AAsBD,wBAAgB,QAAQ,IAAI,MAAM,CAEjC"}
package/dist/args.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import path from "node:path";
2
2
  import { AGENTS_FILE, CLAUDE_FILE, } from "./types.js";
3
- const HELP_TEXT = `agentln — manage CLAUDE.md ⇄ AGENTS.md symlinks across a repo
3
+ const HELP_TEXT = `agentln — manage CLAUDE.md ⇄ AGENTS.md and .claude/skills ⇄ .agents/skills symlinks across a repo
4
4
 
5
5
  Usage:
6
6
  npx agentln [options]
@@ -9,10 +9,12 @@ Usage:
9
9
  Options:
10
10
  --root <path> Repository root (default: current working directory).
11
11
  --source <name> Use CLAUDE.md or AGENTS.md as source of truth (skips prompt).
12
+ Also drives .claude/skills vs .agents/skills as the source-of-truth dir.
12
13
  -y, --yes Non-interactive mode (assume defaults for every prompt).
13
14
  --dry-run Show planned changes without writing anything.
14
- --force Overwrite divergent regular files when replacing with a symlink.
15
- --copy-fallback On Windows, fall back to a file copy if symlink creation is denied.
15
+ --force Overwrite divergent regular files or non-empty skills directories
16
+ when replacing with a symlink.
17
+ --copy-fallback On Windows, fall back to a recursive copy if symlink creation is denied.
16
18
  --no-copy-fallback Disable the copy fallback (default).
17
19
  --verbose Print debug-level information.
18
20
  -h, --help Show this help.
package/dist/args.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE9D,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,0EAA0E;IAC1E,YAAY,EAAE,OAAO,CAAC;CACvB;AAgCD,wBAAsB,aAAa,CACjC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,YAAY,CAAC,CAsHvB;AAED,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC"}
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE9D,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,0EAA0E;IAC1E,YAAY,EAAE,OAAO,CAAC;CACvB;AA4CD,wBAAsB,aAAa,CACjC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,YAAY,CAAC,CAsIvB;AAED,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC"}
package/dist/executor.js CHANGED
@@ -3,27 +3,29 @@ import os from "node:os";
3
3
  import path from "node:path";
4
4
  const IS_WINDOWS = process.platform === "win32";
5
5
  /**
6
- * On Windows, `fs.symlink` needs an explicit type hint. We always use `file`
7
- * for our use case (linking a single file). On POSIX systems the type arg is
8
- * ignored.
6
+ * On Windows, `fs.symlink` needs an explicit type hint ("file" or "dir").
7
+ * On POSIX systems the type arg is ignored.
9
8
  */
10
- async function createRelativeSymlink(linkPath, sourcePath) {
9
+ async function createRelativeSymlink(linkPath, sourcePath, isDirectory) {
11
10
  const target = path.relative(path.dirname(linkPath), sourcePath);
12
- await fs.symlink(target, linkPath, IS_WINDOWS ? "file" : undefined);
11
+ const winType = isDirectory ? "dir" : "file";
12
+ await fs.symlink(target, linkPath, IS_WINDOWS ? winType : undefined);
13
13
  }
14
- async function safeUnlink(p) {
15
- try {
16
- await fs.unlink(p);
14
+ /** Remove a file, symlink, or directory tree. No-op if the path is missing. */
15
+ async function safeRemove(p) {
16
+ await fs.rm(p, { recursive: true, force: true });
17
+ }
18
+ async function ensureParentDir(p) {
19
+ await fs.mkdir(path.dirname(p), { recursive: true });
20
+ }
21
+ async function copyEntry(sourcePath, destPath, isDirectory) {
22
+ if (isDirectory) {
23
+ await fs.cp(sourcePath, destPath, { recursive: true });
17
24
  }
18
- catch (err) {
19
- const code = err.code;
20
- if (code !== "ENOENT")
21
- throw err;
25
+ else {
26
+ await fs.copyFile(sourcePath, destPath);
22
27
  }
23
28
  }
24
- async function copyFile(sourcePath, destPath) {
25
- await fs.copyFile(sourcePath, destPath);
26
- }
27
29
  function isSymlinkPermissionError(err) {
28
30
  const code = err?.code;
29
31
  return code === "EPERM" || code === "EACCES" || code === "ENOSYS";
@@ -50,25 +52,37 @@ export async function executeAction(action, options) {
50
52
  }
51
53
  }
52
54
  case "create-symlink": {
55
+ const noun = action.isDirectory ? "directory symlink" : "symlink";
53
56
  if (options.dryRun) {
54
57
  const verb = action.replacesExisting ? "replace" : "create";
55
- return { action, ok: true, message: `would ${verb} symlink` };
58
+ return { action, ok: true, message: `would ${verb} ${noun}` };
59
+ }
60
+ // Guard real-content replacement (real file or real directory) behind --force.
61
+ if (action.replacesExisting && action.replacesRegularFile && action.isDirectory) {
62
+ return {
63
+ action,
64
+ ok: false,
65
+ message: `${action.linkPath} is a non-empty directory; refusing to replace it ` +
66
+ "with a symlink without --force (this would delete its contents).",
67
+ };
56
68
  }
57
69
  try {
58
70
  if (action.replacesExisting)
59
- await safeUnlink(action.linkPath);
60
- await createRelativeSymlink(action.linkPath, action.sourcePath);
61
- return { action, ok: true, message: "symlink created" };
71
+ await safeRemove(action.linkPath);
72
+ await ensureParentDir(action.linkPath);
73
+ await createRelativeSymlink(action.linkPath, action.sourcePath, action.isDirectory);
74
+ return { action, ok: true, message: `${noun} created` };
62
75
  }
63
76
  catch (err) {
64
77
  if (IS_WINDOWS && isSymlinkPermissionError(err) && options.copyFallback) {
65
78
  try {
66
- await safeUnlink(action.linkPath);
67
- await copyFile(action.sourcePath, action.linkPath);
79
+ await safeRemove(action.linkPath);
80
+ await ensureParentDir(action.linkPath);
81
+ await copyEntry(action.sourcePath, action.linkPath, action.isDirectory);
68
82
  return {
69
83
  action,
70
84
  ok: true,
71
- message: "symlink not permitted on this system; wrote a file copy instead. " +
85
+ message: `${noun} not permitted on this system; wrote a ${action.isDirectory ? "recursive copy" : "file copy"} instead. ` +
72
86
  "Re-run after enabling Developer Mode or with admin privileges " +
73
87
  "to use real symlinks.",
74
88
  fellBackToCopy: true,
@@ -82,20 +96,21 @@ export async function executeAction(action, options) {
82
96
  return {
83
97
  action,
84
98
  ok: false,
85
- message: "creating a symlink was denied by the OS. On Windows, enable " +
99
+ message: `creating a ${noun} was denied by the OS. On Windows, enable ` +
86
100
  "Developer Mode or run an elevated shell, or re-run with " +
87
- "--copy-fallback to write a regular file copy instead.",
101
+ `--copy-fallback to write a ${action.isDirectory ? "recursive copy" : "regular file copy"} instead.`,
88
102
  };
89
103
  }
90
104
  return { action, ok: false, message: errorMessage(err) };
91
105
  }
92
106
  }
93
107
  case "promote-to-source": {
108
+ const noun = action.isDirectory ? "directory" : "file";
94
109
  if (options.dryRun) {
95
110
  return {
96
111
  action,
97
112
  ok: true,
98
- message: `would rename ${path.basename(action.fromPath)} → ${path.basename(action.toPath)} and link back`,
113
+ message: `would rename ${noun} ${path.basename(action.fromPath)} → ${path.basename(action.toPath)} and link back`,
99
114
  };
100
115
  }
101
116
  try {
@@ -117,24 +132,25 @@ export async function executeAction(action, options) {
117
132
  };
118
133
  }
119
134
  if (targetExists)
120
- await safeUnlink(action.toPath);
135
+ await safeRemove(action.toPath);
136
+ await ensureParentDir(action.toPath);
121
137
  await fs.rename(action.fromPath, action.toPath);
122
- await createRelativeSymlink(action.fromPath, action.toPath);
138
+ await createRelativeSymlink(action.fromPath, action.toPath, action.isDirectory);
123
139
  return {
124
140
  action,
125
141
  ok: true,
126
- message: "promoted file to source and linked back",
142
+ message: `promoted ${noun} to source and linked back`,
127
143
  };
128
144
  }
129
145
  catch (err) {
130
146
  if (IS_WINDOWS && isSymlinkPermissionError(err) && options.copyFallback) {
131
147
  try {
132
- await copyFile(action.toPath, action.fromPath);
148
+ await copyEntry(action.toPath, action.fromPath, action.isDirectory);
133
149
  return {
134
150
  action,
135
151
  ok: true,
136
- message: "symlink not permitted; wrote a file copy as fallback. The " +
137
- "two files will diverge on subsequent edits.",
152
+ message: `symlink not permitted; wrote a ${action.isDirectory ? "recursive copy" : "file copy"} as fallback. ` +
153
+ "The two paths will diverge on subsequent edits.",
138
154
  fellBackToCopy: true,
139
155
  };
140
156
  }
@@ -1 +1 @@
1
- {"version":3,"file":"executor.js","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"planner.d.ts","sourceRoot":"","sources":["../src/planner.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,QAAQ,EAEb,KAAK,aAAa,EAClB,KAAK,UAAU,EAChB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB;;;OAGG;IACH,aAAa,EAAE,OAAO,CAAC;IACvB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,IAAI;IACnB,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,uEAAuE;IACvE,UAAU,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,UAAU,EAAE,MAAM,CAAC;CACpB;AAUD,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CA2EhD;AAuDD,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAoB5D"}
1
+ {"version":3,"file":"planner.d.ts","sourceRoot":"","sources":["../src/planner.ts"],"names":[],"mappings":"AAEA,OAAO,EAOL,KAAK,QAAQ,EAEb,KAAK,aAAa,EAClB,KAAK,UAAU,EAChB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB;;;OAGG;IACH,aAAa,EAAE,OAAO,CAAC;IACvB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,IAAI;IACnB,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,uEAAuE;IACvE,UAAU,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,UAAU,EAAE,MAAM,CAAC;CACpB;AAiBD,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAmDhD;AAwID,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAuB5D"}
package/dist/planner.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import path from "node:path";
2
- import { AGENTS_FILE, CLAUDE_FILE, } from "./types.js";
2
+ import { AGENTS_DIR, AGENTS_FILE, CLAUDE_DIR, CLAUDE_FILE, SKILLS_SUBDIR, sourceDirFor, } from "./types.js";
3
3
  function linkName(source) {
4
4
  return source === CLAUDE_FILE ? AGENTS_FILE : CLAUDE_FILE;
5
5
  }
@@ -12,6 +12,8 @@ export function buildPlan(input) {
12
12
  let cleanCount = 0;
13
13
  let emptyCount = 0;
14
14
  const otherName = linkName(source);
15
+ const sourceDir = sourceDirFor(source);
16
+ const otherDir = sourceDir === CLAUDE_DIR ? AGENTS_DIR : CLAUDE_DIR;
15
17
  if (bootstrapRoot) {
16
18
  actions.push({
17
19
  type: "create-root-source",
@@ -20,62 +22,92 @@ export function buildPlan(input) {
20
22
  }
21
23
  for (const dir of dirs) {
22
24
  const isRootDir = dir.dir === root;
23
- const sourceEntry = entryFor(dir, source);
24
- const linkEntry = entryFor(dir, otherName);
25
- const sourcePresent = sourceEntry.kind === "regular-file" ||
26
- (sourceEntry.kind === "correct-symlink" && !isRootDir) ||
27
- // After bootstrap the root source will exist on disk by the time we run.
28
- (isRootDir && bootstrapRoot);
29
- const linkPresent = linkEntry.kind !== "missing";
30
- // Nothing in this directory to manage.
31
- if (!sourcePresent && !linkPresent) {
25
+ // --- File pair: CLAUDE.md <-> AGENTS.md ---
26
+ const fileOutcome = reconcilePair({
27
+ sourceEntry: entryFor(dir, source),
28
+ linkEntry: entryFor(dir, otherName),
29
+ sourcePath: path.join(dir.dir, source),
30
+ linkPath: path.join(dir.dir, otherName),
31
+ isDirectory: false,
32
+ // The root source is bootstrapped earlier, so treat it as present at planning time.
33
+ sourceConsideredPresent: isRootDir && bootstrapRoot,
34
+ force,
35
+ });
36
+ // --- Directory pair: .claude/skills <-> .agents/skills ---
37
+ const skillsOutcome = reconcilePair({
38
+ sourceEntry: skillsEntryFor(dir, sourceDir),
39
+ linkEntry: skillsEntryFor(dir, otherDir),
40
+ sourcePath: path.join(dir.dir, sourceDir, SKILLS_SUBDIR),
41
+ linkPath: path.join(dir.dir, otherDir, SKILLS_SUBDIR),
42
+ isDirectory: true,
43
+ sourceConsideredPresent: false,
44
+ force,
45
+ });
46
+ actions.push(...fileOutcome.actions, ...skillsOutcome.actions);
47
+ const combined = combineStatus(fileOutcome.status, skillsOutcome.status);
48
+ if (combined === "clean")
49
+ cleanCount++;
50
+ else if (combined === "empty")
32
51
  emptyCount++;
33
- continue;
34
- }
35
- // Source exists (or will after bootstrap). Just ensure the link mirrors it.
36
- if (sourcePresent) {
37
- const desired = ensureLink({
38
- sourceName: source,
39
- linkName: otherName,
40
- linkEntry,
41
- dir: dir.dir,
42
- force,
43
- });
44
- if (desired === "ok") {
45
- cleanCount++;
46
- }
47
- else {
48
- actions.push(desired);
49
- }
50
- continue;
51
- }
52
- // No source file in this directory but the link file exists as a regular
53
- // file (or stale/broken symlink). Promote it to source, then link back.
54
- if (linkEntry.kind === "regular-file" ||
55
- linkEntry.kind === "incorrect-symlink" ||
56
- linkEntry.kind === "broken-symlink") {
57
- const sourcePath = path.join(dir.dir, source);
58
- actions.push({
59
- type: "promote-to-source",
60
- fromPath: linkEntry.path,
61
- toPath: sourcePath,
62
- linkBack: true,
63
- });
64
- }
65
- else {
66
- actions.push({
52
+ }
53
+ return { actions, cleanCount, emptyCount };
54
+ }
55
+ function combineStatus(a, b) {
56
+ if (a === "changed" || b === "changed")
57
+ return "changed";
58
+ if (a === "clean" || b === "clean")
59
+ return "clean";
60
+ return "empty";
61
+ }
62
+ function skillsEntryFor(dir, which) {
63
+ return which === CLAUDE_DIR ? dir.claudeSkills : dir.agentsSkills;
64
+ }
65
+ function reconcilePair(args) {
66
+ const { sourceEntry, linkEntry, sourcePath, linkPath, isDirectory, force } = args;
67
+ const sourcePresent = args.sourceConsideredPresent ||
68
+ sourceEntry.kind === "regular-file" ||
69
+ sourceEntry.kind === "correct-symlink";
70
+ const linkPresent = linkEntry.kind !== "missing";
71
+ if (!sourcePresent && !linkPresent) {
72
+ return { actions: [], status: "empty" };
73
+ }
74
+ if (sourcePresent) {
75
+ const desired = ensureLink({ linkEntry, sourcePath, linkPath, isDirectory, force });
76
+ if (desired === "ok")
77
+ return { actions: [], status: "clean" };
78
+ return { actions: [desired], status: "changed" };
79
+ }
80
+ // No source present in this directory; promote the link if it has real
81
+ // content (or even just a salvageable stale symlink target).
82
+ if (linkEntry.kind === "regular-file" ||
83
+ linkEntry.kind === "incorrect-symlink" ||
84
+ linkEntry.kind === "broken-symlink") {
85
+ return {
86
+ actions: [
87
+ {
88
+ type: "promote-to-source",
89
+ fromPath: linkEntry.path,
90
+ toPath: sourcePath,
91
+ linkBack: true,
92
+ isDirectory,
93
+ },
94
+ ],
95
+ status: "changed",
96
+ };
97
+ }
98
+ return {
99
+ actions: [
100
+ {
67
101
  type: "skip",
68
102
  path: linkEntry.path,
69
103
  reason: `unexpected entry kind: ${linkEntry.kind}`,
70
- });
71
- }
72
- }
73
- return { actions, cleanCount, emptyCount };
104
+ },
105
+ ],
106
+ status: "changed",
107
+ };
74
108
  }
75
109
  function ensureLink(args) {
76
- const { sourceName, linkEntry, dir, force } = args;
77
- const sourcePath = path.join(dir, sourceName);
78
- const linkPath = linkEntry.path;
110
+ const { linkEntry, sourcePath, linkPath, isDirectory, force } = args;
79
111
  if (linkEntry.kind === "correct-symlink")
80
112
  return "ok";
81
113
  if (linkEntry.kind === "missing") {
@@ -85,6 +117,7 @@ function ensureLink(args) {
85
117
  sourcePath,
86
118
  replacesExisting: false,
87
119
  replacesRegularFile: false,
120
+ isDirectory,
88
121
  };
89
122
  }
90
123
  if (linkEntry.kind === "incorrect-symlink" ||
@@ -95,15 +128,20 @@ function ensureLink(args) {
95
128
  sourcePath,
96
129
  replacesExisting: true,
97
130
  replacesRegularFile: false,
131
+ isDirectory,
98
132
  };
99
133
  }
100
134
  if (linkEntry.kind === "regular-file") {
135
+ // "regular-file" here means real content of the expected kind (real file
136
+ // for the MD pair, real directory for the skills pair). Replacing real
137
+ // content requires --force so we don't silently destroy data.
101
138
  return {
102
139
  type: "create-symlink",
103
140
  linkPath,
104
141
  sourcePath,
105
142
  replacesExisting: true,
106
143
  replacesRegularFile: !force,
144
+ isDirectory,
107
145
  };
108
146
  }
109
147
  return {
@@ -118,16 +156,19 @@ export function describeAction(action) {
118
156
  return `create empty source file → ${action.sourcePath}`;
119
157
  case "create-symlink": {
120
158
  const rel = path.relative(path.dirname(action.linkPath), action.sourcePath);
159
+ const noun = action.isDirectory ? "directory symlink" : "symlink";
160
+ const realNoun = action.isDirectory ? "directory" : "regular file";
121
161
  const verb = action.replacesExisting
122
162
  ? action.replacesRegularFile
123
- ? "replace regular file"
124
- : "replace stale symlink"
125
- : "create symlink";
163
+ ? `replace ${realNoun}`
164
+ : `replace stale ${noun}`
165
+ : `create ${noun}`;
126
166
  return `${verb} ${action.linkPath} → ${rel}`;
127
167
  }
128
168
  case "promote-to-source": {
129
169
  const rel = path.relative(path.dirname(action.fromPath), action.toPath);
130
- return `rename ${action.fromPath} → ${action.toPath}, then link ${path.basename(action.fromPath)} → ${rel}`;
170
+ const noun = action.isDirectory ? "directory" : "file";
171
+ return `rename ${noun} ${action.fromPath} → ${action.toPath}, then link ${path.basename(action.fromPath)} → ${rel}`;
131
172
  }
132
173
  case "skip":
133
174
  return `skip ${action.path} (${action.reason})`;
@@ -1 +1 @@
1
- {"version":3,"file":"planner.js","sourceRoot":"","sources":["../src/planner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"planner.js","sourceRoot":"","sources":["../src/planner.ts"],"names":[],"mappings":"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"}
package/dist/scanner.d.ts CHANGED
@@ -5,14 +5,23 @@ export interface ScanOptions {
5
5
  followHiddenDirs?: boolean;
6
6
  }
7
7
  /**
8
- * Classify a single CLAUDE.md/AGENTS.md candidate path. Resolves the symlink
9
- * target without following it, so we can decide whether it already points to
10
- * its sibling source file.
8
+ * Classify a single CLAUDE.md/AGENTS.md candidate path, or a managed
9
+ * directory path (e.g. .claude/skills). Resolves the symlink target without
10
+ * following it, so we can decide whether it already points at its sibling
11
+ * source. `expectedKind` determines whether a "real" entry should be a file
12
+ * or a directory; the returned EntryKind reuses `regular-file` to mean
13
+ * "real content at this path" in either mode.
14
+ *
15
+ * For directories, `expectedSiblingTarget` is the relative path that a
16
+ * correctly-shaped symlink should point to (e.g. `../.claude/skills`).
11
17
  */
12
- export declare function classifyEntry(filePath: string, expectedSiblingSource: SourceName | null): Promise<EntryState>;
18
+ export declare function classifyEntry(filePath: string, expectedSiblingTarget: string | null, options?: {
19
+ expectedKind?: "file" | "directory";
20
+ }): Promise<EntryState>;
13
21
  /**
14
- * Build the per-directory state for the two managed files. `source` is the
15
- * repository-wide source-of-truth name; the other file is the link.
22
+ * Build the per-directory state for the two managed files and the two
23
+ * managed skills directories. `source` is the repository-wide source-of-truth
24
+ * name; the other file (and corresponding skills dir) is the link.
16
25
  */
17
26
  export declare function readDirState(dir: string, source: SourceName): Promise<DirState>;
18
27
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,QAAQ,EAEb,KAAK,UAAU,EACf,KAAK,UAAU,EAChB,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,oBAAoB,aAiB/B,CAAC;AAEH,MAAM,WAAW,WAAW;IAC1B,WAAW,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,qBAAqB,EAAE,UAAU,GAAG,IAAI,GACvC,OAAO,CAAC,UAAU,CAAC,CAgDrB;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,QAAQ,CAAC,CAanB;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,UAAU,EAClB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,QAAQ,EAAE,CAAC,CAsCrB;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAmBvD"}
1
+ {"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAGA,OAAO,EAOL,KAAK,QAAQ,EAEb,KAAK,UAAU,EACf,KAAK,UAAU,EAChB,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,oBAAoB,aAiB/B,CAAC;AAEH,MAAM,WAAW,WAAW;IAC1B,WAAW,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,qBAAqB,EAAE,MAAM,GAAG,IAAI,EACpC,OAAO,GAAE;IAAE,YAAY,CAAC,EAAE,MAAM,GAAG,WAAW,CAAA;CAAO,GACpD,OAAO,CAAC,UAAU,CAAC,CA4DrB;AAOD;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,QAAQ,CAAC,CA8BnB;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,UAAU,EAClB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,QAAQ,EAAE,CAAC,CAkDrB;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAmBvD"}
package/dist/scanner.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { promises as fs } from "node:fs";
2
2
  import path from "node:path";
3
- import { AGENTS_FILE, CLAUDE_FILE, } from "./types.js";
3
+ import { AGENTS_DIR, AGENTS_FILE, CLAUDE_DIR, CLAUDE_FILE, SKILLS_SUBDIR, sourceDirFor, } from "./types.js";
4
4
  export const DEFAULT_IGNORED_DIRS = new Set([
5
5
  "node_modules",
6
6
  ".git",
@@ -20,11 +20,18 @@ export const DEFAULT_IGNORED_DIRS = new Set([
20
20
  ".vscode",
21
21
  ]);
22
22
  /**
23
- * Classify a single CLAUDE.md/AGENTS.md candidate path. Resolves the symlink
24
- * target without following it, so we can decide whether it already points to
25
- * its sibling source file.
23
+ * Classify a single CLAUDE.md/AGENTS.md candidate path, or a managed
24
+ * directory path (e.g. .claude/skills). Resolves the symlink target without
25
+ * following it, so we can decide whether it already points at its sibling
26
+ * source. `expectedKind` determines whether a "real" entry should be a file
27
+ * or a directory; the returned EntryKind reuses `regular-file` to mean
28
+ * "real content at this path" in either mode.
29
+ *
30
+ * For directories, `expectedSiblingTarget` is the relative path that a
31
+ * correctly-shaped symlink should point to (e.g. `../.claude/skills`).
26
32
  */
27
- export async function classifyEntry(filePath, expectedSiblingSource) {
33
+ export async function classifyEntry(filePath, expectedSiblingTarget, options = {}) {
34
+ const expectedKind = options.expectedKind ?? "file";
28
35
  let lstat;
29
36
  try {
30
37
  lstat = await fs.lstat(filePath);
@@ -32,9 +39,6 @@ export async function classifyEntry(filePath, expectedSiblingSource) {
32
39
  catch {
33
40
  return { path: filePath, kind: "missing" };
34
41
  }
35
- if (lstat.isDirectory()) {
36
- return { path: filePath, kind: "directory" };
37
- }
38
42
  if (lstat.isSymbolicLink()) {
39
43
  let target;
40
44
  try {
@@ -50,35 +54,59 @@ export async function classifyEntry(filePath, expectedSiblingSource) {
50
54
  catch {
51
55
  return { path: filePath, kind: "broken-symlink", linkTarget: target };
52
56
  }
53
- if (!stat.isFile()) {
57
+ const targetMatchesKind = expectedKind === "file" ? stat.isFile() : stat.isDirectory();
58
+ if (!targetMatchesKind) {
54
59
  return { path: filePath, kind: "incorrect-symlink", linkTarget: target };
55
60
  }
56
- if (expectedSiblingSource) {
57
- // We accept either the bare filename or "./<filename>" as correct.
58
- const normalised = target.replace(/^\.[\\/]/, "");
59
- if (normalised === expectedSiblingSource) {
61
+ if (expectedSiblingTarget) {
62
+ const normalised = normaliseLinkTarget(target);
63
+ if (normalised === normaliseLinkTarget(expectedSiblingTarget)) {
60
64
  return { path: filePath, kind: "correct-symlink", linkTarget: target };
61
65
  }
62
66
  return { path: filePath, kind: "incorrect-symlink", linkTarget: target };
63
67
  }
64
68
  return { path: filePath, kind: "incorrect-symlink", linkTarget: target };
65
69
  }
70
+ if (expectedKind === "directory") {
71
+ if (lstat.isDirectory()) {
72
+ return { path: filePath, kind: "regular-file" };
73
+ }
74
+ if (lstat.isFile()) {
75
+ return { path: filePath, kind: "other" };
76
+ }
77
+ return { path: filePath, kind: "other" };
78
+ }
79
+ if (lstat.isDirectory()) {
80
+ return { path: filePath, kind: "directory" };
81
+ }
66
82
  if (lstat.isFile()) {
67
83
  return { path: filePath, kind: "regular-file" };
68
84
  }
69
85
  return { path: filePath, kind: "other" };
70
86
  }
87
+ function normaliseLinkTarget(target) {
88
+ // Accept both POSIX and Windows separators; strip a leading "./".
89
+ return target.replace(/\\/g, "/").replace(/^\.\//, "");
90
+ }
71
91
  /**
72
- * Build the per-directory state for the two managed files. `source` is the
73
- * repository-wide source-of-truth name; the other file is the link.
92
+ * Build the per-directory state for the two managed files and the two
93
+ * managed skills directories. `source` is the repository-wide source-of-truth
94
+ * name; the other file (and corresponding skills dir) is the link.
74
95
  */
75
96
  export async function readDirState(dir, source) {
76
- const linkName = source === CLAUDE_FILE ? AGENTS_FILE : CLAUDE_FILE;
77
- const [claude, agents] = await Promise.all([
78
- classifyEntry(path.join(dir, CLAUDE_FILE), source === CLAUDE_FILE ? null : linkName === CLAUDE_FILE ? source : null),
79
- classifyEntry(path.join(dir, AGENTS_FILE), source === AGENTS_FILE ? null : linkName === AGENTS_FILE ? source : null),
97
+ const sourceDir = sourceDirFor(source);
98
+ const linkFile = source === CLAUDE_FILE ? AGENTS_FILE : CLAUDE_FILE;
99
+ const linkDir = sourceDir === CLAUDE_DIR ? AGENTS_DIR : CLAUDE_DIR;
100
+ // For the file pair, a correct link points at the bare source filename.
101
+ // For the skills pair, a correct link points at "../<source-dir>/skills".
102
+ const skillsLinkTarget = `../${sourceDir}/${SKILLS_SUBDIR}`;
103
+ const [claude, agents, claudeSkills, agentsSkills] = await Promise.all([
104
+ classifyEntry(path.join(dir, CLAUDE_FILE), source === CLAUDE_FILE ? null : linkFile === CLAUDE_FILE ? source : null),
105
+ classifyEntry(path.join(dir, AGENTS_FILE), source === AGENTS_FILE ? null : linkFile === AGENTS_FILE ? source : null),
106
+ classifyEntry(path.join(dir, CLAUDE_DIR, SKILLS_SUBDIR), sourceDir === CLAUDE_DIR ? null : linkDir === CLAUDE_DIR ? skillsLinkTarget : null, { expectedKind: "directory" }),
107
+ classifyEntry(path.join(dir, AGENTS_DIR, SKILLS_SUBDIR), sourceDir === AGENTS_DIR ? null : linkDir === AGENTS_DIR ? skillsLinkTarget : null, { expectedKind: "directory" }),
80
108
  ]);
81
- return { dir, claude, agents };
109
+ return { dir, claude, agents, claudeSkills, agentsSkills };
82
110
  }
83
111
  /**
84
112
  * Walk the repo recursively and yield every directory that contains at least
@@ -98,8 +126,16 @@ export async function scanRepository(root, source, options = {}) {
98
126
  }
99
127
  let hasClaude = false;
100
128
  let hasAgents = false;
129
+ let hasClaudeManagedDir = false;
130
+ let hasAgentsManagedDir = false;
101
131
  const childDirs = [];
102
132
  for (const entry of entries) {
133
+ if (entry.isDirectory() || entry.isSymbolicLink()) {
134
+ if (entry.name === CLAUDE_DIR)
135
+ hasClaudeManagedDir = true;
136
+ else if (entry.name === AGENTS_DIR)
137
+ hasAgentsManagedDir = true;
138
+ }
103
139
  if (entry.isDirectory()) {
104
140
  if (ignored.has(entry.name))
105
141
  continue;
@@ -114,7 +150,11 @@ export async function scanRepository(root, source, options = {}) {
114
150
  hasAgents = true;
115
151
  }
116
152
  }
117
- if (isRoot || hasClaude || hasAgents) {
153
+ if (isRoot ||
154
+ hasClaude ||
155
+ hasAgents ||
156
+ hasClaudeManagedDir ||
157
+ hasAgentsManagedDir) {
118
158
  results.push(await readDirState(dir, source));
119
159
  }
120
160
  for (const child of childDirs) {
@@ -1 +1 @@
1
- {"version":3,"file":"scanner.js","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scanner.js","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -1,6 +1,11 @@
1
1
  export declare const CLAUDE_FILE = "CLAUDE.md";
2
2
  export declare const AGENTS_FILE = "AGENTS.md";
3
+ export declare const CLAUDE_DIR = ".claude";
4
+ export declare const AGENTS_DIR = ".agents";
5
+ export declare const SKILLS_SUBDIR = "skills";
3
6
  export type SourceName = typeof CLAUDE_FILE | typeof AGENTS_FILE;
7
+ export type SourceDirName = typeof CLAUDE_DIR | typeof AGENTS_DIR;
8
+ export declare function sourceDirFor(source: SourceName): SourceDirName;
4
9
  export interface CliOptions {
5
10
  root: string;
6
11
  yes: boolean;
@@ -26,6 +31,10 @@ export interface DirState {
26
31
  dir: string;
27
32
  claude: EntryState;
28
33
  agents: EntryState;
34
+ /** State of <dir>/.claude/skills (directory, symlink, or missing). */
35
+ claudeSkills: EntryState;
36
+ /** State of <dir>/.agents/skills (directory, symlink, or missing). */
37
+ agentsSkills: EntryState;
29
38
  }
30
39
  export type PlannedAction = {
31
40
  type: "create-symlink";
@@ -35,16 +44,20 @@ export type PlannedAction = {
35
44
  sourcePath: string;
36
45
  /** Whether the link file currently exists and must be removed first. */
37
46
  replacesExisting: boolean;
38
- /** Whether existing entry is a regular file (vs a stale symlink). */
47
+ /** Whether existing entry is real content (regular file or real directory) vs a stale symlink. */
39
48
  replacesRegularFile: boolean;
49
+ /** True when linking a directory (e.g. skills/), false for a single file. */
50
+ isDirectory: boolean;
40
51
  } | {
41
52
  type: "promote-to-source";
42
- /** Existing file that will be renamed (e.g. AGENTS.md in a folder where CLAUDE.md is source). */
53
+ /** Existing entry that will be renamed (e.g. AGENTS.md in a folder where CLAUDE.md is source). */
43
54
  fromPath: string;
44
- /** New name for that file (e.g. CLAUDE.md). */
55
+ /** New name for that entry (e.g. CLAUDE.md). */
45
56
  toPath: string;
46
57
  /** Then create symlink at fromPath -> toPath. */
47
58
  linkBack: true;
59
+ /** True when promoting a directory (e.g. skills/), false for a single file. */
60
+ isDirectory: boolean;
48
61
  } | {
49
62
  type: "create-root-source";
50
63
  /** Create an empty source file at the repository root. */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,cAAc,CAAC;AACvC,eAAO,MAAM,WAAW,cAAc,CAAC;AAEvC,MAAM,MAAM,UAAU,GAAG,OAAO,WAAW,GAAG,OAAO,WAAW,CAAC;AAEjE,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;IACtB,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,MAAM,SAAS,GACjB,SAAS,GACT,cAAc,GACd,iBAAiB,GACjB,mBAAmB,GACnB,gBAAgB,GAChB,WAAW,GACX,OAAO,CAAC;AAEZ,MAAM,WAAW,UAAU;IACzB,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,QAAQ;IACvB,+BAA+B;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,UAAU,CAAC;CACpB;AAED,MAAM,MAAM,aAAa,GACrB;IACE,IAAI,EAAE,gBAAgB,CAAC;IACvB,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;IACjB,gEAAgE;IAChE,UAAU,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,gBAAgB,EAAE,OAAO,CAAC;IAC1B,qEAAqE;IACrE,mBAAmB,EAAE,OAAO,CAAC;CAC9B,GACD;IACE,IAAI,EAAE,mBAAmB,CAAC;IAC1B,iGAAiG;IACjG,QAAQ,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,QAAQ,EAAE,IAAI,CAAC;CAChB,GACD;IACE,IAAI,EAAE,oBAAoB,CAAC;IAC3B,0DAA0D;IAC1D,UAAU,EAAE,MAAM,CAAC;CACpB,GACD;IACE,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEN,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,aAAa,CAAC;IACtB,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,cAAc,CAAC;AACvC,eAAO,MAAM,WAAW,cAAc,CAAC;AAEvC,eAAO,MAAM,UAAU,YAAY,CAAC;AACpC,eAAO,MAAM,UAAU,YAAY,CAAC;AACpC,eAAO,MAAM,aAAa,WAAW,CAAC;AAEtC,MAAM,MAAM,UAAU,GAAG,OAAO,WAAW,GAAG,OAAO,WAAW,CAAC;AACjE,MAAM,MAAM,aAAa,GAAG,OAAO,UAAU,GAAG,OAAO,UAAU,CAAC;AAElE,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,aAAa,CAE9D;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;IACtB,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,MAAM,SAAS,GACjB,SAAS,GACT,cAAc,GACd,iBAAiB,GACjB,mBAAmB,GACnB,gBAAgB,GAChB,WAAW,GACX,OAAO,CAAC;AAEZ,MAAM,WAAW,UAAU;IACzB,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,QAAQ;IACvB,+BAA+B;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,UAAU,CAAC;IACnB,sEAAsE;IACtE,YAAY,EAAE,UAAU,CAAC;IACzB,sEAAsE;IACtE,YAAY,EAAE,UAAU,CAAC;CAC1B;AAED,MAAM,MAAM,aAAa,GACrB;IACE,IAAI,EAAE,gBAAgB,CAAC;IACvB,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;IACjB,gEAAgE;IAChE,UAAU,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,gBAAgB,EAAE,OAAO,CAAC;IAC1B,kGAAkG;IAClG,mBAAmB,EAAE,OAAO,CAAC;IAC7B,6EAA6E;IAC7E,WAAW,EAAE,OAAO,CAAC;CACtB,GACD;IACE,IAAI,EAAE,mBAAmB,CAAC;IAC1B,kGAAkG;IAClG,QAAQ,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,QAAQ,EAAE,IAAI,CAAC;IACf,+EAA+E;IAC/E,WAAW,EAAE,OAAO,CAAC;CACtB,GACD;IACE,IAAI,EAAE,oBAAoB,CAAC;IAC3B,0DAA0D;IAC1D,UAAU,EAAE,MAAM,CAAC;CACpB,GACD;IACE,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEN,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,aAAa,CAAC;IACtB,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B"}
package/dist/types.js CHANGED
@@ -1,3 +1,9 @@
1
1
  export const CLAUDE_FILE = "CLAUDE.md";
2
2
  export const AGENTS_FILE = "AGENTS.md";
3
+ export const CLAUDE_DIR = ".claude";
4
+ export const AGENTS_DIR = ".agents";
5
+ export const SKILLS_SUBDIR = "skills";
6
+ export function sourceDirFor(source) {
7
+ return source === CLAUDE_FILE ? CLAUDE_DIR : AGENTS_DIR;
8
+ }
3
9
  //# sourceMappingURL=types.js.map
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG,WAAW,CAAC;AACvC,MAAM,CAAC,MAAM,WAAW,GAAG,WAAW,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG,WAAW,CAAC;AACvC,MAAM,CAAC,MAAM,WAAW,GAAG,WAAW,CAAC;AAEvC,MAAM,CAAC,MAAM,UAAU,GAAG,SAAS,CAAC;AACpC,MAAM,CAAC,MAAM,UAAU,GAAG,SAAS,CAAC;AACpC,MAAM,CAAC,MAAM,aAAa,GAAG,QAAQ,CAAC;AAKtC,MAAM,UAAU,YAAY,CAAC,MAAkB;IAC7C,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC;AAC1D,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentln",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Cross-platform CLI to manage symlinks between CLAUDE.md and AGENTS.md across a repository.",
5
5
  "keywords": [
6
6
  "claude",
@@ -41,14 +41,14 @@
41
41
  "test": "node --test dist/test"
42
42
  },
43
43
  "dependencies": {
44
- "picocolors": "^1.1.1",
45
- "prompts": "^2.4.2"
44
+ "picocolors": "1.1.1",
45
+ "prompts": "2.4.2"
46
46
  },
47
47
  "devDependencies": {
48
- "@types/node": "^22.10.0",
49
- "@types/prompts": "^2.4.9",
50
- "rimraf": "^6.0.1",
51
- "typescript": "^5.7.2"
48
+ "@types/node": "25.8.0",
49
+ "@types/prompts": "2.4.9",
50
+ "rimraf": "6.1.3",
51
+ "typescript": "6.0.3"
52
52
  },
53
53
  "repository": {
54
54
  "type": "git",
@@ -58,4 +58,4 @@
58
58
  "url": "https://github.com/abaktiar/agentln/issues"
59
59
  },
60
60
  "homepage": "https://github.com/abaktiar/agentln#readme"
61
- }
61
+ }