claudekit-cli 3.35.0-dev.23 → 3.35.0-dev.24

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 +151 -96
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -42500,14 +42500,11 @@ function normalizeCommand(cmd) {
42500
42500
  if (!cmd)
42501
42501
  return "";
42502
42502
  let normalized = cmd;
42503
- normalized = normalized.replace(/"\$HOME"/g, "$HOME");
42504
- normalized = normalized.replace(/"\$CLAUDE_PROJECT_DIR"/g, "$HOME");
42505
- normalized = normalized.replace(/"\$\{HOME\}"/g, "$HOME");
42503
+ normalized = normalized.replace(/"/g, "");
42504
+ normalized = normalized.replace(/~\//g, "$HOME/");
42506
42505
  normalized = normalized.replace(/\$CLAUDE_PROJECT_DIR/g, "$HOME");
42507
42506
  normalized = normalized.replace(/\$\{HOME\}/g, "$HOME");
42508
- normalized = normalized.replace(/"%USERPROFILE%"/g, "$HOME");
42509
42507
  normalized = normalized.replace(/%USERPROFILE%/g, "$HOME");
42510
- normalized = normalized.replace(/"%CLAUDE_PROJECT_DIR%"/g, "$HOME");
42511
42508
  normalized = normalized.replace(/%CLAUDE_PROJECT_DIR%/g, "$HOME");
42512
42509
  normalized = normalized.replace(/\\/g, "/");
42513
42510
  normalized = normalized.replace(/\s+/g, " ").trim();
@@ -50915,11 +50912,17 @@ function registerMigrationRoutes(app) {
50915
50912
  const registry = await readPortableRegistry();
50916
50913
  const targetStates = new Map;
50917
50914
  for (const entry of registry.installations) {
50915
+ if (entry.type === "skill")
50916
+ continue;
50918
50917
  const exists = existsSync20(entry.path);
50919
50918
  const state = { path: entry.path, exists };
50920
50919
  if (exists) {
50921
- const content = await readFile15(entry.path, "utf-8");
50922
- state.currentChecksum = computeContentChecksum(content);
50920
+ try {
50921
+ const content = await readFile15(entry.path, "utf-8");
50922
+ state.currentChecksum = computeContentChecksum(content);
50923
+ } catch (error) {
50924
+ warnReadFailure("registry-target", entry.path, error);
50925
+ }
50923
50926
  }
50924
50927
  targetStates.set(entry.path, state);
50925
50928
  }
@@ -53869,7 +53872,7 @@ var package_default;
53869
53872
  var init_package = __esm(() => {
53870
53873
  package_default = {
53871
53874
  name: "claudekit-cli",
53872
- version: "3.35.0-dev.23",
53875
+ version: "3.35.0-dev.24",
53873
53876
  description: "CLI tool for bootstrapping and updating ClaudeKit projects",
53874
53877
  type: "module",
53875
53878
  repository: {
@@ -64243,7 +64246,7 @@ var init_init_command_help = __esm(() => {
64243
64246
  },
64244
64247
  {
64245
64248
  flags: "--fresh",
64246
- description: "Remove ClaudeKit directories (commands/, agents/, skills/, rules/, hooks/) and reinstall"
64249
+ description: "Full reset: remove CK files, replace settings.json and CLAUDE.md, reinstall from scratch"
64247
64250
  }
64248
64251
  ]
64249
64252
  },
@@ -84784,7 +84787,6 @@ class InstalledSettingsTracker {
84784
84787
 
84785
84788
  // src/domains/installation/merger/settings-processor.ts
84786
84789
  init_settings_merger();
84787
- init_environment();
84788
84790
  init_logger();
84789
84791
  var import_fs_extra11 = __toESM(require_lib3(), 1);
84790
84792
  var import_semver3 = __toESM(require_semver2(), 1);
@@ -84825,13 +84827,13 @@ class SettingsProcessor {
84825
84827
  const sourceContent = await import_fs_extra11.readFile(sourceFile, "utf-8");
84826
84828
  let transformedSource = sourceContent;
84827
84829
  if (this.isGlobal) {
84828
- const homeVar = isWindows() ? '"%USERPROFILE%"' : '"$HOME"';
84830
+ const homeVar = '"$HOME"';
84829
84831
  transformedSource = this.transformClaudePaths(sourceContent, homeVar);
84830
84832
  if (transformedSource !== sourceContent) {
84831
84833
  logger.debug(`Transformed .claude/ paths to ${homeVar}/.claude/ in settings.json for global installation`);
84832
84834
  }
84833
84835
  } else {
84834
- const projectDirVar = isWindows() ? '"%CLAUDE_PROJECT_DIR%"' : '"$CLAUDE_PROJECT_DIR"';
84836
+ const projectDirVar = '"$CLAUDE_PROJECT_DIR"';
84835
84837
  transformedSource = this.transformClaudePaths(sourceContent, projectDirVar);
84836
84838
  if (transformedSource !== sourceContent) {
84837
84839
  logger.debug(`Transformed .claude/ paths to ${projectDirVar}/.claude/ in settings.json for local installation`);
@@ -84841,20 +84843,26 @@ class SettingsProcessor {
84841
84843
  if (destExists && !this.forceOverwriteSettings) {
84842
84844
  await this.selectiveMergeSettings(transformedSource, destFile);
84843
84845
  } else {
84844
- const formattedContent = this.formatJsonContent(transformedSource);
84845
- await import_fs_extra11.writeFile(destFile, formattedContent, "utf-8");
84846
- let parsedSettings;
84847
84846
  try {
84848
- parsedSettings = JSON.parse(formattedContent);
84849
- if (this.forceOverwriteSettings && destExists) {
84850
- logger.debug("Force overwrite enabled, replaced settings.json completely");
84851
- if (this.tracker) {
84852
- await this.tracker.clearTracking();
84847
+ const parsedSettings = JSON.parse(transformedSource);
84848
+ this.fixHookCommandPaths(parsedSettings);
84849
+ await SettingsMerger.writeSettingsFile(destFile, parsedSettings);
84850
+ try {
84851
+ if (this.forceOverwriteSettings && destExists) {
84852
+ logger.debug("Force overwrite enabled, replaced settings.json completely");
84853
+ if (this.tracker) {
84854
+ await this.tracker.clearTracking();
84855
+ }
84853
84856
  }
84857
+ await this.trackInstalledSettings(parsedSettings);
84858
+ } catch {
84859
+ logger.debug("Settings tracking failed (non-fatal)");
84854
84860
  }
84855
- await this.trackInstalledSettings(parsedSettings);
84856
- } catch {}
84857
- await this.injectTeamHooksIfSupported(destFile, parsedSettings);
84861
+ } catch {
84862
+ const formattedContent = this.formatJsonContent(transformedSource);
84863
+ await import_fs_extra11.writeFile(destFile, formattedContent, "utf-8");
84864
+ }
84865
+ await this.injectTeamHooksIfSupported(destFile);
84858
84866
  }
84859
84867
  } catch (error) {
84860
84868
  logger.error(`Failed to process settings.json: ${error}`);
@@ -84914,6 +84922,10 @@ class SettingsProcessor {
84914
84922
  }
84915
84923
  await this.tracker.saveInstalledSettings(installedSettings);
84916
84924
  }
84925
+ const pathsFixed = this.fixHookCommandPaths(mergeResult.merged);
84926
+ if (pathsFixed) {
84927
+ logger.info("Fixed hook command paths to canonical quoted format");
84928
+ }
84917
84929
  await SettingsMerger.writeSettingsFile(destFile, mergeResult.merged);
84918
84930
  logger.success("Merged settings.json (user customizations preserved)");
84919
84931
  await this.injectTeamHooksIfSupported(destFile, mergeResult.merged);
@@ -84999,12 +85011,14 @@ class SettingsProcessor {
84999
85011
  const content = await import_fs_extra11.readFile(destFile, "utf-8");
85000
85012
  if (!content.trim())
85001
85013
  return null;
85002
- const homeVar = isWindows() ? "%USERPROFILE%" : "$HOME";
85014
+ const homeVar = "$HOME";
85003
85015
  let normalized = content;
85004
85016
  normalized = normalized.replace(/"\$CLAUDE_PROJECT_DIR"/g, `"${homeVar}"`);
85005
85017
  normalized = normalized.replace(/\$CLAUDE_PROJECT_DIR/g, homeVar);
85006
85018
  normalized = normalized.replace(/"%CLAUDE_PROJECT_DIR%"/g, `"${homeVar}"`);
85007
85019
  normalized = normalized.replace(/%CLAUDE_PROJECT_DIR%/g, homeVar);
85020
+ normalized = normalized.replace(/"%USERPROFILE%"/g, `"${homeVar}"`);
85021
+ normalized = normalized.replace(/%USERPROFILE%/g, homeVar);
85008
85022
  if (normalized !== content) {
85009
85023
  logger.debug("Normalized $CLAUDE_PROJECT_DIR paths to $HOME in existing global settings");
85010
85024
  }
@@ -85019,15 +85033,85 @@ class SettingsProcessor {
85019
85033
  throw new Error("Settings file contains potentially unsafe path characters");
85020
85034
  }
85021
85035
  let transformed = content;
85022
- const jsonSafePrefix = prefix.includes('"') ? prefix.replace(/"/g, "\\\"") : prefix;
85023
85036
  const rawPrefix = prefix.replace(/"/g, "");
85024
- transformed = transformed.replace(/(node\s+)(?:\.\/)?\.claude\//g, `$1${jsonSafePrefix}/.claude/`);
85037
+ transformed = transformed.replace(/(node\s+)(?:\.\/)?(\.claude\/[^\s"\\]+)/g, `$1\\"${rawPrefix}/$2\\"`);
85025
85038
  if (rawPrefix.includes("HOME") || rawPrefix.includes("USERPROFILE")) {
85026
85039
  transformed = transformed.replace(/\$CLAUDE_PROJECT_DIR/g, rawPrefix);
85027
85040
  transformed = transformed.replace(/%CLAUDE_PROJECT_DIR%/g, rawPrefix);
85028
85041
  }
85029
85042
  return transformed;
85030
85043
  }
85044
+ fixHookCommandPaths(settings) {
85045
+ let fixed = false;
85046
+ if (settings.hooks) {
85047
+ for (const entries of Object.values(settings.hooks)) {
85048
+ for (const entry of entries) {
85049
+ if ("command" in entry && entry.command) {
85050
+ const result = this.fixSingleCommandPath(entry.command);
85051
+ if (result !== entry.command) {
85052
+ entry.command = result;
85053
+ fixed = true;
85054
+ }
85055
+ }
85056
+ if ("hooks" in entry && entry.hooks) {
85057
+ for (const hook of entry.hooks) {
85058
+ if (hook.command) {
85059
+ const result = this.fixSingleCommandPath(hook.command);
85060
+ if (result !== hook.command) {
85061
+ hook.command = result;
85062
+ fixed = true;
85063
+ }
85064
+ }
85065
+ }
85066
+ }
85067
+ }
85068
+ }
85069
+ }
85070
+ const statusLine = settings.statusLine;
85071
+ if (statusLine?.command) {
85072
+ const result = this.fixSingleCommandPath(statusLine.command);
85073
+ if (result !== statusLine.command) {
85074
+ statusLine.command = result;
85075
+ fixed = true;
85076
+ }
85077
+ }
85078
+ return fixed;
85079
+ }
85080
+ fixSingleCommandPath(cmd) {
85081
+ if (!cmd.includes(".claude/") && !cmd.includes(".claude\\"))
85082
+ return cmd;
85083
+ const varOnlyQuotingRe = /^(node\s+)"(\$HOME|\$CLAUDE_PROJECT_DIR|%USERPROFILE%|%CLAUDE_PROJECT_DIR%)"[/\\](.+)$/;
85084
+ const varOnlyMatch = cmd.match(varOnlyQuotingRe);
85085
+ if (varOnlyMatch) {
85086
+ const [, nodePrefix, capturedVar, restPath] = varOnlyMatch;
85087
+ const canonicalVar = this.canonicalizePathVar(capturedVar);
85088
+ return `${nodePrefix}"${canonicalVar}/${restPath.replace(/\\/g, "/")}"`;
85089
+ }
85090
+ const tildeRe = /^(node\s+)~[/\\](.+)$/;
85091
+ const tildeMatch = cmd.match(tildeRe);
85092
+ if (tildeMatch) {
85093
+ const [, nodePrefix, restPath] = tildeMatch;
85094
+ return `${nodePrefix}"$HOME/${restPath.replace(/\\/g, "/")}"`;
85095
+ }
85096
+ const unquotedRe = /^(node\s+)(\$HOME|\$CLAUDE_PROJECT_DIR|%USERPROFILE%|%CLAUDE_PROJECT_DIR%)[/\\](.+)$/;
85097
+ const unquotedMatch = cmd.match(unquotedRe);
85098
+ if (unquotedMatch) {
85099
+ const [, nodePrefix, capturedVar, restPath] = unquotedMatch;
85100
+ const canonicalVar = this.canonicalizePathVar(capturedVar);
85101
+ return `${nodePrefix}"${canonicalVar}/${restPath.replace(/\\/g, "/")}"`;
85102
+ }
85103
+ return cmd;
85104
+ }
85105
+ canonicalizePathVar(capturedVar) {
85106
+ switch (capturedVar) {
85107
+ case "%USERPROFILE%":
85108
+ return "$HOME";
85109
+ case "%CLAUDE_PROJECT_DIR%":
85110
+ return "$CLAUDE_PROJECT_DIR";
85111
+ default:
85112
+ return capturedVar;
85113
+ }
85114
+ }
85031
85115
  detectClaudeCodeVersion() {
85032
85116
  if (this.cachedVersion !== undefined)
85033
85117
  return this.cachedVersion;
@@ -85066,7 +85150,7 @@ class SettingsProcessor {
85066
85150
  logger.warning("Failed to read settings file for team hooks injection");
85067
85151
  return;
85068
85152
  }
85069
- const prefix = this.isGlobal ? isWindows() ? "%USERPROFILE%" : "$HOME" : isWindows() ? "%CLAUDE_PROJECT_DIR%" : "$CLAUDE_PROJECT_DIR";
85153
+ const prefix = this.isGlobal ? "$HOME" : "$CLAUDE_PROJECT_DIR";
85070
85154
  if (!settings.hooks) {
85071
85155
  settings.hooks = {};
85072
85156
  }
@@ -85077,7 +85161,7 @@ class SettingsProcessor {
85077
85161
  { event: "TeammateIdle", handler: "teammate-idle-handler.cjs" }
85078
85162
  ];
85079
85163
  for (const { event, handler } of teamHooks) {
85080
- const hookCommand = `node ${prefix}/.claude/hooks/${handler}`;
85164
+ const hookCommand = `node "${prefix}/.claude/hooks/${handler}"`;
85081
85165
  const eventHooks = settings.hooks[event];
85082
85166
  if (eventHooks && eventHooks.length > 0)
85083
85167
  continue;
@@ -88056,6 +88140,10 @@ Please use only one download method.`);
88056
88140
  if (validOptions.useGit && validOptions.beta) {
88057
88141
  logger.warning("--beta flag is ignored when using --use-git (version already specified via --release)");
88058
88142
  }
88143
+ if (validOptions.fresh && !validOptions.forceOverwriteSettings) {
88144
+ validOptions.forceOverwriteSettings = true;
88145
+ logger.debug("--fresh: auto-enabling settings.json full replace");
88146
+ }
88059
88147
  if (validOptions.fresh && validOptions.sync) {
88060
88148
  throw new Error(`--fresh and --sync are mutually exclusive.
88061
88149
 
@@ -88086,7 +88174,16 @@ async function handlePostInstall(ctx) {
88086
88174
  return ctx;
88087
88175
  }
88088
88176
  if (ctx.options.global) {
88089
- await handleGlobalClaudeMd(ctx);
88177
+ const claudeMdSource = join100(ctx.extractDir, "CLAUDE.md");
88178
+ const claudeMdDest = join100(ctx.resolvedDir, "CLAUDE.md");
88179
+ if (await import_fs_extra30.pathExists(claudeMdSource)) {
88180
+ if (ctx.options.fresh || !await import_fs_extra30.pathExists(claudeMdDest)) {
88181
+ await import_fs_extra30.copy(claudeMdSource, claudeMdDest);
88182
+ logger.success(ctx.options.fresh ? "Replaced CLAUDE.md in global directory (fresh install)" : "Copied CLAUDE.md to global directory");
88183
+ } else {
88184
+ logger.debug("CLAUDE.md already exists in global directory (preserved)");
88185
+ }
88186
+ }
88090
88187
  }
88091
88188
  let installSkills = ctx.options.installSkills;
88092
88189
  if (!ctx.isNonInteractive && !installSkills) {
@@ -88146,49 +88243,6 @@ async function handlePostInstall(ctx) {
88146
88243
  installSkills
88147
88244
  };
88148
88245
  }
88149
- function normalizeLineEndings(content) {
88150
- return content.replace(/\r\n/g, `
88151
- `);
88152
- }
88153
- async function handleGlobalClaudeMd(ctx) {
88154
- if (!ctx.extractDir || !ctx.resolvedDir)
88155
- return;
88156
- const claudeMdSource = join100(ctx.extractDir, "CLAUDE.md");
88157
- const claudeMdDest = join100(ctx.resolvedDir, "CLAUDE.md");
88158
- if (!await import_fs_extra30.pathExists(claudeMdSource))
88159
- return;
88160
- const destExists = await import_fs_extra30.pathExists(claudeMdDest);
88161
- if (!destExists) {
88162
- await import_fs_extra30.copy(claudeMdSource, claudeMdDest);
88163
- logger.success("Copied CLAUDE.md to global directory");
88164
- return;
88165
- }
88166
- if (ctx.options.fresh || ctx.options.forceOverwrite) {
88167
- await import_fs_extra30.copy(claudeMdSource, claudeMdDest);
88168
- logger.success("Updated CLAUDE.md in global directory");
88169
- return;
88170
- }
88171
- const [srcContent, destContent] = await Promise.all([
88172
- import_fs_extra30.readFile(claudeMdSource, "utf-8"),
88173
- import_fs_extra30.readFile(claudeMdDest, "utf-8")
88174
- ]);
88175
- if (normalizeLineEndings(srcContent) === normalizeLineEndings(destContent)) {
88176
- logger.debug("CLAUDE.md already up to date");
88177
- return;
88178
- }
88179
- if (!ctx.isNonInteractive) {
88180
- const shouldOverwrite = await ctx.prompts.confirm(`CLAUDE.md has changed in the new version. Update it?
88181
- (Your customizations will be replaced)`);
88182
- if (!shouldOverwrite) {
88183
- logger.info("CLAUDE.md preserved (user chose to keep existing)");
88184
- return;
88185
- }
88186
- } else {
88187
- logger.warning("Updating CLAUDE.md (content differs from new version)");
88188
- }
88189
- await import_fs_extra30.copy(claudeMdSource, claudeMdDest);
88190
- logger.success("Updated CLAUDE.md (new version detected)");
88191
- }
88192
88246
  // src/commands/init/phases/selection-handler.ts
88193
88247
  init_config_manager();
88194
88248
  init_github_client();
@@ -88850,7 +88904,7 @@ async function handleSelection(ctx) {
88850
88904
  };
88851
88905
  }
88852
88906
  // src/commands/init/phases/sync-handler.ts
88853
- import { copyFile as copyFile7, mkdir as mkdir30, open as open4, readFile as readFile49, rename as rename5, stat as stat17, unlink as unlink11, writeFile as writeFile29 } from "node:fs/promises";
88907
+ import { copyFile as copyFile7, mkdir as mkdir30, open as open4, readFile as readFile48, rename as rename5, stat as stat17, unlink as unlink11, writeFile as writeFile29 } from "node:fs/promises";
88854
88908
  import { dirname as dirname22, join as join103, resolve as resolve21 } from "node:path";
88855
88909
  init_logger();
88856
88910
  init_path_resolver();
@@ -89018,7 +89072,7 @@ async function executeSyncMerge(ctx) {
89018
89072
  try {
89019
89073
  const sourceMetadataPath = join103(upstreamDir, "metadata.json");
89020
89074
  if (await import_fs_extra33.pathExists(sourceMetadataPath)) {
89021
- const content = await readFile49(sourceMetadataPath, "utf-8");
89075
+ const content = await readFile48(sourceMetadataPath, "utf-8");
89022
89076
  const sourceMetadata = JSON.parse(content);
89023
89077
  deletions = sourceMetadata.deletions || [];
89024
89078
  }
@@ -89316,7 +89370,7 @@ async function renameFolders(dirsToRename, extractDir, options2) {
89316
89370
  // src/services/transformers/folder-transform/path-replacer.ts
89317
89371
  init_logger();
89318
89372
  init_types3();
89319
- import { readFile as readFile50, readdir as readdir32, writeFile as writeFile30 } from "node:fs/promises";
89373
+ import { readFile as readFile49, readdir as readdir32, writeFile as writeFile30 } from "node:fs/promises";
89320
89374
  import { join as join105, relative as relative19 } from "node:path";
89321
89375
  var TRANSFORMABLE_FILE_PATTERNS = [
89322
89376
  ".md",
@@ -89383,7 +89437,7 @@ async function transformFileContents(dir, compiledReplacements, options2) {
89383
89437
  if (!shouldTransform)
89384
89438
  continue;
89385
89439
  try {
89386
- const content = await readFile50(fullPath, "utf-8");
89440
+ const content = await readFile49(fullPath, "utf-8");
89387
89441
  let newContent = content;
89388
89442
  let changeCount = 0;
89389
89443
  for (const { regex: regex2, replacement } of compiledReplacements) {
@@ -89505,7 +89559,7 @@ async function transformFolderPaths(extractDir, folders, options2 = {}) {
89505
89559
 
89506
89560
  // src/services/transformers/global-path-transformer.ts
89507
89561
  init_logger();
89508
- import { readFile as readFile51, readdir as readdir33, writeFile as writeFile31 } from "node:fs/promises";
89562
+ import { readFile as readFile50, readdir as readdir33, writeFile as writeFile31 } from "node:fs/promises";
89509
89563
  import { platform as platform13 } from "node:os";
89510
89564
  import { extname as extname5, join as join106 } from "node:path";
89511
89565
  var IS_WINDOWS3 = platform13() === "win32";
@@ -89625,7 +89679,7 @@ async function transformPathsForGlobalInstall(directory, options2 = {}) {
89625
89679
  await processDirectory2(fullPath);
89626
89680
  } else if (entry.isFile() && shouldTransformFile3(entry.name)) {
89627
89681
  try {
89628
- const content = await readFile51(fullPath, "utf-8");
89682
+ const content = await readFile50(fullPath, "utf-8");
89629
89683
  const { transformed, changes } = transformContent(content);
89630
89684
  if (changes > 0) {
89631
89685
  await writeFile31(fullPath, transformed, "utf-8");
@@ -89887,7 +89941,7 @@ init_checksum_utils();
89887
89941
  init_config_discovery();
89888
89942
  var import_picocolors25 = __toESM(require_picocolors(), 1);
89889
89943
  import { existsSync as existsSync51 } from "node:fs";
89890
- import { readFile as readFile52, rm as rm13, unlink as unlink12 } from "node:fs/promises";
89944
+ import { readFile as readFile51, rm as rm13, unlink as unlink12 } from "node:fs/promises";
89891
89945
  import { resolve as resolve22 } from "node:path";
89892
89946
 
89893
89947
  // src/commands/portable/conflict-resolver.ts
@@ -90461,7 +90515,7 @@ async function migrateCommand(options2) {
90461
90515
  for (const action of conflictActions) {
90462
90516
  if (!action.diff && action.targetPath && existsSync51(action.targetPath)) {
90463
90517
  try {
90464
- const targetContent = await readFile52(action.targetPath, "utf-8");
90518
+ const targetContent = await readFile51(action.targetPath, "utf-8");
90465
90519
  const sourceItem = agents2.find((a3) => a3.name === action.item) || commands.find((c2) => c2.name === action.item) || (configItem?.name === action.item ? configItem : null) || ruleItems.find((r2) => r2.name === action.item);
90466
90520
  if (sourceItem) {
90467
90521
  const providerConfig = providers[action.provider];
@@ -90653,26 +90707,27 @@ async function computeTargetStates(selectedProviders, global3) {
90653
90707
  continue;
90654
90708
  if (entry.global !== global3)
90655
90709
  continue;
90656
- try {
90657
- if (existsSync51(entry.path)) {
90658
- const content = await readFile52(entry.path, "utf-8");
90659
- states.set(entry.path, {
90660
- path: entry.path,
90661
- exists: true,
90662
- currentChecksum: computeContentChecksum(content)
90663
- });
90664
- } else {
90665
- states.set(entry.path, {
90666
- path: entry.path,
90667
- exists: false
90668
- });
90669
- }
90670
- } catch {
90710
+ if (entry.type === "skill")
90711
+ continue;
90712
+ const exists = existsSync51(entry.path);
90713
+ if (!exists) {
90671
90714
  states.set(entry.path, {
90672
90715
  path: entry.path,
90673
90716
  exists: false
90674
90717
  });
90718
+ continue;
90719
+ }
90720
+ const state = {
90721
+ path: entry.path,
90722
+ exists: true
90723
+ };
90724
+ try {
90725
+ const content = await readFile51(entry.path, "utf-8");
90726
+ state.currentChecksum = computeContentChecksum(content);
90727
+ } catch (error) {
90728
+ logger.debug(`[migrate] Failed to read target for checksum: ${entry.path} (${String(error)})`);
90675
90729
  }
90730
+ states.set(entry.path, state);
90676
90731
  }
90677
90732
  return states;
90678
90733
  }
@@ -92573,7 +92628,7 @@ function registerCommands(cli) {
92573
92628
  }
92574
92629
  await newCommand(options2);
92575
92630
  });
92576
- cli.command("init", "Initialize or update ClaudeKit project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit to use: engineer, marketing, all, or comma-separated").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--only <pattern>", "Include only files matching glob pattern (can be used multiple times)").option("-g, --global", "Use platform-specific user configuration directory").option("--fresh", "Completely remove .claude directory before downloading (requires confirmation)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--with-sudo", "Include system packages requiring sudo (Linux: ffmpeg, imagemagick)").option("--prefix", "Add /ck: prefix to all slash commands by moving them to commands/ck/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--dry-run", "Preview changes without applying them (requires --prefix)").option("--force-overwrite", "Override ownership protections and delete user-modified files (requires --prefix)").option("--force-overwrite-settings", "Fully replace settings.json instead of selective merge (destroys user customizations)").option("--skip-setup", "Skip interactive configuration wizard").option("--docs-dir <name>", "Custom docs folder name (default: docs)").option("--plans-dir <name>", "Custom plans folder name (default: plans)").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").option("--sync", "Sync config files from upstream with interactive hunk-by-hunk merge").option("--use-git", "Use git clone instead of GitHub API (uses SSH/HTTPS credentials)").option("--archive <path>", "Use local archive file instead of downloading (zip/tar.gz)").option("--kit-path <path>", "Use local kit directory instead of downloading").action(async (options2) => {
92631
+ cli.command("init", "Initialize or update ClaudeKit project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit to use: engineer, marketing, all, or comma-separated").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--only <pattern>", "Include only files matching glob pattern (can be used multiple times)").option("-g, --global", "Use platform-specific user configuration directory").option("--fresh", "Full reset: remove CK files, replace settings.json and CLAUDE.md, reinstall from scratch").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--with-sudo", "Include system packages requiring sudo (Linux: ffmpeg, imagemagick)").option("--prefix", "Add /ck: prefix to all slash commands by moving them to commands/ck/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--dry-run", "Preview changes without applying them (requires --prefix)").option("--force-overwrite", "Override ownership protections and delete user-modified files (requires --prefix)").option("--force-overwrite-settings", "Fully replace settings.json instead of selective merge (destroys user customizations)").option("--skip-setup", "Skip interactive configuration wizard").option("--docs-dir <name>", "Custom docs folder name (default: docs)").option("--plans-dir <name>", "Custom plans folder name (default: plans)").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").option("--sync", "Sync config files from upstream with interactive hunk-by-hunk merge").option("--use-git", "Use git clone instead of GitHub API (uses SSH/HTTPS credentials)").option("--archive <path>", "Use local archive file instead of downloading (zip/tar.gz)").option("--kit-path <path>", "Use local kit directory instead of downloading").action(async (options2) => {
92577
92632
  if (options2.exclude && !Array.isArray(options2.exclude)) {
92578
92633
  options2.exclude = [options2.exclude];
92579
92634
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudekit-cli",
3
- "version": "3.35.0-dev.23",
3
+ "version": "3.35.0-dev.24",
4
4
  "description": "CLI tool for bootstrapping and updating ClaudeKit projects",
5
5
  "type": "module",
6
6
  "repository": {