claudekit-cli 3.23.0 → 3.24.0

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 (2) hide show
  1. package/dist/index.js +380 -156
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -18468,6 +18468,25 @@ class PathResolver {
18468
18468
  }
18469
18469
  return join(homedir(), ".claude");
18470
18470
  }
18471
+ static getOpenCodeDir(global2, baseDir) {
18472
+ const testHome = PathResolver.getTestHomeDir();
18473
+ if (testHome) {
18474
+ return global2 ? join(testHome, ".config", "opencode") : join(baseDir || testHome, ".opencode");
18475
+ }
18476
+ if (!global2) {
18477
+ return join(baseDir || process.cwd(), ".opencode");
18478
+ }
18479
+ const os = platform();
18480
+ if (os === "win32") {
18481
+ const appData = process.env.APPDATA || join(homedir(), "AppData", "Roaming");
18482
+ return join(appData, "opencode");
18483
+ }
18484
+ const xdgConfigHome = process.env.XDG_CONFIG_HOME;
18485
+ if (xdgConfigHome) {
18486
+ return join(xdgConfigHome, "opencode");
18487
+ }
18488
+ return join(homedir(), ".config", "opencode");
18489
+ }
18471
18490
  static getPathPrefix(global2) {
18472
18491
  return global2 ? "" : ".claude";
18473
18492
  }
@@ -39548,13 +39567,156 @@ async function handleMigration(ctx) {
39548
39567
  }
39549
39568
  return ctx;
39550
39569
  }
39570
+ // src/commands/init/phases/opencode-handler.ts
39571
+ import { cp, readdir as readdir22, rm as rm5 } from "node:fs/promises";
39572
+ import { join as join60 } from "node:path";
39573
+
39574
+ // src/services/transformers/opencode-path-transformer.ts
39575
+ init_logger();
39576
+ import { readFile as readFile20, readdir as readdir21, writeFile as writeFile16 } from "node:fs/promises";
39577
+ import { platform as platform10 } from "node:os";
39578
+ import { extname as extname2, join as join59 } from "node:path";
39579
+ var IS_WINDOWS3 = platform10() === "win32";
39580
+ function getOpenCodeGlobalPath() {
39581
+ return IS_WINDOWS3 ? "%APPDATA%/opencode/" : "$HOME/.config/opencode/";
39582
+ }
39583
+ var TRANSFORMABLE_EXTENSIONS2 = new Set([
39584
+ ".md",
39585
+ ".js",
39586
+ ".ts",
39587
+ ".json",
39588
+ ".sh",
39589
+ ".ps1",
39590
+ ".yaml",
39591
+ ".yml",
39592
+ ".toml"
39593
+ ]);
39594
+ function transformOpenCodeContent(content) {
39595
+ let changes = 0;
39596
+ let transformed = content;
39597
+ const globalPath = getOpenCodeGlobalPath();
39598
+ transformed = transformed.replace(/\.\/\.opencode\//g, () => {
39599
+ changes++;
39600
+ return globalPath;
39601
+ });
39602
+ transformed = transformed.replace(/(["'`])\.opencode\//g, (_match, quote) => {
39603
+ changes++;
39604
+ return `${quote}${globalPath}`;
39605
+ });
39606
+ transformed = transformed.replace(/\(\.opencode\//g, () => {
39607
+ changes++;
39608
+ return `(${globalPath}`;
39609
+ });
39610
+ transformed = transformed.replace(/ \.opencode\//g, () => {
39611
+ changes++;
39612
+ return ` ${globalPath}`;
39613
+ });
39614
+ transformed = transformed.replace(/^\.opencode\//gm, () => {
39615
+ changes++;
39616
+ return globalPath;
39617
+ });
39618
+ transformed = transformed.replace(/: \.opencode\//g, () => {
39619
+ changes++;
39620
+ return `: ${globalPath}`;
39621
+ });
39622
+ transformed = transformed.replace(/:\.opencode\//g, () => {
39623
+ changes++;
39624
+ return `:${globalPath}`;
39625
+ });
39626
+ return { transformed, changes };
39627
+ }
39628
+ function shouldTransformFile2(filename) {
39629
+ const ext2 = extname2(filename).toLowerCase();
39630
+ return TRANSFORMABLE_EXTENSIONS2.has(ext2);
39631
+ }
39632
+ async function transformPathsForGlobalOpenCode(directory, options = {}) {
39633
+ let filesTransformed = 0;
39634
+ let totalChanges = 0;
39635
+ let filesSkipped = 0;
39636
+ async function processDirectory2(dir) {
39637
+ const entries = await readdir21(dir, { withFileTypes: true });
39638
+ for (const entry of entries) {
39639
+ const fullPath = join59(dir, entry.name);
39640
+ if (entry.isDirectory()) {
39641
+ if (entry.name === "node_modules" || entry.name.startsWith(".")) {
39642
+ continue;
39643
+ }
39644
+ await processDirectory2(fullPath);
39645
+ } else if (entry.isFile() && shouldTransformFile2(entry.name)) {
39646
+ try {
39647
+ const content = await readFile20(fullPath, "utf-8");
39648
+ const { transformed, changes } = transformOpenCodeContent(content);
39649
+ if (changes > 0) {
39650
+ await writeFile16(fullPath, transformed, "utf-8");
39651
+ filesTransformed++;
39652
+ totalChanges += changes;
39653
+ if (options.verbose) {
39654
+ logger.verbose(`Transformed ${changes} OpenCode path(s) in ${fullPath}`);
39655
+ }
39656
+ }
39657
+ } catch (error) {
39658
+ filesSkipped++;
39659
+ if (options.verbose) {
39660
+ logger.verbose(`Skipping ${fullPath}: ${error instanceof Error ? error.message : "unknown error"}`);
39661
+ }
39662
+ }
39663
+ }
39664
+ }
39665
+ }
39666
+ await processDirectory2(directory);
39667
+ return { filesTransformed, totalChanges, filesSkipped };
39668
+ }
39669
+
39670
+ // src/commands/init/phases/opencode-handler.ts
39671
+ init_logger();
39672
+ var import_fs_extra25 = __toESM(require_lib(), 1);
39673
+ async function handleOpenCode(ctx) {
39674
+ if (ctx.cancelled || !ctx.extractDir || !ctx.resolvedDir) {
39675
+ return ctx;
39676
+ }
39677
+ const openCodeSource = join60(ctx.extractDir, ".opencode");
39678
+ if (!await import_fs_extra25.pathExists(openCodeSource)) {
39679
+ logger.debug("No .opencode directory in archive, skipping");
39680
+ return ctx;
39681
+ }
39682
+ logger.info("Processing .opencode configuration...");
39683
+ if (ctx.options.global) {
39684
+ const targetDir = PathResolver.getOpenCodeDir(true);
39685
+ logger.verbose(`Relocating .opencode to ${targetDir}`);
39686
+ const transformResult = await transformPathsForGlobalOpenCode(openCodeSource, {
39687
+ verbose: logger.isVerbose()
39688
+ });
39689
+ if (transformResult.totalChanges > 0) {
39690
+ logger.success(`Transformed ${transformResult.totalChanges} OpenCode path(s) in ${transformResult.filesTransformed} file(s)`);
39691
+ }
39692
+ await import_fs_extra25.ensureDir(targetDir);
39693
+ const entries = await readdir22(openCodeSource, { withFileTypes: true });
39694
+ for (const entry of entries) {
39695
+ const sourcePath = join60(openCodeSource, entry.name);
39696
+ const targetPath = join60(targetDir, entry.name);
39697
+ if (await import_fs_extra25.pathExists(targetPath)) {
39698
+ if (!ctx.options.forceOverwrite) {
39699
+ logger.verbose(`Skipping existing: ${entry.name}`);
39700
+ continue;
39701
+ }
39702
+ }
39703
+ await cp(sourcePath, targetPath, { recursive: true });
39704
+ logger.verbose(`Copied: ${entry.name}`);
39705
+ }
39706
+ await rm5(openCodeSource, { recursive: true, force: true });
39707
+ logger.success(`OpenCode config installed to ${targetDir}`);
39708
+ } else {
39709
+ logger.debug("Local mode: .opencode will be placed at project root");
39710
+ }
39711
+ return ctx;
39712
+ }
39551
39713
  // src/domains/config/config-manager.ts
39552
39714
  init_logger();
39553
39715
  import { existsSync as existsSync18 } from "node:fs";
39554
- import { mkdir as mkdir19, readFile as readFile20, rename as rename2, rm as rm5, writeFile as writeFile16 } from "node:fs/promises";
39716
+ import { mkdir as mkdir19, readFile as readFile21, rename as rename2, rm as rm6, writeFile as writeFile17 } from "node:fs/promises";
39555
39717
  import { chmod as chmod2 } from "node:fs/promises";
39556
- import { platform as platform10 } from "node:os";
39557
- import { join as join59 } from "node:path";
39718
+ import { platform as platform11 } from "node:os";
39719
+ import { join as join61 } from "node:path";
39558
39720
  init_types2();
39559
39721
  var PROJECT_CONFIG_FILE = ".ck.json";
39560
39722
 
@@ -39562,7 +39724,7 @@ class ConfigManager {
39562
39724
  static config = null;
39563
39725
  static globalFlag = false;
39564
39726
  static getProjectConfigDir(projectDir, global3) {
39565
- return global3 ? projectDir : join59(projectDir, ".claude");
39727
+ return global3 ? projectDir : join61(projectDir, ".claude");
39566
39728
  }
39567
39729
  static setGlobalFlag(global3) {
39568
39730
  ConfigManager.globalFlag = global3;
@@ -39578,7 +39740,7 @@ class ConfigManager {
39578
39740
  const configFile = PathResolver.getConfigFile(ConfigManager.globalFlag);
39579
39741
  try {
39580
39742
  if (existsSync18(configFile)) {
39581
- const content = await readFile20(configFile, "utf-8");
39743
+ const content = await readFile21(configFile, "utf-8");
39582
39744
  const data = JSON.parse(content);
39583
39745
  ConfigManager.config = ConfigSchema.parse(data);
39584
39746
  logger.debug(`Config loaded from ${configFile}`);
@@ -39597,12 +39759,12 @@ class ConfigManager {
39597
39759
  const configFile = PathResolver.getConfigFile(ConfigManager.globalFlag);
39598
39760
  if (!existsSync18(configDir)) {
39599
39761
  await mkdir19(configDir, { recursive: true });
39600
- if (platform10() !== "win32") {
39762
+ if (platform11() !== "win32") {
39601
39763
  await chmod2(configDir, 448);
39602
39764
  }
39603
39765
  }
39604
- await writeFile16(configFile, JSON.stringify(validConfig, null, 2), "utf-8");
39605
- if (platform10() !== "win32") {
39766
+ await writeFile17(configFile, JSON.stringify(validConfig, null, 2), "utf-8");
39767
+ if (platform11() !== "win32") {
39606
39768
  await chmod2(configFile, 384);
39607
39769
  }
39608
39770
  ConfigManager.config = validConfig;
@@ -39629,10 +39791,10 @@ class ConfigManager {
39629
39791
  }
39630
39792
  static async loadProjectConfig(projectDir, global3 = false) {
39631
39793
  const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
39632
- const configPath = join59(configDir, PROJECT_CONFIG_FILE);
39794
+ const configPath = join61(configDir, PROJECT_CONFIG_FILE);
39633
39795
  try {
39634
39796
  if (existsSync18(configPath)) {
39635
- const content = await readFile20(configPath, "utf-8");
39797
+ const content = await readFile21(configPath, "utf-8");
39636
39798
  const data = JSON.parse(content);
39637
39799
  const folders = FoldersConfigSchema.parse(data.paths || data);
39638
39800
  logger.debug(`Project config loaded from ${configPath}`);
@@ -39645,7 +39807,7 @@ class ConfigManager {
39645
39807
  }
39646
39808
  static async saveProjectConfig(projectDir, folders, global3 = false) {
39647
39809
  const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
39648
- const configPath = join59(configDir, PROJECT_CONFIG_FILE);
39810
+ const configPath = join61(configDir, PROJECT_CONFIG_FILE);
39649
39811
  try {
39650
39812
  if (!existsSync18(configDir)) {
39651
39813
  await mkdir19(configDir, { recursive: true });
@@ -39653,7 +39815,7 @@ class ConfigManager {
39653
39815
  let existingConfig = {};
39654
39816
  if (existsSync18(configPath)) {
39655
39817
  try {
39656
- const content = await readFile20(configPath, "utf-8");
39818
+ const content = await readFile21(configPath, "utf-8");
39657
39819
  existingConfig = JSON.parse(content);
39658
39820
  } catch (error) {
39659
39821
  logger.debug(`Could not parse existing config, starting fresh: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -39668,7 +39830,7 @@ class ConfigManager {
39668
39830
  ...validFolders
39669
39831
  }
39670
39832
  };
39671
- await writeFile16(configPath, JSON.stringify(mergedConfig, null, 2), "utf-8");
39833
+ await writeFile17(configPath, JSON.stringify(mergedConfig, null, 2), "utf-8");
39672
39834
  logger.debug(`Project config saved to ${configPath}`);
39673
39835
  } catch (error) {
39674
39836
  throw new Error(`Failed to save project config: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -39694,11 +39856,11 @@ class ConfigManager {
39694
39856
  }
39695
39857
  static projectConfigExists(projectDir, global3 = false) {
39696
39858
  const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
39697
- return existsSync18(join59(configDir, PROJECT_CONFIG_FILE));
39859
+ return existsSync18(join61(configDir, PROJECT_CONFIG_FILE));
39698
39860
  }
39699
39861
  static async migrateNestedConfig(globalDir) {
39700
- const correctPath = join59(globalDir, PROJECT_CONFIG_FILE);
39701
- const incorrectPath = join59(globalDir, ".claude", PROJECT_CONFIG_FILE);
39862
+ const correctPath = join61(globalDir, PROJECT_CONFIG_FILE);
39863
+ const incorrectPath = join61(globalDir, ".claude", PROJECT_CONFIG_FILE);
39702
39864
  if (existsSync18(correctPath)) {
39703
39865
  logger.debug("Config already exists at correct location, skipping migration");
39704
39866
  return false;
@@ -39708,9 +39870,9 @@ class ConfigManager {
39708
39870
  logger.info("Migrating .ck.json from nested location to correct location...");
39709
39871
  await rename2(incorrectPath, correctPath);
39710
39872
  logger.success(`Migrated ${PROJECT_CONFIG_FILE} to ${correctPath}`);
39711
- const nestedClaudeDir = join59(globalDir, ".claude");
39873
+ const nestedClaudeDir = join61(globalDir, ".claude");
39712
39874
  try {
39713
- await rm5(nestedClaudeDir, { recursive: false });
39875
+ await rm6(nestedClaudeDir, { recursive: false });
39714
39876
  logger.debug("Removed empty nested .claude directory");
39715
39877
  } catch (rmError) {
39716
39878
  logger.debug(`Could not remove nested .claude dir (may contain other files): ${rmError instanceof Error ? rmError.message : "Unknown"}`);
@@ -39799,14 +39961,14 @@ Please use only one download method.`);
39799
39961
  };
39800
39962
  }
39801
39963
  // src/commands/init/phases/post-install-handler.ts
39802
- import { join as join62 } from "node:path";
39964
+ import { join as join64 } from "node:path";
39803
39965
 
39804
39966
  // src/domains/installation/setup-wizard.ts
39805
- import { join as join61 } from "node:path";
39967
+ import { join as join63 } from "node:path";
39806
39968
 
39807
39969
  // src/domains/config/config-generator.ts
39808
- var import_fs_extra25 = __toESM(require_lib(), 1);
39809
- import { join as join60 } from "node:path";
39970
+ var import_fs_extra26 = __toESM(require_lib(), 1);
39971
+ import { join as join62 } from "node:path";
39810
39972
  async function generateEnvFile(targetDir, values) {
39811
39973
  const lines = [
39812
39974
  "# Generated by ClaudeKit CLI setup wizard",
@@ -39848,8 +40010,8 @@ async function generateEnvFile(targetDir, values) {
39848
40010
  for (const [key, value] of otherValues) {
39849
40011
  lines.push(`${key}=${value}`);
39850
40012
  }
39851
- const envPath = join60(targetDir, ".env");
39852
- await import_fs_extra25.writeFile(envPath, `${lines.join(`
40013
+ const envPath = join62(targetDir, ".env");
40014
+ await import_fs_extra26.writeFile(envPath, `${lines.join(`
39853
40015
  `)}
39854
40016
  `, { mode: 384 });
39855
40017
  }
@@ -39867,7 +40029,7 @@ function validateApiKey(value, pattern) {
39867
40029
  // src/domains/installation/setup-wizard.ts
39868
40030
  init_logger();
39869
40031
  init_dist2();
39870
- var import_fs_extra26 = __toESM(require_lib(), 1);
40032
+ var import_fs_extra27 = __toESM(require_lib(), 1);
39871
40033
  var ESSENTIAL_CONFIGS = [
39872
40034
  {
39873
40035
  key: "GEMINI_API_KEY",
@@ -39896,7 +40058,7 @@ var ESSENTIAL_CONFIGS = [
39896
40058
  ];
39897
40059
  async function parseEnvFile(path11) {
39898
40060
  try {
39899
- const content = await import_fs_extra26.readFile(path11, "utf-8");
40061
+ const content = await import_fs_extra27.readFile(path11, "utf-8");
39900
40062
  const env2 = {};
39901
40063
  for (const line of content.split(`
39902
40064
  `)) {
@@ -39922,8 +40084,8 @@ async function parseEnvFile(path11) {
39922
40084
  }
39923
40085
  }
39924
40086
  async function checkGlobalConfig() {
39925
- const globalEnvPath = join61(PathResolver.getGlobalKitDir(), ".env");
39926
- if (!await import_fs_extra26.pathExists(globalEnvPath))
40087
+ const globalEnvPath = join63(PathResolver.getGlobalKitDir(), ".env");
40088
+ if (!await import_fs_extra27.pathExists(globalEnvPath))
39927
40089
  return false;
39928
40090
  const env2 = await parseEnvFile(globalEnvPath);
39929
40091
  return Object.keys(env2).length > 0;
@@ -39938,8 +40100,8 @@ async function runSetupWizard(options) {
39938
40100
  let globalEnv = {};
39939
40101
  const hasGlobalConfig = !isGlobal && await checkGlobalConfig();
39940
40102
  if (!isGlobal) {
39941
- const globalEnvPath = join61(PathResolver.getGlobalKitDir(), ".env");
39942
- if (await import_fs_extra26.pathExists(globalEnvPath)) {
40103
+ const globalEnvPath = join63(PathResolver.getGlobalKitDir(), ".env");
40104
+ if (await import_fs_extra27.pathExists(globalEnvPath)) {
39943
40105
  globalEnv = await parseEnvFile(globalEnvPath);
39944
40106
  }
39945
40107
  }
@@ -40001,7 +40163,7 @@ async function runSetupWizard(options) {
40001
40163
  }
40002
40164
  }
40003
40165
  await generateEnvFile(targetDir, values);
40004
- f2.success(`Configuration saved to ${join61(targetDir, ".env")}`);
40166
+ f2.success(`Configuration saved to ${join63(targetDir, ".env")}`);
40005
40167
  return true;
40006
40168
  }
40007
40169
  async function promptForAdditionalGeminiKeys(primaryKey) {
@@ -40051,17 +40213,17 @@ async function promptForAdditionalGeminiKeys(primaryKey) {
40051
40213
 
40052
40214
  // src/commands/init/phases/post-install-handler.ts
40053
40215
  init_logger();
40054
- var import_fs_extra27 = __toESM(require_lib(), 1);
40216
+ var import_fs_extra28 = __toESM(require_lib(), 1);
40055
40217
  async function handlePostInstall(ctx) {
40056
40218
  if (ctx.cancelled || !ctx.extractDir || !ctx.resolvedDir || !ctx.claudeDir) {
40057
40219
  return ctx;
40058
40220
  }
40059
40221
  if (ctx.options.global) {
40060
- const claudeMdSource = join62(ctx.extractDir, "CLAUDE.md");
40061
- const claudeMdDest = join62(ctx.resolvedDir, "CLAUDE.md");
40062
- if (await import_fs_extra27.pathExists(claudeMdSource)) {
40063
- if (!await import_fs_extra27.pathExists(claudeMdDest)) {
40064
- await import_fs_extra27.copy(claudeMdSource, claudeMdDest);
40222
+ const claudeMdSource = join64(ctx.extractDir, "CLAUDE.md");
40223
+ const claudeMdDest = join64(ctx.resolvedDir, "CLAUDE.md");
40224
+ if (await import_fs_extra28.pathExists(claudeMdSource)) {
40225
+ if (!await import_fs_extra28.pathExists(claudeMdDest)) {
40226
+ await import_fs_extra28.copy(claudeMdSource, claudeMdDest);
40065
40227
  logger.success("Copied CLAUDE.md to global directory");
40066
40228
  } else {
40067
40229
  logger.debug("CLAUDE.md already exists in global directory (preserved)");
@@ -40105,8 +40267,8 @@ async function handlePostInstall(ctx) {
40105
40267
  }
40106
40268
  }
40107
40269
  if (!ctx.options.skipSetup && !ctx.isNonInteractive) {
40108
- const envPath = join62(ctx.claudeDir, ".env");
40109
- if (!await import_fs_extra27.pathExists(envPath)) {
40270
+ const envPath = join64(ctx.claudeDir, ".env");
40271
+ if (!await import_fs_extra28.pathExists(envPath)) {
40110
40272
  const shouldSetup = await ctx.prompts.confirm("Set up API keys now? (Gemini API key for ai-multimodal skill, optional webhooks)");
40111
40273
  if (shouldSetup) {
40112
40274
  await runSetupWizard({
@@ -40127,7 +40289,7 @@ Optional: DISCORD_WEBHOOK_URL, TELEGRAM_BOT_TOKEN`, "Configuration skipped");
40127
40289
  }
40128
40290
  // src/commands/init/phases/selection-handler.ts
40129
40291
  import { mkdir as mkdir20 } from "node:fs/promises";
40130
- import { join as join64, resolve as resolve7 } from "node:path";
40292
+ import { join as join66, resolve as resolve7 } from "node:path";
40131
40293
 
40132
40294
  // src/domains/github/kit-access-checker.ts
40133
40295
  init_logger();
@@ -40156,11 +40318,11 @@ async function detectAccessibleKits() {
40156
40318
 
40157
40319
  // src/domains/installation/fresh-installer.ts
40158
40320
  init_logger();
40159
- import { join as join63 } from "node:path";
40160
- var import_fs_extra28 = __toESM(require_lib(), 1);
40321
+ import { join as join65 } from "node:path";
40322
+ var import_fs_extra29 = __toESM(require_lib(), 1);
40161
40323
  var CLAUDEKIT_SUBDIRECTORIES = ["commands", "agents", "skills", "workflows", "hooks"];
40162
40324
  async function handleFreshInstallation(claudeDir, prompts) {
40163
- if (!await import_fs_extra28.pathExists(claudeDir)) {
40325
+ if (!await import_fs_extra29.pathExists(claudeDir)) {
40164
40326
  logger.info(".claude directory does not exist, proceeding with fresh installation");
40165
40327
  return true;
40166
40328
  }
@@ -40175,8 +40337,8 @@ async function handleFreshInstallation(claudeDir, prompts) {
40175
40337
  const { rmSync } = await import("node:fs");
40176
40338
  let removedCount = 0;
40177
40339
  for (const subdir of CLAUDEKIT_SUBDIRECTORIES) {
40178
- const subdirPath = join63(claudeDir, subdir);
40179
- if (await import_fs_extra28.pathExists(subdirPath)) {
40340
+ const subdirPath = join65(claudeDir, subdir);
40341
+ if (await import_fs_extra29.pathExists(subdirPath)) {
40180
40342
  rmSync(subdirPath, { recursive: true, force: true });
40181
40343
  removedCount++;
40182
40344
  logger.debug(`Removed subdirectory: ${subdir}/`);
@@ -40193,7 +40355,7 @@ async function handleFreshInstallation(claudeDir, prompts) {
40193
40355
  // src/commands/init/phases/selection-handler.ts
40194
40356
  init_logger();
40195
40357
  init_types2();
40196
- var import_fs_extra29 = __toESM(require_lib(), 1);
40358
+ var import_fs_extra30 = __toESM(require_lib(), 1);
40197
40359
 
40198
40360
  // src/commands/init/types.ts
40199
40361
  function isSyncContext(ctx) {
@@ -40357,7 +40519,7 @@ async function handleSelection(ctx) {
40357
40519
  return { ...ctx, cancelled: true };
40358
40520
  }
40359
40521
  }
40360
- if (!await import_fs_extra29.pathExists(resolvedDir)) {
40522
+ if (!await import_fs_extra30.pathExists(resolvedDir)) {
40361
40523
  if (ctx.options.global) {
40362
40524
  await mkdir20(resolvedDir, { recursive: true });
40363
40525
  logger.info(`Created global directory: ${resolvedDir}`);
@@ -40369,7 +40531,7 @@ async function handleSelection(ctx) {
40369
40531
  }
40370
40532
  if (!ctx.options.fresh) {
40371
40533
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
40372
- const claudeDir = prefix ? join64(resolvedDir, prefix) : resolvedDir;
40534
+ const claudeDir = prefix ? join66(resolvedDir, prefix) : resolvedDir;
40373
40535
  try {
40374
40536
  const existingMetadata = await readManifest(claudeDir);
40375
40537
  if (existingMetadata?.kits) {
@@ -40401,7 +40563,7 @@ async function handleSelection(ctx) {
40401
40563
  }
40402
40564
  if (ctx.options.fresh) {
40403
40565
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
40404
- const claudeDir = prefix ? join64(resolvedDir, prefix) : resolvedDir;
40566
+ const claudeDir = prefix ? join66(resolvedDir, prefix) : resolvedDir;
40405
40567
  const canProceed = await handleFreshInstallation(claudeDir, ctx.prompts);
40406
40568
  if (!canProceed) {
40407
40569
  return { ...ctx, cancelled: true };
@@ -40419,7 +40581,7 @@ async function handleSelection(ctx) {
40419
40581
  logger.info("Fetching available versions...");
40420
40582
  let currentVersion = null;
40421
40583
  try {
40422
- const metadataPath = ctx.options.global ? join64(PathResolver.getGlobalKitDir(), "metadata.json") : join64(resolvedDir, ".claude", "metadata.json");
40584
+ const metadataPath = ctx.options.global ? join66(PathResolver.getGlobalKitDir(), "metadata.json") : join66(resolvedDir, ".claude", "metadata.json");
40423
40585
  const metadata = await readClaudeKitMetadata(metadataPath);
40424
40586
  currentVersion = metadata?.version || null;
40425
40587
  if (currentVersion) {
@@ -40487,24 +40649,24 @@ async function handleSelection(ctx) {
40487
40649
  };
40488
40650
  }
40489
40651
  // src/commands/init/phases/sync-handler.ts
40490
- import { copyFile as copyFile6, mkdir as mkdir21, open, rename as rename3, stat as stat10, unlink as unlink7, writeFile as writeFile18 } from "node:fs/promises";
40491
- import { dirname as dirname9, join as join65, resolve as resolve8 } from "node:path";
40652
+ import { copyFile as copyFile6, mkdir as mkdir21, open, rename as rename3, stat as stat10, unlink as unlink7, writeFile as writeFile19 } from "node:fs/promises";
40653
+ import { dirname as dirname9, join as join67, resolve as resolve8 } from "node:path";
40492
40654
  init_logger();
40493
- var import_fs_extra30 = __toESM(require_lib(), 1);
40655
+ var import_fs_extra31 = __toESM(require_lib(), 1);
40494
40656
  var import_picocolors19 = __toESM(require_picocolors(), 1);
40495
40657
  async function handleSync(ctx) {
40496
40658
  if (!ctx.options.sync) {
40497
40659
  return ctx;
40498
40660
  }
40499
40661
  const resolvedDir = ctx.options.global ? PathResolver.getGlobalKitDir() : resolve8(ctx.options.dir || ".");
40500
- const claudeDir = ctx.options.global ? resolvedDir : join65(resolvedDir, ".claude");
40501
- if (!await import_fs_extra30.pathExists(claudeDir)) {
40662
+ const claudeDir = ctx.options.global ? resolvedDir : join67(resolvedDir, ".claude");
40663
+ if (!await import_fs_extra31.pathExists(claudeDir)) {
40502
40664
  logger.error("Cannot sync: no .claude directory found");
40503
40665
  ctx.prompts.note("Run 'ck init' without --sync to install first.", "No Installation Found");
40504
40666
  return { ...ctx, cancelled: true };
40505
40667
  }
40506
- const metadataPath = join65(claudeDir, "metadata.json");
40507
- if (!await import_fs_extra30.pathExists(metadataPath)) {
40668
+ const metadataPath = join67(claudeDir, "metadata.json");
40669
+ if (!await import_fs_extra31.pathExists(metadataPath)) {
40508
40670
  logger.error("Cannot sync: no metadata.json found");
40509
40671
  ctx.prompts.note(`Your installation may be from an older version.
40510
40672
  Run 'ck init' to update.`, "Legacy Installation");
@@ -40603,7 +40765,7 @@ function getLockTimeout() {
40603
40765
  var STALE_LOCK_THRESHOLD_MS = 5 * 60 * 1000;
40604
40766
  async function acquireSyncLock(global3) {
40605
40767
  const cacheDir = PathResolver.getCacheDir(global3);
40606
- const lockPath = join65(cacheDir, ".sync-lock");
40768
+ const lockPath = join67(cacheDir, ".sync-lock");
40607
40769
  const startTime = Date.now();
40608
40770
  const lockTimeout = getLockTimeout();
40609
40771
  await mkdir21(dirname9(lockPath), { recursive: true });
@@ -40649,7 +40811,7 @@ async function executeSyncMerge(ctx) {
40649
40811
  const releaseLock = await acquireSyncLock(ctx.options.global);
40650
40812
  try {
40651
40813
  const trackedFiles = ctx.syncTrackedFiles;
40652
- const upstreamDir = ctx.options.global ? join65(ctx.extractDir, ".claude") : ctx.extractDir;
40814
+ const upstreamDir = ctx.options.global ? join67(ctx.extractDir, ".claude") : ctx.extractDir;
40653
40815
  logger.info("Analyzing file changes...");
40654
40816
  const plan = await SyncEngine.createSyncPlan(trackedFiles, ctx.claudeDir, upstreamDir);
40655
40817
  displaySyncPlan(plan);
@@ -40668,7 +40830,7 @@ async function executeSyncMerge(ctx) {
40668
40830
  try {
40669
40831
  const sourcePath = await validateSyncPath(upstreamDir, file.path);
40670
40832
  const targetPath = await validateSyncPath(ctx.claudeDir, file.path);
40671
- const targetDir = join65(targetPath, "..");
40833
+ const targetDir = join67(targetPath, "..");
40672
40834
  try {
40673
40835
  await mkdir21(targetDir, { recursive: true });
40674
40836
  } catch (mkdirError) {
@@ -40749,7 +40911,7 @@ async function executeSyncMerge(ctx) {
40749
40911
  try {
40750
40912
  const tempPath = `${currentPath}.tmp.${Date.now()}`;
40751
40913
  try {
40752
- await writeFile18(tempPath, result.result, "utf-8");
40914
+ await writeFile19(tempPath, result.result, "utf-8");
40753
40915
  await rename3(tempPath, currentPath);
40754
40916
  } catch (atomicError) {
40755
40917
  await unlink7(tempPath).catch(() => {});
@@ -40837,9 +40999,9 @@ async function createBackup(claudeDir, files, backupDir) {
40837
40999
  for (const file of files) {
40838
41000
  try {
40839
41001
  const sourcePath = await validateSyncPath(claudeDir, file.path);
40840
- if (await import_fs_extra30.pathExists(sourcePath)) {
41002
+ if (await import_fs_extra31.pathExists(sourcePath)) {
40841
41003
  const targetPath = await validateSyncPath(backupDir, file.path);
40842
- const targetDir = join65(targetPath, "..");
41004
+ const targetDir = join67(targetPath, "..");
40843
41005
  await mkdir21(targetDir, { recursive: true });
40844
41006
  await copyFile6(sourcePath, targetPath);
40845
41007
  }
@@ -40853,7 +41015,7 @@ async function createBackup(claudeDir, files, backupDir) {
40853
41015
  }
40854
41016
  }
40855
41017
  // src/commands/init/phases/transform-handler.ts
40856
- import { join as join69 } from "node:path";
41018
+ import { join as join71 } from "node:path";
40857
41019
 
40858
41020
  // src/services/transformers/folder-path-transformer.ts
40859
41021
  init_logger();
@@ -40862,40 +41024,40 @@ init_types2();
40862
41024
  // src/services/transformers/folder-transform/folder-renamer.ts
40863
41025
  init_logger();
40864
41026
  init_types2();
40865
- var import_fs_extra31 = __toESM(require_lib(), 1);
40866
- import { rename as rename4, rm as rm6 } from "node:fs/promises";
40867
- import { join as join66, relative as relative12 } from "node:path";
41027
+ var import_fs_extra32 = __toESM(require_lib(), 1);
41028
+ import { rename as rename4, rm as rm7 } from "node:fs/promises";
41029
+ import { join as join68, relative as relative12 } from "node:path";
40868
41030
  async function collectDirsToRename(extractDir, folders) {
40869
41031
  const dirsToRename = [];
40870
41032
  if (folders.docs !== DEFAULT_FOLDERS.docs) {
40871
- const docsPath = join66(extractDir, DEFAULT_FOLDERS.docs);
40872
- if (await import_fs_extra31.pathExists(docsPath)) {
41033
+ const docsPath = join68(extractDir, DEFAULT_FOLDERS.docs);
41034
+ if (await import_fs_extra32.pathExists(docsPath)) {
40873
41035
  dirsToRename.push({
40874
41036
  from: docsPath,
40875
- to: join66(extractDir, folders.docs)
41037
+ to: join68(extractDir, folders.docs)
40876
41038
  });
40877
41039
  }
40878
- const claudeDocsPath = join66(extractDir, ".claude", DEFAULT_FOLDERS.docs);
40879
- if (await import_fs_extra31.pathExists(claudeDocsPath)) {
41040
+ const claudeDocsPath = join68(extractDir, ".claude", DEFAULT_FOLDERS.docs);
41041
+ if (await import_fs_extra32.pathExists(claudeDocsPath)) {
40880
41042
  dirsToRename.push({
40881
41043
  from: claudeDocsPath,
40882
- to: join66(extractDir, ".claude", folders.docs)
41044
+ to: join68(extractDir, ".claude", folders.docs)
40883
41045
  });
40884
41046
  }
40885
41047
  }
40886
41048
  if (folders.plans !== DEFAULT_FOLDERS.plans) {
40887
- const plansPath = join66(extractDir, DEFAULT_FOLDERS.plans);
40888
- if (await import_fs_extra31.pathExists(plansPath)) {
41049
+ const plansPath = join68(extractDir, DEFAULT_FOLDERS.plans);
41050
+ if (await import_fs_extra32.pathExists(plansPath)) {
40889
41051
  dirsToRename.push({
40890
41052
  from: plansPath,
40891
- to: join66(extractDir, folders.plans)
41053
+ to: join68(extractDir, folders.plans)
40892
41054
  });
40893
41055
  }
40894
- const claudePlansPath = join66(extractDir, ".claude", DEFAULT_FOLDERS.plans);
40895
- if (await import_fs_extra31.pathExists(claudePlansPath)) {
41056
+ const claudePlansPath = join68(extractDir, ".claude", DEFAULT_FOLDERS.plans);
41057
+ if (await import_fs_extra32.pathExists(claudePlansPath)) {
40896
41058
  dirsToRename.push({
40897
41059
  from: claudePlansPath,
40898
- to: join66(extractDir, ".claude", folders.plans)
41060
+ to: join68(extractDir, ".claude", folders.plans)
40899
41061
  });
40900
41062
  }
40901
41063
  }
@@ -40907,8 +41069,8 @@ async function moveAcrossDevices(src, dest) {
40907
41069
  } catch (e2) {
40908
41070
  if (e2.code === "EXDEV") {
40909
41071
  logger.debug(`Cross-device move detected, using copy+delete: ${src} -> ${dest}`);
40910
- await import_fs_extra31.copy(src, dest, { overwrite: true });
40911
- await rm6(src, { recursive: true, force: true });
41072
+ await import_fs_extra32.copy(src, dest, { overwrite: true });
41073
+ await rm7(src, { recursive: true, force: true });
40912
41074
  } else {
40913
41075
  throw e2;
40914
41076
  }
@@ -40935,8 +41097,8 @@ async function renameFolders(dirsToRename, extractDir, options) {
40935
41097
  // src/services/transformers/folder-transform/path-replacer.ts
40936
41098
  init_logger();
40937
41099
  init_types2();
40938
- import { readFile as readFile22, readdir as readdir21, writeFile as writeFile19 } from "node:fs/promises";
40939
- import { join as join67, relative as relative13 } from "node:path";
41100
+ import { readFile as readFile23, readdir as readdir23, writeFile as writeFile20 } from "node:fs/promises";
41101
+ import { join as join69, relative as relative13 } from "node:path";
40940
41102
  var TRANSFORMABLE_FILE_PATTERNS = [
40941
41103
  ".md",
40942
41104
  ".txt",
@@ -40987,9 +41149,9 @@ function compileReplacements(replacements) {
40987
41149
  async function transformFileContents(dir, compiledReplacements, options) {
40988
41150
  let filesChanged = 0;
40989
41151
  let replacementsCount = 0;
40990
- const entries = await readdir21(dir, { withFileTypes: true });
41152
+ const entries = await readdir23(dir, { withFileTypes: true });
40991
41153
  for (const entry of entries) {
40992
- const fullPath = join67(dir, entry.name);
41154
+ const fullPath = join69(dir, entry.name);
40993
41155
  if (entry.isDirectory()) {
40994
41156
  if (entry.name === "node_modules" || entry.name === ".git") {
40995
41157
  continue;
@@ -41002,7 +41164,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
41002
41164
  if (!shouldTransform)
41003
41165
  continue;
41004
41166
  try {
41005
- const content = await readFile22(fullPath, "utf-8");
41167
+ const content = await readFile23(fullPath, "utf-8");
41006
41168
  let newContent = content;
41007
41169
  let changeCount = 0;
41008
41170
  for (const { regex: regex2, replacement } of compiledReplacements) {
@@ -41018,7 +41180,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
41018
41180
  if (options.dryRun) {
41019
41181
  logger.debug(`[dry-run] Would update ${relative13(dir, fullPath)}: ${changeCount} replacement(s)`);
41020
41182
  } else {
41021
- await writeFile19(fullPath, newContent, "utf-8");
41183
+ await writeFile20(fullPath, newContent, "utf-8");
41022
41184
  logger.debug(`Updated ${relative13(dir, fullPath)}: ${changeCount} replacement(s)`);
41023
41185
  }
41024
41186
  filesChanged++;
@@ -41124,15 +41286,15 @@ async function transformFolderPaths(extractDir, folders, options = {}) {
41124
41286
 
41125
41287
  // src/services/transformers/global-path-transformer.ts
41126
41288
  init_logger();
41127
- import { readFile as readFile23, readdir as readdir22, writeFile as writeFile20 } from "node:fs/promises";
41128
- import { platform as platform11 } from "node:os";
41129
- import { extname as extname2, join as join68 } from "node:path";
41130
- var IS_WINDOWS3 = platform11() === "win32";
41131
- var HOME_PREFIX = IS_WINDOWS3 ? "%USERPROFILE%" : "$HOME";
41289
+ import { readFile as readFile24, readdir as readdir24, writeFile as writeFile21 } from "node:fs/promises";
41290
+ import { platform as platform12 } from "node:os";
41291
+ import { extname as extname3, join as join70 } from "node:path";
41292
+ var IS_WINDOWS4 = platform12() === "win32";
41293
+ var HOME_PREFIX = IS_WINDOWS4 ? "%USERPROFILE%" : "$HOME";
41132
41294
  function getHomeDirPrefix() {
41133
41295
  return HOME_PREFIX;
41134
41296
  }
41135
- var TRANSFORMABLE_EXTENSIONS2 = new Set([
41297
+ var TRANSFORMABLE_EXTENSIONS3 = new Set([
41136
41298
  ".md",
41137
41299
  ".js",
41138
41300
  ".ts",
@@ -41149,7 +41311,7 @@ function transformContent(content) {
41149
41311
  let transformed = content;
41150
41312
  const homePrefix = getHomeDirPrefix();
41151
41313
  const claudePath = `${homePrefix}/.claude/`;
41152
- if (IS_WINDOWS3) {
41314
+ if (IS_WINDOWS4) {
41153
41315
  transformed = transformed.replace(/\$HOME\/\.claude\//g, () => {
41154
41316
  changes++;
41155
41317
  return claudePath;
@@ -41179,7 +41341,7 @@ function transformContent(content) {
41179
41341
  changes++;
41180
41342
  return claudePath;
41181
41343
  });
41182
- if (IS_WINDOWS3) {
41344
+ if (IS_WINDOWS4) {
41183
41345
  transformed = transformed.replace(/%CLAUDE_PROJECT_DIR%\/\.claude\//g, () => {
41184
41346
  changes++;
41185
41347
  return claudePath;
@@ -41223,10 +41385,10 @@ function transformContent(content) {
41223
41385
  });
41224
41386
  return { transformed, changes };
41225
41387
  }
41226
- function shouldTransformFile2(filename) {
41227
- const ext2 = extname2(filename).toLowerCase();
41388
+ function shouldTransformFile3(filename) {
41389
+ const ext2 = extname3(filename).toLowerCase();
41228
41390
  const basename3 = filename.split("/").pop() || filename;
41229
- return TRANSFORMABLE_EXTENSIONS2.has(ext2) || ALWAYS_TRANSFORM_FILES.has(basename3);
41391
+ return TRANSFORMABLE_EXTENSIONS3.has(ext2) || ALWAYS_TRANSFORM_FILES.has(basename3);
41230
41392
  }
41231
41393
  async function transformPathsForGlobalInstall(directory, options = {}) {
41232
41394
  let filesTransformed = 0;
@@ -41234,20 +41396,20 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
41234
41396
  let filesSkipped = 0;
41235
41397
  const skippedFiles = [];
41236
41398
  async function processDirectory2(dir) {
41237
- const entries = await readdir22(dir, { withFileTypes: true });
41399
+ const entries = await readdir24(dir, { withFileTypes: true });
41238
41400
  for (const entry of entries) {
41239
- const fullPath = join68(dir, entry.name);
41401
+ const fullPath = join70(dir, entry.name);
41240
41402
  if (entry.isDirectory()) {
41241
41403
  if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
41242
41404
  continue;
41243
41405
  }
41244
41406
  await processDirectory2(fullPath);
41245
- } else if (entry.isFile() && shouldTransformFile2(entry.name)) {
41407
+ } else if (entry.isFile() && shouldTransformFile3(entry.name)) {
41246
41408
  try {
41247
- const content = await readFile23(fullPath, "utf-8");
41409
+ const content = await readFile24(fullPath, "utf-8");
41248
41410
  const { transformed, changes } = transformContent(content);
41249
41411
  if (changes > 0) {
41250
- await writeFile20(fullPath, transformed, "utf-8");
41412
+ await writeFile21(fullPath, transformed, "utf-8");
41251
41413
  filesTransformed++;
41252
41414
  totalChanges += changes;
41253
41415
  if (options.verbose) {
@@ -41312,7 +41474,7 @@ async function handleTransforms(ctx) {
41312
41474
  logger.debug(ctx.options.global ? "Saved folder configuration to ~/.claude/.ck.json" : "Saved folder configuration to .claude/.ck.json");
41313
41475
  }
41314
41476
  }
41315
- const claudeDir = ctx.options.global ? ctx.resolvedDir : join69(ctx.resolvedDir, ".claude");
41477
+ const claudeDir = ctx.options.global ? ctx.resolvedDir : join71(ctx.resolvedDir, ".claude");
41316
41478
  return {
41317
41479
  ...ctx,
41318
41480
  foldersConfig,
@@ -41350,6 +41512,9 @@ Installing additional kit: ${kit.name}`);
41350
41512
  extractDir: undefined
41351
41513
  };
41352
41514
  ctx = await handleDownload(ctx);
41515
+ if (ctx.cancelled)
41516
+ return ctx;
41517
+ ctx = await handleOpenCode(ctx);
41353
41518
  if (ctx.cancelled)
41354
41519
  return ctx;
41355
41520
  ctx = await handleTransforms(ctx);
@@ -41416,6 +41581,11 @@ async function executeInit(options, prompts) {
41416
41581
  ctx = await handleDownload(ctx);
41417
41582
  if (ctx.cancelled)
41418
41583
  return;
41584
+ if (!isSyncMode) {
41585
+ ctx = await handleOpenCode(ctx);
41586
+ if (ctx.cancelled)
41587
+ return;
41588
+ }
41419
41589
  if (!isSyncMode) {
41420
41590
  ctx = await handleTransforms(ctx);
41421
41591
  if (ctx.cancelled)
@@ -41497,7 +41667,7 @@ var import_picocolors20 = __toESM(require_picocolors(), 1);
41497
41667
  import { resolve as resolve9 } from "node:path";
41498
41668
  init_logger();
41499
41669
  init_types2();
41500
- var import_fs_extra32 = __toESM(require_lib(), 1);
41670
+ var import_fs_extra33 = __toESM(require_lib(), 1);
41501
41671
  async function directorySetup(validOptions, prompts) {
41502
41672
  const isNonInteractive2 = !process.stdin.isTTY || process.env.CI === "true" || process.env.NON_INTERACTIVE === "true";
41503
41673
  const config = await ConfigManager.get();
@@ -41596,8 +41766,8 @@ async function directorySetup(validOptions, prompts) {
41596
41766
  return null;
41597
41767
  }
41598
41768
  }
41599
- if (await import_fs_extra32.pathExists(resolvedDir)) {
41600
- const files = await import_fs_extra32.readdir(resolvedDir);
41769
+ if (await import_fs_extra33.pathExists(resolvedDir)) {
41770
+ const files = await import_fs_extra33.readdir(resolvedDir);
41601
41771
  const isEmpty = files.length === 0;
41602
41772
  if (!isEmpty) {
41603
41773
  if (isNonInteractive2) {
@@ -41633,7 +41803,7 @@ async function handleDirectorySetup(ctx) {
41633
41803
  };
41634
41804
  }
41635
41805
  // src/commands/new/phases/project-creation.ts
41636
- import { join as join70 } from "node:path";
41806
+ import { join as join72 } from "node:path";
41637
41807
  init_logger();
41638
41808
  init_output_manager();
41639
41809
  init_types2();
@@ -41743,7 +41913,7 @@ async function projectCreation(kit, resolvedDir, validOptions, isNonInteractive2
41743
41913
  output.section("Installing");
41744
41914
  logger.verbose("Installation target", { directory: resolvedDir });
41745
41915
  const merger = new FileMerger;
41746
- const claudeDir = join70(resolvedDir, ".claude");
41916
+ const claudeDir = join72(resolvedDir, ".claude");
41747
41917
  merger.setMultiKitContext(claudeDir, kit);
41748
41918
  if (validOptions.exclude && validOptions.exclude.length > 0) {
41749
41919
  merger.addIgnorePatterns(validOptions.exclude);
@@ -41880,7 +42050,7 @@ init_types2();
41880
42050
  var import_picocolors22 = __toESM(require_picocolors(), 1);
41881
42051
 
41882
42052
  // src/commands/uninstall/installation-detector.ts
41883
- var import_fs_extra33 = __toESM(require_lib(), 1);
42053
+ var import_fs_extra34 = __toESM(require_lib(), 1);
41884
42054
  async function detectInstallations() {
41885
42055
  const installations = [];
41886
42056
  const setup = await getClaudeKitSetup(process.cwd());
@@ -41889,14 +42059,14 @@ async function detectInstallations() {
41889
42059
  installations.push({
41890
42060
  type: "local",
41891
42061
  path: setup.project.path,
41892
- exists: await import_fs_extra33.pathExists(setup.project.path)
42062
+ exists: await import_fs_extra34.pathExists(setup.project.path)
41893
42063
  });
41894
42064
  }
41895
42065
  if (setup.global.path && setup.global.metadata) {
41896
42066
  installations.push({
41897
42067
  type: "global",
41898
42068
  path: setup.global.path,
41899
- exists: await import_fs_extra33.pathExists(setup.global.path)
42069
+ exists: await import_fs_extra34.pathExists(setup.global.path)
41900
42070
  });
41901
42071
  }
41902
42072
  return installations.filter((i) => i.exists);
@@ -41904,13 +42074,13 @@ async function detectInstallations() {
41904
42074
 
41905
42075
  // src/commands/uninstall/removal-handler.ts
41906
42076
  import { readdirSync as readdirSync2, rmSync as rmSync2 } from "node:fs";
41907
- import { join as join72 } from "node:path";
42077
+ import { join as join74 } from "node:path";
41908
42078
  init_logger();
41909
- var import_fs_extra34 = __toESM(require_lib(), 1);
42079
+ var import_fs_extra35 = __toESM(require_lib(), 1);
41910
42080
 
41911
42081
  // src/commands/uninstall/analysis-handler.ts
41912
42082
  import { readdirSync, rmSync } from "node:fs";
41913
- import { dirname as dirname10, join as join71 } from "node:path";
42083
+ import { dirname as dirname10, join as join73 } from "node:path";
41914
42084
  init_logger();
41915
42085
  var import_picocolors21 = __toESM(require_picocolors(), 1);
41916
42086
  function classifyFileByOwnership(ownership, forceOverwrite, deleteReason) {
@@ -41957,7 +42127,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
41957
42127
  if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
41958
42128
  const kitFiles = metadata.kits[kit].files || [];
41959
42129
  for (const trackedFile of kitFiles) {
41960
- const filePath = join71(installation.path, trackedFile.path);
42130
+ const filePath = join73(installation.path, trackedFile.path);
41961
42131
  if (uninstallManifest.filesToPreserve.includes(trackedFile.path)) {
41962
42132
  result.toPreserve.push({ path: trackedFile.path, reason: "shared with other kit" });
41963
42133
  continue;
@@ -41987,7 +42157,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
41987
42157
  return result;
41988
42158
  }
41989
42159
  for (const trackedFile of allTrackedFiles) {
41990
- const filePath = join71(installation.path, trackedFile.path);
42160
+ const filePath = join73(installation.path, trackedFile.path);
41991
42161
  const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
41992
42162
  if (!ownershipResult.exists)
41993
42163
  continue;
@@ -42047,9 +42217,9 @@ async function removeInstallations(installations, options) {
42047
42217
  let removedCount = 0;
42048
42218
  let cleanedDirs = 0;
42049
42219
  for (const item of analysis.toDelete) {
42050
- const filePath = join72(installation.path, item.path);
42051
- if (await import_fs_extra34.pathExists(filePath)) {
42052
- await import_fs_extra34.remove(filePath);
42220
+ const filePath = join74(installation.path, item.path);
42221
+ if (await import_fs_extra35.pathExists(filePath)) {
42222
+ await import_fs_extra35.remove(filePath);
42053
42223
  removedCount++;
42054
42224
  logger.debug(`Removed: ${item.path}`);
42055
42225
  cleanedDirs += await cleanupEmptyDirectories(filePath, installation.path);
@@ -42218,6 +42388,7 @@ ${import_picocolors22.default.yellow("User modifications will be permanently del
42218
42388
  }
42219
42389
  // src/commands/update-cli.ts
42220
42390
  import { exec as exec7 } from "node:child_process";
42391
+ import { join as join76 } from "node:path";
42221
42392
  import { promisify as promisify7 } from "node:util";
42222
42393
 
42223
42394
  // src/domains/github/npm-registry.ts
@@ -42379,14 +42550,14 @@ init_types2();
42379
42550
  // src/domains/versioning/version-cache.ts
42380
42551
  init_logger();
42381
42552
  import { existsSync as existsSync19 } from "node:fs";
42382
- import { mkdir as mkdir22, readFile as readFile24, writeFile as writeFile21 } from "node:fs/promises";
42383
- import { join as join73 } from "node:path";
42553
+ import { mkdir as mkdir22, readFile as readFile25, writeFile as writeFile22 } from "node:fs/promises";
42554
+ import { join as join75 } from "node:path";
42384
42555
  class VersionCacheManager {
42385
42556
  static CACHE_FILENAME = "version-check.json";
42386
42557
  static CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
42387
42558
  static getCacheFile() {
42388
42559
  const cacheDir = PathResolver.getCacheDir(false);
42389
- return join73(cacheDir, VersionCacheManager.CACHE_FILENAME);
42560
+ return join75(cacheDir, VersionCacheManager.CACHE_FILENAME);
42390
42561
  }
42391
42562
  static async load() {
42392
42563
  const cacheFile = VersionCacheManager.getCacheFile();
@@ -42395,7 +42566,7 @@ class VersionCacheManager {
42395
42566
  logger.debug("Version check cache not found");
42396
42567
  return null;
42397
42568
  }
42398
- const content = await readFile24(cacheFile, "utf-8");
42569
+ const content = await readFile25(cacheFile, "utf-8");
42399
42570
  const cache2 = JSON.parse(content);
42400
42571
  if (!cache2.lastCheck || !cache2.currentVersion || !cache2.latestVersion) {
42401
42572
  logger.debug("Invalid cache structure, ignoring");
@@ -42415,7 +42586,7 @@ class VersionCacheManager {
42415
42586
  if (!existsSync19(cacheDir)) {
42416
42587
  await mkdir22(cacheDir, { recursive: true, mode: 448 });
42417
42588
  }
42418
- await writeFile21(cacheFile, JSON.stringify(cache2, null, 2), "utf-8");
42589
+ await writeFile22(cacheFile, JSON.stringify(cache2, null, 2), "utf-8");
42419
42590
  logger.debug(`Version check cache saved to ${cacheFile}`);
42420
42591
  } catch (error) {
42421
42592
  logger.debug(`Failed to save version check cache: ${error}`);
@@ -42624,11 +42795,12 @@ init_logger();
42624
42795
  init_types2();
42625
42796
  init_types2();
42626
42797
  var import_compare_versions5 = __toESM(require_umd(), 1);
42798
+ var import_fs_extra36 = __toESM(require_lib(), 1);
42627
42799
  var import_picocolors24 = __toESM(require_picocolors(), 1);
42628
42800
  // package.json
42629
42801
  var package_default = {
42630
42802
  name: "claudekit-cli",
42631
- version: "3.23.0",
42803
+ version: "3.24.0",
42632
42804
  description: "CLI tool for bootstrapping and updating ClaudeKit projects",
42633
42805
  type: "module",
42634
42806
  repository: {
@@ -42729,18 +42901,51 @@ class CliUpdateError extends ClaudeKitError {
42729
42901
  }
42730
42902
  var PACKAGE_NAME2 = "claudekit-cli";
42731
42903
  var KIT_UPDATE_REMINDER_HEADER = "Note: 'ck update' only updates the CLI tool itself.";
42904
+ function buildInitCommand(isGlobal, kit) {
42905
+ const parts = ["ck init"];
42906
+ if (isGlobal)
42907
+ parts.push("-g");
42908
+ if (kit)
42909
+ parts.push(`--kit ${kit}`);
42910
+ parts.push("--yes --install-skills");
42911
+ return parts.join(" ");
42912
+ }
42913
+ async function readMetadataFile(claudeDir) {
42914
+ const metadataPath = join76(claudeDir, "metadata.json");
42915
+ try {
42916
+ if (!await import_fs_extra36.pathExists(metadataPath)) {
42917
+ return null;
42918
+ }
42919
+ const content = await import_fs_extra36.readFile(metadataPath, "utf-8");
42920
+ return JSON.parse(content);
42921
+ } catch {
42922
+ return null;
42923
+ }
42924
+ }
42732
42925
  async function displayKitUpdateReminder() {
42733
42926
  try {
42734
42927
  const setup = await getClaudeKitSetup();
42735
42928
  const hasLocal = !!setup.project.metadata;
42736
42929
  const hasGlobal = !!setup.global.metadata;
42737
- const localVersion = setup.project.metadata?.version;
42738
- const globalVersion = setup.global.metadata?.version;
42930
+ const localMetadata = hasLocal ? await readMetadataFile(setup.project.path) : null;
42931
+ const globalMetadata = hasGlobal ? await readMetadataFile(setup.global.path) : null;
42932
+ const localKits = localMetadata ? getInstalledKits(localMetadata) : [];
42933
+ const globalKits = globalMetadata ? getInstalledKits(globalMetadata) : [];
42739
42934
  const versionsToCheck = new Set;
42740
- if (localVersion)
42741
- versionsToCheck.add(localVersion);
42742
- if (globalVersion)
42743
- versionsToCheck.add(globalVersion);
42935
+ if (localMetadata) {
42936
+ for (const kit of localKits) {
42937
+ const version = localMetadata.kits?.[kit]?.version || localMetadata.version;
42938
+ if (version)
42939
+ versionsToCheck.add(version);
42940
+ }
42941
+ }
42942
+ if (globalMetadata) {
42943
+ for (const kit of globalKits) {
42944
+ const version = globalMetadata.kits?.[kit]?.version || globalMetadata.version;
42945
+ if (version)
42946
+ versionsToCheck.add(version);
42947
+ }
42948
+ }
42744
42949
  const versionCheckResults = new Map;
42745
42950
  if (versionsToCheck.size > 0) {
42746
42951
  const checkPromises = [...versionsToCheck].map(async (version) => {
@@ -42752,33 +42957,52 @@ async function displayKitUpdateReminder() {
42752
42957
  versionCheckResults.set(version, result);
42753
42958
  }
42754
42959
  }
42755
- const cmdLocal = "ck init";
42756
- const cmdGlobal = "ck init -g";
42757
- const maxCmdLen = Math.max(cmdLocal.length, cmdGlobal.length);
42960
+ const commands = [];
42961
+ if (localKits.length > 0) {
42962
+ for (const kit of localKits) {
42963
+ const cmd = buildInitCommand(false, kit);
42964
+ const version = localMetadata?.kits?.[kit]?.version || localMetadata?.version;
42965
+ commands.push({
42966
+ cmd,
42967
+ desc: `Update local project (${kit}${version ? `@${version}` : ""})`,
42968
+ version
42969
+ });
42970
+ }
42971
+ } else if (hasLocal) {
42972
+ commands.push({ cmd: "ck init", desc: "Update local project" });
42973
+ } else {
42974
+ commands.push({ cmd: "ck init", desc: "Initialize in current project" });
42975
+ }
42976
+ if (globalKits.length > 0) {
42977
+ for (const kit of globalKits) {
42978
+ const cmd = buildInitCommand(true, kit);
42979
+ const version = globalMetadata?.kits?.[kit]?.version || globalMetadata?.version;
42980
+ commands.push({
42981
+ cmd,
42982
+ desc: `Update global ~/.claude (${kit}${version ? `@${version}` : ""})`,
42983
+ version
42984
+ });
42985
+ }
42986
+ } else if (hasGlobal) {
42987
+ commands.push({ cmd: "ck init -g", desc: "Update global ~/.claude" });
42988
+ } else {
42989
+ commands.push({ cmd: "ck init -g", desc: "Initialize global ~/.claude" });
42990
+ }
42991
+ const maxCmdLen = Math.max(...commands.map((c2) => c2.cmd.length));
42758
42992
  const pad = (cmd) => cmd.padEnd(maxCmdLen);
42759
42993
  const lines = [];
42760
42994
  lines.push(import_picocolors24.default.yellow(KIT_UPDATE_REMINDER_HEADER));
42761
42995
  lines.push("");
42762
42996
  lines.push("To update your ClaudeKit content (skills, commands, workflows):");
42763
- if (hasLocal && localVersion) {
42764
- lines.push(` ${import_picocolors24.default.cyan(pad(cmdLocal))} Update local project (${localVersion})`);
42765
- const localCheck = versionCheckResults.get(localVersion);
42766
- if (localCheck?.updateAvailable) {
42767
- const indent = " ".repeat(maxCmdLen + 4);
42768
- lines.push(`${indent}${import_picocolors24.default.green(`→ ${localCheck.latestVersion} available!`)}`);
42769
- }
42770
- } else {
42771
- lines.push(` ${import_picocolors24.default.cyan(pad(cmdLocal))} Initialize in current project`);
42772
- }
42773
- if (hasGlobal && globalVersion) {
42774
- lines.push(` ${import_picocolors24.default.cyan(pad(cmdGlobal))} Update global ~/.claude (${globalVersion})`);
42775
- const globalCheck = versionCheckResults.get(globalVersion);
42776
- if (globalCheck?.updateAvailable) {
42777
- const indent = " ".repeat(maxCmdLen + 4);
42778
- lines.push(`${indent}${import_picocolors24.default.green(`→ ${globalCheck.latestVersion} available!`)}`);
42997
+ for (const { cmd, desc: desc2, version } of commands) {
42998
+ lines.push(` ${import_picocolors24.default.cyan(pad(cmd))} ${desc2}`);
42999
+ if (version) {
43000
+ const versionCheck = versionCheckResults.get(version);
43001
+ if (versionCheck?.updateAvailable) {
43002
+ const indent = " ".repeat(maxCmdLen + 4);
43003
+ lines.push(`${indent}${import_picocolors24.default.green(`→ ${versionCheck.latestVersion} available!`)}`);
43004
+ }
42779
43005
  }
42780
- } else {
42781
- lines.push(` ${import_picocolors24.default.cyan(pad(cmdGlobal))} Initialize global ~/.claude`);
42782
43006
  }
42783
43007
  logger.info("");
42784
43008
  log.info(lines.join(`
@@ -43053,7 +43277,7 @@ function registerCommands(cli) {
43053
43277
 
43054
43278
  // src/cli/version-display.ts
43055
43279
  import { existsSync as existsSync20, readFileSync as readFileSync6 } from "node:fs";
43056
- import { join as join74 } from "node:path";
43280
+ import { join as join77 } from "node:path";
43057
43281
  init_logger();
43058
43282
  init_types2();
43059
43283
  var packageVersion = package_default.version;
@@ -43087,9 +43311,9 @@ async function displayVersion() {
43087
43311
  let localKitVersion = null;
43088
43312
  let isGlobalOnlyKit = false;
43089
43313
  const globalKitDir = PathResolver.getGlobalKitDir();
43090
- const globalMetadataPath = join74(globalKitDir, "metadata.json");
43314
+ const globalMetadataPath = join77(globalKitDir, "metadata.json");
43091
43315
  const prefix = PathResolver.getPathPrefix(false);
43092
- const localMetadataPath = prefix ? join74(process.cwd(), prefix, "metadata.json") : join74(process.cwd(), "metadata.json");
43316
+ const localMetadataPath = prefix ? join77(process.cwd(), prefix, "metadata.json") : join77(process.cwd(), "metadata.json");
43093
43317
  const isLocalSameAsGlobal = localMetadataPath === globalMetadataPath;
43094
43318
  if (!isLocalSameAsGlobal && existsSync20(localMetadataPath)) {
43095
43319
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudekit-cli",
3
- "version": "3.23.0",
3
+ "version": "3.24.0",
4
4
  "description": "CLI tool for bootstrapping and updating ClaudeKit projects",
5
5
  "type": "module",
6
6
  "repository": {