agentscfg 0.1.0-alpha.2 → 0.1.0-alpha.3

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.
Files changed (3) hide show
  1. package/README.md +8 -6
  2. package/dist/cli.cjs +329 -64
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -19,7 +19,8 @@ agentscfg init
19
19
  # edit .agentscfg/instructions/* and .agentscfg/skills/*
20
20
  agentscfg plan
21
21
  agentscfg diff
22
- agentscfg sync
22
+ agentscfg gen
23
+ agentscfg import --from codex
23
24
  ```
24
25
 
25
26
  ## Commands
@@ -29,7 +30,8 @@ init [--force]
29
30
  validate
30
31
  plan [--to claude,opencode,codex] [--json]
31
32
  diff [--to ...]
32
- sync [--to ...] [--remove] [--adopt] [--force] [--allow-dirty]
33
+ gen [--to ...] [--remove] [--adopt] [--force] [--allow-dirty]
34
+ import --from <tool>
33
35
  doctor
34
36
  ```
35
37
 
@@ -66,7 +68,7 @@ Run `agentscfg <command> --help` for detailed help on each command.
66
68
 
67
69
  ### Target Mappings
68
70
 
69
- All files under `.agentscfg/targets/<tool>/` are synced into the tool's config
71
+ All files under `.agentscfg/targets/<tool>/` are generated into the tool's config
70
72
  directory:
71
73
 
72
74
  - `.agentscfg/targets/claude/**` → `.claude/**`
@@ -82,13 +84,13 @@ MCP config:
82
84
  - Generated files include a `agentscfg:generated ... sha256=...` marker.
83
85
  - Guided mode (default) will not overwrite unmanaged files unless you pass
84
86
  `--adopt` or the file already contains the marker.
85
- - If a generated file's hash marker does not match, sync refuses to overwrite
87
+ - If a generated file's hash marker does not match, gen refuses to overwrite
86
88
  unless `--force` is provided.
87
- - `sync` refuses to run on a dirty git working tree unless `--allow-dirty` is set.
89
+ - `gen` refuses to run on a dirty git working tree unless `--allow-dirty` is set.
88
90
 
89
91
  ## Tips
90
92
 
91
- Add generated paths to `.gitignore` and use `agentscfg sync` to regenerate them:
93
+ Add generated paths to `.gitignore` and use `agentscfg gen` to regenerate them:
92
94
 
93
95
  ```text
94
96
  .claude/
package/dist/cli.cjs CHANGED
@@ -26790,6 +26790,9 @@ var findRepoRoot = (start3) => Effect_exports.gen(function* (_) {
26790
26790
  return yield* _(Effect_exports.fail(new RepoRootNotFound()));
26791
26791
  });
26792
26792
 
26793
+ // package.json
26794
+ var version = "0.1.0-alpha.3";
26795
+
26793
26796
  // src/cli/commands/init.ts
26794
26797
  var import_node_path4 = __toESM(require("node:path"), 1);
26795
26798
 
@@ -27097,7 +27100,7 @@ var validateCommand = (repoRoot) => Effect_exports.gen(function* (_) {
27097
27100
  });
27098
27101
 
27099
27102
  // src/core/planner/plan.ts
27100
- var import_node_path10 = __toESM(require("node:path"), 1);
27103
+ var import_node_path9 = __toESM(require("node:path"), 1);
27101
27104
 
27102
27105
  // src/io/hash.ts
27103
27106
  var import_node_crypto = require("node:crypto");
@@ -27214,6 +27217,7 @@ var extractMarkerSha = (content) => {
27214
27217
  var import_node_path6 = __toESM(require("node:path"), 1);
27215
27218
  var claudeInstructionPath = (repoRoot) => import_node_path6.default.join(repoRoot, "CLAUDE.md");
27216
27219
  var claudeSkillsRoot = (repoRoot) => import_node_path6.default.join(repoRoot, ".claude", "skills");
27220
+ var mcpConfigPath = (repoRoot) => import_node_path6.default.join(repoRoot, ".mcp.json");
27217
27221
 
27218
27222
  // src/adapters/codex.ts
27219
27223
  var import_node_path7 = __toESM(require("node:path"), 1);
@@ -27226,10 +27230,6 @@ var opencodeInstructionPath = (repoRoot) => import_node_path8.default.join(repoR
27226
27230
  var opencodeSkillsRoot = (repoRoot) => import_node_path8.default.join(repoRoot, ".opencode", "skill");
27227
27231
  var opencodeClaudeCompatSkillsRoot = (repoRoot) => import_node_path8.default.join(repoRoot, ".claude", "skills");
27228
27232
 
27229
- // src/adapters/mcp.ts
27230
- var import_node_path9 = __toESM(require("node:path"), 1);
27231
- var mcpConfigPath = (repoRoot) => import_node_path9.default.join(repoRoot, ".mcp.json");
27232
-
27233
27233
  // src/core/planner/plan.ts
27234
27234
  var expectedOutputPaths = (repoRoot) => /* @__PURE__ */ new Set([
27235
27235
  claudeInstructionPath(repoRoot),
@@ -27238,7 +27238,7 @@ var expectedOutputPaths = (repoRoot) => /* @__PURE__ */ new Set([
27238
27238
  mcpConfigPath(repoRoot)
27239
27239
  ]);
27240
27240
  var isExpectedOutput = (repoRoot, targetPath) => expectedOutputPaths(repoRoot).has(targetPath);
27241
- var normalizeRel2 = (repoRoot, targetPath) => import_node_path10.default.relative(repoRoot, targetPath).replace(/\\/g, "/");
27241
+ var normalizeRel2 = (repoRoot, targetPath) => import_node_path9.default.relative(repoRoot, targetPath).replace(/\\/g, "/");
27242
27242
  var normalizeLf2 = (input) => input.replace(/\r\n?/g, "\n");
27243
27243
  var applyNewlines2 = (input, mode) => mode === "crlf" ? input.replace(/\n/g, "\r\n") : input;
27244
27244
  var ensureTrailingNewline2 = (input) => input.endsWith("\n") ? input : `${input}
@@ -27250,8 +27250,8 @@ var walkFiles = (dirPath, baseRel = "") => Effect_exports.gen(function* (_) {
27250
27250
  }
27251
27251
  const entries2 = yield* _(readdir(dirPath));
27252
27252
  for (const entry of entries2) {
27253
- const nextRel = baseRel ? import_node_path10.default.join(baseRel, entry.name) : entry.name;
27254
- const nextAbs = import_node_path10.default.join(dirPath, entry.name);
27253
+ const nextRel = baseRel ? import_node_path9.default.join(baseRel, entry.name) : entry.name;
27254
+ const nextAbs = import_node_path9.default.join(dirPath, entry.name);
27255
27255
  if (!shouldIncludePath(nextRel)) {
27256
27256
  continue;
27257
27257
  }
@@ -27340,7 +27340,7 @@ var diffDir = (sourceDir, targetDir, remove8) => Effect_exports.gen(function* (_
27340
27340
  ops.push({
27341
27341
  rel,
27342
27342
  from: src.abs,
27343
- to: import_node_path10.default.join(targetDir, rel),
27343
+ to: import_node_path9.default.join(targetDir, rel),
27344
27344
  mode: src.mode,
27345
27345
  kind: "add"
27346
27346
  });
@@ -27428,7 +27428,7 @@ var planWorkspace = (ws, options) => Effect_exports.gen(function* (_) {
27428
27428
  );
27429
27429
  warnings.push(...result.warnings);
27430
27430
  if (result.op) {
27431
- mkdirs.add(import_node_path10.default.dirname(output.path));
27431
+ mkdirs.add(import_node_path9.default.dirname(output.path));
27432
27432
  ops.push(result.op);
27433
27433
  }
27434
27434
  if (result.adopted) {
@@ -27448,7 +27448,7 @@ var planWorkspace = (ws, options) => Effect_exports.gen(function* (_) {
27448
27448
  );
27449
27449
  warnings.push(...result.warnings);
27450
27450
  if (result.op) {
27451
- mkdirs.add(import_node_path10.default.dirname(output.path));
27451
+ mkdirs.add(import_node_path9.default.dirname(output.path));
27452
27452
  ops.push(result.op);
27453
27453
  }
27454
27454
  if (result.adopted) {
@@ -27458,7 +27458,7 @@ var planWorkspace = (ws, options) => Effect_exports.gen(function* (_) {
27458
27458
  const skillTargets = buildSkillTargets(ws.repoRoot, ws.cfg, targets);
27459
27459
  for (const skill of ws.skills) {
27460
27460
  for (const target of skillTargets) {
27461
- const destDir = import_node_path10.default.join(target.root, skill.name);
27461
+ const destDir = import_node_path9.default.join(target.root, skill.name);
27462
27462
  const managed = managedData ? isManagedPath(ws.repoRoot, destDir, managedData) : false;
27463
27463
  const destExists = yield* _(exists4(destDir));
27464
27464
  if (destExists && !managed && managedData) {
@@ -27472,7 +27472,7 @@ var planWorkspace = (ws, options) => Effect_exports.gen(function* (_) {
27472
27472
  `Managed tracking missing for ${normalizeRel2(
27473
27473
  ws.repoRoot,
27474
27474
  destDir
27475
- )}. Run sync with --adopt to establish ownership.`
27475
+ )}. Run gen with --adopt to establish ownership.`
27476
27476
  );
27477
27477
  continue;
27478
27478
  }
@@ -27491,18 +27491,18 @@ var planWorkspace = (ws, options) => Effect_exports.gen(function* (_) {
27491
27491
  const targetDirMappings = [
27492
27492
  {
27493
27493
  name: "claude",
27494
- source: import_node_path10.default.join(ws.root, "targets", "claude"),
27495
- dest: import_node_path10.default.join(ws.repoRoot, ".claude")
27494
+ source: import_node_path9.default.join(ws.root, "targets", "claude"),
27495
+ dest: import_node_path9.default.join(ws.repoRoot, ".claude")
27496
27496
  },
27497
27497
  {
27498
27498
  name: "opencode",
27499
- source: import_node_path10.default.join(ws.root, "targets", "opencode"),
27500
- dest: import_node_path10.default.join(ws.repoRoot, ".opencode")
27499
+ source: import_node_path9.default.join(ws.root, "targets", "opencode"),
27500
+ dest: import_node_path9.default.join(ws.repoRoot, ".opencode")
27501
27501
  },
27502
27502
  {
27503
27503
  name: "codex",
27504
- source: import_node_path10.default.join(ws.root, "targets", "codex"),
27505
- dest: import_node_path10.default.join(ws.repoRoot, ".codex")
27504
+ source: import_node_path9.default.join(ws.root, "targets", "codex"),
27505
+ dest: import_node_path9.default.join(ws.repoRoot, ".codex")
27506
27506
  }
27507
27507
  ];
27508
27508
  for (const mapping of targetDirMappings) {
@@ -27523,7 +27523,7 @@ var planWorkspace = (ws, options) => Effect_exports.gen(function* (_) {
27523
27523
  `Managed tracking missing for ${normalizeRel2(
27524
27524
  ws.repoRoot,
27525
27525
  mapping.dest
27526
- )}. Run sync with --adopt to establish ownership.`
27526
+ )}. Run gen with --adopt to establish ownership.`
27527
27527
  );
27528
27528
  continue;
27529
27529
  }
@@ -27548,7 +27548,7 @@ var planWorkspace = (ws, options) => Effect_exports.gen(function* (_) {
27548
27548
  for (const dir of dirs) {
27549
27549
  if (skillNames.has(dir.name))
27550
27550
  continue;
27551
- const removePath = import_node_path10.default.join(target.root, dir.name);
27551
+ const removePath = import_node_path9.default.join(target.root, dir.name);
27552
27552
  if (managedData && isManagedPath(ws.repoRoot, removePath, managedData)) {
27553
27553
  ops.push({ type: "RemovePath", path: removePath });
27554
27554
  } else if (!managedData) {
@@ -27556,7 +27556,7 @@ var planWorkspace = (ws, options) => Effect_exports.gen(function* (_) {
27556
27556
  `Managed tracking missing for ${normalizeRel2(
27557
27557
  ws.repoRoot,
27558
27558
  removePath
27559
- )}. Run sync with --adopt to establish ownership.`
27559
+ )}. Run gen with --adopt to establish ownership.`
27560
27560
  );
27561
27561
  } else {
27562
27562
  warnings.push(
@@ -27573,7 +27573,7 @@ var planWorkspace = (ws, options) => Effect_exports.gen(function* (_) {
27573
27573
  if (!managedData && options.adopt) {
27574
27574
  const base = defaultManaged();
27575
27575
  const updated = adopted.length ? addAdopted(ws.repoRoot, base, adopted, /* @__PURE__ */ new Date()) : base;
27576
- mkdirs.add(import_node_path10.default.dirname(managedPathValue));
27576
+ mkdirs.add(import_node_path9.default.dirname(managedPathValue));
27577
27577
  ops.push({
27578
27578
  type: "WriteFile",
27579
27579
  path: managedPathValue,
@@ -27583,7 +27583,7 @@ var planWorkspace = (ws, options) => Effect_exports.gen(function* (_) {
27583
27583
  } else if ((options.adopt || !managedData) && adopted.length > 0) {
27584
27584
  const base = managedData ?? defaultManaged();
27585
27585
  const updated = addAdopted(ws.repoRoot, base, adopted, /* @__PURE__ */ new Date());
27586
- mkdirs.add(import_node_path10.default.dirname(managedPathValue));
27586
+ mkdirs.add(import_node_path9.default.dirname(managedPathValue));
27587
27587
  ops.push({
27588
27588
  type: "WriteFile",
27589
27589
  path: managedPathValue,
@@ -27592,7 +27592,7 @@ var planWorkspace = (ws, options) => Effect_exports.gen(function* (_) {
27592
27592
  });
27593
27593
  } else if (!managedData) {
27594
27594
  warnings.push(
27595
- "managed tracking missing; run sync with --adopt to establish ownership"
27595
+ "managed tracking missing; run gen with --adopt to establish ownership"
27596
27596
  );
27597
27597
  }
27598
27598
  const orderedMkdirs = Array.from(mkdirs).filter((dir) => dir && dir !== ".").sort((a, b) => a.localeCompare(b));
@@ -27628,7 +27628,7 @@ var planCommand = (repoRoot, options) => Effect_exports.gen(function* (_) {
27628
27628
  });
27629
27629
 
27630
27630
  // src/core/planner/diff.ts
27631
- var import_node_path11 = __toESM(require("node:path"), 1);
27631
+ var import_node_path10 = __toESM(require("node:path"), 1);
27632
27632
 
27633
27633
  // node_modules/diff/libesm/diff/base.js
27634
27634
  var Diff = class {
@@ -28075,7 +28075,7 @@ var renderDiff = (repoRoot, plan) => Effect_exports.gen(function* (_) {
28075
28075
  if (op.type === "WriteFile") {
28076
28076
  const existsNow = yield* _(exists4(op.path));
28077
28077
  const before2 = existsNow ? yield* _(readFileString(op.path)) : "";
28078
- const relPath = import_node_path11.default.relative(repoRoot, op.path).replace(/\\/g, "/");
28078
+ const relPath = import_node_path10.default.relative(repoRoot, op.path).replace(/\\/g, "/");
28079
28079
  const patch9 = createTwoFilesPatch(
28080
28080
  relPath,
28081
28081
  relPath,
@@ -28165,8 +28165,8 @@ var isDirty = (repoRoot) => Effect_exports.tryPromise({
28165
28165
  catch: (err) => new IoError("Failed to check git status", String(err))
28166
28166
  });
28167
28167
 
28168
- // src/cli/commands/sync.ts
28169
- var syncCommand = (repoRoot, options) => Effect_exports.gen(function* (_) {
28168
+ // src/cli/commands/gen.ts
28169
+ var genCommand = (repoRoot, options) => Effect_exports.gen(function* (_) {
28170
28170
  const gitRepo = yield* _(isGitRepo(repoRoot));
28171
28171
  if (gitRepo) {
28172
28172
  const dirty = yield* _(isDirty(repoRoot));
@@ -28174,7 +28174,7 @@ var syncCommand = (repoRoot, options) => Effect_exports.gen(function* (_) {
28174
28174
  return yield* _(
28175
28175
  Effect_exports.fail(
28176
28176
  new DirtyRepoError(
28177
- "Refusing to sync: git working tree is dirty. Commit/stash, or pass --allow-dirty."
28177
+ "Refusing to run gen: git working tree is dirty. Commit/stash, or pass --allow-dirty."
28178
28178
  )
28179
28179
  )
28180
28180
  );
@@ -28188,11 +28188,11 @@ var syncCommand = (repoRoot, options) => Effect_exports.gen(function* (_) {
28188
28188
  });
28189
28189
 
28190
28190
  // src/cli/commands/doctor.ts
28191
- var import_node_path12 = __toESM(require("node:path"), 1);
28191
+ var import_node_path11 = __toESM(require("node:path"), 1);
28192
28192
  var doctorCommand = (repoRoot) => Effect_exports.gen(function* (_) {
28193
- const root = import_node_path12.default.join(repoRoot, ".agentscfg");
28194
- const configPath = import_node_path12.default.join(root, "agentscfg.jsonc");
28195
- const basePath = import_node_path12.default.join(root, "instructions", "BASE.md");
28193
+ const root = import_node_path11.default.join(repoRoot, ".agentscfg");
28194
+ const configPath = import_node_path11.default.join(root, "agentscfg.jsonc");
28195
+ const basePath = import_node_path11.default.join(root, "instructions", "BASE.md");
28196
28196
  const workspacePresent = yield* _(exists4(root));
28197
28197
  const configPresent = yield* _(exists4(configPath));
28198
28198
  const basePresent = yield* _(exists4(basePath));
@@ -28226,11 +28226,11 @@ var doctorCommand = (repoRoot) => Effect_exports.gen(function* (_) {
28226
28226
  }
28227
28227
  const outputPaths = [
28228
28228
  claudeInstructionPath(repoRoot),
28229
- import_node_path12.default.join(repoRoot, ".claude"),
28229
+ import_node_path11.default.join(repoRoot, ".claude"),
28230
28230
  opencodeInstructionPath(repoRoot),
28231
- import_node_path12.default.join(repoRoot, ".opencode"),
28231
+ import_node_path11.default.join(repoRoot, ".opencode"),
28232
28232
  codexInstructionPath(repoRoot),
28233
- import_node_path12.default.join(repoRoot, ".codex"),
28233
+ import_node_path11.default.join(repoRoot, ".codex"),
28234
28234
  mcpConfigPath(repoRoot),
28235
28235
  claudeSkillsRoot(repoRoot),
28236
28236
  opencodeSkillsRoot(repoRoot),
@@ -28263,7 +28263,7 @@ var doctorCommand = (repoRoot) => Effect_exports.gen(function* (_) {
28263
28263
  });
28264
28264
 
28265
28265
  // src/cli/commands/status.ts
28266
- var import_node_path13 = __toESM(require("node:path"), 1);
28266
+ var import_node_path12 = __toESM(require("node:path"), 1);
28267
28267
  var getInstructionPath = (target, repoRoot) => {
28268
28268
  switch (target) {
28269
28269
  case "claude":
@@ -28349,11 +28349,11 @@ var statusCommand = (repoRoot, options) => Effect_exports.gen(function* (_) {
28349
28349
  name: target,
28350
28350
  enabled: enabled2,
28351
28351
  instruction: {
28352
- path: import_node_path13.default.relative(repoRoot, instructionPath),
28352
+ path: import_node_path12.default.relative(repoRoot, instructionPath),
28353
28353
  status: instructionStatus
28354
28354
  },
28355
28355
  skillsRoot: {
28356
- path: import_node_path13.default.relative(repoRoot, skillsRootPath),
28356
+ path: import_node_path12.default.relative(repoRoot, skillsRootPath),
28357
28357
  status: skillsStatus
28358
28358
  }
28359
28359
  });
@@ -28373,19 +28373,19 @@ var statusCommand = (repoRoot, options) => Effect_exports.gen(function* (_) {
28373
28373
  });
28374
28374
 
28375
28375
  // src/cli/commands/clean.ts
28376
- var import_node_path14 = __toESM(require("node:path"), 1);
28376
+ var import_node_path13 = __toESM(require("node:path"), 1);
28377
28377
  var normalizeRel3 = (relPath) => relPath.replace(/\\/g, "/");
28378
28378
  var expandManagedPaths = (repoRoot, managedData) => Effect_exports.gen(function* (_) {
28379
28379
  const paths = [];
28380
28380
  for (const entry of managedData.managed) {
28381
28381
  if (entry.endsWith("/**")) {
28382
28382
  const prefix = entry.slice(0, -3);
28383
- const dirPath = import_node_path14.default.join(repoRoot, prefix);
28383
+ const dirPath = import_node_path13.default.join(repoRoot, prefix);
28384
28384
  if (yield* _(exists4(dirPath))) {
28385
28385
  paths.push(dirPath);
28386
28386
  }
28387
28387
  } else {
28388
- const filePath = import_node_path14.default.join(repoRoot, entry);
28388
+ const filePath = import_node_path13.default.join(repoRoot, entry);
28389
28389
  if (yield* _(exists4(filePath))) {
28390
28390
  paths.push(filePath);
28391
28391
  }
@@ -28394,7 +28394,7 @@ var expandManagedPaths = (repoRoot, managedData) => Effect_exports.gen(function*
28394
28394
  return paths;
28395
28395
  });
28396
28396
  var cleanCommand = (repoRoot, dryRun) => Effect_exports.gen(function* (_) {
28397
- const workspaceRoot = import_node_path14.default.join(repoRoot, ".agentscfg");
28397
+ const workspaceRoot = import_node_path13.default.join(repoRoot, ".agentscfg");
28398
28398
  if (!(yield* _(exists4(workspaceRoot)))) {
28399
28399
  return yield* _(
28400
28400
  Effect_exports.fail(
@@ -28407,7 +28407,7 @@ var cleanCommand = (repoRoot, dryRun) => Effect_exports.gen(function* (_) {
28407
28407
  const removed = [];
28408
28408
  const skipped = [];
28409
28409
  for (const targetPath of pathsToRemove) {
28410
- const rel = normalizeRel3(import_node_path14.default.relative(repoRoot, targetPath));
28410
+ const rel = normalizeRel3(import_node_path13.default.relative(repoRoot, targetPath));
28411
28411
  if (dryRun) {
28412
28412
  removed.push(rel);
28413
28413
  } else {
@@ -28426,6 +28426,209 @@ var cleanCommand = (repoRoot, dryRun) => Effect_exports.gen(function* (_) {
28426
28426
  };
28427
28427
  });
28428
28428
 
28429
+ // src/cli/commands/import.ts
28430
+ var import_node_path14 = __toESM(require("node:path"), 1);
28431
+ var normalizeLf3 = (input) => input.replace(/\r\n?/g, "\n");
28432
+ var ensureTrailingNewline3 = (input) => input.endsWith("\n") ? input : `${input}
28433
+ `;
28434
+ var stripGeneratedFooter = (lines) => {
28435
+ let end3 = lines.length;
28436
+ while (end3 > 0 && lines[end3 - 1]?.trim() === "") {
28437
+ end3 -= 1;
28438
+ }
28439
+ if (end3 > 0 && /agentscfg:generated/i.test(lines[end3 - 1] ?? "")) {
28440
+ end3 -= 1;
28441
+ }
28442
+ while (end3 > 0 && lines[end3 - 1]?.trim() === "") {
28443
+ end3 -= 1;
28444
+ }
28445
+ return lines.slice(0, end3);
28446
+ };
28447
+ var normalizeSection = (lines) => {
28448
+ const trimmed2 = stripGeneratedFooter(lines);
28449
+ if (trimmed2[0] === "") {
28450
+ trimmed2.shift();
28451
+ }
28452
+ return trimmed2.join("\n");
28453
+ };
28454
+ var extractInstructions = (content) => {
28455
+ const normalized = normalizeLf3(content);
28456
+ const lines = normalized.split("\n");
28457
+ const baseIndex = lines.findIndex((line) => line.trim() === "## Base");
28458
+ if (baseIndex === -1) {
28459
+ const base2 = ensureTrailingNewline3(
28460
+ stripGeneratedFooter(lines).join("\n")
28461
+ );
28462
+ return { base: base2, project: void 0, parsed: false };
28463
+ }
28464
+ const projectIndex = lines.findIndex(
28465
+ (line, idx) => idx > baseIndex && line.trim() === "## Project"
28466
+ );
28467
+ const baseLines = projectIndex === -1 ? lines.slice(baseIndex + 1) : lines.slice(baseIndex + 1, projectIndex);
28468
+ const base = ensureTrailingNewline3(normalizeSection(baseLines));
28469
+ if (projectIndex === -1) {
28470
+ return { base, project: void 0, parsed: true };
28471
+ }
28472
+ const projectLines = lines.slice(projectIndex + 1);
28473
+ const project = ensureTrailingNewline3(normalizeSection(projectLines));
28474
+ return { base, project, parsed: true };
28475
+ };
28476
+ var walkFiles2 = (dirPath, baseRel = "", exclude3) => Effect_exports.gen(function* (_) {
28477
+ const results = [];
28478
+ if (!(yield* _(exists4(dirPath)))) {
28479
+ return results;
28480
+ }
28481
+ const entries2 = yield* _(readdir(dirPath));
28482
+ for (const entry of entries2) {
28483
+ const nextRel = baseRel ? import_node_path14.default.join(baseRel, entry.name) : entry.name;
28484
+ const nextRelNormalized = nextRel.replace(/\\/g, "/");
28485
+ if (!shouldIncludePath(nextRelNormalized)) {
28486
+ continue;
28487
+ }
28488
+ if (exclude3 && exclude3(nextRelNormalized)) {
28489
+ continue;
28490
+ }
28491
+ const nextAbs = import_node_path14.default.join(dirPath, entry.name);
28492
+ if (entry.isDirectory()) {
28493
+ const nested3 = yield* _(walkFiles2(nextAbs, nextRel, exclude3));
28494
+ results.push(...nested3);
28495
+ } else if (entry.isFile()) {
28496
+ const st = yield* _(stat(nextAbs));
28497
+ results.push({
28498
+ rel: nextRelNormalized,
28499
+ abs: nextAbs,
28500
+ mode: st.mode
28501
+ });
28502
+ }
28503
+ }
28504
+ return results.sort((a, b) => a.rel.localeCompare(b.rel));
28505
+ });
28506
+ var copyDir = (sourceRoot, destRoot, exclude3) => Effect_exports.gen(function* (_) {
28507
+ const files = yield* _(walkFiles2(sourceRoot, "", exclude3));
28508
+ for (const file of files) {
28509
+ const destPath = import_node_path14.default.join(destRoot, file.rel);
28510
+ yield* _(copyFile(file.abs, destPath, file.mode));
28511
+ }
28512
+ return files.length;
28513
+ });
28514
+ var ensureWorkspace = (repoRoot) => Effect_exports.gen(function* (_) {
28515
+ const root = import_node_path14.default.join(repoRoot, ".agentscfg");
28516
+ if (!(yield* _(exists4(root)))) {
28517
+ return yield* _(Effect_exports.fail(new WorkspaceMissing()));
28518
+ }
28519
+ const configPath = import_node_path14.default.join(root, "agentscfg.jsonc");
28520
+ if (!(yield* _(exists4(configPath)))) {
28521
+ return yield* _(Effect_exports.fail(new InvalidConfig("Missing agentscfg.jsonc")));
28522
+ }
28523
+ return {
28524
+ root,
28525
+ instructionsRoot: import_node_path14.default.join(root, "instructions"),
28526
+ basePath: import_node_path14.default.join(root, "instructions", "BASE.md"),
28527
+ projectPath: import_node_path14.default.join(root, "instructions", "PROJECT.md"),
28528
+ skillsRoot: import_node_path14.default.join(root, "skills"),
28529
+ targetsRoot: import_node_path14.default.join(root, "targets"),
28530
+ mcpRoot: import_node_path14.default.join(root, "mcp"),
28531
+ mcpPath: import_node_path14.default.join(root, "mcp", "mcp.json")
28532
+ };
28533
+ });
28534
+ var resolveSource = (repoRoot, from) => {
28535
+ switch (from) {
28536
+ case "claude":
28537
+ return {
28538
+ instructionPath: claudeInstructionPath(repoRoot),
28539
+ skillsRoot: claudeSkillsRoot(repoRoot),
28540
+ targetsRoot: import_node_path14.default.join(repoRoot, ".claude")
28541
+ };
28542
+ case "opencode":
28543
+ return {
28544
+ instructionPath: opencodeInstructionPath(repoRoot),
28545
+ skillsRoot: opencodeSkillsRoot(repoRoot),
28546
+ targetsRoot: import_node_path14.default.join(repoRoot, ".opencode")
28547
+ };
28548
+ case "codex":
28549
+ return {
28550
+ instructionPath: codexInstructionPath(repoRoot),
28551
+ skillsRoot: codexSkillsRoot(repoRoot),
28552
+ targetsRoot: import_node_path14.default.join(repoRoot, ".codex")
28553
+ };
28554
+ }
28555
+ };
28556
+ var buildTargetExcludes = (from) => {
28557
+ if (from === "opencode") {
28558
+ return (rel) => rel === "skill" || rel.startsWith("skill/") || rel === "agent/default.md";
28559
+ }
28560
+ if (from === "claude" || from === "codex") {
28561
+ return (rel) => rel === "skills" || rel.startsWith("skills/");
28562
+ }
28563
+ return void 0;
28564
+ };
28565
+ var importCommand = (repoRoot, from) => Effect_exports.gen(function* (_) {
28566
+ if (typeof from !== "string") {
28567
+ return yield* _(
28568
+ Effect_exports.fail(new InvalidConfig("Missing --from (claude|opencode|codex)"))
28569
+ );
28570
+ }
28571
+ const source = from.trim().toLowerCase();
28572
+ if (source !== "claude" && source !== "opencode" && source !== "codex") {
28573
+ return yield* _(
28574
+ Effect_exports.fail(new InvalidConfig("Invalid --from (claude|opencode|codex)"))
28575
+ );
28576
+ }
28577
+ const ws = yield* _(ensureWorkspace(repoRoot));
28578
+ const tool = source;
28579
+ const mapping = resolveSource(repoRoot, tool);
28580
+ const warnings = [];
28581
+ if (!(yield* _(exists4(mapping.instructionPath)))) {
28582
+ return yield* _(
28583
+ Effect_exports.fail(new IoError(`Missing source instructions at ${mapping.instructionPath}`))
28584
+ );
28585
+ }
28586
+ const instructionContent = yield* _(readFileString(mapping.instructionPath));
28587
+ const parsed = extractInstructions(instructionContent);
28588
+ yield* _(writeFileAtomic(ws.basePath, parsed.base));
28589
+ let projectWritten = false;
28590
+ let projectRemoved = false;
28591
+ if (parsed.project !== void 0) {
28592
+ yield* _(writeFileAtomic(ws.projectPath, parsed.project));
28593
+ projectWritten = true;
28594
+ } else if (yield* _(exists4(ws.projectPath))) {
28595
+ yield* _(rm(ws.projectPath));
28596
+ projectRemoved = true;
28597
+ }
28598
+ let skillsCount = 0;
28599
+ if (yield* _(exists4(mapping.skillsRoot))) {
28600
+ skillsCount = yield* _(copyDir(mapping.skillsRoot, ws.skillsRoot));
28601
+ } else {
28602
+ warnings.push(`No skills found at ${mapping.skillsRoot}`);
28603
+ }
28604
+ let targetsCount = 0;
28605
+ if (yield* _(exists4(mapping.targetsRoot))) {
28606
+ const destRoot = import_node_path14.default.join(ws.targetsRoot, tool);
28607
+ targetsCount = yield* _(
28608
+ copyDir(mapping.targetsRoot, destRoot, buildTargetExcludes(tool))
28609
+ );
28610
+ } else {
28611
+ warnings.push(`No target config found at ${mapping.targetsRoot}`);
28612
+ }
28613
+ let mcpCopied = false;
28614
+ const mcpSource = mcpConfigPath(repoRoot);
28615
+ if (yield* _(exists4(mcpSource))) {
28616
+ yield* _(copyFile(mcpSource, ws.mcpPath));
28617
+ mcpCopied = true;
28618
+ }
28619
+ if (!parsed.parsed) {
28620
+ warnings.push("Instructions did not match generated format; imported as BASE.md");
28621
+ }
28622
+ return {
28623
+ from: tool,
28624
+ instructions: { base: true, project: projectWritten, removedProject: projectRemoved },
28625
+ skills: { files: skillsCount },
28626
+ targets: { files: targetsCount },
28627
+ mcp: { copied: mcpCopied },
28628
+ warnings
28629
+ };
28630
+ });
28631
+
28429
28632
  // src/cli/render.ts
28430
28633
  var import_node_path15 = __toESM(require("node:path"), 1);
28431
28634
 
@@ -28487,7 +28690,7 @@ var renderPlanSummary = (plan) => {
28487
28690
  };
28488
28691
  var renderWarnings = (warnings) => warnings.length > 0 ? `${yellow("Warnings:")}
28489
28692
  ${warnings.map((w) => yellow(` - ${w}`)).join("\n")}` : "";
28490
- var renderSyncSummary = (plan) => {
28693
+ var renderGenSummary = (plan) => {
28491
28694
  const lines = [];
28492
28695
  const writeOps = plan.ops.filter((op) => op.type === "WriteFile");
28493
28696
  const copyOps = plan.ops.filter((op) => op.type === "CopyDir");
@@ -28621,8 +28824,31 @@ var renderDoctorReport = (report) => {
28621
28824
  }
28622
28825
  return lines.join("\n");
28623
28826
  };
28827
+ var renderImportSummary = (result) => {
28828
+ const lines = [];
28829
+ lines.push(green(`\u2713 Imported from ${result.from}`));
28830
+ const instructionParts = ["BASE.md"];
28831
+ if (result.instructions.project)
28832
+ instructionParts.push("PROJECT.md");
28833
+ lines.push(cyan(` \u25CB instructions: ${instructionParts.join(", ")}`));
28834
+ lines.push(
28835
+ cyan(
28836
+ ` \u25CB skills: ${result.skills.files} file${result.skills.files === 1 ? "" : "s"}`
28837
+ )
28838
+ );
28839
+ lines.push(
28840
+ cyan(
28841
+ ` \u25CB targets: ${result.targets.files} file${result.targets.files === 1 ? "" : "s"}`
28842
+ )
28843
+ );
28844
+ lines.push(
28845
+ cyan(` \u25CB mcp: ${result.mcp.copied ? "copied" : "not found"}`)
28846
+ );
28847
+ return lines.join("\n");
28848
+ };
28624
28849
 
28625
28850
  // src/cli/args.ts
28851
+ var FLAGS_WITH_VALUES = /* @__PURE__ */ new Set(["--to", "--from"]);
28626
28852
  var parseArgs = (argv) => {
28627
28853
  const args2 = [...argv];
28628
28854
  const command = args2.shift() ?? "help";
@@ -28638,7 +28864,7 @@ var parseArgs = (argv) => {
28638
28864
  if (value3 !== void 0) {
28639
28865
  flags[flag] = value3;
28640
28866
  } else if (args2[0] && !args2[0].startsWith("--")) {
28641
- if (flag === "--to") {
28867
+ if (FLAGS_WITH_VALUES.has(flag)) {
28642
28868
  flags[flag] = args2.shift();
28643
28869
  } else {
28644
28870
  flags[flag] = true;
@@ -28682,12 +28908,14 @@ Usage: agentscfg <command> [options]
28682
28908
  Commands:
28683
28909
  init Initialize a new .agentscfg workspace
28684
28910
  validate Validate workspace structure
28685
- status Show sync status at a glance
28686
- plan Show what sync would do without making changes
28911
+ status Show generation status at a glance
28912
+ plan Show what gen would do without making changes
28687
28913
  diff Show file diffs for planned changes
28688
- sync Apply planned changes to target files
28914
+ gen Apply planned changes to target files
28915
+ import Import config from an existing agent setup
28689
28916
  clean Remove all generated files
28690
28917
  doctor Diagnose workspace health
28918
+ version Show CLI version
28691
28919
 
28692
28920
  Run 'agentscfg <command> --help' for command-specific help.`;
28693
28921
  var INIT_HELP = `agentscfg init - Initialize a new .agentscfg workspace
@@ -28719,7 +28947,7 @@ Checks that:
28719
28947
 
28720
28948
  Example:
28721
28949
  agentscfg validate`;
28722
- var PLAN_HELP = `agentscfg plan - Show what sync would do without making changes
28950
+ var PLAN_HELP = `agentscfg plan - Show what gen would do without making changes
28723
28951
 
28724
28952
  Usage: agentscfg plan [options]
28725
28953
 
@@ -28747,9 +28975,9 @@ Shows unified diffs for all files that would change.
28747
28975
  Examples:
28748
28976
  agentscfg diff
28749
28977
  agentscfg diff --to codex`;
28750
- var SYNC_HELP = `agentscfg sync - Apply planned changes to target files
28978
+ var GEN_HELP = `agentscfg gen - Apply planned changes to target files
28751
28979
 
28752
- Usage: agentscfg sync [options]
28980
+ Usage: agentscfg gen [options]
28753
28981
 
28754
28982
  Options:
28755
28983
  --to <targets> Comma-separated targets: claude,opencode,codex
@@ -28757,19 +28985,19 @@ Options:
28757
28985
  --remove Remove orphaned managed files
28758
28986
  --adopt Adopt unmanaged files that match expected content
28759
28987
  --force Overwrite unmanaged files (use with caution)
28760
- --allow-dirty Allow sync even with uncommitted git changes
28988
+ --allow-dirty Allow gen even with uncommitted git changes
28761
28989
 
28762
28990
  Safety:
28763
- By default, sync refuses to run if git has uncommitted changes.
28991
+ By default, gen refuses to run if git has uncommitted changes.
28764
28992
  Use --allow-dirty to override (not recommended).
28765
28993
 
28766
28994
  Files not generated by agentscfg are protected. Use --adopt to
28767
28995
  take ownership of matching files, or --force to overwrite.
28768
28996
 
28769
28997
  Examples:
28770
- agentscfg sync
28771
- agentscfg sync --to claude --allow-dirty
28772
- agentscfg sync --remove --adopt`;
28998
+ agentscfg gen
28999
+ agentscfg gen --to claude --allow-dirty
29000
+ agentscfg gen --remove --adopt`;
28773
29001
  var DOCTOR_HELP = `agentscfg doctor - Diagnose workspace health
28774
29002
 
28775
29003
  Usage: agentscfg doctor
@@ -28782,7 +29010,20 @@ Checks for:
28782
29010
 
28783
29011
  Example:
28784
29012
  agentscfg doctor`;
28785
- var STATUS_HELP = `agentscfg status - Show sync status at a glance
29013
+ var IMPORT_HELP = `agentscfg import - Import config from an existing agent setup
29014
+
29015
+ Usage: agentscfg import --from <tool>
29016
+
29017
+ Options:
29018
+ --from <tool> Source tool: claude, opencode, codex
29019
+
29020
+ Imports instructions, skills, targets, and MCP config into .agentscfg/.
29021
+ Requires an existing .agentscfg/ workspace (run agentscfg init).
29022
+
29023
+ Examples:
29024
+ agentscfg import --from codex
29025
+ agentscfg import --from claude`;
29026
+ var STATUS_HELP = `agentscfg status - Show generation status at a glance
28786
29027
 
28787
29028
  Usage: agentscfg status [options]
28788
29029
 
@@ -28815,15 +29056,25 @@ Removes all files managed by agentscfg:
28815
29056
  Examples:
28816
29057
  agentscfg clean --dry-run
28817
29058
  agentscfg clean`;
29059
+ var VERSION_HELP = `agentscfg version - Show CLI version
29060
+
29061
+ Usage: agentscfg version
29062
+
29063
+ Displays the current version of the agentscfg CLI.
29064
+
29065
+ Example:
29066
+ agentscfg version`;
28818
29067
  var COMMAND_HELP = {
28819
29068
  init: INIT_HELP,
28820
29069
  validate: VALIDATE_HELP,
28821
29070
  status: STATUS_HELP,
28822
29071
  plan: PLAN_HELP,
28823
29072
  diff: DIFF_HELP,
28824
- sync: SYNC_HELP,
29073
+ gen: GEN_HELP,
29074
+ import: IMPORT_HELP,
28825
29075
  clean: CLEAN_HELP,
28826
- doctor: DOCTOR_HELP
29076
+ doctor: DOCTOR_HELP,
29077
+ version: VERSION_HELP
28827
29078
  };
28828
29079
  var getHelp = (command) => {
28829
29080
  if (command && command in COMMAND_HELP) {
@@ -28877,6 +29128,10 @@ var run = async () => {
28877
29128
  info(getHelp(command));
28878
29129
  return;
28879
29130
  }
29131
+ if (command === "version") {
29132
+ info(`agentscfg v${version}`);
29133
+ return;
29134
+ }
28880
29135
  try {
28881
29136
  repoRoot = await findRepoRoot(cwd).pipe(Effect_exports.runPromise);
28882
29137
  } catch (err) {
@@ -28926,11 +29181,11 @@ var run = async () => {
28926
29181
  console.log(diff8 || "(no changes)");
28927
29182
  return;
28928
29183
  }
28929
- case "sync": {
28930
- const plan = await syncCommand(repoRoot, buildOptions(flags)).pipe(
29184
+ case "gen": {
29185
+ const plan = await genCommand(repoRoot, buildOptions(flags)).pipe(
28931
29186
  Effect_exports.runPromise
28932
29187
  );
28933
- info(renderSyncSummary(plan));
29188
+ info(renderGenSummary(plan));
28934
29189
  const warnings = renderWarnings(plan.warnings);
28935
29190
  if (warnings)
28936
29191
  info(warnings);
@@ -28956,6 +29211,16 @@ var run = async () => {
28956
29211
  info(renderDoctorReport(report));
28957
29212
  return;
28958
29213
  }
29214
+ case "import": {
29215
+ const result = await importCommand(repoRoot, flags["--from"]).pipe(
29216
+ Effect_exports.runPromise
29217
+ );
29218
+ info(renderImportSummary(result));
29219
+ const warnings = renderWarnings(result.warnings);
29220
+ if (warnings)
29221
+ info(warnings);
29222
+ return;
29223
+ }
28959
29224
  case "help":
28960
29225
  default: {
28961
29226
  info(getHelp(flags["--help"] ? void 0 : void 0));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentscfg",
3
- "version": "0.1.0-alpha.2",
3
+ "version": "0.1.0-alpha.3",
4
4
  "type": "module",
5
5
  "main": "./dist/cli.cjs",
6
6
  "bin": {