claudekit-cli 3.41.1-dev.3 → 3.41.1-dev.4

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 +710 -613
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -56493,6 +56493,11 @@ var init_skill_routes = __esm(() => {
56493
56493
  });
56494
56494
 
56495
56495
  // src/domains/github/npm-registry.ts
56496
+ var exports_npm_registry = {};
56497
+ __export(exports_npm_registry, {
56498
+ redactRegistryUrlForLog: () => redactRegistryUrlForLog,
56499
+ NpmRegistryClient: () => NpmRegistryClient
56500
+ });
56496
56501
  function redactRegistryUrlForLog(url) {
56497
56502
  if (!url)
56498
56503
  return url;
@@ -57189,232 +57194,182 @@ var init_package_manager_detector = __esm(() => {
57189
57194
  };
57190
57195
  });
57191
57196
 
57192
- // src/domains/migration/metadata-migration.ts
57193
- import { join as join45 } from "node:path";
57194
- async function detectMetadataFormat(claudeDir2) {
57195
- const metadataPath = join45(claudeDir2, "metadata.json");
57196
- if (!await import_fs_extra3.pathExists(metadataPath)) {
57197
- return { format: "none", metadata: null, detectedKit: null };
57198
- }
57199
- try {
57200
- const content = await import_fs_extra3.readFile(metadataPath, "utf-8");
57201
- const parsed = JSON.parse(content);
57202
- if (parsed.kits && Object.keys(parsed.kits).length > 0) {
57203
- const installedKits = Object.keys(parsed.kits);
57204
- return {
57205
- format: "multi-kit",
57206
- metadata: parsed,
57207
- detectedKit: installedKits[0] || null
57208
- };
57197
+ // package.json
57198
+ var package_default;
57199
+ var init_package = __esm(() => {
57200
+ package_default = {
57201
+ name: "claudekit-cli",
57202
+ version: "3.41.1-dev.4",
57203
+ description: "CLI tool for bootstrapping and updating ClaudeKit projects",
57204
+ type: "module",
57205
+ repository: {
57206
+ type: "git",
57207
+ url: "git+https://github.com/mrgoonie/claudekit-cli.git"
57208
+ },
57209
+ publishConfig: {
57210
+ access: "public",
57211
+ registry: "https://registry.npmjs.org"
57212
+ },
57213
+ bin: {
57214
+ ck: "bin/ck.js"
57215
+ },
57216
+ files: [
57217
+ "bin/ck.js",
57218
+ "dist/index.js",
57219
+ "dist/ui/"
57220
+ ],
57221
+ scripts: {
57222
+ tauri: "tauri",
57223
+ "tauri:dev": "tauri dev",
57224
+ "tauri:build": "tauri build",
57225
+ dev: "bun run src/index.ts",
57226
+ "dashboard:dev": "cd src/ui && bun install --silent && cd ../.. && bun run src/index.ts config ui --dev",
57227
+ "dashboard:tauri": "cd src/ui && bun install --silent && cd ../.. && bun run src/index.ts config ui --dev --no-open --port 3456",
57228
+ "ui:build": "cd src/ui && bun install --silent && bun run build",
57229
+ "ui:dev": "cd src/ui && bun run dev",
57230
+ build: `bun build src/index.ts --outdir dist --target node --external @octokit/rest --external better-sqlite3 && node -e "const fs=require('fs'),f='dist/index.js',c=fs.readFileSync(f,'utf-8');fs.writeFileSync(f,c.replace(/^#!.*\\n\\/\\/ @bun\\n/,''))"`,
57231
+ "verify:package": "node scripts/prepublish-check.js",
57232
+ test: "bun test",
57233
+ "test:integration": "CK_RUN_CLI_INTEGRATION=1 bun test tests/integration/cli.test.ts",
57234
+ "test:watch": "bun test --watch",
57235
+ "test:quick": "./scripts/dev-quick-start.sh test",
57236
+ lint: "biome check .",
57237
+ "lint:fix": "biome check --fix .",
57238
+ "lint:fix-unsafe": "biome check --fix --unsafe .",
57239
+ format: "biome format --write .",
57240
+ typecheck: "tsc --noEmit",
57241
+ "dev:quick": "./scripts/dev-quick-start.sh",
57242
+ "dev:all": "./scripts/dev-quick-start.sh all",
57243
+ metrics: "bun run scripts/workflow-metrics.ts",
57244
+ validate: "bun run typecheck && bun run lint && bun test && bun run build",
57245
+ "install:hooks": "./.githooks/install.sh",
57246
+ prepare: `node -e "try{require('child_process').execSync('git rev-parse --git-dir',{stdio:'ignore'});require('child_process').execSync('bash .githooks/install.sh',{stdio:'inherit'})}catch(e){console.warn('[i] Hook install skipped:',e.message)}"`
57247
+ },
57248
+ keywords: [
57249
+ "cli",
57250
+ "claudekit",
57251
+ "boilerplate",
57252
+ "bootstrap",
57253
+ "template"
57254
+ ],
57255
+ author: "ClaudeKit",
57256
+ license: "MIT",
57257
+ engines: {
57258
+ node: ">=18.0.0"
57259
+ },
57260
+ dependencies: {
57261
+ "@clack/prompts": "^0.7.0",
57262
+ "@octokit/rest": "^22.0.0",
57263
+ "better-sqlite3": "^12.6.2",
57264
+ cac: "^6.7.14",
57265
+ chokidar: "^5.0.0",
57266
+ "cli-progress": "^3.12.0",
57267
+ "compare-versions": "^6.1.1",
57268
+ diff: "^8.0.3",
57269
+ express: "^5.2.1",
57270
+ "extract-zip": "^2.0.1",
57271
+ "fs-extra": "^11.2.0",
57272
+ "get-port": "^7.1.0",
57273
+ "gray-matter": "^4.0.3",
57274
+ ignore: "^5.3.2",
57275
+ minimatch: "^10.1.1",
57276
+ open: "^11.0.0",
57277
+ ora: "^8.0.0",
57278
+ "p-limit": "^7.2.0",
57279
+ picocolors: "^1.1.1",
57280
+ picomatch: "^4.0.3",
57281
+ "proper-lockfile": "^4.1.2",
57282
+ semver: "^7.7.3",
57283
+ tar: "^7.4.3",
57284
+ tmp: "^0.2.3",
57285
+ ws: "^8.19.0",
57286
+ zod: "^3.23.8"
57287
+ },
57288
+ devDependencies: {
57289
+ "@biomejs/biome": "^1.9.4",
57290
+ "@semantic-release/changelog": "^6.0.3",
57291
+ "@semantic-release/git": "^10.0.1",
57292
+ "@tauri-apps/cli": "^2",
57293
+ "@types/better-sqlite3": "^7.6.13",
57294
+ "@types/bun": "latest",
57295
+ "@types/cli-progress": "^3.11.6",
57296
+ "@types/diff": "^8.0.0",
57297
+ "@types/express": "^5.0.6",
57298
+ "@types/fs-extra": "^11.0.4",
57299
+ "@types/node": "^22.19.7",
57300
+ "@types/picomatch": "^4.0.2",
57301
+ "@types/proper-lockfile": "^4.1.4",
57302
+ "@types/semver": "^7.7.1",
57303
+ "@types/tar": "^6.1.13",
57304
+ "@types/tmp": "^0.2.6",
57305
+ "@types/ws": "^8.18.1",
57306
+ "conventional-changelog-conventionalcommits": "^9.1.0",
57307
+ "semantic-release": "^24.2.0",
57308
+ typescript: "^5.7.2"
57209
57309
  }
57210
- if (parsed.name || parsed.version || parsed.files) {
57211
- let detectedKit = null;
57212
- const nameToCheck = parsed.name || "";
57213
- if (/\bengineer\b/i.test(nameToCheck)) {
57214
- detectedKit = "engineer";
57215
- } else if (/\bmarketing\b/i.test(nameToCheck)) {
57216
- detectedKit = "marketing";
57217
- } else {
57218
- detectedKit = "engineer";
57310
+ };
57311
+ });
57312
+
57313
+ // node_modules/compare-versions/lib/umd/index.js
57314
+ var require_umd = __commonJS((exports, module) => {
57315
+ (function(global3, factory) {
57316
+ typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define(["exports"], factory) : (global3 = typeof globalThis !== "undefined" ? globalThis : global3 || self, factory(global3.compareVersions = {}));
57317
+ })(exports, function(exports2) {
57318
+ const semver2 = /^[v^~<>=]*?(\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+))?(?:-([\da-z\-]+(?:\.[\da-z\-]+)*))?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i;
57319
+ const validateAndParse = (version) => {
57320
+ if (typeof version !== "string") {
57321
+ throw new TypeError("Invalid argument expected string");
57219
57322
  }
57220
- return { format: "legacy", metadata: parsed, detectedKit };
57221
- }
57222
- logger.warning("Metadata file exists but has unrecognized format (missing kits, name, version, or files)");
57223
- return { format: "none", metadata: null, detectedKit: null };
57224
- } catch (error) {
57225
- logger.warning(`Failed to read metadata file (may be corrupted): ${error}`);
57226
- return { format: "none", metadata: null, detectedKit: null };
57227
- }
57228
- }
57229
- async function migrateToMultiKit(claudeDir2) {
57230
- const detection = await detectMetadataFormat(claudeDir2);
57231
- if (detection.format === "multi-kit") {
57232
- return {
57233
- success: true,
57234
- migrated: false,
57235
- fromFormat: "multi-kit",
57236
- toFormat: "multi-kit"
57323
+ const match = version.match(semver2);
57324
+ if (!match) {
57325
+ throw new Error(`Invalid argument not valid semver ('${version}' received)`);
57326
+ }
57327
+ match.shift();
57328
+ return match;
57237
57329
  };
57238
- }
57239
- if (detection.format === "none") {
57240
- return {
57241
- success: true,
57242
- migrated: false,
57243
- fromFormat: "none",
57244
- toFormat: "multi-kit"
57330
+ const isWildcard = (s) => s === "*" || s === "x" || s === "X";
57331
+ const tryParse = (v2) => {
57332
+ const n = parseInt(v2, 10);
57333
+ return isNaN(n) ? v2 : n;
57245
57334
  };
57246
- }
57247
- const metadataPath = join45(claudeDir2, "metadata.json");
57248
- const legacy = detection.metadata;
57249
- if (!legacy) {
57250
- return {
57251
- success: false,
57252
- migrated: false,
57253
- fromFormat: "legacy",
57254
- toFormat: "multi-kit",
57255
- error: "Metadata exists but could not be read"
57335
+ const forceType = (a3, b3) => typeof a3 !== typeof b3 ? [String(a3), String(b3)] : [a3, b3];
57336
+ const compareStrings = (a3, b3) => {
57337
+ if (isWildcard(a3) || isWildcard(b3))
57338
+ return 0;
57339
+ const [ap, bp] = forceType(tryParse(a3), tryParse(b3));
57340
+ if (ap > bp)
57341
+ return 1;
57342
+ if (ap < bp)
57343
+ return -1;
57344
+ return 0;
57256
57345
  };
57257
- }
57258
- const legacyKit = detection.detectedKit || "engineer";
57259
- try {
57260
- const kitMetadata = {
57261
- version: legacy.version || "unknown",
57262
- installedAt: legacy.installedAt || new Date().toISOString(),
57263
- files: legacy.files || []
57346
+ const compareSegments = (a3, b3) => {
57347
+ for (let i = 0;i < Math.max(a3.length, b3.length); i++) {
57348
+ const r2 = compareStrings(a3[i] || "0", b3[i] || "0");
57349
+ if (r2 !== 0)
57350
+ return r2;
57351
+ }
57352
+ return 0;
57264
57353
  };
57265
- const multiKit = {
57266
- kits: {
57267
- [legacyKit]: kitMetadata
57268
- },
57269
- scope: legacy.scope,
57270
- name: legacy.name,
57271
- version: legacy.version,
57272
- installedAt: legacy.installedAt,
57273
- installedFiles: legacy.installedFiles,
57274
- userConfigFiles: legacy.userConfigFiles,
57275
- files: legacy.files
57354
+ const compareVersions = (v1, v2) => {
57355
+ const n1 = validateAndParse(v1);
57356
+ const n2 = validateAndParse(v2);
57357
+ const p1 = n1.pop();
57358
+ const p2 = n2.pop();
57359
+ const r2 = compareSegments(n1, n2);
57360
+ if (r2 !== 0)
57361
+ return r2;
57362
+ if (p1 && p2) {
57363
+ return compareSegments(p1.split("."), p2.split("."));
57364
+ } else if (p1 || p2) {
57365
+ return p1 ? -1 : 1;
57366
+ }
57367
+ return 0;
57276
57368
  };
57277
- await import_fs_extra3.writeFile(metadataPath, JSON.stringify(multiKit, null, 2), "utf-8");
57278
- logger.info(`Migrated metadata from legacy format to multi-kit (detected: ${legacyKit})`);
57279
- return {
57280
- success: true,
57281
- migrated: true,
57282
- fromFormat: "legacy",
57283
- toFormat: "multi-kit"
57284
- };
57285
- } catch (error) {
57286
- const errorMsg = error instanceof Error ? error.message : "Unknown error";
57287
- logger.error(`Metadata migration failed: ${errorMsg}`);
57288
- return {
57289
- success: false,
57290
- migrated: false,
57291
- fromFormat: "legacy",
57292
- toFormat: "multi-kit",
57293
- error: errorMsg
57294
- };
57295
- }
57296
- }
57297
- function getKitMetadata(metadata, kit) {
57298
- if (metadata.kits?.[kit]) {
57299
- return metadata.kits[kit];
57300
- }
57301
- if (!metadata.kits && metadata.version) {
57302
- return {
57303
- version: metadata.version,
57304
- installedAt: metadata.installedAt || "",
57305
- files: metadata.files
57306
- };
57307
- }
57308
- return null;
57309
- }
57310
- function getAllTrackedFiles(metadata) {
57311
- if (metadata.kits) {
57312
- const allFiles = [];
57313
- for (const kit of Object.values(metadata.kits)) {
57314
- if (kit.files) {
57315
- allFiles.push(...kit.files);
57316
- }
57317
- }
57318
- return allFiles;
57319
- }
57320
- return metadata.files || [];
57321
- }
57322
- function getTrackedFilesForKit(metadata, kitType) {
57323
- if (metadata.kits?.[kitType]) {
57324
- return metadata.kits[kitType].files || [];
57325
- }
57326
- const detectedKits = getInstalledKits(metadata);
57327
- if (detectedKits.includes(kitType)) {
57328
- return metadata.files || [];
57329
- }
57330
- return [];
57331
- }
57332
- function getInstalledKits(metadata) {
57333
- if (metadata.kits) {
57334
- return Object.keys(metadata.kits);
57335
- }
57336
- const nameToCheck = metadata.name || "";
57337
- const kits = [];
57338
- if (/\bengineer\b/i.test(nameToCheck)) {
57339
- kits.push("engineer");
57340
- }
57341
- if (/\bmarketing\b/i.test(nameToCheck)) {
57342
- kits.push("marketing");
57343
- }
57344
- if (kits.length > 0) {
57345
- return kits;
57346
- }
57347
- if (metadata.version) {
57348
- return ["engineer"];
57349
- }
57350
- return [];
57351
- }
57352
- var import_fs_extra3;
57353
- var init_metadata_migration = __esm(() => {
57354
- init_logger();
57355
- import_fs_extra3 = __toESM(require_lib3(), 1);
57356
- });
57357
-
57358
- // node_modules/compare-versions/lib/umd/index.js
57359
- var require_umd = __commonJS((exports, module) => {
57360
- (function(global3, factory) {
57361
- typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define(["exports"], factory) : (global3 = typeof globalThis !== "undefined" ? globalThis : global3 || self, factory(global3.compareVersions = {}));
57362
- })(exports, function(exports2) {
57363
- const semver2 = /^[v^~<>=]*?(\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+))?(?:-([\da-z\-]+(?:\.[\da-z\-]+)*))?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i;
57364
- const validateAndParse = (version) => {
57365
- if (typeof version !== "string") {
57366
- throw new TypeError("Invalid argument expected string");
57367
- }
57368
- const match = version.match(semver2);
57369
- if (!match) {
57370
- throw new Error(`Invalid argument not valid semver ('${version}' received)`);
57371
- }
57372
- match.shift();
57373
- return match;
57374
- };
57375
- const isWildcard = (s) => s === "*" || s === "x" || s === "X";
57376
- const tryParse = (v2) => {
57377
- const n = parseInt(v2, 10);
57378
- return isNaN(n) ? v2 : n;
57379
- };
57380
- const forceType = (a3, b3) => typeof a3 !== typeof b3 ? [String(a3), String(b3)] : [a3, b3];
57381
- const compareStrings = (a3, b3) => {
57382
- if (isWildcard(a3) || isWildcard(b3))
57383
- return 0;
57384
- const [ap, bp] = forceType(tryParse(a3), tryParse(b3));
57385
- if (ap > bp)
57386
- return 1;
57387
- if (ap < bp)
57388
- return -1;
57389
- return 0;
57390
- };
57391
- const compareSegments = (a3, b3) => {
57392
- for (let i = 0;i < Math.max(a3.length, b3.length); i++) {
57393
- const r2 = compareStrings(a3[i] || "0", b3[i] || "0");
57394
- if (r2 !== 0)
57395
- return r2;
57396
- }
57397
- return 0;
57398
- };
57399
- const compareVersions = (v1, v2) => {
57400
- const n1 = validateAndParse(v1);
57401
- const n2 = validateAndParse(v2);
57402
- const p1 = n1.pop();
57403
- const p2 = n2.pop();
57404
- const r2 = compareSegments(n1, n2);
57405
- if (r2 !== 0)
57406
- return r2;
57407
- if (p1 && p2) {
57408
- return compareSegments(p1.split("."), p2.split("."));
57409
- } else if (p1 || p2) {
57410
- return p1 ? -1 : 1;
57411
- }
57412
- return 0;
57413
- };
57414
- const compare = (v1, v2, operator) => {
57415
- assertValidOperator(operator);
57416
- const res = compareVersions(v1, v2);
57417
- return operatorResMap[operator].includes(res);
57369
+ const compare = (v1, v2, operator) => {
57370
+ assertValidOperator(operator);
57371
+ const res = compareVersions(v1, v2);
57372
+ return operatorResMap[operator].includes(res);
57418
57373
  };
57419
57374
  const operatorResMap = {
57420
57375
  ">": [1],
@@ -57526,222 +57481,463 @@ var init_version_utils = __esm(() => {
57526
57481
  import_compare_versions = __toESM(require_umd(), 1);
57527
57482
  });
57528
57483
 
57529
- // src/services/file-operations/claudekit-scanner.ts
57530
- import { join as join46 } from "node:path";
57531
- async function scanClaudeKitDirectory(directoryPath) {
57532
- const counts = {
57533
- agents: 0,
57534
- commands: 0,
57535
- rules: 0,
57536
- skills: 0
57537
- };
57538
- try {
57539
- if (!await import_fs_extra4.pathExists(directoryPath)) {
57540
- return counts;
57541
- }
57542
- const items = await import_fs_extra4.readdir(directoryPath);
57543
- if (items.includes("agents")) {
57544
- const agentsPath = join46(directoryPath, "agents");
57545
- const agentFiles = await import_fs_extra4.readdir(agentsPath);
57546
- counts.agents = agentFiles.filter((file) => file.endsWith(".md")).length;
57547
- }
57548
- if (items.includes("commands")) {
57549
- const commandsPath = join46(directoryPath, "commands");
57550
- const commandFiles = await import_fs_extra4.readdir(commandsPath);
57551
- counts.commands = commandFiles.filter((file) => file.endsWith(".md")).length;
57552
- }
57553
- if (items.includes("rules")) {
57554
- const rulesPath = join46(directoryPath, "rules");
57555
- const ruleFiles = await import_fs_extra4.readdir(rulesPath);
57556
- counts.rules = ruleFiles.filter((file) => file.endsWith(".md")).length;
57557
- } else if (items.includes("workflows")) {
57558
- const workflowsPath = join46(directoryPath, "workflows");
57559
- const workflowFiles = await import_fs_extra4.readdir(workflowsPath);
57560
- counts.rules = workflowFiles.filter((file) => file.endsWith(".md")).length;
57484
+ // src/commands/update/error.ts
57485
+ var CliUpdateError;
57486
+ var init_error = __esm(() => {
57487
+ init_types3();
57488
+ CliUpdateError = class CliUpdateError extends ClaudeKitError {
57489
+ constructor(message) {
57490
+ super(message, "CLI_UPDATE_ERROR");
57491
+ this.name = "CliUpdateError";
57561
57492
  }
57562
- if (items.includes("skills")) {
57563
- const skillsPath = join46(directoryPath, "skills");
57564
- const skillItems = await import_fs_extra4.readdir(skillsPath);
57565
- let skillCount = 0;
57566
- for (const item of skillItems) {
57567
- if (SKIP_DIRS_CLAUDE_INTERNAL.includes(item)) {
57568
- continue;
57569
- }
57570
- const itemPath = join46(skillsPath, item);
57571
- const stat8 = await import_fs_extra4.readdir(itemPath).catch(() => null);
57572
- if (stat8?.includes("SKILL.md")) {
57573
- skillCount++;
57574
- }
57575
- }
57576
- counts.skills = skillCount;
57493
+ };
57494
+ });
57495
+
57496
+ // src/commands/update/channel-resolver.ts
57497
+ async function resolveTargetVersion(opts, deps) {
57498
+ const client = deps.npmRegistryClient ?? NpmRegistryClient;
57499
+ const registryUrl = deps.registryUrl ?? undefined;
57500
+ const { spinnerStop } = deps;
57501
+ if (opts.release && opts.release !== "latest") {
57502
+ let exists;
57503
+ try {
57504
+ exists = await client.versionExists(CLAUDEKIT_CLI_NPM_PACKAGE_NAME, opts.release, registryUrl);
57505
+ } catch (error) {
57506
+ spinnerStop("Version check failed");
57507
+ const message = error instanceof Error ? error.message : "Unknown error";
57508
+ logger.verbose(`Release check failed for ${opts.release}: ${message}`);
57509
+ const registryHint = registryUrl ? ` (${redactRegistryUrlForLog(registryUrl)})` : " (default registry)";
57510
+ throw new CliUpdateError(`Failed to verify version ${opts.release} on npm registry${registryHint}. Check registry settings/network connectivity and try again.`);
57511
+ }
57512
+ if (!exists) {
57513
+ spinnerStop("Version not found");
57514
+ throw new CliUpdateError(`Version ${opts.release} does not exist on npm registry. Run 'ck versions' to see available versions.`);
57515
+ }
57516
+ const targetVersion2 = opts.release;
57517
+ spinnerStop(`Target version: ${targetVersion2}`);
57518
+ return { targetVersion: targetVersion2, targetIsPrerelease: isPrereleaseVersion(targetVersion2) };
57519
+ }
57520
+ const usePrereleaseChannel = opts.dev || opts.beta;
57521
+ if (usePrereleaseChannel) {
57522
+ let targetVersion2 = await client.getDevVersion(CLAUDEKIT_CLI_NPM_PACKAGE_NAME, registryUrl);
57523
+ if (!targetVersion2) {
57524
+ spinnerStop("No dev version available");
57525
+ logger.warning("No dev version found. Using latest stable version instead.");
57526
+ targetVersion2 = await client.getLatestVersion(CLAUDEKIT_CLI_NPM_PACKAGE_NAME, registryUrl);
57527
+ } else {
57528
+ spinnerStop(`Latest dev version: ${targetVersion2}`);
57529
+ return { targetVersion: targetVersion2, targetIsPrerelease: isPrereleaseVersion(targetVersion2) };
57577
57530
  }
57578
- } catch (error) {}
57579
- return counts;
57580
- }
57581
- async function readClaudeKitMetadata(metadataPath) {
57582
- try {
57583
- if (!await import_fs_extra4.pathExists(metadataPath)) {
57584
- return null;
57531
+ if (!targetVersion2) {
57532
+ throw new CliUpdateError("Failed to fetch version information from npm registry. Check your internet connection and try again.");
57585
57533
  }
57586
- const content = await import_fs_extra4.readFile(metadataPath, "utf8");
57587
- const metadata = JSON.parse(content);
57588
- return metadata;
57589
- } catch {
57590
- return null;
57534
+ spinnerStop(`Latest version: ${targetVersion2}`);
57535
+ return { targetVersion: targetVersion2, targetIsPrerelease: isPrereleaseVersion(targetVersion2) };
57536
+ }
57537
+ const targetVersion = await client.getLatestVersion(CLAUDEKIT_CLI_NPM_PACKAGE_NAME, registryUrl);
57538
+ spinnerStop(`Latest version: ${targetVersion || "unknown"}`);
57539
+ if (!targetVersion) {
57540
+ throw new CliUpdateError("Failed to fetch version information from npm registry. Check your internet connection and try again.");
57591
57541
  }
57542
+ return { targetVersion, targetIsPrerelease: isPrereleaseVersion(targetVersion) };
57592
57543
  }
57593
- function getGlobalInstallDir() {
57594
- return PathResolver.getGlobalKitDir();
57544
+ var init_channel_resolver = __esm(() => {
57545
+ init_npm_registry();
57546
+ init_npm_registry();
57547
+ init_version_utils();
57548
+ init_claudekit_constants();
57549
+ init_logger();
57550
+ init_error();
57551
+ });
57552
+
57553
+ // src/commands/update/registry-client.ts
57554
+ function redactCommandForLog(command) {
57555
+ if (!command)
57556
+ return command;
57557
+ const redactedRegistryFlags = command.replace(/(--registry(?:=|\s+))(['"]?)(\S+?)(\2)(?=\s|$)/g, (_match, prefix, quote, url) => `${prefix}${quote}${redactRegistryUrlForLog(url)}${quote}`);
57558
+ return redactedRegistryFlags.replace(/https?:\/\/[^\s"']+/g, (url) => redactRegistryUrlForLog(url));
57595
57559
  }
57596
- async function getClaudeKitSetup(projectDir = process.cwd()) {
57597
- const setup = {
57598
- global: {
57599
- path: "",
57600
- metadata: null,
57601
- components: { agents: 0, commands: 0, rules: 0, skills: 0 }
57602
- },
57603
- project: {
57604
- path: "",
57605
- metadata: null,
57606
- components: { agents: 0, commands: 0, rules: 0, skills: 0 }
57607
- }
57608
- };
57609
- const globalDir = getGlobalInstallDir();
57610
- if (await import_fs_extra4.pathExists(globalDir)) {
57611
- setup.global.path = globalDir;
57612
- setup.global.metadata = await readClaudeKitMetadata(join46(globalDir, "metadata.json"));
57613
- setup.global.components = await scanClaudeKitDirectory(globalDir);
57560
+ var init_registry_client = __esm(() => {
57561
+ init_npm_registry();
57562
+ });
57563
+
57564
+ // src/commands/update/version-comparator.ts
57565
+ function compareCliVersions(currentVersion, targetVersion, opts) {
57566
+ const comparison = import_compare_versions2.compareVersions(currentVersion, targetVersion);
57567
+ if (comparison === 0) {
57568
+ return { status: "up-to-date" };
57614
57569
  }
57615
- const projectClaudeDir = join46(projectDir, ".claude");
57616
- const isLocalSameAsGlobal = projectClaudeDir === globalDir;
57617
- if (!isLocalSameAsGlobal && await import_fs_extra4.pathExists(projectClaudeDir)) {
57618
- setup.project.path = projectClaudeDir;
57619
- setup.project.metadata = await readClaudeKitMetadata(join46(projectClaudeDir, "metadata.json"));
57620
- setup.project.components = await scanClaudeKitDirectory(projectClaudeDir);
57570
+ const isDevChannelSwitch = (opts.dev || opts.beta) && isPrereleaseVersion(targetVersion) && !isPrereleaseVersion(currentVersion);
57571
+ if (isDevChannelSwitch) {
57572
+ return { status: "dev-channel-switch", changeType: "upgrade" };
57621
57573
  }
57622
- return setup;
57574
+ if (comparison > 0 && !opts.release) {
57575
+ return { status: "newer", changeType: "downgrade" };
57576
+ }
57577
+ return { status: "older", changeType: comparison < 0 ? "upgrade" : "downgrade" };
57623
57578
  }
57624
- var import_fs_extra4;
57625
- var init_claudekit_scanner = __esm(() => {
57626
- init_path_resolver();
57627
- init_skip_directories();
57628
- import_fs_extra4 = __toESM(require_lib3(), 1);
57629
- });
57630
-
57631
- // package.json
57632
- var package_default;
57633
- var init_package = __esm(() => {
57634
- package_default = {
57635
- name: "claudekit-cli",
57636
- version: "3.41.1-dev.3",
57637
- description: "CLI tool for bootstrapping and updating ClaudeKit projects",
57638
- type: "module",
57639
- repository: {
57640
- type: "git",
57641
- url: "git+https://github.com/mrgoonie/claudekit-cli.git"
57642
- },
57643
- publishConfig: {
57644
- access: "public",
57645
- registry: "https://registry.npmjs.org"
57646
- },
57647
- bin: {
57648
- ck: "bin/ck.js"
57649
- },
57650
- files: [
57651
- "bin/ck.js",
57652
- "dist/index.js",
57653
- "dist/ui/"
57654
- ],
57655
- scripts: {
57656
- tauri: "tauri",
57657
- "tauri:dev": "tauri dev",
57658
- "tauri:build": "tauri build",
57659
- dev: "bun run src/index.ts",
57660
- "dashboard:dev": "cd src/ui && bun install --silent && cd ../.. && bun run src/index.ts config ui --dev",
57661
- "dashboard:tauri": "cd src/ui && bun install --silent && cd ../.. && bun run src/index.ts config ui --dev --no-open --port 3456",
57662
- "ui:build": "cd src/ui && bun install --silent && bun run build",
57663
- "ui:dev": "cd src/ui && bun run dev",
57664
- build: `bun build src/index.ts --outdir dist --target node --external @octokit/rest --external better-sqlite3 && node -e "const fs=require('fs'),f='dist/index.js',c=fs.readFileSync(f,'utf-8');fs.writeFileSync(f,c.replace(/^#!.*\\n\\/\\/ @bun\\n/,''))"`,
57665
- "verify:package": "node scripts/prepublish-check.js",
57666
- test: "bun test",
57667
- "test:integration": "CK_RUN_CLI_INTEGRATION=1 bun test tests/integration/cli.test.ts",
57668
- "test:watch": "bun test --watch",
57669
- "test:quick": "./scripts/dev-quick-start.sh test",
57670
- lint: "biome check .",
57671
- "lint:fix": "biome check --fix .",
57672
- "lint:fix-unsafe": "biome check --fix --unsafe .",
57673
- format: "biome format --write .",
57674
- typecheck: "tsc --noEmit",
57675
- "dev:quick": "./scripts/dev-quick-start.sh",
57676
- "dev:all": "./scripts/dev-quick-start.sh all",
57677
- metrics: "bun run scripts/workflow-metrics.ts",
57678
- validate: "bun run typecheck && bun run lint && bun test && bun run build",
57679
- "install:hooks": "./.githooks/install.sh",
57680
- prepare: `node -e "try{require('child_process').execSync('git rev-parse --git-dir',{stdio:'ignore'});require('child_process').execSync('bash .githooks/install.sh',{stdio:'inherit'})}catch(e){console.warn('[i] Hook install skipped:',e.message)}"`
57681
- },
57682
- keywords: [
57683
- "cli",
57684
- "claudekit",
57685
- "boilerplate",
57686
- "bootstrap",
57687
- "template"
57688
- ],
57689
- author: "ClaudeKit",
57690
- license: "MIT",
57691
- engines: {
57692
- node: ">=18.0.0"
57693
- },
57694
- dependencies: {
57695
- "@clack/prompts": "^0.7.0",
57696
- "@octokit/rest": "^22.0.0",
57697
- "better-sqlite3": "^12.6.2",
57698
- cac: "^6.7.14",
57699
- chokidar: "^5.0.0",
57700
- "cli-progress": "^3.12.0",
57701
- "compare-versions": "^6.1.1",
57702
- diff: "^8.0.3",
57703
- express: "^5.2.1",
57704
- "extract-zip": "^2.0.1",
57705
- "fs-extra": "^11.2.0",
57706
- "get-port": "^7.1.0",
57707
- "gray-matter": "^4.0.3",
57708
- ignore: "^5.3.2",
57709
- minimatch: "^10.1.1",
57710
- open: "^11.0.0",
57711
- ora: "^8.0.0",
57712
- "p-limit": "^7.2.0",
57713
- picocolors: "^1.1.1",
57714
- picomatch: "^4.0.3",
57715
- "proper-lockfile": "^4.1.2",
57716
- semver: "^7.7.3",
57717
- tar: "^7.4.3",
57718
- tmp: "^0.2.3",
57719
- ws: "^8.19.0",
57720
- zod: "^3.23.8"
57579
+ function isBetaVersion(version) {
57580
+ return isPrereleaseVersion(version);
57581
+ }
57582
+ function parseCliVersionFromOutput(output2) {
57583
+ if (!output2)
57584
+ return null;
57585
+ const match = output2.match(/CLI Version:\s*(\S+)/);
57586
+ return match ? match[1] : null;
57587
+ }
57588
+ var import_compare_versions2;
57589
+ var init_version_comparator = __esm(() => {
57590
+ init_version_utils();
57591
+ import_compare_versions2 = __toESM(require_umd(), 1);
57592
+ });
57593
+
57594
+ // src/commands/update/package-manager-runner.ts
57595
+ function extractCommandStdout(result) {
57596
+ if (typeof result === "string")
57597
+ return result;
57598
+ if (result && typeof result.stdout === "string")
57599
+ return result.stdout;
57600
+ return "";
57601
+ }
57602
+ async function runPackageManagerUpdate(updateCmd, pm, deps) {
57603
+ const { execAsyncFn, spinnerStart, spinnerStop } = deps;
57604
+ spinnerStart("Updating CLI...");
57605
+ try {
57606
+ await execAsyncFn(updateCmd, { timeout: 120000 });
57607
+ spinnerStop("Update completed");
57608
+ } catch (error) {
57609
+ spinnerStop("Update failed");
57610
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
57611
+ if (errorMessage.includes("EACCES") || errorMessage.includes("EPERM") || errorMessage.includes("permission") || errorMessage.includes("Access is denied")) {
57612
+ const permHint = pm === "npm" ? `
57613
+
57614
+ Or fix npm permissions: https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally` : "";
57615
+ const isWindows3 = process.platform === "win32";
57616
+ const elevationHint = isWindows3 ? `Run your terminal as Administrator and retry: ${updateCmd}` : `sudo ${updateCmd}`;
57617
+ throw new CliUpdateError(`Permission denied. Try: ${elevationHint}${permHint}`);
57618
+ }
57619
+ logger.error(`Update failed: ${errorMessage}`);
57620
+ logger.info(`Try running: ${updateCmd}`);
57621
+ throw new CliUpdateError(`Update failed: ${errorMessage}
57622
+
57623
+ Manual update: ${updateCmd}`);
57624
+ }
57625
+ }
57626
+ async function verifyInstalledVersion(targetVersion, updateCmd, deps) {
57627
+ const { execAsyncFn, spinnerStart, spinnerStop } = deps;
57628
+ spinnerStart("Verifying installation...");
57629
+ try {
57630
+ const versionResult = await execAsyncFn("ck --version", { timeout: 5000 });
57631
+ const stdout = extractCommandStdout(versionResult);
57632
+ const activeVersion = parseCliVersionFromOutput(stdout);
57633
+ if (!activeVersion) {
57634
+ spinnerStop("Verification failed");
57635
+ const message = `Update completed but could not parse 'ck --version' output.
57636
+ Please restart your terminal and run 'ck --version'. Expected: ${targetVersion}
57637
+
57638
+ Manual update: ${redactCommandForLog(updateCmd)}`;
57639
+ logger.error(message);
57640
+ throw new CliUpdateError(message);
57641
+ }
57642
+ spinnerStop(`Installed version: ${activeVersion}`);
57643
+ if (activeVersion !== targetVersion) {
57644
+ const mismatchMessage = `Update did not activate the requested version.
57645
+ Expected: ${targetVersion}
57646
+ Active ck: ${activeVersion}
57647
+
57648
+ Likely causes: multiple global installations (npm/bun/pnpm/yarn) or stale shell shim/cache (common on Windows).
57649
+ Run '${redactCommandForLog(updateCmd)}' manually, restart terminal, then check command resolution:
57650
+ - Windows: where ck
57651
+ - macOS/Linux: which -a ck`;
57652
+ logger.error(mismatchMessage);
57653
+ throw new CliUpdateError(mismatchMessage);
57654
+ }
57655
+ return activeVersion;
57656
+ } catch (error) {
57657
+ if (error instanceof CliUpdateError)
57658
+ throw error;
57659
+ spinnerStop("Verification failed");
57660
+ const message = `Update completed but automatic verification failed.
57661
+ Please restart your terminal and run 'ck --version'. Expected: ${targetVersion}
57662
+
57663
+ Manual update: ${redactCommandForLog(updateCmd)}`;
57664
+ logger.error(message);
57665
+ throw new CliUpdateError(message);
57666
+ }
57667
+ }
57668
+ var init_package_manager_runner = __esm(() => {
57669
+ init_logger();
57670
+ init_error();
57671
+ init_registry_client();
57672
+ init_version_comparator();
57673
+ });
57674
+
57675
+ // src/domains/migration/metadata-migration.ts
57676
+ import { join as join45 } from "node:path";
57677
+ async function detectMetadataFormat(claudeDir2) {
57678
+ const metadataPath = join45(claudeDir2, "metadata.json");
57679
+ if (!await import_fs_extra3.pathExists(metadataPath)) {
57680
+ return { format: "none", metadata: null, detectedKit: null };
57681
+ }
57682
+ try {
57683
+ const content = await import_fs_extra3.readFile(metadataPath, "utf-8");
57684
+ const parsed = JSON.parse(content);
57685
+ if (parsed.kits && Object.keys(parsed.kits).length > 0) {
57686
+ const installedKits = Object.keys(parsed.kits);
57687
+ return {
57688
+ format: "multi-kit",
57689
+ metadata: parsed,
57690
+ detectedKit: installedKits[0] || null
57691
+ };
57692
+ }
57693
+ if (parsed.name || parsed.version || parsed.files) {
57694
+ let detectedKit = null;
57695
+ const nameToCheck = parsed.name || "";
57696
+ if (/\bengineer\b/i.test(nameToCheck)) {
57697
+ detectedKit = "engineer";
57698
+ } else if (/\bmarketing\b/i.test(nameToCheck)) {
57699
+ detectedKit = "marketing";
57700
+ } else {
57701
+ detectedKit = "engineer";
57702
+ }
57703
+ return { format: "legacy", metadata: parsed, detectedKit };
57704
+ }
57705
+ logger.warning("Metadata file exists but has unrecognized format (missing kits, name, version, or files)");
57706
+ return { format: "none", metadata: null, detectedKit: null };
57707
+ } catch (error) {
57708
+ logger.warning(`Failed to read metadata file (may be corrupted): ${error}`);
57709
+ return { format: "none", metadata: null, detectedKit: null };
57710
+ }
57711
+ }
57712
+ async function migrateToMultiKit(claudeDir2) {
57713
+ const detection = await detectMetadataFormat(claudeDir2);
57714
+ if (detection.format === "multi-kit") {
57715
+ return {
57716
+ success: true,
57717
+ migrated: false,
57718
+ fromFormat: "multi-kit",
57719
+ toFormat: "multi-kit"
57720
+ };
57721
+ }
57722
+ if (detection.format === "none") {
57723
+ return {
57724
+ success: true,
57725
+ migrated: false,
57726
+ fromFormat: "none",
57727
+ toFormat: "multi-kit"
57728
+ };
57729
+ }
57730
+ const metadataPath = join45(claudeDir2, "metadata.json");
57731
+ const legacy = detection.metadata;
57732
+ if (!legacy) {
57733
+ return {
57734
+ success: false,
57735
+ migrated: false,
57736
+ fromFormat: "legacy",
57737
+ toFormat: "multi-kit",
57738
+ error: "Metadata exists but could not be read"
57739
+ };
57740
+ }
57741
+ const legacyKit = detection.detectedKit || "engineer";
57742
+ try {
57743
+ const kitMetadata = {
57744
+ version: legacy.version || "unknown",
57745
+ installedAt: legacy.installedAt || new Date().toISOString(),
57746
+ files: legacy.files || []
57747
+ };
57748
+ const multiKit = {
57749
+ kits: {
57750
+ [legacyKit]: kitMetadata
57751
+ },
57752
+ scope: legacy.scope,
57753
+ name: legacy.name,
57754
+ version: legacy.version,
57755
+ installedAt: legacy.installedAt,
57756
+ installedFiles: legacy.installedFiles,
57757
+ userConfigFiles: legacy.userConfigFiles,
57758
+ files: legacy.files
57759
+ };
57760
+ await import_fs_extra3.writeFile(metadataPath, JSON.stringify(multiKit, null, 2), "utf-8");
57761
+ logger.info(`Migrated metadata from legacy format to multi-kit (detected: ${legacyKit})`);
57762
+ return {
57763
+ success: true,
57764
+ migrated: true,
57765
+ fromFormat: "legacy",
57766
+ toFormat: "multi-kit"
57767
+ };
57768
+ } catch (error) {
57769
+ const errorMsg = error instanceof Error ? error.message : "Unknown error";
57770
+ logger.error(`Metadata migration failed: ${errorMsg}`);
57771
+ return {
57772
+ success: false,
57773
+ migrated: false,
57774
+ fromFormat: "legacy",
57775
+ toFormat: "multi-kit",
57776
+ error: errorMsg
57777
+ };
57778
+ }
57779
+ }
57780
+ function getKitMetadata(metadata, kit) {
57781
+ if (metadata.kits?.[kit]) {
57782
+ return metadata.kits[kit];
57783
+ }
57784
+ if (!metadata.kits && metadata.version) {
57785
+ return {
57786
+ version: metadata.version,
57787
+ installedAt: metadata.installedAt || "",
57788
+ files: metadata.files
57789
+ };
57790
+ }
57791
+ return null;
57792
+ }
57793
+ function getAllTrackedFiles(metadata) {
57794
+ if (metadata.kits) {
57795
+ const allFiles = [];
57796
+ for (const kit of Object.values(metadata.kits)) {
57797
+ if (kit.files) {
57798
+ allFiles.push(...kit.files);
57799
+ }
57800
+ }
57801
+ return allFiles;
57802
+ }
57803
+ return metadata.files || [];
57804
+ }
57805
+ function getTrackedFilesForKit(metadata, kitType) {
57806
+ if (metadata.kits?.[kitType]) {
57807
+ return metadata.kits[kitType].files || [];
57808
+ }
57809
+ const detectedKits = getInstalledKits(metadata);
57810
+ if (detectedKits.includes(kitType)) {
57811
+ return metadata.files || [];
57812
+ }
57813
+ return [];
57814
+ }
57815
+ function getInstalledKits(metadata) {
57816
+ if (metadata.kits) {
57817
+ return Object.keys(metadata.kits);
57818
+ }
57819
+ const nameToCheck = metadata.name || "";
57820
+ const kits = [];
57821
+ if (/\bengineer\b/i.test(nameToCheck)) {
57822
+ kits.push("engineer");
57823
+ }
57824
+ if (/\bmarketing\b/i.test(nameToCheck)) {
57825
+ kits.push("marketing");
57826
+ }
57827
+ if (kits.length > 0) {
57828
+ return kits;
57829
+ }
57830
+ if (metadata.version) {
57831
+ return ["engineer"];
57832
+ }
57833
+ return [];
57834
+ }
57835
+ var import_fs_extra3;
57836
+ var init_metadata_migration = __esm(() => {
57837
+ init_logger();
57838
+ import_fs_extra3 = __toESM(require_lib3(), 1);
57839
+ });
57840
+
57841
+ // src/services/file-operations/claudekit-scanner.ts
57842
+ import { join as join46 } from "node:path";
57843
+ async function scanClaudeKitDirectory(directoryPath) {
57844
+ const counts = {
57845
+ agents: 0,
57846
+ commands: 0,
57847
+ rules: 0,
57848
+ skills: 0
57849
+ };
57850
+ try {
57851
+ if (!await import_fs_extra4.pathExists(directoryPath)) {
57852
+ return counts;
57853
+ }
57854
+ const items = await import_fs_extra4.readdir(directoryPath);
57855
+ if (items.includes("agents")) {
57856
+ const agentsPath = join46(directoryPath, "agents");
57857
+ const agentFiles = await import_fs_extra4.readdir(agentsPath);
57858
+ counts.agents = agentFiles.filter((file) => file.endsWith(".md")).length;
57859
+ }
57860
+ if (items.includes("commands")) {
57861
+ const commandsPath = join46(directoryPath, "commands");
57862
+ const commandFiles = await import_fs_extra4.readdir(commandsPath);
57863
+ counts.commands = commandFiles.filter((file) => file.endsWith(".md")).length;
57864
+ }
57865
+ if (items.includes("rules")) {
57866
+ const rulesPath = join46(directoryPath, "rules");
57867
+ const ruleFiles = await import_fs_extra4.readdir(rulesPath);
57868
+ counts.rules = ruleFiles.filter((file) => file.endsWith(".md")).length;
57869
+ } else if (items.includes("workflows")) {
57870
+ const workflowsPath = join46(directoryPath, "workflows");
57871
+ const workflowFiles = await import_fs_extra4.readdir(workflowsPath);
57872
+ counts.rules = workflowFiles.filter((file) => file.endsWith(".md")).length;
57873
+ }
57874
+ if (items.includes("skills")) {
57875
+ const skillsPath = join46(directoryPath, "skills");
57876
+ const skillItems = await import_fs_extra4.readdir(skillsPath);
57877
+ let skillCount = 0;
57878
+ for (const item of skillItems) {
57879
+ if (SKIP_DIRS_CLAUDE_INTERNAL.includes(item)) {
57880
+ continue;
57881
+ }
57882
+ const itemPath = join46(skillsPath, item);
57883
+ const stat8 = await import_fs_extra4.readdir(itemPath).catch(() => null);
57884
+ if (stat8?.includes("SKILL.md")) {
57885
+ skillCount++;
57886
+ }
57887
+ }
57888
+ counts.skills = skillCount;
57889
+ }
57890
+ } catch (error) {}
57891
+ return counts;
57892
+ }
57893
+ async function readClaudeKitMetadata(metadataPath) {
57894
+ try {
57895
+ if (!await import_fs_extra4.pathExists(metadataPath)) {
57896
+ return null;
57897
+ }
57898
+ const content = await import_fs_extra4.readFile(metadataPath, "utf8");
57899
+ const metadata = JSON.parse(content);
57900
+ return metadata;
57901
+ } catch {
57902
+ return null;
57903
+ }
57904
+ }
57905
+ function getGlobalInstallDir() {
57906
+ return PathResolver.getGlobalKitDir();
57907
+ }
57908
+ async function getClaudeKitSetup(projectDir = process.cwd()) {
57909
+ const setup = {
57910
+ global: {
57911
+ path: "",
57912
+ metadata: null,
57913
+ components: { agents: 0, commands: 0, rules: 0, skills: 0 }
57721
57914
  },
57722
- devDependencies: {
57723
- "@biomejs/biome": "^1.9.4",
57724
- "@semantic-release/changelog": "^6.0.3",
57725
- "@semantic-release/git": "^10.0.1",
57726
- "@tauri-apps/cli": "^2",
57727
- "@types/better-sqlite3": "^7.6.13",
57728
- "@types/bun": "latest",
57729
- "@types/cli-progress": "^3.11.6",
57730
- "@types/diff": "^8.0.0",
57731
- "@types/express": "^5.0.6",
57732
- "@types/fs-extra": "^11.0.4",
57733
- "@types/node": "^22.19.7",
57734
- "@types/picomatch": "^4.0.2",
57735
- "@types/proper-lockfile": "^4.1.4",
57736
- "@types/semver": "^7.7.1",
57737
- "@types/tar": "^6.1.13",
57738
- "@types/tmp": "^0.2.6",
57739
- "@types/ws": "^8.18.1",
57740
- "conventional-changelog-conventionalcommits": "^9.1.0",
57741
- "semantic-release": "^24.2.0",
57742
- typescript: "^5.7.2"
57915
+ project: {
57916
+ path: "",
57917
+ metadata: null,
57918
+ components: { agents: 0, commands: 0, rules: 0, skills: 0 }
57743
57919
  }
57744
57920
  };
57921
+ const globalDir = getGlobalInstallDir();
57922
+ if (await import_fs_extra4.pathExists(globalDir)) {
57923
+ setup.global.path = globalDir;
57924
+ setup.global.metadata = await readClaudeKitMetadata(join46(globalDir, "metadata.json"));
57925
+ setup.global.components = await scanClaudeKitDirectory(globalDir);
57926
+ }
57927
+ const projectClaudeDir = join46(projectDir, ".claude");
57928
+ const isLocalSameAsGlobal = projectClaudeDir === globalDir;
57929
+ if (!isLocalSameAsGlobal && await import_fs_extra4.pathExists(projectClaudeDir)) {
57930
+ setup.project.path = projectClaudeDir;
57931
+ setup.project.metadata = await readClaudeKitMetadata(join46(projectClaudeDir, "metadata.json"));
57932
+ setup.project.components = await scanClaudeKitDirectory(projectClaudeDir);
57933
+ }
57934
+ return setup;
57935
+ }
57936
+ var import_fs_extra4;
57937
+ var init_claudekit_scanner = __esm(() => {
57938
+ init_path_resolver();
57939
+ init_skip_directories();
57940
+ import_fs_extra4 = __toESM(require_lib3(), 1);
57745
57941
  });
57746
57942
 
57747
57943
  // src/domains/github/github-auth.ts
@@ -58151,7 +58347,7 @@ ${action.title}:`);
58151
58347
  }
58152
58348
 
58153
58349
  // src/domains/error/index.ts
58154
- var init_error = () => {};
58350
+ var init_error2 = () => {};
58155
58351
 
58156
58352
  // src/domains/github/client/error-handler.ts
58157
58353
  async function handleHttpError(error, context) {
@@ -58182,7 +58378,7 @@ Need help? Run with: ${verboseFlag}`);
58182
58378
  `), classified.httpStatus);
58183
58379
  }
58184
58380
  var init_error_handler2 = __esm(() => {
58185
- init_error();
58381
+ init_error2();
58186
58382
  init_types3();
58187
58383
  init_auth_api();
58188
58384
  });
@@ -58303,7 +58499,7 @@ class VersionFormatter {
58303
58499
  static compare(v1, v2) {
58304
58500
  const normV1 = VersionFormatter.normalize(v1);
58305
58501
  const normV2 = VersionFormatter.normalize(v2);
58306
- return import_compare_versions2.compareVersions(normV1, normV2);
58502
+ return import_compare_versions3.compareVersions(normV1, normV2);
58307
58503
  }
58308
58504
  static formatRelativeTime(dateString) {
58309
58505
  if (!dateString)
@@ -58391,20 +58587,20 @@ class VersionFormatter {
58391
58587
  const majorA = Number.parseInt(normA.split(".")[0], 10);
58392
58588
  const majorB = Number.parseInt(normB.split(".")[0], 10);
58393
58589
  if (majorA === 0 && majorB === 0) {
58394
- return import_compare_versions2.compareVersions(normB, normA);
58590
+ return import_compare_versions3.compareVersions(normB, normA);
58395
58591
  }
58396
58592
  if (majorA === 0)
58397
58593
  return 1;
58398
58594
  if (majorB === 0)
58399
58595
  return -1;
58400
- return import_compare_versions2.compareVersions(normB, normA);
58596
+ return import_compare_versions3.compareVersions(normB, normA);
58401
58597
  });
58402
58598
  }
58403
58599
  }
58404
- var import_compare_versions2;
58600
+ var import_compare_versions3;
58405
58601
  var init_version_formatter = __esm(() => {
58406
58602
  init_logger();
58407
- import_compare_versions2 = __toESM(require_umd(), 1);
58603
+ import_compare_versions3 = __toESM(require_umd(), 1);
58408
58604
  });
58409
58605
 
58410
58606
  // src/domains/versioning/release-filter.ts
@@ -58913,64 +59109,16 @@ var init_github_client = __esm(() => {
58913
59109
  init_client();
58914
59110
  });
58915
59111
 
58916
- // src/commands/update-cli.ts
59112
+ // src/commands/update/post-update-handler.ts
58917
59113
  import { exec as exec2, spawn as spawn2 } from "node:child_process";
58918
59114
  import { join as join48 } from "node:path";
58919
59115
  import { promisify as promisify8 } from "node:util";
58920
- function getDefaultUpdateCliCommandDeps() {
58921
- return {
58922
- currentVersion: package_default.version,
58923
- execAsyncFn: execAsync2,
58924
- packageManagerDetector: PackageManagerDetector,
58925
- npmRegistryClient: NpmRegistryClient,
58926
- promptKitUpdateFn: promptKitUpdate,
58927
- promptMigrateUpdateFn: promptMigrateUpdate
58928
- };
58929
- }
58930
- function extractCommandStdout(result) {
58931
- if (typeof result === "string") {
58932
- return result;
58933
- }
58934
- if (result && typeof result.stdout === "string") {
58935
- return result.stdout;
58936
- }
58937
- return "";
58938
- }
58939
- function redactCommandForLog(command) {
58940
- if (!command)
58941
- return command;
58942
- const redactedRegistryFlags = command.replace(/(--registry(?:=|\s+))(['"]?)(\S+?)(\2)(?=\s|$)/g, (_match, prefix, quote, url) => `${prefix}${quote}${redactRegistryUrlForLog(url)}${quote}`);
58943
- return redactedRegistryFlags.replace(/https?:\/\/[^\s"']+/g, (url) => redactRegistryUrlForLog(url));
58944
- }
58945
- function buildInitCommand(isGlobal, kit, beta, yes) {
58946
- const parts = ["ck init"];
58947
- if (isGlobal)
58948
- parts.push("-g");
58949
- if (kit)
58950
- parts.push(`--kit ${kit}`);
58951
- if (yes)
58952
- parts.push("--yes");
58953
- parts.push("--install-skills");
58954
- if (beta)
58955
- parts.push("--beta");
58956
- return parts.join(" ");
58957
- }
58958
- function isBetaVersion(version) {
58959
- return isPrereleaseVersion(version);
58960
- }
58961
- function parseCliVersionFromOutput(output2) {
58962
- if (!output2)
58963
- return null;
58964
- const match = output2.match(/CLI Version:\s*(\S+)/);
58965
- return match ? match[1] : null;
58966
- }
58967
59116
  function selectKitForUpdate(params) {
58968
59117
  const { hasLocal, hasGlobal, localKits, globalKits } = params;
58969
59118
  const hasLocalKit = localKits.length > 0 || hasLocal;
58970
59119
  const hasGlobalKit = globalKits.length > 0 || hasGlobal;
58971
- if (!hasLocalKit && !hasGlobalKit) {
59120
+ if (!hasLocalKit && !hasGlobalKit)
58972
59121
  return null;
58973
- }
58974
59122
  if (hasGlobalKit && !hasLocalKit) {
58975
59123
  const kit2 = globalKits[0] || localKits[0];
58976
59124
  return {
@@ -58997,9 +59145,8 @@ function selectKitForUpdate(params) {
58997
59145
  async function readMetadataFile(claudeDir2) {
58998
59146
  const metadataPath = join48(claudeDir2, "metadata.json");
58999
59147
  try {
59000
- if (!await import_fs_extra5.pathExists(metadataPath)) {
59148
+ if (!await import_fs_extra5.pathExists(metadataPath))
59001
59149
  return null;
59002
- }
59003
59150
  const content = await import_fs_extra5.readFile(metadataPath, "utf-8");
59004
59151
  const parsed = JSON.parse(content);
59005
59152
  const validated = MetadataSchema.safeParse(parsed);
@@ -59013,6 +59160,19 @@ async function readMetadataFile(claudeDir2) {
59013
59160
  return null;
59014
59161
  }
59015
59162
  }
59163
+ function buildInitCommand(isGlobal, kit, beta, yes) {
59164
+ const parts = ["ck init"];
59165
+ if (isGlobal)
59166
+ parts.push("-g");
59167
+ if (kit)
59168
+ parts.push(`--kit ${kit}`);
59169
+ if (yes)
59170
+ parts.push("--yes");
59171
+ parts.push("--install-skills");
59172
+ if (beta)
59173
+ parts.push("--beta");
59174
+ return parts.join(" ");
59175
+ }
59016
59176
  async function fetchLatestReleaseTag(kit, beta) {
59017
59177
  try {
59018
59178
  const { GitHubClient: GitHubClient2 } = await Promise.resolve().then(() => (init_github_client(), exports_github_client));
@@ -59066,14 +59226,11 @@ async function promptKitUpdate(beta, yes, deps) {
59066
59226
  const ckConfig = await loadFullConfigFn(null);
59067
59227
  autoInit = ckConfig.config.updatePipeline?.autoInitAfterUpdate ?? false;
59068
59228
  } catch {}
59069
- if (alreadyAtLatest && !autoInit) {
59229
+ if (alreadyAtLatest && !autoInit)
59070
59230
  return;
59071
- }
59072
59231
  if (!yes && !autoInit) {
59073
59232
  logger.info("");
59074
- const shouldUpdate = await confirmFn({
59075
- message: promptMessage
59076
- });
59233
+ const shouldUpdate = await confirmFn({ message: promptMessage });
59077
59234
  if (isCancelFn(shouldUpdate) || !shouldUpdate) {
59078
59235
  log.info("Skipped kit content update");
59079
59236
  return;
@@ -59211,6 +59368,37 @@ async function promptMigrateUpdate(deps) {
59211
59368
  logger.verbose(`Migrate step skipped: ${error instanceof Error ? error.message : "unknown"}`);
59212
59369
  }
59213
59370
  }
59371
+ var import_fs_extra5, execAsync2, SAFE_PROVIDER_NAME;
59372
+ var init_post_update_handler = __esm(() => {
59373
+ init_ck_config_manager();
59374
+ init_metadata_migration();
59375
+ init_version_utils();
59376
+ init_claudekit_scanner();
59377
+ init_logger();
59378
+ init_safe_prompts();
59379
+ init_types3();
59380
+ init_version_comparator();
59381
+ import_fs_extra5 = __toESM(require_lib3(), 1);
59382
+ execAsync2 = promisify8(exec2);
59383
+ SAFE_PROVIDER_NAME = /^[a-z0-9-]+$/;
59384
+ });
59385
+
59386
+ // src/commands/update-cli.ts
59387
+ function getDefaultUpdateCliCommandDeps() {
59388
+ return {
59389
+ currentVersion: package_default.version,
59390
+ execAsyncFn: async (cmd, opts) => {
59391
+ const { exec: exec3 } = await import("node:child_process");
59392
+ const { promisify: promisify9 } = await import("node:util");
59393
+ const result = await promisify9(exec3)(cmd, opts);
59394
+ return { stdout: String(result.stdout ?? ""), stderr: String(result.stderr ?? "") };
59395
+ },
59396
+ packageManagerDetector: PackageManagerDetector,
59397
+ npmRegistryClient: NpmRegistryClient,
59398
+ promptKitUpdateFn: promptKitUpdate,
59399
+ promptMigrateUpdateFn: promptMigrateUpdate
59400
+ };
59401
+ }
59214
59402
  async function updateCliCommand(options2, deps = getDefaultUpdateCliCommandDeps()) {
59215
59403
  const s = de();
59216
59404
  intro("[>] ClaudeKit CLI - Update");
@@ -59235,64 +59423,31 @@ async function updateCliCommand(options2, deps = getDefaultUpdateCliCommandDeps(
59235
59423
  const userRegistry = await packageManagerDetector.getNpmRegistryUrl();
59236
59424
  if (userRegistry) {
59237
59425
  registryUrl = userRegistry;
59238
- logger.verbose(`Using npm configured registry: ${redactRegistryUrlForLog(registryUrl)}`);
59426
+ const { redactRegistryUrlForLog: redactRegistryUrlForLog2 } = await Promise.resolve().then(() => (init_npm_registry(), exports_npm_registry));
59427
+ logger.verbose(`Using npm configured registry: ${redactRegistryUrlForLog2(registryUrl)}`);
59239
59428
  }
59240
59429
  }
59241
59430
  s.start("Checking for updates...");
59242
- let targetVersion = null;
59243
- const usePrereleaseChannel = opts.dev || opts.beta;
59244
- if (opts.release && opts.release !== "latest") {
59245
- try {
59246
- const exists = await npmRegistryClient.versionExists(CLAUDEKIT_CLI_NPM_PACKAGE_NAME, opts.release, registryUrl);
59247
- if (!exists) {
59248
- s.stop("Version not found");
59249
- throw new CliUpdateError(`Version ${opts.release} does not exist on npm registry. Run 'ck versions' to see available versions.`);
59250
- }
59251
- } catch (error) {
59252
- if (error instanceof CliUpdateError) {
59253
- throw error;
59254
- }
59255
- s.stop("Version check failed");
59256
- const message = error instanceof Error ? error.message : "Unknown error";
59257
- logger.verbose(`Release check failed for ${opts.release}: ${message}`);
59258
- const registryHint = registryUrl ? ` (${redactRegistryUrlForLog(registryUrl)})` : " (default registry)";
59259
- throw new CliUpdateError(`Failed to verify version ${opts.release} on npm registry${registryHint}. Check registry settings/network connectivity and try again.`);
59260
- }
59261
- targetVersion = opts.release;
59262
- s.stop(`Target version: ${targetVersion}`);
59263
- } else if (usePrereleaseChannel) {
59264
- targetVersion = await npmRegistryClient.getDevVersion(CLAUDEKIT_CLI_NPM_PACKAGE_NAME, registryUrl);
59265
- if (!targetVersion) {
59266
- s.stop("No dev version available");
59267
- logger.warning("No dev version found. Using latest stable version instead.");
59268
- targetVersion = await npmRegistryClient.getLatestVersion(CLAUDEKIT_CLI_NPM_PACKAGE_NAME, registryUrl);
59269
- } else {
59270
- s.stop(`Latest dev version: ${targetVersion}`);
59271
- }
59272
- } else {
59273
- targetVersion = await npmRegistryClient.getLatestVersion(CLAUDEKIT_CLI_NPM_PACKAGE_NAME, registryUrl);
59274
- s.stop(`Latest version: ${targetVersion || "unknown"}`);
59275
- }
59276
- if (!targetVersion) {
59277
- 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)}`);
59278
- }
59279
- const comparison = import_compare_versions3.compareVersions(currentVersion, targetVersion);
59280
- const targetIsPrerelease = isPrereleaseVersion(targetVersion);
59281
- if (comparison === 0) {
59431
+ const { targetVersion, targetIsPrerelease } = await resolveTargetVersion(opts, {
59432
+ npmRegistryClient,
59433
+ registryUrl,
59434
+ spinnerStop: (msg) => s.stop(msg)
59435
+ });
59436
+ const outcome = compareCliVersions(currentVersion, targetVersion, opts);
59437
+ if (outcome.status === "up-to-date") {
59282
59438
  outro(`[+] Already on the latest CLI version (${currentVersion})`);
59283
59439
  await promptKitUpdateFn(targetIsPrerelease, opts.yes);
59284
59440
  await promptMigrateUpdateFn();
59285
59441
  return;
59286
59442
  }
59287
- const isDevChannelSwitch = (opts.dev || opts.beta) && isBetaVersion(targetVersion) && !isBetaVersion(currentVersion);
59288
- if (comparison > 0 && !opts.release && !isDevChannelSwitch) {
59443
+ if (outcome.status === "newer") {
59289
59444
  outro(`[+] Current version (${currentVersion}) is newer than latest (${targetVersion})`);
59290
59445
  await promptKitUpdateFn(targetIsPrerelease, opts.yes);
59291
59446
  await promptMigrateUpdateFn();
59292
59447
  return;
59293
59448
  }
59294
- const isUpgrade = comparison < 0 || isDevChannelSwitch;
59295
- const changeType = isUpgrade ? "upgrade" : "downgrade";
59449
+ const isUpgrade = outcome.changeType === "upgrade";
59450
+ const changeType = outcome.changeType;
59296
59451
  logger.info(`${isUpgrade ? "[^]" : "[v]"} ${changeType}: ${currentVersion} -> ${targetVersion}`);
59297
59452
  if (opts.check) {
59298
59453
  note(`CLI update available: ${currentVersion} -> ${targetVersion}
@@ -59314,71 +59469,19 @@ Run 'ck update' to install`, "Update Check");
59314
59469
  }
59315
59470
  const updateCmd = packageManagerDetector.getUpdateCommand(pm, CLAUDEKIT_CLI_NPM_PACKAGE_NAME, targetVersion, registryUrl);
59316
59471
  logger.info(`Running: ${redactCommandForLog(updateCmd)}`);
59317
- s.start("Updating CLI...");
59318
- try {
59319
- await execAsyncFn(updateCmd, {
59320
- timeout: 120000
59321
- });
59322
- s.stop("Update completed");
59323
- } catch (error) {
59324
- s.stop("Update failed");
59325
- const errorMessage = error instanceof Error ? error.message : "Unknown error";
59326
- if (errorMessage.includes("EACCES") || errorMessage.includes("EPERM") || errorMessage.includes("permission") || errorMessage.includes("Access is denied")) {
59327
- const permHint = pm === "npm" ? `
59328
-
59329
- Or fix npm permissions: https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally` : "";
59330
- const isWindows3 = process.platform === "win32";
59331
- const elevationHint = isWindows3 ? `Run your terminal as Administrator and retry: ${updateCmd}` : `sudo ${updateCmd}`;
59332
- throw new CliUpdateError(`Permission denied. Try: ${elevationHint}${permHint}`);
59333
- }
59334
- logger.error(`Update failed: ${errorMessage}`);
59335
- logger.info(`Try running: ${redactCommandForLog(updateCmd)}`);
59336
- throw new CliUpdateError(`Update failed: ${errorMessage}
59337
-
59338
- Manual update: ${updateCmd}`);
59339
- }
59340
- s.start("Verifying installation...");
59341
- try {
59342
- const versionResult = await execAsyncFn("ck --version", { timeout: 5000 });
59343
- const stdout = extractCommandStdout(versionResult);
59344
- const activeVersion = parseCliVersionFromOutput(stdout);
59345
- if (!activeVersion) {
59346
- s.stop("Verification failed");
59347
- const message = `Update completed but could not parse 'ck --version' output.
59348
- Please restart your terminal and run 'ck --version'. Expected: ${targetVersion}
59349
-
59350
- Manual update: ${redactCommandForLog(updateCmd)}`;
59351
- logger.error(message);
59352
- throw new CliUpdateError(message);
59353
- }
59354
- s.stop(`Installed version: ${activeVersion}`);
59355
- if (activeVersion !== targetVersion) {
59356
- const mismatchMessage = `Update did not activate the requested version.
59357
- Expected: ${targetVersion}
59358
- Active ck: ${activeVersion}
59359
-
59360
- Likely causes: multiple global installations (npm/bun/pnpm/yarn) or stale shell shim/cache (common on Windows).
59361
- Run '${redactCommandForLog(updateCmd)}' manually, restart terminal, then check command resolution:
59362
- - Windows: where ck
59363
- - macOS/Linux: which -a ck`;
59364
- logger.error(mismatchMessage);
59365
- throw new CliUpdateError(mismatchMessage);
59366
- }
59367
- outro(`[+] Successfully updated ClaudeKit CLI to ${activeVersion}`);
59368
- await promptKitUpdateFn(targetIsPrerelease, opts.yes);
59369
- await promptMigrateUpdateFn();
59370
- } catch (error) {
59371
- if (error instanceof CliUpdateError) {
59372
- throw error;
59373
- }
59374
- s.stop("Verification failed");
59375
- const message = `Update completed but automatic verification failed.
59376
- Please restart your terminal and run 'ck --version'. Expected: ${targetVersion}
59377
-
59378
- Manual update: ${redactCommandForLog(updateCmd)}`;
59379
- logger.error(message);
59380
- throw new CliUpdateError(message);
59381
- }
59472
+ await runPackageManagerUpdate(updateCmd, pm, {
59473
+ execAsyncFn,
59474
+ spinnerStart: (msg) => s.start(msg),
59475
+ spinnerStop: (msg) => s.stop(msg)
59476
+ });
59477
+ const activeVersion = await verifyInstalledVersion(targetVersion, updateCmd, {
59478
+ execAsyncFn,
59479
+ spinnerStart: (msg) => s.start(msg),
59480
+ spinnerStop: (msg) => s.stop(msg)
59481
+ });
59482
+ outro(`[+] Successfully updated ClaudeKit CLI to ${activeVersion}`);
59483
+ await promptKitUpdateFn(targetIsPrerelease, opts.yes);
59484
+ await promptMigrateUpdateFn();
59382
59485
  } catch (error) {
59383
59486
  if (error instanceof CliUpdateError) {
59384
59487
  throw error;
@@ -59388,30 +59491,24 @@ Manual update: ${redactCommandForLog(updateCmd)}`;
59388
59491
  throw new CliUpdateError(errorMessage);
59389
59492
  }
59390
59493
  }
59391
- var import_compare_versions3, import_fs_extra5, execAsync2, CliUpdateError, SAFE_PROVIDER_NAME;
59392
59494
  var init_update_cli = __esm(() => {
59393
- init_ck_config_manager();
59394
59495
  init_npm_registry();
59395
59496
  init_package_manager_detector();
59396
- init_metadata_migration();
59397
- init_version_utils();
59398
- init_claudekit_scanner();
59399
59497
  init_claudekit_constants();
59400
59498
  init_logger();
59401
59499
  init_safe_prompts();
59402
59500
  init_types3();
59403
- init_types3();
59404
59501
  init_package();
59405
- import_compare_versions3 = __toESM(require_umd(), 1);
59406
- import_fs_extra5 = __toESM(require_lib3(), 1);
59407
- execAsync2 = promisify8(exec2);
59408
- CliUpdateError = class CliUpdateError extends ClaudeKitError {
59409
- constructor(message) {
59410
- super(message, "CLI_UPDATE_ERROR");
59411
- this.name = "CliUpdateError";
59412
- }
59413
- };
59414
- SAFE_PROVIDER_NAME = /^[a-z0-9-]+$/;
59502
+ init_channel_resolver();
59503
+ init_error();
59504
+ init_package_manager_runner();
59505
+ init_post_update_handler();
59506
+ init_registry_client();
59507
+ init_version_comparator();
59508
+ init_error();
59509
+ init_version_comparator();
59510
+ init_post_update_handler();
59511
+ init_registry_client();
59415
59512
  });
59416
59513
 
59417
59514
  // src/domains/versioning/version-cache.ts