claudekit-cli 4.3.1-dev.1 → 4.3.1-dev.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/cli-manifest.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "4.3.1-dev.1",
3
- "generatedAt": "2026-05-14T14:42:20.256Z",
2
+ "version": "4.3.1-dev.2",
3
+ "generatedAt": "2026-05-19T18:58:29.031Z",
4
4
  "commands": {
5
5
  "agents": {
6
6
  "name": "agents",
@@ -1635,6 +1635,12 @@
1635
1635
  }
1636
1636
  ]
1637
1637
  }
1638
+ ],
1639
+ "sections": [
1640
+ {
1641
+ "title": "Agent Editing Reminder",
1642
+ "content": "After creating a plan, Claude Code agents should read `plan.md` and every generated `phase-*.md` before editing. The files already exist; Write/Edit without Read can be rejected after wasting tokens."
1643
+ }
1638
1644
  ]
1639
1645
  },
1640
1646
  {
package/dist/index.js CHANGED
@@ -12564,6 +12564,16 @@ import { existsSync as existsSync2 } from "node:fs";
12564
12564
  import { mkdir, readFile as readFile2, rename, unlink, writeFile } from "node:fs/promises";
12565
12565
  import { homedir as homedir3 } from "node:os";
12566
12566
  import { dirname, join as join2, resolve } from "node:path";
12567
+ function getPortableRegistryPaths() {
12568
+ const home2 = homedir3();
12569
+ const claudekitDir = join2(home2, ".claudekit");
12570
+ return {
12571
+ registryPath: join2(claudekitDir, "portable-registry.json"),
12572
+ registryLockPath: join2(claudekitDir, "portable-registry.lock"),
12573
+ legacyRegistryPath: join2(claudekitDir, "skill-registry.json"),
12574
+ migrationLockPath: join2(claudekitDir, ".migration.lock")
12575
+ };
12576
+ }
12567
12577
  function isErrnoCode(error, code) {
12568
12578
  return typeof error === "object" && error !== null && "code" in error && error.code === code;
12569
12579
  }
@@ -12597,8 +12607,9 @@ function getCliVersion() {
12597
12607
  }
12598
12608
  }
12599
12609
  async function migrateLegacyRegistry() {
12610
+ const { legacyRegistryPath } = getPortableRegistryPaths();
12600
12611
  try {
12601
- const content = await readFile2(LEGACY_REGISTRY_PATH, "utf-8");
12612
+ const content = await readFile2(legacyRegistryPath, "utf-8");
12602
12613
  const data = JSON.parse(content);
12603
12614
  const legacy = LegacyRegistrySchema.parse(data);
12604
12615
  const installations = legacy.installations.map((i) => ({
@@ -12707,9 +12718,10 @@ async function repairStaleRegistryV3(registry) {
12707
12718
  }
12708
12719
  async function persistCurrentStaleRegistryV3Repair(preparedRepair) {
12709
12720
  return withRegistryLock(async () => {
12721
+ const { registryPath } = getPortableRegistryPaths();
12710
12722
  let content;
12711
12723
  try {
12712
- content = await readFile2(REGISTRY_PATH, "utf-8");
12724
+ content = await readFile2(registryPath, "utf-8");
12713
12725
  } catch (error) {
12714
12726
  if (isErrnoCode(error, "ENOENT")) {
12715
12727
  return readPortableRegistryInternal({ persistStaleV3Repair: false });
@@ -12741,8 +12753,9 @@ async function persistCurrentStaleRegistryV3Repair(preparedRepair) {
12741
12753
  });
12742
12754
  }
12743
12755
  async function isMigrationLocked() {
12756
+ const { migrationLockPath } = getPortableRegistryPaths();
12744
12757
  try {
12745
- const lockContent = await readFile2(MIGRATION_LOCK_PATH, "utf-8");
12758
+ const lockContent = await readFile2(migrationLockPath, "utf-8");
12746
12759
  const lockTime = Number.parseInt(lockContent, 10);
12747
12760
  if (Number.isNaN(lockTime)) {
12748
12761
  logger.verbose("Migration lock timestamp is invalid, treating lock as active");
@@ -12754,7 +12767,7 @@ async function isMigrationLocked() {
12754
12767
  return true;
12755
12768
  }
12756
12769
  logger.verbose("Removing stale migration lock");
12757
- await unlink(MIGRATION_LOCK_PATH);
12770
+ await unlink(migrationLockPath);
12758
12771
  return false;
12759
12772
  } catch (error) {
12760
12773
  if (isErrnoCode(error, "ENOENT")) {
@@ -12765,23 +12778,26 @@ async function isMigrationLocked() {
12765
12778
  }
12766
12779
  }
12767
12780
  async function createMigrationLock() {
12768
- const lockDir = dirname(MIGRATION_LOCK_PATH);
12781
+ const { migrationLockPath } = getPortableRegistryPaths();
12782
+ const lockDir = dirname(migrationLockPath);
12769
12783
  if (!existsSync2(lockDir)) {
12770
12784
  await mkdir(lockDir, { recursive: true });
12771
12785
  }
12772
- await writeFile(MIGRATION_LOCK_PATH, Date.now().toString(), "utf-8");
12786
+ await writeFile(migrationLockPath, Date.now().toString(), "utf-8");
12773
12787
  }
12774
12788
  async function removeMigrationLock() {
12789
+ const { migrationLockPath } = getPortableRegistryPaths();
12775
12790
  try {
12776
- await unlink(MIGRATION_LOCK_PATH);
12791
+ await unlink(migrationLockPath);
12777
12792
  } catch {}
12778
12793
  }
12779
12794
  async function readPortableRegistry() {
12780
12795
  return readPortableRegistryInternal({ persistStaleV3Repair: true });
12781
12796
  }
12782
12797
  async function readPortableRegistryInternal(options2) {
12798
+ const { registryPath } = getPortableRegistryPaths();
12783
12799
  try {
12784
- const content = await readFile2(REGISTRY_PATH, "utf-8");
12800
+ const content = await readFile2(registryPath, "utf-8");
12785
12801
  let data;
12786
12802
  try {
12787
12803
  data = JSON.parse(content);
@@ -12850,15 +12866,16 @@ async function readPortableRegistryWithinRegistryLock() {
12850
12866
  return readPortableRegistryInternal({ persistStaleV3Repair: false });
12851
12867
  }
12852
12868
  async function writePortableRegistry(registry) {
12853
- const dir = dirname(REGISTRY_PATH);
12869
+ const { registryPath } = getPortableRegistryPaths();
12870
+ const dir = dirname(registryPath);
12854
12871
  if (!existsSync2(dir)) {
12855
12872
  await mkdir(dir, { recursive: true });
12856
12873
  }
12857
12874
  const normalizedRegistry = normalizePortableRegistryChecksums(registry);
12858
- const tempPath = `${REGISTRY_PATH}.tmp-${process.pid}-${Date.now()}`;
12875
+ const tempPath = `${registryPath}.tmp-${process.pid}-${Date.now()}`;
12859
12876
  try {
12860
12877
  await writeFile(tempPath, JSON.stringify(normalizedRegistry, null, 2), "utf-8");
12861
- await rename(tempPath, REGISTRY_PATH);
12878
+ await rename(tempPath, registryPath);
12862
12879
  } catch (error) {
12863
12880
  try {
12864
12881
  await unlink(tempPath);
@@ -12867,14 +12884,15 @@ async function writePortableRegistry(registry) {
12867
12884
  }
12868
12885
  }
12869
12886
  async function withRegistryLock(operation) {
12870
- const lockDir = dirname(REGISTRY_LOCK_PATH);
12887
+ const { registryLockPath } = getPortableRegistryPaths();
12888
+ const lockDir = dirname(registryLockPath);
12871
12889
  if (!existsSync2(lockDir)) {
12872
12890
  await mkdir(lockDir, { recursive: true });
12873
12891
  }
12874
- if (!existsSync2(REGISTRY_LOCK_PATH)) {
12875
- await writeFile(REGISTRY_LOCK_PATH, "", "utf-8");
12892
+ if (!existsSync2(registryLockPath)) {
12893
+ await writeFile(registryLockPath, "", "utf-8");
12876
12894
  }
12877
- const release = await import_proper_lockfile.default.lock(REGISTRY_LOCK_PATH, {
12895
+ const release = await import_proper_lockfile.default.lock(registryLockPath, {
12878
12896
  realpath: false,
12879
12897
  retries: {
12880
12898
  retries: 5,
@@ -12975,17 +12993,12 @@ async function syncPortableRegistry() {
12975
12993
  return { removed };
12976
12994
  });
12977
12995
  }
12978
- var import_proper_lockfile, home2, REGISTRY_PATH, REGISTRY_LOCK_PATH, LEGACY_REGISTRY_PATH, MIGRATION_LOCK_PATH, PortableInstallationSchema, PortableRegistrySchema, PortableInstallationSchemaV3, PortableRegistrySchemaV3, RepairablePortableRegistrySchemaV3, LegacyInstallationSchema, LegacyRegistrySchema;
12996
+ var import_proper_lockfile, PortableInstallationSchema, PortableRegistrySchema, PortableInstallationSchemaV3, PortableRegistrySchemaV3, RepairablePortableRegistrySchemaV3, LegacyInstallationSchema, LegacyRegistrySchema;
12979
12997
  var init_portable_registry = __esm(() => {
12980
12998
  init_zod();
12981
12999
  init_logger();
12982
13000
  init_checksum_utils();
12983
13001
  import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
12984
- home2 = homedir3();
12985
- REGISTRY_PATH = join2(home2, ".claudekit", "portable-registry.json");
12986
- REGISTRY_LOCK_PATH = join2(home2, ".claudekit", "portable-registry.lock");
12987
- LEGACY_REGISTRY_PATH = join2(home2, ".claudekit", "skill-registry.json");
12988
- MIGRATION_LOCK_PATH = join2(home2, ".claudekit", ".migration.lock");
12989
13002
  PortableInstallationSchema = exports_external.object({
12990
13003
  item: exports_external.string(),
12991
13004
  type: exports_external.enum(["agent", "command", "skill", "config", "rules", "hooks"]),
@@ -13046,6 +13059,12 @@ import { existsSync as existsSync3 } from "node:fs";
13046
13059
  import { mkdir as mkdir2, readFile as readFile3, realpath, unlink as unlink2, writeFile as writeFile2 } from "node:fs/promises";
13047
13060
  import { homedir as homedir4 } from "node:os";
13048
13061
  import { basename, dirname as dirname2, isAbsolute, join as join3, relative, resolve as resolve2 } from "node:path";
13062
+ function resolveCodexTomlRegistryDeps(deps) {
13063
+ return {
13064
+ ...defaultCodexTomlRegistryDeps,
13065
+ ...deps
13066
+ };
13067
+ }
13049
13068
  async function ensureDir(filePath) {
13050
13069
  const dir = dirname2(filePath);
13051
13070
  if (!existsSync3(dir)) {
@@ -13299,12 +13318,13 @@ async function restoreFileSnapshots(snapshots) {
13299
13318
  await restoreFileSnapshot(snapshots[index]);
13300
13319
  }
13301
13320
  }
13302
- async function rollbackRegistryEntries(entries, portableType, provider, global2) {
13321
+ async function rollbackRegistryEntries(entries, portableType, provider, global2, registryDeps) {
13303
13322
  for (let index = entries.length - 1;index >= 0; index -= 1) {
13304
- await removePortableInstallation(entries[index].itemName, portableType, provider, global2);
13323
+ await registryDeps.removePortableInstallation(entries[index].itemName, portableType, provider, global2);
13305
13324
  }
13306
13325
  }
13307
- async function installCodexToml(items, provider, portableType, options2) {
13326
+ async function installCodexToml(items, provider, portableType, options2, deps) {
13327
+ const registryDeps = resolveCodexTomlRegistryDeps(deps);
13308
13328
  const config = providers[provider];
13309
13329
  const pathConfig = config.agents;
13310
13330
  if (!pathConfig) {
@@ -13487,7 +13507,7 @@ async function installCodexToml(items, provider, portableType, options2) {
13487
13507
  }
13488
13508
  await writeFile2(configTomlPath, mergeResult.content, "utf-8");
13489
13509
  for (const install of pendingInstalls) {
13490
- await addPortableInstallation(install.itemName, portableType, provider, options2.global, install.agentTomlPath, install.sourcePath, {
13510
+ await registryDeps.addPortableInstallation(install.itemName, portableType, provider, options2.global, install.agentTomlPath, install.sourcePath, {
13491
13511
  sourceChecksum: install.sourceChecksum,
13492
13512
  targetChecksum: install.targetChecksum,
13493
13513
  ownedSections: [install.slug],
@@ -13506,7 +13526,7 @@ async function installCodexToml(items, provider, portableType, options2) {
13506
13526
  let message = error instanceof Error ? error.message : "Unknown error";
13507
13527
  if (addedRegistryEntries.length > 0) {
13508
13528
  try {
13509
- await rollbackRegistryEntries(addedRegistryEntries, portableType, provider, options2.global);
13529
+ await rollbackRegistryEntries(addedRegistryEntries, portableType, provider, options2.global, registryDeps);
13510
13530
  } catch (rollbackRegistryError) {
13511
13531
  const rollbackMessage = rollbackRegistryError instanceof Error ? rollbackRegistryError.message : "Unknown registry rollback error";
13512
13532
  message = `${message}; registry rollback failed: ${rollbackMessage}`;
@@ -13632,7 +13652,7 @@ async function cleanupStaleCodexConfigEntries(options2) {
13632
13652
  return [];
13633
13653
  }
13634
13654
  }
13635
- var import_proper_lockfile2, SENTINEL_START = "# --- ck-managed-agents-start ---", SENTINEL_END = "# --- ck-managed-agents-end ---", MAX_WINDOWS_PATH_LENGTH = 240;
13655
+ var import_proper_lockfile2, SENTINEL_START = "# --- ck-managed-agents-start ---", SENTINEL_END = "# --- ck-managed-agents-end ---", MAX_WINDOWS_PATH_LENGTH = 240, defaultCodexTomlRegistryDeps;
13636
13656
  var init_codex_toml_installer = __esm(() => {
13637
13657
  init_logger();
13638
13658
  init_checksum_utils();
@@ -13641,6 +13661,10 @@ var init_codex_toml_installer = __esm(() => {
13641
13661
  init_portable_registry();
13642
13662
  init_provider_registry();
13643
13663
  import_proper_lockfile2 = __toESM(require_proper_lockfile(), 1);
13664
+ defaultCodexTomlRegistryDeps = {
13665
+ addPortableInstallation,
13666
+ removePortableInstallation
13667
+ };
13644
13668
  });
13645
13669
 
13646
13670
  // src/commands/portable/merge-single-sections.ts
@@ -13888,6 +13912,12 @@ function validateStrategyTargetPath(targetPath, options2) {
13888
13912
  }
13889
13913
  return null;
13890
13914
  }
13915
+ function resolvePortableInstallerRegistryDeps(deps) {
13916
+ return {
13917
+ ...defaultPortableInstallerRegistryDeps,
13918
+ ...deps
13919
+ };
13920
+ }
13891
13921
  function resolvePerFileOutputFilename(filename, pathConfig) {
13892
13922
  if (pathConfig.nestedCommands !== false || !filename.includes("/")) {
13893
13923
  return filename;
@@ -14049,7 +14079,7 @@ function buildPerFileCollisionSkips(items, provider, configDisplayName, basePath
14049
14079
  }
14050
14080
  return skipped;
14051
14081
  }
14052
- async function installPerFileItems(items, provider, portableType, pathConfig, options2) {
14082
+ async function installPerFileItems(items, provider, portableType, pathConfig, options2, registryDeps) {
14053
14083
  const config = providers[provider];
14054
14084
  const results = [];
14055
14085
  let aggregateChars = 0;
@@ -14101,7 +14131,7 @@ async function installPerFileItems(items, provider, portableType, pathConfig, op
14101
14131
  continue;
14102
14132
  }
14103
14133
  }
14104
- const result = await installPerFile(item, provider, portableType, options2);
14134
+ const result = await installPerFile(item, provider, portableType, options2, registryDeps);
14105
14135
  if (totalCharLimit && result.success && !result.skipped) {
14106
14136
  aggregateChars += itemSize;
14107
14137
  }
@@ -14189,7 +14219,7 @@ function parseYamlModesFile(content) {
14189
14219
  }
14190
14220
  return modes;
14191
14221
  }
14192
- async function installPerFile(item, provider, portableType, options2) {
14222
+ async function installPerFile(item, provider, portableType, options2, registryDeps) {
14193
14223
  const config = providers[provider];
14194
14224
  const typeKey = getProviderPathKeyForPortableType(portableType);
14195
14225
  const pathConfig = config[typeKey];
@@ -14274,7 +14304,7 @@ async function installPerFile(item, provider, portableType, options2) {
14274
14304
  await writeFile3(targetPath, result.content, "utf-8");
14275
14305
  const sourceChecksum = computeContentChecksum(result.content);
14276
14306
  const targetChecksum = sourceChecksum;
14277
- await addPortableInstallation(item.name, portableType, provider, options2.global, targetPath, item.sourcePath, {
14307
+ await registryDeps.addPortableInstallation(item.name, portableType, provider, options2.global, targetPath, item.sourcePath, {
14278
14308
  sourceChecksum,
14279
14309
  targetChecksum,
14280
14310
  installSource: "kit"
@@ -14307,7 +14337,7 @@ async function installPerFile(item, provider, portableType, options2) {
14307
14337
  };
14308
14338
  }
14309
14339
  }
14310
- async function installMergeSingle(items, provider, portableType, options2) {
14340
+ async function installMergeSingle(items, provider, portableType, options2, registryDeps) {
14311
14341
  const config = providers[provider];
14312
14342
  const typeKey = getProviderPathKeyForPortableType(portableType);
14313
14343
  const pathConfig = config[typeKey];
@@ -14479,7 +14509,7 @@ ${sections.join(`
14479
14509
  const sectionContent = newOwnedSections.get(sectionKey) || "";
14480
14510
  const sourceChecksum = newSourceChecksums.get(sectionKey) ?? computeContentChecksum(item.body);
14481
14511
  const targetChecksum = computeContentChecksum(sectionContent);
14482
- await addPortableInstallation(item.name, portableType, provider, options2.global, targetPath, item.sourcePath, {
14512
+ await registryDeps.addPortableInstallation(item.name, portableType, provider, options2.global, targetPath, item.sourcePath, {
14483
14513
  sourceChecksum,
14484
14514
  targetChecksum,
14485
14515
  ownedSections: [sectionKey],
@@ -14522,7 +14552,7 @@ ${sections.join(`
14522
14552
  };
14523
14553
  }
14524
14554
  }
14525
- async function installYamlMerge(items, provider, portableType, options2) {
14555
+ async function installYamlMerge(items, provider, portableType, options2, registryDeps) {
14526
14556
  const config = providers[provider];
14527
14557
  const typeKey = getProviderPathKeyForPortableType(portableType);
14528
14558
  const pathConfig = config[typeKey];
@@ -14628,7 +14658,7 @@ async function installYamlMerge(items, provider, portableType, options2) {
14628
14658
  for (const item of items) {
14629
14659
  const result = convertItem(item, pathConfig.format, provider, { global: options2.global });
14630
14660
  const sourceChecksum = computeContentChecksum(result.content);
14631
- await addPortableInstallation(item.name, portableType, provider, options2.global, targetPath, item.sourcePath, {
14661
+ await registryDeps.addPortableInstallation(item.name, portableType, provider, options2.global, targetPath, item.sourcePath, {
14632
14662
  sourceChecksum,
14633
14663
  targetChecksum,
14634
14664
  ownedSections,
@@ -14660,7 +14690,7 @@ async function installYamlMerge(items, provider, portableType, options2) {
14660
14690
  };
14661
14691
  }
14662
14692
  }
14663
- async function installJsonMerge(items, provider, portableType, options2) {
14693
+ async function installJsonMerge(items, provider, portableType, options2, registryDeps) {
14664
14694
  const config = providers[provider];
14665
14695
  const typeKey = getProviderPathKeyForPortableType(portableType);
14666
14696
  const pathConfig = config[typeKey];
@@ -14838,7 +14868,7 @@ ${item.body}
14838
14868
  for (const item of items) {
14839
14869
  const result = convertItem(item, pathConfig.format, provider, { global: options2.global });
14840
14870
  const sourceChecksum = computeContentChecksum(result.content);
14841
- await addPortableInstallation(item.name, portableType, provider, options2.global, modesPath, item.sourcePath, {
14871
+ await registryDeps.addPortableInstallation(item.name, portableType, provider, options2.global, modesPath, item.sourcePath, {
14842
14872
  sourceChecksum,
14843
14873
  targetChecksum,
14844
14874
  ownedSections,
@@ -14870,7 +14900,8 @@ ${item.body}
14870
14900
  };
14871
14901
  }
14872
14902
  }
14873
- async function installPortableItem(items, provider, portableType, options2) {
14903
+ async function installPortableItem(items, provider, portableType, options2, deps) {
14904
+ const registryDeps = resolvePortableInstallerRegistryDeps(deps);
14874
14905
  const config = providers[provider];
14875
14906
  const typeKey = getProviderPathKeyForPortableType(portableType);
14876
14907
  const pathConfig = config[typeKey];
@@ -14885,17 +14916,17 @@ async function installPortableItem(items, provider, portableType, options2) {
14885
14916
  }
14886
14917
  switch (pathConfig.writeStrategy) {
14887
14918
  case "merge-single":
14888
- return installMergeSingle(items, provider, portableType, options2);
14919
+ return installMergeSingle(items, provider, portableType, options2, registryDeps);
14889
14920
  case "yaml-merge":
14890
- return installYamlMerge(items, provider, portableType, options2);
14921
+ return installYamlMerge(items, provider, portableType, options2, registryDeps);
14891
14922
  case "json-merge":
14892
- return installJsonMerge(items, provider, portableType, options2);
14923
+ return installJsonMerge(items, provider, portableType, options2, registryDeps);
14893
14924
  case "codex-toml":
14894
- return installCodexToml(items, provider, portableType, options2);
14925
+ return installCodexToml(items, provider, portableType, options2, registryDeps);
14895
14926
  case "single-file":
14896
- return installPerFile(items[0], provider, portableType, options2);
14927
+ return installPerFile(items[0], provider, portableType, options2, registryDeps);
14897
14928
  case "codex-hooks":
14898
- return installPerFile(items[0], provider, portableType, options2);
14929
+ return installPerFile(items[0], provider, portableType, options2, registryDeps);
14899
14930
  case "per-file": {
14900
14931
  const results = [];
14901
14932
  let aggregateChars = 0;
@@ -14943,7 +14974,7 @@ async function installPortableItem(items, provider, portableType, options2) {
14943
14974
  continue;
14944
14975
  }
14945
14976
  }
14946
- const result = await installPerFile(item, provider, portableType, options2);
14977
+ const result = await installPerFile(item, provider, portableType, options2, registryDeps);
14947
14978
  if (totalCharLimit && result.success && !result.skipped) {
14948
14979
  aggregateChars += itemSize;
14949
14980
  }
@@ -14979,7 +15010,8 @@ async function installPortableItem(items, provider, portableType, options2) {
14979
15010
  }
14980
15011
  }
14981
15012
  }
14982
- async function installPortableItems(items, targetProviders, portableType, options2) {
15013
+ async function installPortableItems(items, targetProviders, portableType, options2, deps) {
15014
+ const registryDeps = resolvePortableInstallerRegistryDeps(deps);
14983
15015
  const uniqueProviders = Array.from(new Set(targetProviders));
14984
15016
  const results = [];
14985
15017
  for (const provider of uniqueProviders) {
@@ -14988,14 +15020,14 @@ async function installPortableItems(items, targetProviders, portableType, option
14988
15020
  const pathConfig = config[typeKey];
14989
15021
  const providerOptions = { ...options2 };
14990
15022
  if (pathConfig?.writeStrategy === "per-file") {
14991
- results.push(...await installPerFileItems(items, provider, portableType, pathConfig, providerOptions));
15023
+ results.push(...await installPerFileItems(items, provider, portableType, pathConfig, providerOptions, registryDeps));
14992
15024
  continue;
14993
15025
  }
14994
- results.push(await installPortableItem(items, provider, portableType, providerOptions));
15026
+ results.push(await installPortableItem(items, provider, portableType, providerOptions, registryDeps));
14995
15027
  }
14996
15028
  return results;
14997
15029
  }
14998
- var import_proper_lockfile3, ClineCustomModeSchema, ClineCustomModesFileSchema;
15030
+ var import_proper_lockfile3, ClineCustomModeSchema, ClineCustomModesFileSchema, defaultPortableInstallerRegistryDeps;
14999
15031
  var init_portable_installer = __esm(() => {
15000
15032
  init_zod();
15001
15033
  init_checksum_utils();
@@ -15018,6 +15050,9 @@ var init_portable_installer = __esm(() => {
15018
15050
  ClineCustomModesFileSchema = exports_external.object({
15019
15051
  customModes: exports_external.array(ClineCustomModeSchema).optional()
15020
15052
  });
15053
+ defaultPortableInstallerRegistryDeps = {
15054
+ addPortableInstallation
15055
+ };
15021
15056
  });
15022
15057
 
15023
15058
  // src/commands/portable/types.ts
@@ -49406,7 +49441,7 @@ function resolveAgentDirs() {
49406
49441
  dirs.push({ path: candidate, label: rel });
49407
49442
  }
49408
49443
  }
49409
- const globalPath = join28(home3, ".claude", "agents");
49444
+ const globalPath = join28(home2, ".claude", "agents");
49410
49445
  dirs.push({ path: globalPath, label: "~/.claude/agents" });
49411
49446
  const seen = new Set;
49412
49447
  return dirs.filter(({ path: path3 }) => {
@@ -49495,11 +49530,11 @@ function registerAgentsBrowserRoutes(app) {
49495
49530
  res.status(404).json({ error: "Agent not found" });
49496
49531
  });
49497
49532
  }
49498
- var home3;
49533
+ var home2;
49499
49534
  var init_agents_routes = __esm(() => {
49500
49535
  init_frontmatter_parser();
49501
49536
  init_kit_layout();
49502
- home3 = homedir15();
49537
+ home2 = homedir15();
49503
49538
  });
49504
49539
 
49505
49540
  // src/schemas/ck-config.schema.json
@@ -51551,10 +51586,10 @@ function mergeServers(lists) {
51551
51586
  function isSafeProjectPath(projectPath) {
51552
51587
  if (projectPath.includes(".."))
51553
51588
  return false;
51554
- const home4 = homedir23();
51589
+ const home3 = homedir23();
51555
51590
  try {
51556
51591
  const resolved = resolve14(projectPath);
51557
- if (!resolved.startsWith(home4))
51592
+ if (!resolved.startsWith(home3))
51558
51593
  return false;
51559
51594
  return existsSync21(resolved);
51560
51595
  } catch {
@@ -51918,9 +51953,9 @@ async function copyHooksCompanionDirs(sourceDir, targetDir) {
51918
51953
  function resolveSourceOrigin(sourcePath) {
51919
51954
  if (!sourcePath)
51920
51955
  return "global";
51921
- const home4 = homedir24();
51956
+ const home3 = homedir24();
51922
51957
  const cwd2 = process.cwd();
51923
- if (cwd2 === home4)
51958
+ if (cwd2 === home3)
51924
51959
  return "global";
51925
51960
  const cwdPrefix = cwd2.endsWith(sep6) ? cwd2 : `${cwd2}${sep6}`;
51926
51961
  if (sourcePath === cwd2 || sourcePath.startsWith(cwdPrefix))
@@ -54450,12 +54485,12 @@ function scrubHookEntry(entry, event, capabilities, pathRewrite) {
54450
54485
  }
54451
54486
  function rewriteCommandPath(command, pathRewrite) {
54452
54487
  if (pathRewrite.commandSubstitutions && pathRewrite.commandSubstitutions.size > 0) {
54453
- const home4 = homedir26();
54488
+ const home3 = homedir26();
54454
54489
  for (const [originalAbsPath, wrapperAbsPath] of pathRewrite.commandSubstitutions) {
54455
54490
  const candidates = new Set([
54456
54491
  originalAbsPath,
54457
- originalAbsPath.replace(home4, "$HOME"),
54458
- originalAbsPath.replace(home4, "~")
54492
+ originalAbsPath.replace(home3, "$HOME"),
54493
+ originalAbsPath.replace(home3, "~")
54459
54494
  ]);
54460
54495
  for (const candidate of candidates) {
54461
54496
  if (command.includes(candidate)) {
@@ -55432,14 +55467,15 @@ var init_portable_manifest = __esm(() => {
55432
55467
  function shouldBackfillRegistry(action) {
55433
55468
  return action.action === "skip" && action.backfillRegistry === true && typeof action.targetPath === "string" && action.targetPath.length > 0 && typeof action.sourceChecksum === "string" && !isUnknownChecksum(action.sourceChecksum) && typeof action.currentTargetChecksum === "string" && !isUnknownChecksum(action.currentTargetChecksum);
55434
55469
  }
55435
- async function backfillRegistryChecksums(actions, registry) {
55470
+ async function backfillRegistryChecksums(actions, registry, deps) {
55471
+ const addInstallation = deps?.addPortableInstallation ?? addPortableInstallation;
55436
55472
  for (const action of actions) {
55437
55473
  if (!shouldBackfillRegistry(action))
55438
55474
  continue;
55439
55475
  const registryEntry = registry.installations.find((entry) => entry.item === action.item && entry.type === action.type && entry.provider === action.provider && entry.global === action.global);
55440
55476
  if (!registryEntry)
55441
55477
  continue;
55442
- await addPortableInstallation(action.item, action.type, action.provider, action.global, action.targetPath, registryEntry.sourcePath, {
55478
+ await addInstallation(action.item, action.type, action.provider, action.global, action.targetPath, registryEntry.sourcePath, {
55443
55479
  sourceChecksum: action.sourceChecksum,
55444
55480
  targetChecksum: action.currentTargetChecksum,
55445
55481
  ownedSections: registryEntry.ownedSections,
@@ -56728,6 +56764,12 @@ import { existsSync as existsSync30 } from "node:fs";
56728
56764
  import { readFile as readFile26, rm as rm8 } from "node:fs/promises";
56729
56765
  import { homedir as homedir29 } from "node:os";
56730
56766
  import { basename as basename17, join as join46, resolve as resolve23 } from "node:path";
56767
+ function resolveRegistryDeps(deps) {
56768
+ return {
56769
+ ...defaultRegistryDeps,
56770
+ ...deps?.registry
56771
+ };
56772
+ }
56731
56773
  function isDisallowedControlCode(codePoint) {
56732
56774
  return codePoint >= 0 && codePoint <= 8 || codePoint >= 11 && codePoint <= 31 || codePoint >= 127 && codePoint <= 159;
56733
56775
  }
@@ -56962,7 +57004,7 @@ async function executePlanDeleteAction(action, options2) {
56962
57004
  if (!shouldPreserveTarget && action.targetPath && existsSync30(action.targetPath)) {
56963
57005
  await rm8(action.targetPath, { recursive: true, force: true });
56964
57006
  }
56965
- await removePortableInstallation(action.item, action.type, action.provider, action.global, action.targetPath ? { path: action.targetPath } : undefined);
57007
+ await (options2?.removePortableInstallation ?? removePortableInstallation)(action.item, action.type, action.provider, action.global, action.targetPath ? { path: action.targetPath } : undefined);
56966
57008
  return {
56967
57009
  provider: action.provider,
56968
57010
  providerDisplayName: providers[action.provider]?.displayName || action.provider,
@@ -57333,7 +57375,8 @@ function getCapabilities(provider) {
57333
57375
  hooks: config.hooks !== null
57334
57376
  };
57335
57377
  }
57336
- function registerMigrationRoutes(app) {
57378
+ function registerMigrationRoutes(app, deps) {
57379
+ const registryDeps = resolveRegistryDeps(deps);
57337
57380
  app.get("/api/migrate/providers", async (_req, res) => {
57338
57381
  try {
57339
57382
  const detected = new Set(await detectInstalledProviders());
@@ -57367,12 +57410,12 @@ function registerMigrationRoutes(app) {
57367
57410
  };
57368
57411
  const discovered = await discoverMigrationItems(includeAll);
57369
57412
  const cwd2 = process.cwd();
57370
- const home4 = homedir29();
57413
+ const home3 = homedir29();
57371
57414
  res.status(200).json({
57372
57415
  cwd: cwd2,
57373
57416
  targetPaths: {
57374
57417
  project: join46(cwd2, ".claude"),
57375
- global: join46(home4, ".claude")
57418
+ global: join46(home3, ".claude")
57376
57419
  },
57377
57420
  sourcePaths: discovered.sourcePaths,
57378
57421
  sourceOrigins: {
@@ -57541,7 +57584,7 @@ function registerMigrationRoutes(app) {
57541
57584
  warnReadFailure("hook", hook.name, error);
57542
57585
  }
57543
57586
  }
57544
- const registry = await readPortableRegistry();
57587
+ const registry = await registryDeps.readPortableRegistry();
57545
57588
  const targetStates = await buildTargetStates(registry.installations, {
57546
57589
  onReadFailure: (entryPath, error) => warnReadFailure("registry-target", entryPath, error)
57547
57590
  });
@@ -57650,7 +57693,7 @@ function registerMigrationRoutes(app) {
57650
57693
  }
57651
57694
  const configSource = sourceParsed.value;
57652
57695
  const discovered = await discoverMigrationItems(include, configSource);
57653
- const registry = await readPortableRegistry();
57696
+ const registry = await registryDeps.readPortableRegistry();
57654
57697
  const candidates = [];
57655
57698
  if (include.agents) {
57656
57699
  addCandidates(discovered.agents.map((a3) => ({
@@ -57903,15 +57946,18 @@ function registerMigrationRoutes(app) {
57903
57946
  const writtenPaths = new Set(allResults.filter((r2) => r2.success && !r2.skipped && r2.path.length > 0).map((r2) => resolve23(r2.path)));
57904
57947
  for (const deleteAction of deleteActions) {
57905
57948
  const deleteResult = await executePlanDeleteAction(deleteAction, {
57906
- preservePaths: writtenPaths
57949
+ preservePaths: writtenPaths,
57950
+ removePortableInstallation: registryDeps.removePortableInstallation
57907
57951
  });
57908
57952
  deleteResult.portableType = deleteAction.type;
57909
57953
  deleteResult.itemName = deleteAction.item;
57910
57954
  allResults.push(deleteResult);
57911
57955
  }
57912
57956
  try {
57913
- const registry = await readPortableRegistry();
57914
- await backfillRegistryChecksums(plan.actions, registry);
57957
+ const registry = await registryDeps.readPortableRegistry();
57958
+ await backfillRegistryChecksums(plan.actions, registry, {
57959
+ addPortableInstallation: registryDeps.addPortableInstallation
57960
+ });
57915
57961
  } catch {}
57916
57962
  for (const provider of allPlanProviders) {
57917
57963
  if (providers[provider]?.agents?.writeStrategy !== "codex-toml")
@@ -57928,7 +57974,7 @@ function registerMigrationRoutes(app) {
57928
57974
  });
57929
57975
  if (staleSlugs.length > 0) {
57930
57976
  const staleSlugSet = new Set(staleSlugs.map((s) => `${s}.toml`));
57931
- await removeInstallationsByFilter((i) => i.type === "agent" && i.provider === provider && i.global === scope && staleSlugSet.has(basename17(i.path)));
57977
+ await registryDeps.removeInstallationsByFilter((i) => i.type === "agent" && i.provider === provider && i.global === scope && staleSlugSet.has(basename17(i.path)));
57932
57978
  }
57933
57979
  }
57934
57980
  }
@@ -57939,7 +57985,7 @@ function registerMigrationRoutes(app) {
57939
57985
  const kitRoot = (agentSrc ? resolve23(agentSrc, "..") : null) ?? (cmdSrc ? resolve23(cmdSrc, "..") : null) ?? (skillSrc ? resolve23(skillSrc, "..") : null) ?? null;
57940
57986
  const manifest = kitRoot ? await loadPortableManifest(kitRoot) : null;
57941
57987
  if (manifest?.cliVersion) {
57942
- await updateAppliedManifestVersion(manifest.cliVersion);
57988
+ await registryDeps.updateAppliedManifestVersion(manifest.cliVersion);
57943
57989
  }
57944
57990
  } catch {}
57945
57991
  const responseResults2 = [...allResults, ...hookRegistrationResults2];
@@ -58141,7 +58187,7 @@ function registerMigrationRoutes(app) {
58141
58187
  }
58142
58188
  });
58143
58189
  }
58144
- var MIGRATION_TYPES, MAX_PROVIDER_COUNT = 20, MAX_PLAN_ACTIONS = 5000, ALLOWED_CONFIG_SOURCE_KEYS, CONFLICT_RESOLUTION_SCHEMA, RECONCILE_ACTION_SCHEMA, RECONCILE_BANNER_SCHEMA, RECONCILE_PLAN_SCHEMA, PLAN_EXECUTE_PAYLOAD_SCHEMA, PLURAL_TO_SINGULAR, shellHookWarningShown = false;
58190
+ var defaultRegistryDeps, MIGRATION_TYPES, MAX_PROVIDER_COUNT = 20, MAX_PLAN_ACTIONS = 5000, ALLOWED_CONFIG_SOURCE_KEYS, CONFLICT_RESOLUTION_SCHEMA, RECONCILE_ACTION_SCHEMA, RECONCILE_BANNER_SCHEMA, RECONCILE_PLAN_SCHEMA, PLAN_EXECUTE_PAYLOAD_SCHEMA, PLURAL_TO_SINGULAR, shellHookWarningShown = false;
58145
58191
  var init_migration_routes = __esm(() => {
58146
58192
  init_agents_discovery();
58147
58193
  init_commands_discovery();
@@ -58163,6 +58209,13 @@ var init_migration_routes = __esm(() => {
58163
58209
  init_logger();
58164
58210
  init_zod();
58165
58211
  init_migration_result_utils();
58212
+ defaultRegistryDeps = {
58213
+ addPortableInstallation,
58214
+ readPortableRegistry,
58215
+ removeInstallationsByFilter,
58216
+ removePortableInstallation,
58217
+ updateAppliedManifestVersion
58218
+ };
58166
58219
  MIGRATION_TYPES = [
58167
58220
  "agents",
58168
58221
  "commands",
@@ -60998,8 +61051,8 @@ function toDateStr(d3) {
60998
61051
  return `${y3}-${m2}-${day}`;
60999
61052
  }
61000
61053
  async function scanActivityMetrics(periodDays) {
61001
- const home4 = homedir33();
61002
- const projectsDir2 = join56(home4, ".claude", "projects");
61054
+ const home3 = homedir33();
61055
+ const projectsDir2 = join56(home3, ".claude", "projects");
61003
61056
  const cutoff = new Date;
61004
61057
  cutoff.setDate(cutoff.getDate() - periodDays);
61005
61058
  const dailyMap = new Map;
@@ -61069,29 +61122,29 @@ async function scanActivityMetrics(periodDays) {
61069
61122
  return { totalSessions, projects: projectActivities, dailyCounts };
61070
61123
  }
61071
61124
  async function resolveSessionDir(projectId) {
61072
- const home4 = homedir33();
61125
+ const home3 = homedir33();
61073
61126
  if (projectId.startsWith("discovered-")) {
61074
61127
  try {
61075
61128
  const encodedPathB64 = projectId.slice("discovered-".length);
61076
61129
  const projectPath = Buffer.from(encodedPathB64, "base64url").toString("utf-8");
61077
61130
  const claudeEncoded = encodePath(projectPath);
61078
- return join56(home4, ".claude", "projects", claudeEncoded);
61131
+ return join56(home3, ".claude", "projects", claudeEncoded);
61079
61132
  } catch {
61080
61133
  return null;
61081
61134
  }
61082
61135
  }
61083
61136
  if (projectId === "current") {
61084
61137
  const cwdEncoded = encodePath(process.cwd());
61085
- return join56(home4, ".claude", "projects", cwdEncoded);
61138
+ return join56(home3, ".claude", "projects", cwdEncoded);
61086
61139
  }
61087
61140
  if (projectId === "global") {
61088
- const globalEncoded = encodePath(join56(home4, ".claude"));
61089
- return join56(home4, ".claude", "projects", globalEncoded);
61141
+ const globalEncoded = encodePath(join56(home3, ".claude"));
61142
+ return join56(home3, ".claude", "projects", globalEncoded);
61090
61143
  }
61091
61144
  const registered = await ProjectsRegistryManager.getProject(projectId);
61092
61145
  if (registered) {
61093
61146
  const claudeEncoded = encodePath(registered.path);
61094
- return join56(home4, ".claude", "projects", claudeEncoded);
61147
+ return join56(home3, ".claude", "projects", claudeEncoded);
61095
61148
  }
61096
61149
  return null;
61097
61150
  }
@@ -61243,8 +61296,8 @@ async function parseSessionDetail(filePath, limit, offset) {
61243
61296
  }
61244
61297
  function registerSessionRoutes(app) {
61245
61298
  app.get("/api/sessions", async (_req, res) => {
61246
- const home4 = homedir33();
61247
- const projectsDir2 = join56(home4, ".claude", "projects");
61299
+ const home3 = homedir33();
61300
+ const projectsDir2 = join56(home3, ".claude", "projects");
61248
61301
  if (!existsSync38(projectsDir2)) {
61249
61302
  res.json({ projects: [] });
61250
61303
  return;
@@ -61927,10 +61980,10 @@ function hasOpenCodeInstallSignal2() {
61927
61980
  join59(process.cwd(), "opencode.jsonc"),
61928
61981
  join59(process.cwd(), ".opencode/agents"),
61929
61982
  join59(process.cwd(), ".opencode/commands"),
61930
- join59(home4, ".config/opencode/AGENTS.md"),
61931
- join59(home4, ".config/opencode/agents"),
61932
- join59(home4, ".config/opencode/commands"),
61933
- join59(home4, ".opencode", "bin", OPENCODE_BINARY_NAME2)
61983
+ join59(home3, ".config/opencode/AGENTS.md"),
61984
+ join59(home3, ".config/opencode/agents"),
61985
+ join59(home3, ".config/opencode/commands"),
61986
+ join59(home3, ".opencode", "bin", OPENCODE_BINARY_NAME2)
61934
61987
  ]);
61935
61988
  }
61936
61989
  async function detectInstalledAgents() {
@@ -61954,108 +62007,108 @@ function isSkillInstalled(skillName, agent, options2) {
61954
62007
  const installPath = getInstallPath(skillName, agent, options2);
61955
62008
  return existsSync39(installPath);
61956
62009
  }
61957
- var home4, OPENCODE_BINARY_NAME2, agents;
62010
+ var home3, OPENCODE_BINARY_NAME2, agents;
61958
62011
  var init_agents = __esm(() => {
61959
- home4 = homedir37();
62012
+ home3 = homedir37();
61960
62013
  OPENCODE_BINARY_NAME2 = platform5() === "win32" ? "opencode.exe" : "opencode";
61961
62014
  agents = {
61962
62015
  "claude-code": {
61963
62016
  name: "claude-code",
61964
62017
  displayName: "Claude Code",
61965
62018
  projectPath: ".claude/skills",
61966
- globalPath: join59(home4, ".claude/skills"),
61967
- detect: async () => existsSync39(join59(home4, ".claude"))
62019
+ globalPath: join59(home3, ".claude/skills"),
62020
+ detect: async () => existsSync39(join59(home3, ".claude"))
61968
62021
  },
61969
62022
  cursor: {
61970
62023
  name: "cursor",
61971
62024
  displayName: "Cursor",
61972
62025
  projectPath: ".cursor/skills",
61973
- globalPath: join59(home4, ".cursor/skills"),
61974
- detect: async () => existsSync39(join59(home4, ".cursor"))
62026
+ globalPath: join59(home3, ".cursor/skills"),
62027
+ detect: async () => existsSync39(join59(home3, ".cursor"))
61975
62028
  },
61976
62029
  codex: {
61977
62030
  name: "codex",
61978
62031
  displayName: "Codex",
61979
62032
  projectPath: ".codex/skills",
61980
- globalPath: join59(home4, ".codex/skills"),
61981
- detect: async () => existsSync39(join59(home4, ".codex"))
62033
+ globalPath: join59(home3, ".codex/skills"),
62034
+ detect: async () => existsSync39(join59(home3, ".codex"))
61982
62035
  },
61983
62036
  opencode: {
61984
62037
  name: "opencode",
61985
62038
  displayName: "OpenCode",
61986
62039
  projectPath: ".claude/skills",
61987
- globalPath: join59(home4, ".claude/skills"),
62040
+ globalPath: join59(home3, ".claude/skills"),
61988
62041
  detect: async () => hasOpenCodeInstallSignal2()
61989
62042
  },
61990
62043
  goose: {
61991
62044
  name: "goose",
61992
62045
  displayName: "Goose",
61993
62046
  projectPath: ".goose/skills",
61994
- globalPath: join59(home4, ".config/goose/skills"),
61995
- detect: async () => existsSync39(join59(home4, ".config/goose"))
62047
+ globalPath: join59(home3, ".config/goose/skills"),
62048
+ detect: async () => existsSync39(join59(home3, ".config/goose"))
61996
62049
  },
61997
62050
  "gemini-cli": {
61998
62051
  name: "gemini-cli",
61999
62052
  displayName: "Gemini CLI",
62000
62053
  projectPath: ".agents/skills",
62001
- globalPath: join59(home4, ".agents/skills"),
62002
- detect: async () => existsSync39(join59(home4, ".gemini"))
62054
+ globalPath: join59(home3, ".agents/skills"),
62055
+ detect: async () => existsSync39(join59(home3, ".gemini"))
62003
62056
  },
62004
62057
  antigravity: {
62005
62058
  name: "antigravity",
62006
62059
  displayName: "Antigravity",
62007
62060
  projectPath: ".agent/skills",
62008
- globalPath: join59(home4, ".gemini/antigravity/skills"),
62009
- detect: async () => existsSync39(join59(process.cwd(), ".agent")) || existsSync39(join59(home4, ".gemini/antigravity"))
62061
+ globalPath: join59(home3, ".gemini/antigravity/skills"),
62062
+ detect: async () => existsSync39(join59(process.cwd(), ".agent")) || existsSync39(join59(home3, ".gemini/antigravity"))
62010
62063
  },
62011
62064
  "github-copilot": {
62012
62065
  name: "github-copilot",
62013
62066
  displayName: "GitHub Copilot",
62014
62067
  projectPath: ".github/skills",
62015
- globalPath: join59(home4, ".copilot/skills"),
62016
- detect: async () => existsSync39(join59(home4, ".copilot"))
62068
+ globalPath: join59(home3, ".copilot/skills"),
62069
+ detect: async () => existsSync39(join59(home3, ".copilot"))
62017
62070
  },
62018
62071
  amp: {
62019
62072
  name: "amp",
62020
62073
  displayName: "Amp",
62021
62074
  projectPath: ".agents/skills",
62022
- globalPath: join59(home4, ".config/agents/skills"),
62023
- detect: async () => existsSync39(join59(home4, ".config/amp"))
62075
+ globalPath: join59(home3, ".config/agents/skills"),
62076
+ detect: async () => existsSync39(join59(home3, ".config/amp"))
62024
62077
  },
62025
62078
  kilo: {
62026
62079
  name: "kilo",
62027
62080
  displayName: "Kilo Code",
62028
62081
  projectPath: ".kilocode/skills",
62029
- globalPath: join59(home4, ".kilocode/skills"),
62030
- detect: async () => existsSync39(join59(home4, ".kilocode"))
62082
+ globalPath: join59(home3, ".kilocode/skills"),
62083
+ detect: async () => existsSync39(join59(home3, ".kilocode"))
62031
62084
  },
62032
62085
  roo: {
62033
62086
  name: "roo",
62034
62087
  displayName: "Roo Code",
62035
62088
  projectPath: ".roo/skills",
62036
- globalPath: join59(home4, ".roo/skills"),
62037
- detect: async () => existsSync39(join59(home4, ".roo"))
62089
+ globalPath: join59(home3, ".roo/skills"),
62090
+ detect: async () => existsSync39(join59(home3, ".roo"))
62038
62091
  },
62039
62092
  windsurf: {
62040
62093
  name: "windsurf",
62041
62094
  displayName: "Windsurf",
62042
62095
  projectPath: ".windsurf/skills",
62043
- globalPath: join59(home4, ".codeium/windsurf/skills"),
62044
- detect: async () => existsSync39(join59(home4, ".codeium/windsurf"))
62096
+ globalPath: join59(home3, ".codeium/windsurf/skills"),
62097
+ detect: async () => existsSync39(join59(home3, ".codeium/windsurf"))
62045
62098
  },
62046
62099
  cline: {
62047
62100
  name: "cline",
62048
62101
  displayName: "Cline",
62049
62102
  projectPath: ".cline/skills",
62050
- globalPath: join59(home4, ".cline/skills"),
62051
- detect: async () => existsSync39(join59(home4, ".cline"))
62103
+ globalPath: join59(home3, ".cline/skills"),
62104
+ detect: async () => existsSync39(join59(home3, ".cline"))
62052
62105
  },
62053
62106
  openhands: {
62054
62107
  name: "openhands",
62055
62108
  displayName: "OpenHands",
62056
62109
  projectPath: ".openhands/skills",
62057
- globalPath: join59(home4, ".openhands/skills"),
62058
- detect: async () => existsSync39(join59(home4, ".openhands"))
62110
+ globalPath: join59(home3, ".openhands/skills"),
62111
+ detect: async () => existsSync39(join59(home3, ".openhands"))
62059
62112
  }
62060
62113
  };
62061
62114
  });
@@ -62096,15 +62149,15 @@ function migrateRegistryPaths(registry) {
62096
62149
  }
62097
62150
  async function readRegistry2() {
62098
62151
  try {
62099
- if (!existsSync40(REGISTRY_PATH2)) {
62152
+ if (!existsSync40(REGISTRY_PATH)) {
62100
62153
  return { version: "1.0", installations: [] };
62101
62154
  }
62102
- const content = await readFile31(REGISTRY_PATH2, "utf-8");
62155
+ const content = await readFile31(REGISTRY_PATH, "utf-8");
62103
62156
  const data = JSON.parse(content);
62104
62157
  const registry = SkillRegistrySchema.parse(data);
62105
62158
  if (migrateRegistryPaths(registry)) {
62106
62159
  try {
62107
- await writeFile15(REGISTRY_PATH2, JSON.stringify(registry, null, 2), "utf-8");
62160
+ await writeFile15(REGISTRY_PATH, JSON.stringify(registry, null, 2), "utf-8");
62108
62161
  } catch {}
62109
62162
  }
62110
62163
  return registry;
@@ -62116,11 +62169,11 @@ async function readRegistry2() {
62116
62169
  }
62117
62170
  }
62118
62171
  async function writeRegistry2(registry) {
62119
- const dir = dirname25(REGISTRY_PATH2);
62172
+ const dir = dirname25(REGISTRY_PATH);
62120
62173
  if (!existsSync40(dir)) {
62121
62174
  await mkdir15(dir, { recursive: true });
62122
62175
  }
62123
- await writeFile15(REGISTRY_PATH2, JSON.stringify(registry, null, 2), "utf-8");
62176
+ await writeFile15(REGISTRY_PATH, JSON.stringify(registry, null, 2), "utf-8");
62124
62177
  }
62125
62178
  async function addInstallation(skill, agent, global3, path6, sourcePath) {
62126
62179
  const registry = await readRegistry2();
@@ -62172,11 +62225,11 @@ async function syncRegistry() {
62172
62225
  }
62173
62226
  return { removed };
62174
62227
  }
62175
- var home5, REGISTRY_PATH2, SkillInstallationSchema, SkillRegistrySchema, REGISTRY_PATH_MIGRATIONS;
62228
+ var home4, REGISTRY_PATH, SkillInstallationSchema, SkillRegistrySchema, REGISTRY_PATH_MIGRATIONS;
62176
62229
  var init_skills_registry = __esm(() => {
62177
62230
  init_zod();
62178
- home5 = homedir38();
62179
- REGISTRY_PATH2 = join60(home5, ".claudekit", "skill-registry.json");
62231
+ home4 = homedir38();
62232
+ REGISTRY_PATH = join60(home4, ".claudekit", "skill-registry.json");
62180
62233
  SkillInstallationSchema = exports_external.object({
62181
62234
  skill: exports_external.string(),
62182
62235
  agent: exports_external.string(),
@@ -63287,7 +63340,7 @@ var package_default;
63287
63340
  var init_package = __esm(() => {
63288
63341
  package_default = {
63289
63342
  name: "claudekit-cli",
63290
- version: "4.3.1-dev.1",
63343
+ version: "4.3.1-dev.2",
63291
63344
  description: "CLI tool for bootstrapping and updating ClaudeKit projects",
63292
63345
  type: "module",
63293
63346
  repository: {
@@ -65804,12 +65857,12 @@ function extractHookReferencePaths(cmd) {
65804
65857
  }
65805
65858
  function resolveHookScriptPath(scriptPath, projectDir) {
65806
65859
  let resolved = scriptPath.replace(/\\/g, "/");
65807
- const home6 = homedir40();
65808
- resolved = resolved.replace(/^\$\{?HOME\}?/, home6);
65860
+ const home5 = homedir40();
65861
+ resolved = resolved.replace(/^\$\{?HOME\}?/, home5);
65809
65862
  resolved = resolved.replace(/^\$\{?CLAUDE_PROJECT_DIR\}?/, projectDir);
65810
- resolved = resolved.replace(/^%USERPROFILE%/, home6);
65863
+ resolved = resolved.replace(/^%USERPROFILE%/, home5);
65811
65864
  resolved = resolved.replace(/^%CLAUDE_PROJECT_DIR%/, projectDir);
65812
- resolved = resolved.replace(/^~\//, `${home6}/`);
65865
+ resolved = resolved.replace(/^~\//, `${home5}/`);
65813
65866
  if (resolved.startsWith(".claude/") || resolved === ".claude") {
65814
65867
  resolved = join67(projectDir, resolved);
65815
65868
  }
@@ -80168,6 +80221,12 @@ var init_plan_command_help = __esm(() => {
80168
80221
  title: "Scope Options",
80169
80222
  options: [{ flags: "-g, --global", description: "Create plan in global plans scope" }]
80170
80223
  }
80224
+ ],
80225
+ sections: [
80226
+ {
80227
+ title: "Agent Editing Reminder",
80228
+ content: "After creating a plan, Claude Code agents should read `plan.md` and every generated `phase-*.md` before editing. The files already exist; Write/Edit without Read can be rejected after wasting tokens."
80229
+ }
80171
80230
  ]
80172
80231
  },
80173
80232
  {
@@ -84596,6 +84655,16 @@ init_provider_registry();
84596
84655
  import { existsSync as existsSync9 } from "node:fs";
84597
84656
  import { lstat as lstat3, rm as rm2 } from "node:fs/promises";
84598
84657
  import { basename as basename5, dirname as dirname6, join as join17, relative as relative4, resolve as resolve8, sep as sep4 } from "node:path";
84658
+ var defaultCommandRegistryDeps = {
84659
+ readPortableRegistry,
84660
+ removePortableInstallation
84661
+ };
84662
+ function resolveCommandRegistryDeps(deps) {
84663
+ return {
84664
+ ...defaultCommandRegistryDeps,
84665
+ ...deps
84666
+ };
84667
+ }
84599
84668
  function isPathWithinBase(targetPath, basePath) {
84600
84669
  const resolvedTarget = resolve8(targetPath);
84601
84670
  const resolvedBase = resolve8(basePath);
@@ -84727,8 +84796,9 @@ async function removeCommandTarget(targetPath, provider, basePath) {
84727
84796
  }
84728
84797
  await rm2(targetPath, { recursive: true, force: true });
84729
84798
  }
84730
- async function uninstallCommandFromProvider(commandName, provider, global3) {
84731
- const registry = await readPortableRegistry();
84799
+ async function uninstallCommandFromProvider(commandName, provider, global3, deps) {
84800
+ const registryDeps = resolveCommandRegistryDeps(deps);
84801
+ const registry = await registryDeps.readPortableRegistry();
84732
84802
  const installations = findPortableInstallations(registry, commandName, "command", provider, global3);
84733
84803
  if (installations.length === 0) {
84734
84804
  return {
@@ -84749,7 +84819,7 @@ async function uninstallCommandFromProvider(commandName, provider, global3) {
84749
84819
  if (fileExists) {
84750
84820
  await removeCommandTarget(installation.path, provider, basePath);
84751
84821
  }
84752
- await removePortableInstallation(commandName, "command", provider, global3);
84822
+ await registryDeps.removePortableInstallation(commandName, "command", provider, global3);
84753
84823
  return {
84754
84824
  item: commandName,
84755
84825
  provider,
@@ -84771,7 +84841,8 @@ async function uninstallCommandFromProvider(commandName, provider, global3) {
84771
84841
  };
84772
84842
  }
84773
84843
  }
84774
- async function forceUninstallCommandFromProvider(commandName, provider, global3) {
84844
+ async function forceUninstallCommandFromProvider(commandName, provider, global3, deps) {
84845
+ const registryDeps = resolveCommandRegistryDeps(deps);
84775
84846
  const config = providers[provider];
84776
84847
  const pathConfig = config.commands;
84777
84848
  if (!pathConfig) {
@@ -84841,7 +84912,7 @@ async function forceUninstallCommandFromProvider(commandName, provider, global3)
84841
84912
  }
84842
84913
  try {
84843
84914
  await removeCommandTarget(targetPath, provider, basePath);
84844
- await removePortableInstallation(commandName, "command", provider, global3);
84915
+ await registryDeps.removePortableInstallation(commandName, "command", provider, global3);
84845
84916
  return {
84846
84917
  item: commandName,
84847
84918
  provider,
@@ -84862,8 +84933,9 @@ async function forceUninstallCommandFromProvider(commandName, provider, global3)
84862
84933
  };
84863
84934
  }
84864
84935
  }
84865
- async function getInstalledCommands(provider, global3) {
84866
- const registry = await readPortableRegistry();
84936
+ async function getInstalledCommands(provider, global3, deps) {
84937
+ const registryDeps = resolveCommandRegistryDeps(deps);
84938
+ const registry = await registryDeps.readPortableRegistry();
84867
84939
  return registry.installations.filter((i) => {
84868
84940
  if (i.type !== "command")
84869
84941
  return false;
@@ -84876,9 +84948,20 @@ async function getInstalledCommands(provider, global3) {
84876
84948
  }
84877
84949
 
84878
84950
  // src/commands/commands/commands-command.ts
84879
- async function listCommands(showInstalled) {
84951
+ var defaultCommandsRegistryDeps = {
84952
+ readPortableRegistry,
84953
+ removePortableInstallation,
84954
+ syncPortableRegistry
84955
+ };
84956
+ function resolveCommandsRegistryDeps(options2) {
84957
+ return {
84958
+ ...defaultCommandsRegistryDeps,
84959
+ ...options2?.registry
84960
+ };
84961
+ }
84962
+ async function listCommands(showInstalled, registryDeps) {
84880
84963
  if (showInstalled) {
84881
- const installations = await getInstalledCommands();
84964
+ const installations = await getInstalledCommands(undefined, undefined, registryDeps);
84882
84965
  if (installations.length === 0) {
84883
84966
  f2.warn("No commands installed via ck commands.");
84884
84967
  return;
@@ -84930,9 +85013,9 @@ async function listCommands(showInstalled) {
84930
85013
  console.log(import_picocolors13.default.dim(` Source: ${sourcePath}`));
84931
85014
  console.log();
84932
85015
  }
84933
- async function handleUninstall2(options2) {
85016
+ async function handleUninstall2(options2, registryDeps) {
84934
85017
  if (!options2.name) {
84935
- const installations = await getInstalledCommands();
85018
+ const installations = await getInstalledCommands(undefined, undefined, registryDeps);
84936
85019
  if (installations.length === 0) {
84937
85020
  f2.warn("No commands installed via ck commands.");
84938
85021
  return;
@@ -84964,7 +85047,7 @@ async function handleUninstall2(options2) {
84964
85047
  const spinner2 = de();
84965
85048
  spinner2.start("Uninstalling...");
84966
85049
  for (const inst of toUninstall) {
84967
- await uninstallCommandFromProvider(inst.item, inst.provider, inst.global);
85050
+ await uninstallCommandFromProvider(inst.item, inst.provider, inst.global, registryDeps);
84968
85051
  }
84969
85052
  spinner2.stop("Uninstall complete");
84970
85053
  f2.success(`Removed ${toUninstall.length} command(s)`);
@@ -84990,7 +85073,7 @@ async function handleUninstall2(options2) {
84990
85073
  const spinner2 = de();
84991
85074
  spinner2.start("Force uninstalling...");
84992
85075
  const targets = options2.agent;
84993
- const results = await Promise.all(targets.map((provider) => forceUninstallCommandFromProvider(trimmedName, provider, options2.global ?? false)));
85076
+ const results = await Promise.all(targets.map((provider) => forceUninstallCommandFromProvider(trimmedName, provider, options2.global ?? false, registryDeps)));
84994
85077
  const successCount2 = results.filter((result) => result.success).length;
84995
85078
  spinner2.stop("Force uninstall complete");
84996
85079
  for (const result of results) {
@@ -85005,7 +85088,7 @@ async function handleUninstall2(options2) {
85005
85088
  }
85006
85089
  return true;
85007
85090
  };
85008
- const registry = await readPortableRegistry();
85091
+ const registry = await registryDeps.readPortableRegistry();
85009
85092
  const matches = registry.installations.filter((i) => i.type === "command" && i.item.toLowerCase() === trimmedName.toLowerCase());
85010
85093
  if (matches.length === 0) {
85011
85094
  if (options2.force) {
@@ -85048,7 +85131,7 @@ async function handleUninstall2(options2) {
85048
85131
  spinner.start("Uninstalling...");
85049
85132
  let successCount = 0;
85050
85133
  for (const inst of toRemove) {
85051
- const result = await uninstallCommandFromProvider(inst.item, inst.provider, inst.global);
85134
+ const result = await uninstallCommandFromProvider(inst.item, inst.provider, inst.global, registryDeps);
85052
85135
  if (result.success)
85053
85136
  successCount++;
85054
85137
  }
@@ -85059,11 +85142,12 @@ async function commandsCommand(options2) {
85059
85142
  console.log();
85060
85143
  oe(import_picocolors13.default.bgCyan(import_picocolors13.default.black(" ck commands ")));
85061
85144
  try {
85145
+ const registryDeps = resolveCommandsRegistryDeps(options2);
85062
85146
  const validOptions = PortableCommandOptionsSchema.parse(options2);
85063
85147
  if (validOptions.sync) {
85064
85148
  const spinner2 = de();
85065
85149
  spinner2.start("Syncing registry...");
85066
- const { removed } = await syncPortableRegistry();
85150
+ const { removed } = await registryDeps.syncPortableRegistry();
85067
85151
  spinner2.stop("Sync complete");
85068
85152
  if (removed.length > 0) {
85069
85153
  const cmdRemoved = removed.filter((r2) => r2.type === "command");
@@ -85075,12 +85159,12 @@ async function commandsCommand(options2) {
85075
85159
  return;
85076
85160
  }
85077
85161
  if (validOptions.uninstall) {
85078
- await handleUninstall2(validOptions);
85162
+ await handleUninstall2(validOptions, registryDeps);
85079
85163
  $e(import_picocolors13.default.green("Done!"));
85080
85164
  return;
85081
85165
  }
85082
85166
  if (validOptions.list) {
85083
- await listCommands(validOptions.installed ?? false);
85167
+ await listCommands(validOptions.installed ?? false, registryDeps);
85084
85168
  $e(import_picocolors13.default.dim("Use --name <command> to install a specific command"));
85085
85169
  return;
85086
85170
  }
@@ -87266,16 +87350,16 @@ async function checkPathRefsValid(projectDir) {
87266
87350
  };
87267
87351
  }
87268
87352
  const baseDir = dirname28(claudeMdPath);
87269
- const home6 = homedir42();
87353
+ const home5 = homedir42();
87270
87354
  const broken = [];
87271
87355
  for (const ref of refs) {
87272
87356
  let refPath;
87273
87357
  if (ref.startsWith("$HOME") || ref.startsWith("${HOME}") || ref.startsWith("%USERPROFILE%")) {
87274
- refPath = normalize6(ref.replace(/^\$\{?HOME\}?/, home6).replace("%USERPROFILE%", home6));
87358
+ refPath = normalize6(ref.replace(/^\$\{?HOME\}?/, home5).replace("%USERPROFILE%", home5));
87275
87359
  } else if (ref.startsWith("$CLAUDE_PROJECT_DIR") || ref.startsWith("${CLAUDE_PROJECT_DIR}") || ref.startsWith("%CLAUDE_PROJECT_DIR%")) {
87276
87360
  refPath = normalize6(ref.replace(/^\$\{?CLAUDE_PROJECT_DIR\}?/, projectDir).replace("%CLAUDE_PROJECT_DIR%", projectDir));
87277
87361
  } else if (ref.startsWith("~")) {
87278
- refPath = normalize6(ref.replace(/^~/, home6));
87362
+ refPath = normalize6(ref.replace(/^~/, home5));
87279
87363
  } else if (ref.startsWith("/")) {
87280
87364
  refPath = normalize6(ref);
87281
87365
  } else if (/^[A-Za-z]:/.test(ref)) {
@@ -87284,7 +87368,7 @@ async function checkPathRefsValid(projectDir) {
87284
87368
  refPath = resolve35(baseDir, ref);
87285
87369
  }
87286
87370
  const normalizedPath = normalize6(refPath);
87287
- const isWithinHome = normalizedPath.startsWith(home6);
87371
+ const isWithinHome = normalizedPath.startsWith(home5);
87288
87372
  const isWithinBase2 = normalizedPath.startsWith(normalize6(baseDir));
87289
87373
  const isAbsoluteAllowed = ref.startsWith("/") || /^[A-Za-z]:/.test(ref);
87290
87374
  if (!isWithinHome && !isWithinBase2 && !isAbsoluteAllowed) {
@@ -89271,8 +89355,8 @@ class ReportGenerator {
89271
89355
  };
89272
89356
  }
89273
89357
  scrubPath(path7) {
89274
- const home6 = process.env.HOME || process.env.USERPROFILE || "";
89275
- return home6 ? path7.replace(home6, "~") : path7;
89358
+ const home5 = process.env.HOME || process.env.USERPROFILE || "";
89359
+ return home5 ? path7.replace(home5, "~") : path7;
89276
89360
  }
89277
89361
  getStatusIcon(status) {
89278
89362
  switch (status) {
@@ -89386,8 +89470,8 @@ class DoctorUIRenderer {
89386
89470
  }
89387
89471
  }
89388
89472
  shortenPath(path7) {
89389
- const home6 = process.env.HOME || process.env.USERPROFILE || "";
89390
- let shortened = home6 ? path7.replace(home6, "~") : path7;
89473
+ const home5 = process.env.HOME || process.env.USERPROFILE || "";
89474
+ let shortened = home5 ? path7.replace(home5, "~") : path7;
89391
89475
  const maxLen = 50;
89392
89476
  if (shortened.length > maxLen) {
89393
89477
  const start = shortened.slice(0, 20);
@@ -108253,11 +108337,11 @@ function wrapText(value, width) {
108253
108337
  }
108254
108338
  function formatDisplayPath(value) {
108255
108339
  const normalized = value.replace(/\\/g, "/");
108256
- const home6 = homedir48().replace(/\\/g, "/");
108257
- if (normalized === home6)
108340
+ const home5 = homedir48().replace(/\\/g, "/");
108341
+ if (normalized === home5)
108258
108342
  return "~";
108259
- if (normalized.startsWith(`${home6}/`)) {
108260
- return normalized.replace(home6, "~");
108343
+ if (normalized.startsWith(`${home5}/`)) {
108344
+ return normalized.replace(home5, "~");
108261
108345
  }
108262
108346
  return normalized;
108263
108347
  }
@@ -108712,8 +108796,8 @@ function pickGenericModel(models) {
108712
108796
  return sorted[0] ?? null;
108713
108797
  }
108714
108798
  async function resolveOpenCodeDefaultModel(opts = {}) {
108715
- const home6 = opts.homeDir ?? homedir50();
108716
- const authedProviders = await readAuthedProviders(home6);
108799
+ const home5 = opts.homeDir ?? homedir50();
108800
+ const authedProviders = await readAuthedProviders(home5);
108717
108801
  if (authedProviders.length === 0) {
108718
108802
  return { ok: false, reason: "no-auth", authedProviders: [] };
108719
108803
  }
@@ -111315,6 +111399,17 @@ init_plans_registry();
111315
111399
  init_output_manager();
111316
111400
  var import_picocolors33 = __toESM(require_picocolors(), 1);
111317
111401
  import { basename as basename31, dirname as dirname45, relative as relative32, resolve as resolve53 } from "node:path";
111402
+ function quoteReadTarget(filePath) {
111403
+ return `"${filePath.replace(/\\/g, "/").replace(/"/g, "\\\"")}"`;
111404
+ }
111405
+ function buildPlanCreateReadReminder(planFile, phaseFiles, cwd2 = process.cwd()) {
111406
+ const files = [planFile, ...phaseFiles].map((file) => quoteReadTarget(relative32(cwd2, file)));
111407
+ return [
111408
+ " [i] Claude Code agents: read plan.md and every phase-*.md before editing.",
111409
+ " These files already exist; Write/Edit without Read may be rejected after wasting tokens.",
111410
+ ` cat ${files.join(" ")}`
111411
+ ];
111412
+ }
111318
111413
  async function handleCreate(target, options2) {
111319
111414
  if (!options2.title) {
111320
111415
  output.error("[X] --title is required for create");
@@ -111392,6 +111487,9 @@ async function handleCreate(target, options2) {
111392
111487
  for (const f3 of result.phaseFiles) {
111393
111488
  console.log(` [ ] ${basename31(f3)}`);
111394
111489
  }
111490
+ for (const line of buildPlanCreateReadReminder(result.planFile, result.phaseFiles)) {
111491
+ console.log(line);
111492
+ }
111395
111493
  console.log();
111396
111494
  }
111397
111495
  async function handleCheck(target, options2) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudekit-cli",
3
- "version": "4.3.1-dev.1",
3
+ "version": "4.3.1-dev.2",
4
4
  "description": "CLI tool for bootstrapping and updating ClaudeKit projects",
5
5
  "type": "module",
6
6
  "repository": {