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

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 +709 -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.5",
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,462 @@ 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_version_utils();
57547
+ init_claudekit_constants();
57548
+ init_logger();
57549
+ init_error();
57550
+ });
57551
+
57552
+ // src/commands/update/registry-client.ts
57553
+ function redactCommandForLog(command) {
57554
+ if (!command)
57555
+ return command;
57556
+ const redactedRegistryFlags = command.replace(/(--registry(?:=|\s+))(['"]?)(\S+?)(\2)(?=\s|$)/g, (_match, prefix, quote, url) => `${prefix}${quote}${redactRegistryUrlForLog(url)}${quote}`);
57557
+ return redactedRegistryFlags.replace(/https?:\/\/[^\s"']+/g, (url) => redactRegistryUrlForLog(url));
57595
57558
  }
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);
57559
+ var init_registry_client = __esm(() => {
57560
+ init_npm_registry();
57561
+ });
57562
+
57563
+ // src/commands/update/version-comparator.ts
57564
+ function compareCliVersions(currentVersion, targetVersion, opts) {
57565
+ const comparison = import_compare_versions2.compareVersions(currentVersion, targetVersion);
57566
+ if (comparison === 0) {
57567
+ return { status: "up-to-date" };
57614
57568
  }
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);
57569
+ const isDevChannelSwitch = (opts.dev || opts.beta) && isPrereleaseVersion(targetVersion) && !isPrereleaseVersion(currentVersion);
57570
+ if (isDevChannelSwitch) {
57571
+ return { status: "dev-channel-switch", changeType: "upgrade" };
57621
57572
  }
57622
- return setup;
57573
+ if (comparison > 0 && !opts.release) {
57574
+ return { status: "newer", changeType: "downgrade" };
57575
+ }
57576
+ return { status: "older", changeType: comparison < 0 ? "upgrade" : "downgrade" };
57623
57577
  }
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"
57578
+ function isBetaVersion(version) {
57579
+ return isPrereleaseVersion(version);
57580
+ }
57581
+ function parseCliVersionFromOutput(output2) {
57582
+ if (!output2)
57583
+ return null;
57584
+ const match = output2.match(/CLI Version:\s*(\S+)/);
57585
+ return match ? match[1] : null;
57586
+ }
57587
+ var import_compare_versions2;
57588
+ var init_version_comparator = __esm(() => {
57589
+ init_version_utils();
57590
+ import_compare_versions2 = __toESM(require_umd(), 1);
57591
+ });
57592
+
57593
+ // src/commands/update/package-manager-runner.ts
57594
+ function extractCommandStdout(result) {
57595
+ if (typeof result === "string")
57596
+ return result;
57597
+ if (result && typeof result.stdout === "string")
57598
+ return result.stdout;
57599
+ return "";
57600
+ }
57601
+ async function runPackageManagerUpdate(updateCmd, pm, deps) {
57602
+ const { execAsyncFn, spinnerStart, spinnerStop } = deps;
57603
+ spinnerStart("Updating CLI...");
57604
+ try {
57605
+ await execAsyncFn(updateCmd, { timeout: 120000 });
57606
+ spinnerStop("Update completed");
57607
+ } catch (error) {
57608
+ spinnerStop("Update failed");
57609
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
57610
+ if (errorMessage.includes("EACCES") || errorMessage.includes("EPERM") || errorMessage.includes("permission") || errorMessage.includes("Access is denied")) {
57611
+ const permHint = pm === "npm" ? `
57612
+
57613
+ Or fix npm permissions: https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally` : "";
57614
+ const isWindows3 = process.platform === "win32";
57615
+ const elevationHint = isWindows3 ? `Run your terminal as Administrator and retry: ${updateCmd}` : `sudo ${updateCmd}`;
57616
+ throw new CliUpdateError(`Permission denied. Try: ${elevationHint}${permHint}`);
57617
+ }
57618
+ logger.error(`Update failed: ${errorMessage}`);
57619
+ logger.info(`Try running: ${updateCmd}`);
57620
+ throw new CliUpdateError(`Update failed: ${errorMessage}
57621
+
57622
+ Manual update: ${updateCmd}`);
57623
+ }
57624
+ }
57625
+ async function verifyInstalledVersion(targetVersion, updateCmd, deps) {
57626
+ const { execAsyncFn, spinnerStart, spinnerStop } = deps;
57627
+ spinnerStart("Verifying installation...");
57628
+ try {
57629
+ const versionResult = await execAsyncFn("ck --version", { timeout: 5000 });
57630
+ const stdout = extractCommandStdout(versionResult);
57631
+ const activeVersion = parseCliVersionFromOutput(stdout);
57632
+ if (!activeVersion) {
57633
+ spinnerStop("Verification failed");
57634
+ const message = `Update completed but could not parse 'ck --version' output.
57635
+ Please restart your terminal and run 'ck --version'. Expected: ${targetVersion}
57636
+
57637
+ Manual update: ${redactCommandForLog(updateCmd)}`;
57638
+ logger.error(message);
57639
+ throw new CliUpdateError(message);
57640
+ }
57641
+ spinnerStop(`Installed version: ${activeVersion}`);
57642
+ if (activeVersion !== targetVersion) {
57643
+ const mismatchMessage = `Update did not activate the requested version.
57644
+ Expected: ${targetVersion}
57645
+ Active ck: ${activeVersion}
57646
+
57647
+ Likely causes: multiple global installations (npm/bun/pnpm/yarn) or stale shell shim/cache (common on Windows).
57648
+ Run '${redactCommandForLog(updateCmd)}' manually, restart terminal, then check command resolution:
57649
+ - Windows: where ck
57650
+ - macOS/Linux: which -a ck`;
57651
+ logger.error(mismatchMessage);
57652
+ throw new CliUpdateError(mismatchMessage);
57653
+ }
57654
+ return activeVersion;
57655
+ } catch (error) {
57656
+ if (error instanceof CliUpdateError)
57657
+ throw error;
57658
+ spinnerStop("Verification failed");
57659
+ const message = `Update completed but automatic verification failed.
57660
+ Please restart your terminal and run 'ck --version'. Expected: ${targetVersion}
57661
+
57662
+ Manual update: ${redactCommandForLog(updateCmd)}`;
57663
+ logger.error(message);
57664
+ throw new CliUpdateError(message);
57665
+ }
57666
+ }
57667
+ var init_package_manager_runner = __esm(() => {
57668
+ init_logger();
57669
+ init_error();
57670
+ init_registry_client();
57671
+ init_version_comparator();
57672
+ });
57673
+
57674
+ // src/domains/migration/metadata-migration.ts
57675
+ import { join as join45 } from "node:path";
57676
+ async function detectMetadataFormat(claudeDir2) {
57677
+ const metadataPath = join45(claudeDir2, "metadata.json");
57678
+ if (!await import_fs_extra3.pathExists(metadataPath)) {
57679
+ return { format: "none", metadata: null, detectedKit: null };
57680
+ }
57681
+ try {
57682
+ const content = await import_fs_extra3.readFile(metadataPath, "utf-8");
57683
+ const parsed = JSON.parse(content);
57684
+ if (parsed.kits && Object.keys(parsed.kits).length > 0) {
57685
+ const installedKits = Object.keys(parsed.kits);
57686
+ return {
57687
+ format: "multi-kit",
57688
+ metadata: parsed,
57689
+ detectedKit: installedKits[0] || null
57690
+ };
57691
+ }
57692
+ if (parsed.name || parsed.version || parsed.files) {
57693
+ let detectedKit = null;
57694
+ const nameToCheck = parsed.name || "";
57695
+ if (/\bengineer\b/i.test(nameToCheck)) {
57696
+ detectedKit = "engineer";
57697
+ } else if (/\bmarketing\b/i.test(nameToCheck)) {
57698
+ detectedKit = "marketing";
57699
+ } else {
57700
+ detectedKit = "engineer";
57701
+ }
57702
+ return { format: "legacy", metadata: parsed, detectedKit };
57703
+ }
57704
+ logger.warning("Metadata file exists but has unrecognized format (missing kits, name, version, or files)");
57705
+ return { format: "none", metadata: null, detectedKit: null };
57706
+ } catch (error) {
57707
+ logger.warning(`Failed to read metadata file (may be corrupted): ${error}`);
57708
+ return { format: "none", metadata: null, detectedKit: null };
57709
+ }
57710
+ }
57711
+ async function migrateToMultiKit(claudeDir2) {
57712
+ const detection = await detectMetadataFormat(claudeDir2);
57713
+ if (detection.format === "multi-kit") {
57714
+ return {
57715
+ success: true,
57716
+ migrated: false,
57717
+ fromFormat: "multi-kit",
57718
+ toFormat: "multi-kit"
57719
+ };
57720
+ }
57721
+ if (detection.format === "none") {
57722
+ return {
57723
+ success: true,
57724
+ migrated: false,
57725
+ fromFormat: "none",
57726
+ toFormat: "multi-kit"
57727
+ };
57728
+ }
57729
+ const metadataPath = join45(claudeDir2, "metadata.json");
57730
+ const legacy = detection.metadata;
57731
+ if (!legacy) {
57732
+ return {
57733
+ success: false,
57734
+ migrated: false,
57735
+ fromFormat: "legacy",
57736
+ toFormat: "multi-kit",
57737
+ error: "Metadata exists but could not be read"
57738
+ };
57739
+ }
57740
+ const legacyKit = detection.detectedKit || "engineer";
57741
+ try {
57742
+ const kitMetadata = {
57743
+ version: legacy.version || "unknown",
57744
+ installedAt: legacy.installedAt || new Date().toISOString(),
57745
+ files: legacy.files || []
57746
+ };
57747
+ const multiKit = {
57748
+ kits: {
57749
+ [legacyKit]: kitMetadata
57750
+ },
57751
+ scope: legacy.scope,
57752
+ name: legacy.name,
57753
+ version: legacy.version,
57754
+ installedAt: legacy.installedAt,
57755
+ installedFiles: legacy.installedFiles,
57756
+ userConfigFiles: legacy.userConfigFiles,
57757
+ files: legacy.files
57758
+ };
57759
+ await import_fs_extra3.writeFile(metadataPath, JSON.stringify(multiKit, null, 2), "utf-8");
57760
+ logger.info(`Migrated metadata from legacy format to multi-kit (detected: ${legacyKit})`);
57761
+ return {
57762
+ success: true,
57763
+ migrated: true,
57764
+ fromFormat: "legacy",
57765
+ toFormat: "multi-kit"
57766
+ };
57767
+ } catch (error) {
57768
+ const errorMsg = error instanceof Error ? error.message : "Unknown error";
57769
+ logger.error(`Metadata migration failed: ${errorMsg}`);
57770
+ return {
57771
+ success: false,
57772
+ migrated: false,
57773
+ fromFormat: "legacy",
57774
+ toFormat: "multi-kit",
57775
+ error: errorMsg
57776
+ };
57777
+ }
57778
+ }
57779
+ function getKitMetadata(metadata, kit) {
57780
+ if (metadata.kits?.[kit]) {
57781
+ return metadata.kits[kit];
57782
+ }
57783
+ if (!metadata.kits && metadata.version) {
57784
+ return {
57785
+ version: metadata.version,
57786
+ installedAt: metadata.installedAt || "",
57787
+ files: metadata.files
57788
+ };
57789
+ }
57790
+ return null;
57791
+ }
57792
+ function getAllTrackedFiles(metadata) {
57793
+ if (metadata.kits) {
57794
+ const allFiles = [];
57795
+ for (const kit of Object.values(metadata.kits)) {
57796
+ if (kit.files) {
57797
+ allFiles.push(...kit.files);
57798
+ }
57799
+ }
57800
+ return allFiles;
57801
+ }
57802
+ return metadata.files || [];
57803
+ }
57804
+ function getTrackedFilesForKit(metadata, kitType) {
57805
+ if (metadata.kits?.[kitType]) {
57806
+ return metadata.kits[kitType].files || [];
57807
+ }
57808
+ const detectedKits = getInstalledKits(metadata);
57809
+ if (detectedKits.includes(kitType)) {
57810
+ return metadata.files || [];
57811
+ }
57812
+ return [];
57813
+ }
57814
+ function getInstalledKits(metadata) {
57815
+ if (metadata.kits) {
57816
+ return Object.keys(metadata.kits);
57817
+ }
57818
+ const nameToCheck = metadata.name || "";
57819
+ const kits = [];
57820
+ if (/\bengineer\b/i.test(nameToCheck)) {
57821
+ kits.push("engineer");
57822
+ }
57823
+ if (/\bmarketing\b/i.test(nameToCheck)) {
57824
+ kits.push("marketing");
57825
+ }
57826
+ if (kits.length > 0) {
57827
+ return kits;
57828
+ }
57829
+ if (metadata.version) {
57830
+ return ["engineer"];
57831
+ }
57832
+ return [];
57833
+ }
57834
+ var import_fs_extra3;
57835
+ var init_metadata_migration = __esm(() => {
57836
+ init_logger();
57837
+ import_fs_extra3 = __toESM(require_lib3(), 1);
57838
+ });
57839
+
57840
+ // src/services/file-operations/claudekit-scanner.ts
57841
+ import { join as join46 } from "node:path";
57842
+ async function scanClaudeKitDirectory(directoryPath) {
57843
+ const counts = {
57844
+ agents: 0,
57845
+ commands: 0,
57846
+ rules: 0,
57847
+ skills: 0
57848
+ };
57849
+ try {
57850
+ if (!await import_fs_extra4.pathExists(directoryPath)) {
57851
+ return counts;
57852
+ }
57853
+ const items = await import_fs_extra4.readdir(directoryPath);
57854
+ if (items.includes("agents")) {
57855
+ const agentsPath = join46(directoryPath, "agents");
57856
+ const agentFiles = await import_fs_extra4.readdir(agentsPath);
57857
+ counts.agents = agentFiles.filter((file) => file.endsWith(".md")).length;
57858
+ }
57859
+ if (items.includes("commands")) {
57860
+ const commandsPath = join46(directoryPath, "commands");
57861
+ const commandFiles = await import_fs_extra4.readdir(commandsPath);
57862
+ counts.commands = commandFiles.filter((file) => file.endsWith(".md")).length;
57863
+ }
57864
+ if (items.includes("rules")) {
57865
+ const rulesPath = join46(directoryPath, "rules");
57866
+ const ruleFiles = await import_fs_extra4.readdir(rulesPath);
57867
+ counts.rules = ruleFiles.filter((file) => file.endsWith(".md")).length;
57868
+ } else if (items.includes("workflows")) {
57869
+ const workflowsPath = join46(directoryPath, "workflows");
57870
+ const workflowFiles = await import_fs_extra4.readdir(workflowsPath);
57871
+ counts.rules = workflowFiles.filter((file) => file.endsWith(".md")).length;
57872
+ }
57873
+ if (items.includes("skills")) {
57874
+ const skillsPath = join46(directoryPath, "skills");
57875
+ const skillItems = await import_fs_extra4.readdir(skillsPath);
57876
+ let skillCount = 0;
57877
+ for (const item of skillItems) {
57878
+ if (SKIP_DIRS_CLAUDE_INTERNAL.includes(item)) {
57879
+ continue;
57880
+ }
57881
+ const itemPath = join46(skillsPath, item);
57882
+ const stat8 = await import_fs_extra4.readdir(itemPath).catch(() => null);
57883
+ if (stat8?.includes("SKILL.md")) {
57884
+ skillCount++;
57885
+ }
57886
+ }
57887
+ counts.skills = skillCount;
57888
+ }
57889
+ } catch (error) {}
57890
+ return counts;
57891
+ }
57892
+ async function readClaudeKitMetadata(metadataPath) {
57893
+ try {
57894
+ if (!await import_fs_extra4.pathExists(metadataPath)) {
57895
+ return null;
57896
+ }
57897
+ const content = await import_fs_extra4.readFile(metadataPath, "utf8");
57898
+ const metadata = JSON.parse(content);
57899
+ return metadata;
57900
+ } catch {
57901
+ return null;
57902
+ }
57903
+ }
57904
+ function getGlobalInstallDir() {
57905
+ return PathResolver.getGlobalKitDir();
57906
+ }
57907
+ async function getClaudeKitSetup(projectDir = process.cwd()) {
57908
+ const setup = {
57909
+ global: {
57910
+ path: "",
57911
+ metadata: null,
57912
+ components: { agents: 0, commands: 0, rules: 0, skills: 0 }
57721
57913
  },
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"
57914
+ project: {
57915
+ path: "",
57916
+ metadata: null,
57917
+ components: { agents: 0, commands: 0, rules: 0, skills: 0 }
57743
57918
  }
57744
57919
  };
57920
+ const globalDir = getGlobalInstallDir();
57921
+ if (await import_fs_extra4.pathExists(globalDir)) {
57922
+ setup.global.path = globalDir;
57923
+ setup.global.metadata = await readClaudeKitMetadata(join46(globalDir, "metadata.json"));
57924
+ setup.global.components = await scanClaudeKitDirectory(globalDir);
57925
+ }
57926
+ const projectClaudeDir = join46(projectDir, ".claude");
57927
+ const isLocalSameAsGlobal = projectClaudeDir === globalDir;
57928
+ if (!isLocalSameAsGlobal && await import_fs_extra4.pathExists(projectClaudeDir)) {
57929
+ setup.project.path = projectClaudeDir;
57930
+ setup.project.metadata = await readClaudeKitMetadata(join46(projectClaudeDir, "metadata.json"));
57931
+ setup.project.components = await scanClaudeKitDirectory(projectClaudeDir);
57932
+ }
57933
+ return setup;
57934
+ }
57935
+ var import_fs_extra4;
57936
+ var init_claudekit_scanner = __esm(() => {
57937
+ init_path_resolver();
57938
+ init_skip_directories();
57939
+ import_fs_extra4 = __toESM(require_lib3(), 1);
57745
57940
  });
57746
57941
 
57747
57942
  // src/domains/github/github-auth.ts
@@ -58151,7 +58346,7 @@ ${action.title}:`);
58151
58346
  }
58152
58347
 
58153
58348
  // src/domains/error/index.ts
58154
- var init_error = () => {};
58349
+ var init_error2 = () => {};
58155
58350
 
58156
58351
  // src/domains/github/client/error-handler.ts
58157
58352
  async function handleHttpError(error, context) {
@@ -58182,7 +58377,7 @@ Need help? Run with: ${verboseFlag}`);
58182
58377
  `), classified.httpStatus);
58183
58378
  }
58184
58379
  var init_error_handler2 = __esm(() => {
58185
- init_error();
58380
+ init_error2();
58186
58381
  init_types3();
58187
58382
  init_auth_api();
58188
58383
  });
@@ -58303,7 +58498,7 @@ class VersionFormatter {
58303
58498
  static compare(v1, v2) {
58304
58499
  const normV1 = VersionFormatter.normalize(v1);
58305
58500
  const normV2 = VersionFormatter.normalize(v2);
58306
- return import_compare_versions2.compareVersions(normV1, normV2);
58501
+ return import_compare_versions3.compareVersions(normV1, normV2);
58307
58502
  }
58308
58503
  static formatRelativeTime(dateString) {
58309
58504
  if (!dateString)
@@ -58391,20 +58586,20 @@ class VersionFormatter {
58391
58586
  const majorA = Number.parseInt(normA.split(".")[0], 10);
58392
58587
  const majorB = Number.parseInt(normB.split(".")[0], 10);
58393
58588
  if (majorA === 0 && majorB === 0) {
58394
- return import_compare_versions2.compareVersions(normB, normA);
58589
+ return import_compare_versions3.compareVersions(normB, normA);
58395
58590
  }
58396
58591
  if (majorA === 0)
58397
58592
  return 1;
58398
58593
  if (majorB === 0)
58399
58594
  return -1;
58400
- return import_compare_versions2.compareVersions(normB, normA);
58595
+ return import_compare_versions3.compareVersions(normB, normA);
58401
58596
  });
58402
58597
  }
58403
58598
  }
58404
- var import_compare_versions2;
58599
+ var import_compare_versions3;
58405
58600
  var init_version_formatter = __esm(() => {
58406
58601
  init_logger();
58407
- import_compare_versions2 = __toESM(require_umd(), 1);
58602
+ import_compare_versions3 = __toESM(require_umd(), 1);
58408
58603
  });
58409
58604
 
58410
58605
  // src/domains/versioning/release-filter.ts
@@ -58913,64 +59108,16 @@ var init_github_client = __esm(() => {
58913
59108
  init_client();
58914
59109
  });
58915
59110
 
58916
- // src/commands/update-cli.ts
59111
+ // src/commands/update/post-update-handler.ts
58917
59112
  import { exec as exec2, spawn as spawn2 } from "node:child_process";
58918
59113
  import { join as join48 } from "node:path";
58919
59114
  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
59115
  function selectKitForUpdate(params) {
58968
59116
  const { hasLocal, hasGlobal, localKits, globalKits } = params;
58969
59117
  const hasLocalKit = localKits.length > 0 || hasLocal;
58970
59118
  const hasGlobalKit = globalKits.length > 0 || hasGlobal;
58971
- if (!hasLocalKit && !hasGlobalKit) {
59119
+ if (!hasLocalKit && !hasGlobalKit)
58972
59120
  return null;
58973
- }
58974
59121
  if (hasGlobalKit && !hasLocalKit) {
58975
59122
  const kit2 = globalKits[0] || localKits[0];
58976
59123
  return {
@@ -58997,9 +59144,8 @@ function selectKitForUpdate(params) {
58997
59144
  async function readMetadataFile(claudeDir2) {
58998
59145
  const metadataPath = join48(claudeDir2, "metadata.json");
58999
59146
  try {
59000
- if (!await import_fs_extra5.pathExists(metadataPath)) {
59147
+ if (!await import_fs_extra5.pathExists(metadataPath))
59001
59148
  return null;
59002
- }
59003
59149
  const content = await import_fs_extra5.readFile(metadataPath, "utf-8");
59004
59150
  const parsed = JSON.parse(content);
59005
59151
  const validated = MetadataSchema.safeParse(parsed);
@@ -59013,6 +59159,19 @@ async function readMetadataFile(claudeDir2) {
59013
59159
  return null;
59014
59160
  }
59015
59161
  }
59162
+ function buildInitCommand(isGlobal, kit, beta, yes) {
59163
+ const parts = ["ck init"];
59164
+ if (isGlobal)
59165
+ parts.push("-g");
59166
+ if (kit)
59167
+ parts.push(`--kit ${kit}`);
59168
+ if (yes)
59169
+ parts.push("--yes");
59170
+ parts.push("--install-skills");
59171
+ if (beta)
59172
+ parts.push("--beta");
59173
+ return parts.join(" ");
59174
+ }
59016
59175
  async function fetchLatestReleaseTag(kit, beta) {
59017
59176
  try {
59018
59177
  const { GitHubClient: GitHubClient2 } = await Promise.resolve().then(() => (init_github_client(), exports_github_client));
@@ -59066,14 +59225,11 @@ async function promptKitUpdate(beta, yes, deps) {
59066
59225
  const ckConfig = await loadFullConfigFn(null);
59067
59226
  autoInit = ckConfig.config.updatePipeline?.autoInitAfterUpdate ?? false;
59068
59227
  } catch {}
59069
- if (alreadyAtLatest && !autoInit) {
59228
+ if (alreadyAtLatest && !autoInit)
59070
59229
  return;
59071
- }
59072
59230
  if (!yes && !autoInit) {
59073
59231
  logger.info("");
59074
- const shouldUpdate = await confirmFn({
59075
- message: promptMessage
59076
- });
59232
+ const shouldUpdate = await confirmFn({ message: promptMessage });
59077
59233
  if (isCancelFn(shouldUpdate) || !shouldUpdate) {
59078
59234
  log.info("Skipped kit content update");
59079
59235
  return;
@@ -59211,6 +59367,37 @@ async function promptMigrateUpdate(deps) {
59211
59367
  logger.verbose(`Migrate step skipped: ${error instanceof Error ? error.message : "unknown"}`);
59212
59368
  }
59213
59369
  }
59370
+ var import_fs_extra5, execAsync2, SAFE_PROVIDER_NAME;
59371
+ var init_post_update_handler = __esm(() => {
59372
+ init_ck_config_manager();
59373
+ init_metadata_migration();
59374
+ init_version_utils();
59375
+ init_claudekit_scanner();
59376
+ init_logger();
59377
+ init_safe_prompts();
59378
+ init_types3();
59379
+ init_version_comparator();
59380
+ import_fs_extra5 = __toESM(require_lib3(), 1);
59381
+ execAsync2 = promisify8(exec2);
59382
+ SAFE_PROVIDER_NAME = /^[a-z0-9-]+$/;
59383
+ });
59384
+
59385
+ // src/commands/update-cli.ts
59386
+ function getDefaultUpdateCliCommandDeps() {
59387
+ return {
59388
+ currentVersion: package_default.version,
59389
+ execAsyncFn: async (cmd, opts) => {
59390
+ const { exec: exec3 } = await import("node:child_process");
59391
+ const { promisify: promisify9 } = await import("node:util");
59392
+ const result = await promisify9(exec3)(cmd, opts);
59393
+ return { stdout: String(result.stdout ?? ""), stderr: String(result.stderr ?? "") };
59394
+ },
59395
+ packageManagerDetector: PackageManagerDetector,
59396
+ npmRegistryClient: NpmRegistryClient,
59397
+ promptKitUpdateFn: promptKitUpdate,
59398
+ promptMigrateUpdateFn: promptMigrateUpdate
59399
+ };
59400
+ }
59214
59401
  async function updateCliCommand(options2, deps = getDefaultUpdateCliCommandDeps()) {
59215
59402
  const s = de();
59216
59403
  intro("[>] ClaudeKit CLI - Update");
@@ -59235,64 +59422,31 @@ async function updateCliCommand(options2, deps = getDefaultUpdateCliCommandDeps(
59235
59422
  const userRegistry = await packageManagerDetector.getNpmRegistryUrl();
59236
59423
  if (userRegistry) {
59237
59424
  registryUrl = userRegistry;
59238
- logger.verbose(`Using npm configured registry: ${redactRegistryUrlForLog(registryUrl)}`);
59425
+ const { redactRegistryUrlForLog: redactRegistryUrlForLog2 } = await Promise.resolve().then(() => (init_npm_registry(), exports_npm_registry));
59426
+ logger.verbose(`Using npm configured registry: ${redactRegistryUrlForLog2(registryUrl)}`);
59239
59427
  }
59240
59428
  }
59241
59429
  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) {
59430
+ const { targetVersion, targetIsPrerelease } = await resolveTargetVersion(opts, {
59431
+ npmRegistryClient,
59432
+ registryUrl,
59433
+ spinnerStop: (msg) => s.stop(msg)
59434
+ });
59435
+ const outcome = compareCliVersions(currentVersion, targetVersion, opts);
59436
+ if (outcome.status === "up-to-date") {
59282
59437
  outro(`[+] Already on the latest CLI version (${currentVersion})`);
59283
59438
  await promptKitUpdateFn(targetIsPrerelease, opts.yes);
59284
59439
  await promptMigrateUpdateFn();
59285
59440
  return;
59286
59441
  }
59287
- const isDevChannelSwitch = (opts.dev || opts.beta) && isBetaVersion(targetVersion) && !isBetaVersion(currentVersion);
59288
- if (comparison > 0 && !opts.release && !isDevChannelSwitch) {
59442
+ if (outcome.status === "newer") {
59289
59443
  outro(`[+] Current version (${currentVersion}) is newer than latest (${targetVersion})`);
59290
59444
  await promptKitUpdateFn(targetIsPrerelease, opts.yes);
59291
59445
  await promptMigrateUpdateFn();
59292
59446
  return;
59293
59447
  }
59294
- const isUpgrade = comparison < 0 || isDevChannelSwitch;
59295
- const changeType = isUpgrade ? "upgrade" : "downgrade";
59448
+ const isUpgrade = outcome.changeType === "upgrade";
59449
+ const changeType = outcome.changeType;
59296
59450
  logger.info(`${isUpgrade ? "[^]" : "[v]"} ${changeType}: ${currentVersion} -> ${targetVersion}`);
59297
59451
  if (opts.check) {
59298
59452
  note(`CLI update available: ${currentVersion} -> ${targetVersion}
@@ -59314,71 +59468,19 @@ Run 'ck update' to install`, "Update Check");
59314
59468
  }
59315
59469
  const updateCmd = packageManagerDetector.getUpdateCommand(pm, CLAUDEKIT_CLI_NPM_PACKAGE_NAME, targetVersion, registryUrl);
59316
59470
  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
- }
59471
+ await runPackageManagerUpdate(updateCmd, pm, {
59472
+ execAsyncFn,
59473
+ spinnerStart: (msg) => s.start(msg),
59474
+ spinnerStop: (msg) => s.stop(msg)
59475
+ });
59476
+ const activeVersion = await verifyInstalledVersion(targetVersion, updateCmd, {
59477
+ execAsyncFn,
59478
+ spinnerStart: (msg) => s.start(msg),
59479
+ spinnerStop: (msg) => s.stop(msg)
59480
+ });
59481
+ outro(`[+] Successfully updated ClaudeKit CLI to ${activeVersion}`);
59482
+ await promptKitUpdateFn(targetIsPrerelease, opts.yes);
59483
+ await promptMigrateUpdateFn();
59382
59484
  } catch (error) {
59383
59485
  if (error instanceof CliUpdateError) {
59384
59486
  throw error;
@@ -59388,30 +59490,24 @@ Manual update: ${redactCommandForLog(updateCmd)}`;
59388
59490
  throw new CliUpdateError(errorMessage);
59389
59491
  }
59390
59492
  }
59391
- var import_compare_versions3, import_fs_extra5, execAsync2, CliUpdateError, SAFE_PROVIDER_NAME;
59392
59493
  var init_update_cli = __esm(() => {
59393
- init_ck_config_manager();
59394
59494
  init_npm_registry();
59395
59495
  init_package_manager_detector();
59396
- init_metadata_migration();
59397
- init_version_utils();
59398
- init_claudekit_scanner();
59399
59496
  init_claudekit_constants();
59400
59497
  init_logger();
59401
59498
  init_safe_prompts();
59402
59499
  init_types3();
59403
- init_types3();
59404
59500
  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-]+$/;
59501
+ init_channel_resolver();
59502
+ init_error();
59503
+ init_package_manager_runner();
59504
+ init_post_update_handler();
59505
+ init_registry_client();
59506
+ init_version_comparator();
59507
+ init_error();
59508
+ init_version_comparator();
59509
+ init_post_update_handler();
59510
+ init_registry_client();
59415
59511
  });
59416
59512
 
59417
59513
  // src/domains/versioning/version-cache.ts