claudekit-cli 3.36.0-dev.17 → 3.36.0-dev.19

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 +551 -512
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -11183,13 +11183,11 @@ var init_provider_registry = __esm(() => {
11183
11183
  join(cwd, ".codex/config.toml"),
11184
11184
  join(cwd, ".codex/agents"),
11185
11185
  join(cwd, ".codex/prompts"),
11186
- join(cwd, ".agents/skills"),
11187
11186
  join(home, ".codex/config.toml"),
11188
11187
  join(home, ".codex/agents"),
11189
11188
  join(home, ".codex/AGENTS.md"),
11190
11189
  join(home, ".codex/instructions.md"),
11191
- join(home, ".codex/prompts"),
11192
- join(home, ".agents/skills")
11190
+ join(home, ".codex/prompts")
11193
11191
  ])
11194
11192
  },
11195
11193
  droid: {
@@ -11271,7 +11269,7 @@ var init_provider_registry = __esm(() => {
11271
11269
  },
11272
11270
  commands: null,
11273
11271
  skills: {
11274
- projectPath: ".cursor/skills",
11272
+ projectPath: ".agents/skills",
11275
11273
  globalPath: join(home, ".cursor/skills"),
11276
11274
  format: "direct-copy",
11277
11275
  writeStrategy: "per-file",
@@ -11295,7 +11293,6 @@ var init_provider_registry = __esm(() => {
11295
11293
  settingsJsonPath: null,
11296
11294
  detect: async () => hasAnyInstallSignal([
11297
11295
  join(cwd, ".cursor/rules"),
11298
- join(cwd, ".cursor/skills"),
11299
11296
  join(home, ".cursor/rules"),
11300
11297
  join(home, ".cursor/skills")
11301
11298
  ])
@@ -11409,8 +11406,8 @@ var init_provider_registry = __esm(() => {
11409
11406
  nestedCommands: false
11410
11407
  },
11411
11408
  skills: {
11412
- projectPath: ".windsurf/skills",
11413
- globalPath: join(home, ".codeium/windsurf/skills"),
11409
+ projectPath: ".agents/skills",
11410
+ globalPath: join(home, ".agents/skills"),
11414
11411
  format: "direct-copy",
11415
11412
  writeStrategy: "per-file",
11416
11413
  fileExtension: ".md"
@@ -11436,10 +11433,8 @@ var init_provider_registry = __esm(() => {
11436
11433
  settingsJsonPath: null,
11437
11434
  detect: async () => hasAnyInstallSignal([
11438
11435
  join(cwd, ".windsurf/rules"),
11439
- join(cwd, ".windsurf/skills"),
11440
11436
  join(cwd, ".windsurf/workflows"),
11441
11437
  join(home, ".codeium/windsurf/rules"),
11442
- join(home, ".codeium/windsurf/skills"),
11443
11438
  join(home, ".codeium/windsurf/workflows")
11444
11439
  ])
11445
11440
  },
@@ -11504,8 +11499,8 @@ var init_provider_registry = __esm(() => {
11504
11499
  fileExtension: ".toml"
11505
11500
  },
11506
11501
  skills: {
11507
- projectPath: ".gemini/skills",
11508
- globalPath: join(home, ".gemini/skills"),
11502
+ projectPath: ".agents/skills",
11503
+ globalPath: join(home, ".agents/skills"),
11509
11504
  format: "direct-copy",
11510
11505
  writeStrategy: "per-file",
11511
11506
  fileExtension: ".md"
@@ -11528,10 +11523,8 @@ var init_provider_registry = __esm(() => {
11528
11523
  settingsJsonPath: null,
11529
11524
  detect: async () => hasAnyInstallSignal([
11530
11525
  join(cwd, ".gemini/commands"),
11531
- join(cwd, ".gemini/skills"),
11532
11526
  join(cwd, "GEMINI.md"),
11533
11527
  join(home, ".gemini/commands"),
11534
- join(home, ".gemini/skills"),
11535
11528
  join(home, ".gemini/GEMINI.md")
11536
11529
  ])
11537
11530
  },
@@ -11572,11 +11565,9 @@ var init_provider_registry = __esm(() => {
11572
11565
  settingsJsonPath: null,
11573
11566
  detect: async () => hasAnyInstallSignal([
11574
11567
  join(cwd, ".amp/rules"),
11575
- join(cwd, ".agents/skills"),
11576
11568
  join(cwd, "AGENT.md"),
11577
- join(home, ".config/AGENT.md"),
11578
11569
  join(home, ".config/amp/rules"),
11579
- join(home, ".config/agents/skills")
11570
+ join(home, ".config/AGENT.md")
11580
11571
  ])
11581
11572
  },
11582
11573
  antigravity: {
@@ -55913,108 +55904,6 @@ var init_metadata_migration = __esm(() => {
55913
55904
  import_fs_extra3 = __toESM(require_lib3(), 1);
55914
55905
  });
55915
55906
 
55916
- // src/services/file-operations/claudekit-scanner.ts
55917
- import { join as join40 } from "node:path";
55918
- async function scanClaudeKitDirectory(directoryPath) {
55919
- const counts = {
55920
- agents: 0,
55921
- commands: 0,
55922
- rules: 0,
55923
- skills: 0
55924
- };
55925
- try {
55926
- if (!await import_fs_extra4.pathExists(directoryPath)) {
55927
- return counts;
55928
- }
55929
- const items = await import_fs_extra4.readdir(directoryPath);
55930
- if (items.includes("agents")) {
55931
- const agentsPath = join40(directoryPath, "agents");
55932
- const agentFiles = await import_fs_extra4.readdir(agentsPath);
55933
- counts.agents = agentFiles.filter((file) => file.endsWith(".md")).length;
55934
- }
55935
- if (items.includes("commands")) {
55936
- const commandsPath = join40(directoryPath, "commands");
55937
- const commandFiles = await import_fs_extra4.readdir(commandsPath);
55938
- counts.commands = commandFiles.filter((file) => file.endsWith(".md")).length;
55939
- }
55940
- if (items.includes("rules")) {
55941
- const rulesPath = join40(directoryPath, "rules");
55942
- const ruleFiles = await import_fs_extra4.readdir(rulesPath);
55943
- counts.rules = ruleFiles.filter((file) => file.endsWith(".md")).length;
55944
- } else if (items.includes("workflows")) {
55945
- const workflowsPath = join40(directoryPath, "workflows");
55946
- const workflowFiles = await import_fs_extra4.readdir(workflowsPath);
55947
- counts.rules = workflowFiles.filter((file) => file.endsWith(".md")).length;
55948
- }
55949
- if (items.includes("skills")) {
55950
- const skillsPath = join40(directoryPath, "skills");
55951
- const skillItems = await import_fs_extra4.readdir(skillsPath);
55952
- let skillCount = 0;
55953
- for (const item of skillItems) {
55954
- if (SKIP_DIRS_CLAUDE_INTERNAL.includes(item)) {
55955
- continue;
55956
- }
55957
- const itemPath = join40(skillsPath, item);
55958
- const stat8 = await import_fs_extra4.readdir(itemPath).catch(() => null);
55959
- if (stat8?.includes("SKILL.md")) {
55960
- skillCount++;
55961
- }
55962
- }
55963
- counts.skills = skillCount;
55964
- }
55965
- } catch (error) {}
55966
- return counts;
55967
- }
55968
- async function readClaudeKitMetadata(metadataPath) {
55969
- try {
55970
- if (!await import_fs_extra4.pathExists(metadataPath)) {
55971
- return null;
55972
- }
55973
- const content = await import_fs_extra4.readFile(metadataPath, "utf8");
55974
- const metadata = JSON.parse(content);
55975
- return metadata;
55976
- } catch {
55977
- return null;
55978
- }
55979
- }
55980
- function getGlobalInstallDir() {
55981
- return PathResolver.getGlobalKitDir();
55982
- }
55983
- async function getClaudeKitSetup(projectDir = process.cwd()) {
55984
- const setup = {
55985
- global: {
55986
- path: "",
55987
- metadata: null,
55988
- components: { agents: 0, commands: 0, rules: 0, skills: 0 }
55989
- },
55990
- project: {
55991
- path: "",
55992
- metadata: null,
55993
- components: { agents: 0, commands: 0, rules: 0, skills: 0 }
55994
- }
55995
- };
55996
- const globalDir = getGlobalInstallDir();
55997
- if (await import_fs_extra4.pathExists(globalDir)) {
55998
- setup.global.path = globalDir;
55999
- setup.global.metadata = await readClaudeKitMetadata(join40(globalDir, "metadata.json"));
56000
- setup.global.components = await scanClaudeKitDirectory(globalDir);
56001
- }
56002
- const projectClaudeDir = join40(projectDir, ".claude");
56003
- const isLocalSameAsGlobal = projectClaudeDir === globalDir;
56004
- if (!isLocalSameAsGlobal && await import_fs_extra4.pathExists(projectClaudeDir)) {
56005
- setup.project.path = projectClaudeDir;
56006
- setup.project.metadata = await readClaudeKitMetadata(join40(projectClaudeDir, "metadata.json"));
56007
- setup.project.components = await scanClaudeKitDirectory(projectClaudeDir);
56008
- }
56009
- return setup;
56010
- }
56011
- var import_fs_extra4;
56012
- var init_claudekit_scanner = __esm(() => {
56013
- init_path_resolver();
56014
- init_skip_directories();
56015
- import_fs_extra4 = __toESM(require_lib3(), 1);
56016
- });
56017
-
56018
55907
  // node_modules/compare-versions/lib/umd/index.js
56019
55908
  var require_umd = __commonJS((exports, module) => {
56020
55909
  (function(global3, factory) {
@@ -56137,12 +56026,158 @@ var require_umd = __commonJS((exports, module) => {
56137
56026
  });
56138
56027
  });
56139
56028
 
56029
+ // src/domains/versioning/checking/version-utils.ts
56030
+ function isUpdateCheckDisabled() {
56031
+ return process.env.NO_UPDATE_NOTIFIER === "1" || process.env.NO_UPDATE_NOTIFIER === "true" || !process.stdout.isTTY;
56032
+ }
56033
+ function normalizeVersion(version) {
56034
+ return version.replace(/^v/i, "");
56035
+ }
56036
+ function parseVersionParts(version) {
56037
+ const normalized = normalizeVersion(version);
56038
+ const [base, ...prereleaseParts] = normalized.split("-");
56039
+ return {
56040
+ base,
56041
+ prerelease: prereleaseParts.length > 0 ? prereleaseParts.join("-") : null
56042
+ };
56043
+ }
56044
+ function isDevPrereleaseOfSameBase(currentVersion, latestVersion) {
56045
+ const current = parseVersionParts(currentVersion);
56046
+ const latest = parseVersionParts(latestVersion);
56047
+ if (!current.prerelease?.startsWith("dev"))
56048
+ return false;
56049
+ if (latest.prerelease !== null)
56050
+ return false;
56051
+ return current.base === latest.base;
56052
+ }
56053
+ function versionsMatch(installed, latest) {
56054
+ return normalizeVersion(installed) === normalizeVersion(latest);
56055
+ }
56056
+ function isNewerVersion(currentVersion, latestVersion) {
56057
+ try {
56058
+ const current = normalizeVersion(currentVersion);
56059
+ const latest = normalizeVersion(latestVersion);
56060
+ if (isDevPrereleaseOfSameBase(current, latest)) {
56061
+ return false;
56062
+ }
56063
+ return import_compare_versions.compareVersions(latest, current) > 0;
56064
+ } catch {
56065
+ return false;
56066
+ }
56067
+ }
56068
+ var import_compare_versions;
56069
+ var init_version_utils = __esm(() => {
56070
+ import_compare_versions = __toESM(require_umd(), 1);
56071
+ });
56072
+
56073
+ // src/services/file-operations/claudekit-scanner.ts
56074
+ import { join as join40 } from "node:path";
56075
+ async function scanClaudeKitDirectory(directoryPath) {
56076
+ const counts = {
56077
+ agents: 0,
56078
+ commands: 0,
56079
+ rules: 0,
56080
+ skills: 0
56081
+ };
56082
+ try {
56083
+ if (!await import_fs_extra4.pathExists(directoryPath)) {
56084
+ return counts;
56085
+ }
56086
+ const items = await import_fs_extra4.readdir(directoryPath);
56087
+ if (items.includes("agents")) {
56088
+ const agentsPath = join40(directoryPath, "agents");
56089
+ const agentFiles = await import_fs_extra4.readdir(agentsPath);
56090
+ counts.agents = agentFiles.filter((file) => file.endsWith(".md")).length;
56091
+ }
56092
+ if (items.includes("commands")) {
56093
+ const commandsPath = join40(directoryPath, "commands");
56094
+ const commandFiles = await import_fs_extra4.readdir(commandsPath);
56095
+ counts.commands = commandFiles.filter((file) => file.endsWith(".md")).length;
56096
+ }
56097
+ if (items.includes("rules")) {
56098
+ const rulesPath = join40(directoryPath, "rules");
56099
+ const ruleFiles = await import_fs_extra4.readdir(rulesPath);
56100
+ counts.rules = ruleFiles.filter((file) => file.endsWith(".md")).length;
56101
+ } else if (items.includes("workflows")) {
56102
+ const workflowsPath = join40(directoryPath, "workflows");
56103
+ const workflowFiles = await import_fs_extra4.readdir(workflowsPath);
56104
+ counts.rules = workflowFiles.filter((file) => file.endsWith(".md")).length;
56105
+ }
56106
+ if (items.includes("skills")) {
56107
+ const skillsPath = join40(directoryPath, "skills");
56108
+ const skillItems = await import_fs_extra4.readdir(skillsPath);
56109
+ let skillCount = 0;
56110
+ for (const item of skillItems) {
56111
+ if (SKIP_DIRS_CLAUDE_INTERNAL.includes(item)) {
56112
+ continue;
56113
+ }
56114
+ const itemPath = join40(skillsPath, item);
56115
+ const stat8 = await import_fs_extra4.readdir(itemPath).catch(() => null);
56116
+ if (stat8?.includes("SKILL.md")) {
56117
+ skillCount++;
56118
+ }
56119
+ }
56120
+ counts.skills = skillCount;
56121
+ }
56122
+ } catch (error) {}
56123
+ return counts;
56124
+ }
56125
+ async function readClaudeKitMetadata(metadataPath) {
56126
+ try {
56127
+ if (!await import_fs_extra4.pathExists(metadataPath)) {
56128
+ return null;
56129
+ }
56130
+ const content = await import_fs_extra4.readFile(metadataPath, "utf8");
56131
+ const metadata = JSON.parse(content);
56132
+ return metadata;
56133
+ } catch {
56134
+ return null;
56135
+ }
56136
+ }
56137
+ function getGlobalInstallDir() {
56138
+ return PathResolver.getGlobalKitDir();
56139
+ }
56140
+ async function getClaudeKitSetup(projectDir = process.cwd()) {
56141
+ const setup = {
56142
+ global: {
56143
+ path: "",
56144
+ metadata: null,
56145
+ components: { agents: 0, commands: 0, rules: 0, skills: 0 }
56146
+ },
56147
+ project: {
56148
+ path: "",
56149
+ metadata: null,
56150
+ components: { agents: 0, commands: 0, rules: 0, skills: 0 }
56151
+ }
56152
+ };
56153
+ const globalDir = getGlobalInstallDir();
56154
+ if (await import_fs_extra4.pathExists(globalDir)) {
56155
+ setup.global.path = globalDir;
56156
+ setup.global.metadata = await readClaudeKitMetadata(join40(globalDir, "metadata.json"));
56157
+ setup.global.components = await scanClaudeKitDirectory(globalDir);
56158
+ }
56159
+ const projectClaudeDir = join40(projectDir, ".claude");
56160
+ const isLocalSameAsGlobal = projectClaudeDir === globalDir;
56161
+ if (!isLocalSameAsGlobal && await import_fs_extra4.pathExists(projectClaudeDir)) {
56162
+ setup.project.path = projectClaudeDir;
56163
+ setup.project.metadata = await readClaudeKitMetadata(join40(projectClaudeDir, "metadata.json"));
56164
+ setup.project.components = await scanClaudeKitDirectory(projectClaudeDir);
56165
+ }
56166
+ return setup;
56167
+ }
56168
+ var import_fs_extra4;
56169
+ var init_claudekit_scanner = __esm(() => {
56170
+ init_path_resolver();
56171
+ init_skip_directories();
56172
+ import_fs_extra4 = __toESM(require_lib3(), 1);
56173
+ });
56174
+
56140
56175
  // package.json
56141
56176
  var package_default;
56142
56177
  var init_package = __esm(() => {
56143
56178
  package_default = {
56144
56179
  name: "claudekit-cli",
56145
- version: "3.36.0-dev.17",
56180
+ version: "3.36.0-dev.19",
56146
56181
  description: "CLI tool for bootstrapping and updating ClaudeKit projects",
56147
56182
  type: "module",
56148
56183
  repository: {
@@ -56249,365 +56284,6 @@ var init_package = __esm(() => {
56249
56284
  };
56250
56285
  });
56251
56286
 
56252
- // src/commands/update-cli.ts
56253
- import { exec as exec2 } from "node:child_process";
56254
- import { join as join41 } from "node:path";
56255
- import { promisify as promisify8 } from "node:util";
56256
- function getDefaultUpdateCliCommandDeps() {
56257
- return {
56258
- currentVersion: package_default.version,
56259
- execAsyncFn: execAsync2,
56260
- packageManagerDetector: PackageManagerDetector,
56261
- npmRegistryClient: NpmRegistryClient,
56262
- promptKitUpdateFn: promptKitUpdate
56263
- };
56264
- }
56265
- function extractCommandStdout(result) {
56266
- if (typeof result === "string") {
56267
- return result;
56268
- }
56269
- if (result && typeof result.stdout === "string") {
56270
- return result.stdout;
56271
- }
56272
- return "";
56273
- }
56274
- function redactCommandForLog(command) {
56275
- if (!command)
56276
- return command;
56277
- const redactedRegistryFlags = command.replace(/(--registry(?:=|\s+))(['"]?)(\S+?)(\2)(?=\s|$)/g, (_match, prefix, quote, url) => `${prefix}${quote}${redactRegistryUrlForLog(url)}${quote}`);
56278
- return redactedRegistryFlags.replace(/https?:\/\/[^\s"']+/g, (url) => redactRegistryUrlForLog(url));
56279
- }
56280
- function buildInitCommand(isGlobal, kit, beta) {
56281
- const parts = ["ck init"];
56282
- if (isGlobal)
56283
- parts.push("-g");
56284
- if (kit)
56285
- parts.push(`--kit ${kit}`);
56286
- parts.push("--yes --install-skills");
56287
- if (beta)
56288
- parts.push("--beta");
56289
- return parts.join(" ");
56290
- }
56291
- function isBetaVersion(version) {
56292
- if (!version)
56293
- return false;
56294
- return /-(beta|alpha|rc|dev)[.\d]/i.test(version);
56295
- }
56296
- function parseCliVersionFromOutput(output2) {
56297
- if (!output2)
56298
- return null;
56299
- const match = output2.match(/CLI Version:\s*(\S+)/);
56300
- return match ? match[1] : null;
56301
- }
56302
- function selectKitForUpdate(params) {
56303
- const { hasLocal, hasGlobal, localKits, globalKits } = params;
56304
- const hasLocalKit = localKits.length > 0 || hasLocal;
56305
- const hasGlobalKit = globalKits.length > 0 || hasGlobal;
56306
- if (!hasLocalKit && !hasGlobalKit) {
56307
- return null;
56308
- }
56309
- if (hasGlobalKit && !hasLocalKit) {
56310
- const kit2 = globalKits[0] || localKits[0];
56311
- return {
56312
- isGlobal: true,
56313
- kit: kit2,
56314
- promptMessage: `Update global ClaudeKit content${kit2 ? ` (${kit2})` : ""}?`
56315
- };
56316
- }
56317
- if (hasLocalKit && !hasGlobalKit) {
56318
- const kit2 = localKits[0] || globalKits[0];
56319
- return {
56320
- isGlobal: false,
56321
- kit: kit2,
56322
- promptMessage: `Update local project ClaudeKit content${kit2 ? ` (${kit2})` : ""}?`
56323
- };
56324
- }
56325
- const kit = globalKits[0] || localKits[0];
56326
- return {
56327
- isGlobal: true,
56328
- kit,
56329
- promptMessage: `Update global ClaudeKit content${kit ? ` (${kit})` : ""}?`
56330
- };
56331
- }
56332
- async function readMetadataFile(claudeDir2) {
56333
- const metadataPath = join41(claudeDir2, "metadata.json");
56334
- try {
56335
- if (!await import_fs_extra5.pathExists(metadataPath)) {
56336
- return null;
56337
- }
56338
- const content = await import_fs_extra5.readFile(metadataPath, "utf-8");
56339
- const parsed = JSON.parse(content);
56340
- const validated = MetadataSchema.safeParse(parsed);
56341
- if (!validated.success) {
56342
- logger.verbose(`Invalid metadata format: ${validated.error.message}`);
56343
- return null;
56344
- }
56345
- return validated.data;
56346
- } catch (error) {
56347
- logger.verbose(`Failed to read metadata: ${error instanceof Error ? error.message : "unknown"}`);
56348
- return null;
56349
- }
56350
- }
56351
- async function promptKitUpdate(beta, yes, deps) {
56352
- try {
56353
- const execFn = deps?.execAsyncFn ?? execAsync2;
56354
- const setup = await (deps?.getSetupFn ?? getClaudeKitSetup)();
56355
- const hasLocal = !!setup.project.metadata;
56356
- const hasGlobal = !!setup.global.metadata;
56357
- const localMetadata = hasLocal ? await readMetadataFile(setup.project.path) : null;
56358
- const globalMetadata = hasGlobal ? await readMetadataFile(setup.global.path) : null;
56359
- const localKits = localMetadata ? getInstalledKits(localMetadata) : [];
56360
- const globalKits = globalMetadata ? getInstalledKits(globalMetadata) : [];
56361
- const selection = selectKitForUpdate({ hasLocal, hasGlobal, localKits, globalKits });
56362
- if (!selection) {
56363
- logger.verbose("No ClaudeKit installations detected, skipping kit update prompt");
56364
- return;
56365
- }
56366
- const kitVersion = selection.kit ? selection.isGlobal ? globalMetadata?.kits?.[selection.kit]?.version : localMetadata?.kits?.[selection.kit]?.version : undefined;
56367
- const isBetaInstalled = isBetaVersion(kitVersion);
56368
- const initCmd = buildInitCommand(selection.isGlobal, selection.kit, beta || isBetaInstalled);
56369
- const promptMessage = selection.promptMessage;
56370
- if (selection.kit && kitVersion) {
56371
- logger.info(`Current kit version: ${selection.kit}@${kitVersion}`);
56372
- }
56373
- if (!yes) {
56374
- logger.info("");
56375
- const shouldUpdate = await se({
56376
- message: promptMessage
56377
- });
56378
- if (lD(shouldUpdate) || !shouldUpdate) {
56379
- log.info("Skipped kit content update");
56380
- return;
56381
- }
56382
- } else {
56383
- logger.verbose("Auto-proceeding with kit update (--yes flag)");
56384
- }
56385
- logger.info(`Running: ${initCmd}`);
56386
- const s = (deps?.spinnerFn ?? de)();
56387
- s.start("Updating ClaudeKit content...");
56388
- try {
56389
- await execFn(initCmd, {
56390
- timeout: 300000
56391
- });
56392
- let newKitVersion;
56393
- try {
56394
- const claudeDir2 = selection.isGlobal ? setup.global.path : setup.project.path;
56395
- const updatedMetadata = await readMetadataFile(claudeDir2);
56396
- newKitVersion = selection.kit ? updatedMetadata?.kits?.[selection.kit]?.version : undefined;
56397
- } catch {}
56398
- if (selection.kit && kitVersion && newKitVersion && kitVersion !== newKitVersion) {
56399
- s.stop(`Kit updated: ${selection.kit}@${kitVersion} -> ${newKitVersion}`);
56400
- } else if (selection.kit && newKitVersion) {
56401
- s.stop(`Kit content updated (${selection.kit}@${newKitVersion})`);
56402
- } else {
56403
- s.stop("Kit content updated");
56404
- }
56405
- } catch (error) {
56406
- s.stop("Kit update finished");
56407
- const errorMsg = error instanceof Error ? error.message : "unknown";
56408
- if (errorMsg.includes("exit code") && !errorMsg.includes("exit code 0")) {
56409
- logger.warning("Kit content update may have encountered issues");
56410
- logger.verbose(`Error: ${errorMsg}`);
56411
- } else {
56412
- logger.verbose(`Init command completed: ${errorMsg}`);
56413
- }
56414
- }
56415
- } catch (error) {
56416
- logger.verbose(`Failed to prompt for kit update: ${error instanceof Error ? error.message : "unknown error"}`);
56417
- }
56418
- }
56419
- async function updateCliCommand(options2, deps = getDefaultUpdateCliCommandDeps()) {
56420
- const s = de();
56421
- intro("[>] ClaudeKit CLI - Update");
56422
- try {
56423
- const {
56424
- currentVersion,
56425
- execAsyncFn,
56426
- packageManagerDetector,
56427
- npmRegistryClient,
56428
- promptKitUpdateFn
56429
- } = deps;
56430
- const opts = UpdateCliOptionsSchema.parse(options2);
56431
- logger.info(`Current CLI version: ${currentVersion}`);
56432
- s.start("Detecting package manager...");
56433
- const pm = await packageManagerDetector.detect();
56434
- const pmVersion = await packageManagerDetector.getVersion(pm);
56435
- s.stop(`Using ${packageManagerDetector.getDisplayName(pm)}${pmVersion ? ` v${pmVersion}` : ""}`);
56436
- logger.verbose(`Detected package manager: ${pm}`);
56437
- let registryUrl = opts.registry;
56438
- if (!registryUrl && pm === "npm") {
56439
- const userRegistry = await packageManagerDetector.getNpmRegistryUrl();
56440
- if (userRegistry) {
56441
- registryUrl = userRegistry;
56442
- logger.verbose(`Using npm configured registry: ${redactRegistryUrlForLog(registryUrl)}`);
56443
- }
56444
- }
56445
- s.start("Checking for updates...");
56446
- let targetVersion = null;
56447
- if (opts.release && opts.release !== "latest") {
56448
- try {
56449
- const exists = await npmRegistryClient.versionExists(CLAUDEKIT_CLI_NPM_PACKAGE_NAME, opts.release, registryUrl);
56450
- if (!exists) {
56451
- s.stop("Version not found");
56452
- throw new CliUpdateError(`Version ${opts.release} does not exist on npm registry. Run 'ck versions' to see available versions.`);
56453
- }
56454
- } catch (error) {
56455
- if (error instanceof CliUpdateError) {
56456
- throw error;
56457
- }
56458
- s.stop("Version check failed");
56459
- const message = error instanceof Error ? error.message : "Unknown error";
56460
- logger.verbose(`Release check failed for ${opts.release}: ${message}`);
56461
- const registryHint = registryUrl ? ` (${redactRegistryUrlForLog(registryUrl)})` : " (default registry)";
56462
- throw new CliUpdateError(`Failed to verify version ${opts.release} on npm registry${registryHint}. Check registry settings/network connectivity and try again.`);
56463
- }
56464
- targetVersion = opts.release;
56465
- s.stop(`Target version: ${targetVersion}`);
56466
- } else if (opts.dev || opts.beta) {
56467
- targetVersion = await npmRegistryClient.getDevVersion(CLAUDEKIT_CLI_NPM_PACKAGE_NAME, registryUrl);
56468
- if (!targetVersion) {
56469
- s.stop("No dev version available");
56470
- logger.warning("No dev version found. Using latest stable version instead.");
56471
- targetVersion = await npmRegistryClient.getLatestVersion(CLAUDEKIT_CLI_NPM_PACKAGE_NAME, registryUrl);
56472
- } else {
56473
- s.stop(`Latest dev version: ${targetVersion}`);
56474
- }
56475
- } else {
56476
- targetVersion = await npmRegistryClient.getLatestVersion(CLAUDEKIT_CLI_NPM_PACKAGE_NAME, registryUrl);
56477
- s.stop(`Latest version: ${targetVersion || "unknown"}`);
56478
- }
56479
- if (!targetVersion) {
56480
- throw new CliUpdateError(`Failed to fetch version information from npm registry. Check your internet connection and try again. Manual update: ${packageManagerDetector.getUpdateCommand(pm, CLAUDEKIT_CLI_NPM_PACKAGE_NAME, undefined, registryUrl)}`);
56481
- }
56482
- const comparison = import_compare_versions.compareVersions(currentVersion, targetVersion);
56483
- if (comparison === 0) {
56484
- outro(`[+] Already on the latest CLI version (${currentVersion})`);
56485
- await promptKitUpdateFn(opts.dev || opts.beta, opts.yes);
56486
- return;
56487
- }
56488
- const isDevChannelSwitch = (opts.dev || opts.beta) && isBetaVersion(targetVersion) && !isBetaVersion(currentVersion);
56489
- if (comparison > 0 && !opts.release && !isDevChannelSwitch) {
56490
- outro(`[+] Current version (${currentVersion}) is newer than latest (${targetVersion})`);
56491
- return;
56492
- }
56493
- const isUpgrade = comparison < 0 || isDevChannelSwitch;
56494
- const changeType = isUpgrade ? "upgrade" : "downgrade";
56495
- logger.info(`${isUpgrade ? "[^]" : "[v]"} ${changeType}: ${currentVersion} -> ${targetVersion}`);
56496
- if (opts.check) {
56497
- note(`CLI update available: ${currentVersion} -> ${targetVersion}
56498
-
56499
- Run 'ck update' to install`, "Update Check");
56500
- await promptKitUpdateFn(opts.dev || opts.beta, opts.yes);
56501
- outro("Check complete");
56502
- return;
56503
- }
56504
- if (!opts.yes) {
56505
- const shouldUpdate = await se({
56506
- message: `${isUpgrade ? "Update" : "Downgrade"} CLI from ${currentVersion} to ${targetVersion}?`
56507
- });
56508
- if (lD(shouldUpdate) || !shouldUpdate) {
56509
- outro("Update cancelled");
56510
- return;
56511
- }
56512
- }
56513
- const updateCmd = packageManagerDetector.getUpdateCommand(pm, CLAUDEKIT_CLI_NPM_PACKAGE_NAME, targetVersion, registryUrl);
56514
- logger.info(`Running: ${redactCommandForLog(updateCmd)}`);
56515
- s.start("Updating CLI...");
56516
- try {
56517
- await execAsyncFn(updateCmd, {
56518
- timeout: 120000
56519
- });
56520
- s.stop("Update completed");
56521
- } catch (error) {
56522
- s.stop("Update failed");
56523
- const errorMessage = error instanceof Error ? error.message : "Unknown error";
56524
- if (errorMessage.includes("EACCES") || errorMessage.includes("EPERM") || errorMessage.includes("permission") || errorMessage.includes("Access is denied")) {
56525
- const permHint = pm === "npm" ? `
56526
-
56527
- Or fix npm permissions: https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally` : "";
56528
- const isWindows3 = process.platform === "win32";
56529
- const elevationHint = isWindows3 ? `Run your terminal as Administrator and retry: ${updateCmd}` : `sudo ${updateCmd}`;
56530
- throw new CliUpdateError(`Permission denied. Try: ${elevationHint}${permHint}`);
56531
- }
56532
- logger.error(`Update failed: ${errorMessage}`);
56533
- logger.info(`Try running: ${redactCommandForLog(updateCmd)}`);
56534
- throw new CliUpdateError(`Update failed: ${errorMessage}
56535
-
56536
- Manual update: ${updateCmd}`);
56537
- }
56538
- s.start("Verifying installation...");
56539
- try {
56540
- const versionResult = await execAsyncFn("ck --version", { timeout: 5000 });
56541
- const stdout = extractCommandStdout(versionResult);
56542
- const activeVersion = parseCliVersionFromOutput(stdout);
56543
- if (!activeVersion) {
56544
- s.stop("Verification failed");
56545
- const message = `Update completed but could not parse 'ck --version' output.
56546
- Please restart your terminal and run 'ck --version'. Expected: ${targetVersion}
56547
-
56548
- Manual update: ${redactCommandForLog(updateCmd)}`;
56549
- logger.error(message);
56550
- throw new CliUpdateError(message);
56551
- }
56552
- s.stop(`Installed version: ${activeVersion}`);
56553
- if (activeVersion !== targetVersion) {
56554
- const mismatchMessage = `Update did not activate the requested version.
56555
- Expected: ${targetVersion}
56556
- Active ck: ${activeVersion}
56557
-
56558
- Likely causes: multiple global installations (npm/bun/pnpm/yarn) or stale shell shim/cache (common on Windows).
56559
- Run '${redactCommandForLog(updateCmd)}' manually, restart terminal, then check command resolution:
56560
- - Windows: where ck
56561
- - macOS/Linux: which -a ck`;
56562
- logger.error(mismatchMessage);
56563
- throw new CliUpdateError(mismatchMessage);
56564
- }
56565
- outro(`[+] Successfully updated ClaudeKit CLI to ${activeVersion}`);
56566
- await promptKitUpdateFn(opts.dev || opts.beta, opts.yes);
56567
- } catch (error) {
56568
- if (error instanceof CliUpdateError) {
56569
- throw error;
56570
- }
56571
- s.stop("Verification failed");
56572
- const message = `Update completed but automatic verification failed.
56573
- Please restart your terminal and run 'ck --version'. Expected: ${targetVersion}
56574
-
56575
- Manual update: ${redactCommandForLog(updateCmd)}`;
56576
- logger.error(message);
56577
- throw new CliUpdateError(message);
56578
- }
56579
- } catch (error) {
56580
- if (error instanceof CliUpdateError) {
56581
- throw error;
56582
- }
56583
- const errorMessage = error instanceof Error ? error.message : "Unknown error";
56584
- logger.error(`Update failed: ${errorMessage}`);
56585
- throw new CliUpdateError(errorMessage);
56586
- }
56587
- }
56588
- var import_compare_versions, import_fs_extra5, execAsync2, CliUpdateError;
56589
- var init_update_cli = __esm(() => {
56590
- init_npm_registry();
56591
- init_package_manager_detector();
56592
- init_metadata_migration();
56593
- init_claudekit_scanner();
56594
- init_claudekit_constants();
56595
- init_logger();
56596
- init_safe_prompts();
56597
- init_types3();
56598
- init_types3();
56599
- init_package();
56600
- import_compare_versions = __toESM(require_umd(), 1);
56601
- import_fs_extra5 = __toESM(require_lib3(), 1);
56602
- execAsync2 = promisify8(exec2);
56603
- CliUpdateError = class CliUpdateError extends ClaudeKitError {
56604
- constructor(message) {
56605
- super(message, "CLI_UPDATE_ERROR");
56606
- this.name = "CliUpdateError";
56607
- }
56608
- };
56609
- });
56610
-
56611
56287
  // src/domains/github/github-auth.ts
56612
56288
  import { execSync } from "node:child_process";
56613
56289
 
@@ -57053,8 +56729,8 @@ var init_error_handler2 = __esm(() => {
57053
56729
 
57054
56730
  // src/domains/versioning/release-cache.ts
57055
56731
  import { existsSync as existsSync35 } from "node:fs";
57056
- import { mkdir as mkdir12, readFile as readFile26, unlink as unlink6, writeFile as writeFile14 } from "node:fs/promises";
57057
- import { join as join42 } from "node:path";
56732
+ import { mkdir as mkdir12, readFile as readFile25, unlink as unlink6, writeFile as writeFile14 } from "node:fs/promises";
56733
+ import { join as join41 } from "node:path";
57058
56734
  var ReleaseCacheEntrySchema, ReleaseCache;
57059
56735
  var init_release_cache = __esm(() => {
57060
56736
  init_logger();
@@ -57069,7 +56745,7 @@ var init_release_cache = __esm(() => {
57069
56745
  static CACHE_TTL_SECONDS = Number(process.env.CK_CACHE_TTL) || 3600;
57070
56746
  cacheDir;
57071
56747
  constructor() {
57072
- this.cacheDir = join42(PathResolver.getCacheDir(false), ReleaseCache.CACHE_DIR);
56748
+ this.cacheDir = join41(PathResolver.getCacheDir(false), ReleaseCache.CACHE_DIR);
57073
56749
  }
57074
56750
  async get(key) {
57075
56751
  const cacheFile = this.getCachePath(key);
@@ -57078,7 +56754,7 @@ var init_release_cache = __esm(() => {
57078
56754
  logger.debug(`Release cache not found for key: ${key}`);
57079
56755
  return null;
57080
56756
  }
57081
- const content = await readFile26(cacheFile, "utf-8");
56757
+ const content = await readFile25(cacheFile, "utf-8");
57082
56758
  const parsed = JSON.parse(content);
57083
56759
  const cacheEntry = ReleaseCacheEntrySchema.parse(parsed);
57084
56760
  if (this.isExpired(cacheEntry.timestamp)) {
@@ -57127,7 +56803,7 @@ var init_release_cache = __esm(() => {
57127
56803
  const files = await readdir10(this.cacheDir);
57128
56804
  for (const file of files) {
57129
56805
  if (file.endsWith(".json")) {
57130
- await unlink6(join42(this.cacheDir, file));
56806
+ await unlink6(join41(this.cacheDir, file));
57131
56807
  }
57132
56808
  }
57133
56809
  logger.debug("All release cache cleared");
@@ -57138,7 +56814,7 @@ var init_release_cache = __esm(() => {
57138
56814
  }
57139
56815
  getCachePath(key) {
57140
56816
  const safeKey = key.replace(/[^a-zA-Z0-9_-]/g, "_");
57141
- return join42(this.cacheDir, `${safeKey}.json`);
56817
+ return join41(this.cacheDir, `${safeKey}.json`);
57142
56818
  }
57143
56819
  isExpired(timestamp) {
57144
56820
  const now = Date.now();
@@ -57736,6 +57412,11 @@ var init_client = __esm(() => {
57736
57412
  });
57737
57413
 
57738
57414
  // src/domains/github/github-client.ts
57415
+ var exports_github_client = {};
57416
+ __export(exports_github_client, {
57417
+ GitHubClient: () => GitHubClient
57418
+ });
57419
+
57739
57420
  class GitHubClient {
57740
57421
  releasesApi;
57741
57422
  repoApi;
@@ -57772,45 +57453,387 @@ var init_github_client = __esm(() => {
57772
57453
  init_client();
57773
57454
  });
57774
57455
 
57775
- // src/domains/versioning/checking/version-utils.ts
57776
- function isUpdateCheckDisabled() {
57777
- return process.env.NO_UPDATE_NOTIFIER === "1" || process.env.NO_UPDATE_NOTIFIER === "true" || !process.stdout.isTTY;
57456
+ // src/commands/update-cli.ts
57457
+ import { exec as exec2 } from "node:child_process";
57458
+ import { join as join42 } from "node:path";
57459
+ import { promisify as promisify8 } from "node:util";
57460
+ function getDefaultUpdateCliCommandDeps() {
57461
+ return {
57462
+ currentVersion: package_default.version,
57463
+ execAsyncFn: execAsync2,
57464
+ packageManagerDetector: PackageManagerDetector,
57465
+ npmRegistryClient: NpmRegistryClient,
57466
+ promptKitUpdateFn: promptKitUpdate
57467
+ };
57778
57468
  }
57779
- function normalizeVersion(version) {
57780
- return version.replace(/^v/i, "");
57469
+ function extractCommandStdout(result) {
57470
+ if (typeof result === "string") {
57471
+ return result;
57472
+ }
57473
+ if (result && typeof result.stdout === "string") {
57474
+ return result.stdout;
57475
+ }
57476
+ return "";
57781
57477
  }
57782
- function parseVersionParts(version) {
57783
- const normalized = normalizeVersion(version);
57784
- const [base, ...prereleaseParts] = normalized.split("-");
57478
+ function redactCommandForLog(command) {
57479
+ if (!command)
57480
+ return command;
57481
+ const redactedRegistryFlags = command.replace(/(--registry(?:=|\s+))(['"]?)(\S+?)(\2)(?=\s|$)/g, (_match, prefix, quote, url) => `${prefix}${quote}${redactRegistryUrlForLog(url)}${quote}`);
57482
+ return redactedRegistryFlags.replace(/https?:\/\/[^\s"']+/g, (url) => redactRegistryUrlForLog(url));
57483
+ }
57484
+ function buildInitCommand(isGlobal, kit, beta) {
57485
+ const parts = ["ck init"];
57486
+ if (isGlobal)
57487
+ parts.push("-g");
57488
+ if (kit)
57489
+ parts.push(`--kit ${kit}`);
57490
+ parts.push("--yes --install-skills");
57491
+ if (beta)
57492
+ parts.push("--beta");
57493
+ return parts.join(" ");
57494
+ }
57495
+ function isBetaVersion(version) {
57496
+ if (!version)
57497
+ return false;
57498
+ return /-(beta|alpha|rc|dev)[.\d]/i.test(version);
57499
+ }
57500
+ function parseCliVersionFromOutput(output2) {
57501
+ if (!output2)
57502
+ return null;
57503
+ const match = output2.match(/CLI Version:\s*(\S+)/);
57504
+ return match ? match[1] : null;
57505
+ }
57506
+ function selectKitForUpdate(params) {
57507
+ const { hasLocal, hasGlobal, localKits, globalKits } = params;
57508
+ const hasLocalKit = localKits.length > 0 || hasLocal;
57509
+ const hasGlobalKit = globalKits.length > 0 || hasGlobal;
57510
+ if (!hasLocalKit && !hasGlobalKit) {
57511
+ return null;
57512
+ }
57513
+ if (hasGlobalKit && !hasLocalKit) {
57514
+ const kit2 = globalKits[0] || localKits[0];
57515
+ return {
57516
+ isGlobal: true,
57517
+ kit: kit2,
57518
+ promptMessage: `Update global ClaudeKit content${kit2 ? ` (${kit2})` : ""}?`
57519
+ };
57520
+ }
57521
+ if (hasLocalKit && !hasGlobalKit) {
57522
+ const kit2 = localKits[0] || globalKits[0];
57523
+ return {
57524
+ isGlobal: false,
57525
+ kit: kit2,
57526
+ promptMessage: `Update local project ClaudeKit content${kit2 ? ` (${kit2})` : ""}?`
57527
+ };
57528
+ }
57529
+ const kit = globalKits[0] || localKits[0];
57785
57530
  return {
57786
- base,
57787
- prerelease: prereleaseParts.length > 0 ? prereleaseParts.join("-") : null
57531
+ isGlobal: true,
57532
+ kit,
57533
+ promptMessage: `Update global ClaudeKit content${kit ? ` (${kit})` : ""}?`
57788
57534
  };
57789
57535
  }
57790
- function isDevPrereleaseOfSameBase(currentVersion, latestVersion) {
57791
- const current = parseVersionParts(currentVersion);
57792
- const latest = parseVersionParts(latestVersion);
57793
- if (!current.prerelease?.startsWith("dev"))
57794
- return false;
57795
- if (latest.prerelease !== null)
57796
- return false;
57797
- return current.base === latest.base;
57536
+ async function readMetadataFile(claudeDir2) {
57537
+ const metadataPath = join42(claudeDir2, "metadata.json");
57538
+ try {
57539
+ if (!await import_fs_extra5.pathExists(metadataPath)) {
57540
+ return null;
57541
+ }
57542
+ const content = await import_fs_extra5.readFile(metadataPath, "utf-8");
57543
+ const parsed = JSON.parse(content);
57544
+ const validated = MetadataSchema.safeParse(parsed);
57545
+ if (!validated.success) {
57546
+ logger.verbose(`Invalid metadata format: ${validated.error.message}`);
57547
+ return null;
57548
+ }
57549
+ return validated.data;
57550
+ } catch (error) {
57551
+ logger.verbose(`Failed to read metadata: ${error instanceof Error ? error.message : "unknown"}`);
57552
+ return null;
57553
+ }
57798
57554
  }
57799
- function isNewerVersion(currentVersion, latestVersion) {
57555
+ async function fetchLatestReleaseTag(kit, beta) {
57800
57556
  try {
57801
- const current = normalizeVersion(currentVersion);
57802
- const latest = normalizeVersion(latestVersion);
57803
- if (isDevPrereleaseOfSameBase(current, latest)) {
57804
- return false;
57557
+ const { GitHubClient: GitHubClient2 } = await Promise.resolve().then(() => (init_github_client(), exports_github_client));
57558
+ const github = new GitHubClient2;
57559
+ const kitConfig = AVAILABLE_KITS[kit];
57560
+ const release = await github.getLatestRelease(kitConfig, beta);
57561
+ return release.tag_name;
57562
+ } catch (error) {
57563
+ logger.verbose(`Could not fetch latest release tag: ${error instanceof Error ? error.message : "unknown"}`);
57564
+ return null;
57565
+ }
57566
+ }
57567
+ async function promptKitUpdate(beta, yes, deps) {
57568
+ try {
57569
+ const execFn = deps?.execAsyncFn ?? execAsync2;
57570
+ const setup = await (deps?.getSetupFn ?? getClaudeKitSetup)();
57571
+ const hasLocal = !!setup.project.metadata;
57572
+ const hasGlobal = !!setup.global.metadata;
57573
+ const localMetadata = hasLocal ? await readMetadataFile(setup.project.path) : null;
57574
+ const globalMetadata = hasGlobal ? await readMetadataFile(setup.global.path) : null;
57575
+ const localKits = localMetadata ? getInstalledKits(localMetadata) : [];
57576
+ const globalKits = globalMetadata ? getInstalledKits(globalMetadata) : [];
57577
+ const selection = selectKitForUpdate({ hasLocal, hasGlobal, localKits, globalKits });
57578
+ if (!selection) {
57579
+ logger.verbose("No ClaudeKit installations detected, skipping kit update prompt");
57580
+ return;
57805
57581
  }
57806
- return import_compare_versions3.compareVersions(latest, current) > 0;
57807
- } catch {
57808
- return false;
57582
+ const kitVersion = selection.kit ? selection.isGlobal ? globalMetadata?.kits?.[selection.kit]?.version : localMetadata?.kits?.[selection.kit]?.version : undefined;
57583
+ const isBetaInstalled = isBetaVersion(kitVersion);
57584
+ const initCmd = buildInitCommand(selection.isGlobal, selection.kit, beta || isBetaInstalled);
57585
+ const promptMessage = selection.promptMessage;
57586
+ if (selection.kit && kitVersion) {
57587
+ logger.info(`Current kit version: ${selection.kit}@${kitVersion}`);
57588
+ }
57589
+ if (yes && selection.kit && kitVersion) {
57590
+ const getTagFn = deps?.getLatestReleaseTagFn ?? fetchLatestReleaseTag;
57591
+ const latestTag = await getTagFn(selection.kit, beta || isBetaInstalled);
57592
+ if (latestTag && versionsMatch(kitVersion, latestTag)) {
57593
+ logger.success(`Already at latest version (${selection.kit}@${kitVersion}), skipping reinstall`);
57594
+ return;
57595
+ }
57596
+ if (latestTag) {
57597
+ logger.info(`Kit update available: ${kitVersion} -> ${latestTag}`);
57598
+ }
57599
+ }
57600
+ if (!yes) {
57601
+ logger.info("");
57602
+ const shouldUpdate = await se({
57603
+ message: promptMessage
57604
+ });
57605
+ if (lD(shouldUpdate) || !shouldUpdate) {
57606
+ log.info("Skipped kit content update");
57607
+ return;
57608
+ }
57609
+ } else {
57610
+ logger.verbose("Auto-proceeding with kit update (--yes flag)");
57611
+ }
57612
+ logger.info(`Running: ${initCmd}`);
57613
+ const s = (deps?.spinnerFn ?? de)();
57614
+ s.start("Updating ClaudeKit content...");
57615
+ try {
57616
+ await execFn(initCmd, {
57617
+ timeout: 300000
57618
+ });
57619
+ let newKitVersion;
57620
+ try {
57621
+ const claudeDir2 = selection.isGlobal ? setup.global.path : setup.project.path;
57622
+ const updatedMetadata = await readMetadataFile(claudeDir2);
57623
+ newKitVersion = selection.kit ? updatedMetadata?.kits?.[selection.kit]?.version : undefined;
57624
+ } catch {}
57625
+ if (selection.kit && kitVersion && newKitVersion && kitVersion !== newKitVersion) {
57626
+ s.stop(`Kit updated: ${selection.kit}@${kitVersion} -> ${newKitVersion}`);
57627
+ } else if (selection.kit && newKitVersion) {
57628
+ s.stop(`Kit content updated (${selection.kit}@${newKitVersion})`);
57629
+ } else {
57630
+ s.stop("Kit content updated");
57631
+ }
57632
+ } catch (error) {
57633
+ s.stop("Kit update finished");
57634
+ const errorMsg = error instanceof Error ? error.message : "unknown";
57635
+ if (errorMsg.includes("exit code") && !errorMsg.includes("exit code 0")) {
57636
+ logger.warning("Kit content update may have encountered issues");
57637
+ logger.verbose(`Error: ${errorMsg}`);
57638
+ } else {
57639
+ logger.verbose(`Init command completed: ${errorMsg}`);
57640
+ }
57641
+ }
57642
+ } catch (error) {
57643
+ logger.verbose(`Failed to prompt for kit update: ${error instanceof Error ? error.message : "unknown error"}`);
57809
57644
  }
57810
57645
  }
57811
- var import_compare_versions3;
57812
- var init_version_utils = __esm(() => {
57646
+ async function updateCliCommand(options2, deps = getDefaultUpdateCliCommandDeps()) {
57647
+ const s = de();
57648
+ intro("[>] ClaudeKit CLI - Update");
57649
+ try {
57650
+ const {
57651
+ currentVersion,
57652
+ execAsyncFn,
57653
+ packageManagerDetector,
57654
+ npmRegistryClient,
57655
+ promptKitUpdateFn
57656
+ } = deps;
57657
+ const opts = UpdateCliOptionsSchema.parse(options2);
57658
+ logger.info(`Current CLI version: ${currentVersion}`);
57659
+ s.start("Detecting package manager...");
57660
+ const pm = await packageManagerDetector.detect();
57661
+ const pmVersion = await packageManagerDetector.getVersion(pm);
57662
+ s.stop(`Using ${packageManagerDetector.getDisplayName(pm)}${pmVersion ? ` v${pmVersion}` : ""}`);
57663
+ logger.verbose(`Detected package manager: ${pm}`);
57664
+ let registryUrl = opts.registry;
57665
+ if (!registryUrl && pm === "npm") {
57666
+ const userRegistry = await packageManagerDetector.getNpmRegistryUrl();
57667
+ if (userRegistry) {
57668
+ registryUrl = userRegistry;
57669
+ logger.verbose(`Using npm configured registry: ${redactRegistryUrlForLog(registryUrl)}`);
57670
+ }
57671
+ }
57672
+ s.start("Checking for updates...");
57673
+ let targetVersion = null;
57674
+ if (opts.release && opts.release !== "latest") {
57675
+ try {
57676
+ const exists = await npmRegistryClient.versionExists(CLAUDEKIT_CLI_NPM_PACKAGE_NAME, opts.release, registryUrl);
57677
+ if (!exists) {
57678
+ s.stop("Version not found");
57679
+ throw new CliUpdateError(`Version ${opts.release} does not exist on npm registry. Run 'ck versions' to see available versions.`);
57680
+ }
57681
+ } catch (error) {
57682
+ if (error instanceof CliUpdateError) {
57683
+ throw error;
57684
+ }
57685
+ s.stop("Version check failed");
57686
+ const message = error instanceof Error ? error.message : "Unknown error";
57687
+ logger.verbose(`Release check failed for ${opts.release}: ${message}`);
57688
+ const registryHint = registryUrl ? ` (${redactRegistryUrlForLog(registryUrl)})` : " (default registry)";
57689
+ throw new CliUpdateError(`Failed to verify version ${opts.release} on npm registry${registryHint}. Check registry settings/network connectivity and try again.`);
57690
+ }
57691
+ targetVersion = opts.release;
57692
+ s.stop(`Target version: ${targetVersion}`);
57693
+ } else if (opts.dev || opts.beta) {
57694
+ targetVersion = await npmRegistryClient.getDevVersion(CLAUDEKIT_CLI_NPM_PACKAGE_NAME, registryUrl);
57695
+ if (!targetVersion) {
57696
+ s.stop("No dev version available");
57697
+ logger.warning("No dev version found. Using latest stable version instead.");
57698
+ targetVersion = await npmRegistryClient.getLatestVersion(CLAUDEKIT_CLI_NPM_PACKAGE_NAME, registryUrl);
57699
+ } else {
57700
+ s.stop(`Latest dev version: ${targetVersion}`);
57701
+ }
57702
+ } else {
57703
+ targetVersion = await npmRegistryClient.getLatestVersion(CLAUDEKIT_CLI_NPM_PACKAGE_NAME, registryUrl);
57704
+ s.stop(`Latest version: ${targetVersion || "unknown"}`);
57705
+ }
57706
+ if (!targetVersion) {
57707
+ throw new CliUpdateError(`Failed to fetch version information from npm registry. Check your internet connection and try again. Manual update: ${packageManagerDetector.getUpdateCommand(pm, CLAUDEKIT_CLI_NPM_PACKAGE_NAME, undefined, registryUrl)}`);
57708
+ }
57709
+ const comparison = import_compare_versions3.compareVersions(currentVersion, targetVersion);
57710
+ if (comparison === 0) {
57711
+ outro(`[+] Already on the latest CLI version (${currentVersion})`);
57712
+ await promptKitUpdateFn(opts.dev || opts.beta, opts.yes);
57713
+ return;
57714
+ }
57715
+ const isDevChannelSwitch = (opts.dev || opts.beta) && isBetaVersion(targetVersion) && !isBetaVersion(currentVersion);
57716
+ if (comparison > 0 && !opts.release && !isDevChannelSwitch) {
57717
+ outro(`[+] Current version (${currentVersion}) is newer than latest (${targetVersion})`);
57718
+ return;
57719
+ }
57720
+ const isUpgrade = comparison < 0 || isDevChannelSwitch;
57721
+ const changeType = isUpgrade ? "upgrade" : "downgrade";
57722
+ logger.info(`${isUpgrade ? "[^]" : "[v]"} ${changeType}: ${currentVersion} -> ${targetVersion}`);
57723
+ if (opts.check) {
57724
+ note(`CLI update available: ${currentVersion} -> ${targetVersion}
57725
+
57726
+ Run 'ck update' to install`, "Update Check");
57727
+ await promptKitUpdateFn(opts.dev || opts.beta, opts.yes);
57728
+ outro("Check complete");
57729
+ return;
57730
+ }
57731
+ if (!opts.yes) {
57732
+ const shouldUpdate = await se({
57733
+ message: `${isUpgrade ? "Update" : "Downgrade"} CLI from ${currentVersion} to ${targetVersion}?`
57734
+ });
57735
+ if (lD(shouldUpdate) || !shouldUpdate) {
57736
+ outro("Update cancelled");
57737
+ return;
57738
+ }
57739
+ }
57740
+ const updateCmd = packageManagerDetector.getUpdateCommand(pm, CLAUDEKIT_CLI_NPM_PACKAGE_NAME, targetVersion, registryUrl);
57741
+ logger.info(`Running: ${redactCommandForLog(updateCmd)}`);
57742
+ s.start("Updating CLI...");
57743
+ try {
57744
+ await execAsyncFn(updateCmd, {
57745
+ timeout: 120000
57746
+ });
57747
+ s.stop("Update completed");
57748
+ } catch (error) {
57749
+ s.stop("Update failed");
57750
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
57751
+ if (errorMessage.includes("EACCES") || errorMessage.includes("EPERM") || errorMessage.includes("permission") || errorMessage.includes("Access is denied")) {
57752
+ const permHint = pm === "npm" ? `
57753
+
57754
+ Or fix npm permissions: https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally` : "";
57755
+ const isWindows3 = process.platform === "win32";
57756
+ const elevationHint = isWindows3 ? `Run your terminal as Administrator and retry: ${updateCmd}` : `sudo ${updateCmd}`;
57757
+ throw new CliUpdateError(`Permission denied. Try: ${elevationHint}${permHint}`);
57758
+ }
57759
+ logger.error(`Update failed: ${errorMessage}`);
57760
+ logger.info(`Try running: ${redactCommandForLog(updateCmd)}`);
57761
+ throw new CliUpdateError(`Update failed: ${errorMessage}
57762
+
57763
+ Manual update: ${updateCmd}`);
57764
+ }
57765
+ s.start("Verifying installation...");
57766
+ try {
57767
+ const versionResult = await execAsyncFn("ck --version", { timeout: 5000 });
57768
+ const stdout = extractCommandStdout(versionResult);
57769
+ const activeVersion = parseCliVersionFromOutput(stdout);
57770
+ if (!activeVersion) {
57771
+ s.stop("Verification failed");
57772
+ const message = `Update completed but could not parse 'ck --version' output.
57773
+ Please restart your terminal and run 'ck --version'. Expected: ${targetVersion}
57774
+
57775
+ Manual update: ${redactCommandForLog(updateCmd)}`;
57776
+ logger.error(message);
57777
+ throw new CliUpdateError(message);
57778
+ }
57779
+ s.stop(`Installed version: ${activeVersion}`);
57780
+ if (activeVersion !== targetVersion) {
57781
+ const mismatchMessage = `Update did not activate the requested version.
57782
+ Expected: ${targetVersion}
57783
+ Active ck: ${activeVersion}
57784
+
57785
+ Likely causes: multiple global installations (npm/bun/pnpm/yarn) or stale shell shim/cache (common on Windows).
57786
+ Run '${redactCommandForLog(updateCmd)}' manually, restart terminal, then check command resolution:
57787
+ - Windows: where ck
57788
+ - macOS/Linux: which -a ck`;
57789
+ logger.error(mismatchMessage);
57790
+ throw new CliUpdateError(mismatchMessage);
57791
+ }
57792
+ outro(`[+] Successfully updated ClaudeKit CLI to ${activeVersion}`);
57793
+ await promptKitUpdateFn(opts.dev || opts.beta, opts.yes);
57794
+ } catch (error) {
57795
+ if (error instanceof CliUpdateError) {
57796
+ throw error;
57797
+ }
57798
+ s.stop("Verification failed");
57799
+ const message = `Update completed but automatic verification failed.
57800
+ Please restart your terminal and run 'ck --version'. Expected: ${targetVersion}
57801
+
57802
+ Manual update: ${redactCommandForLog(updateCmd)}`;
57803
+ logger.error(message);
57804
+ throw new CliUpdateError(message);
57805
+ }
57806
+ } catch (error) {
57807
+ if (error instanceof CliUpdateError) {
57808
+ throw error;
57809
+ }
57810
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
57811
+ logger.error(`Update failed: ${errorMessage}`);
57812
+ throw new CliUpdateError(errorMessage);
57813
+ }
57814
+ }
57815
+ var import_compare_versions3, import_fs_extra5, execAsync2, CliUpdateError;
57816
+ var init_update_cli = __esm(() => {
57817
+ init_npm_registry();
57818
+ init_package_manager_detector();
57819
+ init_metadata_migration();
57820
+ init_version_utils();
57821
+ init_claudekit_scanner();
57822
+ init_claudekit_constants();
57823
+ init_logger();
57824
+ init_safe_prompts();
57825
+ init_types3();
57826
+ init_types3();
57827
+ init_package();
57813
57828
  import_compare_versions3 = __toESM(require_umd(), 1);
57829
+ import_fs_extra5 = __toESM(require_lib3(), 1);
57830
+ execAsync2 = promisify8(exec2);
57831
+ CliUpdateError = class CliUpdateError extends ClaudeKitError {
57832
+ constructor(message) {
57833
+ super(message, "CLI_UPDATE_ERROR");
57834
+ this.name = "CliUpdateError";
57835
+ }
57836
+ };
57814
57837
  });
57815
57838
 
57816
57839
  // src/domains/versioning/version-cache.ts
@@ -91106,6 +91129,7 @@ async function handleFreshInstallation(claudeDir2, prompts) {
91106
91129
  }
91107
91130
 
91108
91131
  // src/commands/init/phases/selection-handler.ts
91132
+ init_version_utils();
91109
91133
  init_claudekit_scanner();
91110
91134
  init_logger();
91111
91135
  init_path_resolver();
@@ -91426,6 +91450,21 @@ async function handleSelection(ctx) {
91426
91450
  logger.success(`Found: ${release.tag_name}`);
91427
91451
  }
91428
91452
  }
91453
+ const releaseTag = release?.tag_name;
91454
+ if (ctx.options.yes && !ctx.options.fresh && releaseTag && !isOfflineMode && !pendingKits?.length) {
91455
+ try {
91456
+ const prefix = PathResolver.getPathPrefix(ctx.options.global);
91457
+ const claudeDir2 = prefix ? join106(resolvedDir, prefix) : resolvedDir;
91458
+ const existingMetadata = await readManifest(claudeDir2);
91459
+ const installedKitVersion = existingMetadata?.kits?.[kitType]?.version;
91460
+ if (installedKitVersion && versionsMatch(installedKitVersion, releaseTag)) {
91461
+ logger.success(`Already at latest version (${kitType}@${installedKitVersion}), skipping reinstall`);
91462
+ return { ...ctx, cancelled: true };
91463
+ }
91464
+ } catch (error) {
91465
+ logger.verbose(`Metadata read failed, proceeding with installation: ${error instanceof Error ? error.message : "unknown"}`);
91466
+ }
91467
+ }
91429
91468
  return {
91430
91469
  ...ctx,
91431
91470
  kit,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudekit-cli",
3
- "version": "3.36.0-dev.17",
3
+ "version": "3.36.0-dev.19",
4
4
  "description": "CLI tool for bootstrapping and updating ClaudeKit projects",
5
5
  "type": "module",
6
6
  "repository": {