claudekit-cli 3.13.2 → 3.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +667 -601
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -14524,7 +14524,7 @@ var updateCommandHelp;
14524
14524
  var init_update_command_help = __esm(() => {
14525
14525
  updateCommandHelp = {
14526
14526
  name: "update",
14527
- description: "Update ClaudeKit CLI to the latest version",
14527
+ description: "Update ClaudeKit CLI tool only (not kit content)",
14528
14528
  usage: "ck update [options]",
14529
14529
  examples: [
14530
14530
  {
@@ -14587,7 +14587,7 @@ var init_update_command_help = __esm(() => {
14587
14587
  sections: [
14588
14588
  {
14589
14589
  title: "Note",
14590
- content: "'ck update' now only updates the ClaudeKit CLI itself. To update a kit installation, use 'ck init'."
14590
+ content: "'ck update' updates the CLI tool only. To update kit content (skills, commands, workflows), use 'ck init' for local or 'ck init -g' for global."
14591
14591
  }
14592
14592
  ]
14593
14593
  };
@@ -14674,22 +14674,22 @@ function padEnd(text, width) {
14674
14674
  const padding = Math.max(0, width - visibleLength);
14675
14675
  return text + " ".repeat(padding);
14676
14676
  }
14677
- var import_picocolors21, NO_COLOR, isColorSupported, identity = (text) => text, colors, defaultTheme;
14677
+ var import_picocolors23, NO_COLOR, isColorSupported, identity = (text) => text, colors, defaultTheme;
14678
14678
  var init_help_colors = __esm(() => {
14679
- import_picocolors21 = __toESM(require_picocolors(), 1);
14679
+ import_picocolors23 = __toESM(require_picocolors(), 1);
14680
14680
  NO_COLOR = process.env.NO_COLOR !== undefined;
14681
14681
  isColorSupported = !NO_COLOR && Boolean(process.stdout.isTTY);
14682
14682
  colors = {
14683
- banner: isColorSupported ? import_picocolors21.default.cyan : identity,
14684
- command: isColorSupported ? import_picocolors21.default.bold : identity,
14685
- heading: isColorSupported ? import_picocolors21.default.yellow : identity,
14686
- flag: isColorSupported ? import_picocolors21.default.green : identity,
14687
- description: isColorSupported ? import_picocolors21.default.gray : identity,
14688
- example: isColorSupported ? import_picocolors21.default.blue : identity,
14689
- warning: isColorSupported ? import_picocolors21.default.yellow : identity,
14690
- error: isColorSupported ? import_picocolors21.default.red : identity,
14691
- muted: isColorSupported ? import_picocolors21.default.dim : identity,
14692
- success: isColorSupported ? import_picocolors21.default.green : identity
14683
+ banner: isColorSupported ? import_picocolors23.default.cyan : identity,
14684
+ command: isColorSupported ? import_picocolors23.default.bold : identity,
14685
+ heading: isColorSupported ? import_picocolors23.default.yellow : identity,
14686
+ flag: isColorSupported ? import_picocolors23.default.green : identity,
14687
+ description: isColorSupported ? import_picocolors23.default.gray : identity,
14688
+ example: isColorSupported ? import_picocolors23.default.blue : identity,
14689
+ warning: isColorSupported ? import_picocolors23.default.yellow : identity,
14690
+ error: isColorSupported ? import_picocolors23.default.red : identity,
14691
+ muted: isColorSupported ? import_picocolors23.default.dim : identity,
14692
+ success: isColorSupported ? import_picocolors23.default.green : identity
14693
14693
  };
14694
14694
  defaultTheme = {
14695
14695
  banner: colors.banner,
@@ -35392,6 +35392,7 @@ Protected files (.env, etc.) were not modified.`;
35392
35392
  // src/commands/new/new-command.ts
35393
35393
  init_logger();
35394
35394
  init_types2();
35395
+ var import_picocolors15 = __toESM(require_picocolors(), 1);
35395
35396
 
35396
35397
  // src/commands/new/phases/directory-setup.ts
35397
35398
  import { resolve as resolve8 } from "node:path";
@@ -35668,6 +35669,7 @@ async function newCommand(options) {
35668
35669
  if (ctx.cancelled)
35669
35670
  return;
35670
35671
  prompts.outro(`✨ Project created successfully at ${ctx.resolvedDir}`);
35672
+ log.info(`${import_picocolors15.default.dim("Tip:")} To update later: ${import_picocolors15.default.cyan("ck update")} (CLI) + ${import_picocolors15.default.cyan("ck init")} (kit content)`);
35671
35673
  } catch (error) {
35672
35674
  logger.error(error instanceof Error ? error.message : "Unknown error occurred");
35673
35675
  process.exit(1);
@@ -35676,7 +35678,7 @@ async function newCommand(options) {
35676
35678
  // src/commands/uninstall/uninstall-command.ts
35677
35679
  init_logger();
35678
35680
  init_types2();
35679
- var import_picocolors16 = __toESM(require_picocolors(), 1);
35681
+ var import_picocolors17 = __toESM(require_picocolors(), 1);
35680
35682
 
35681
35683
  // src/commands/uninstall/installation-detector.ts
35682
35684
  var import_fs_extra32 = __toESM(require_lib(), 1);
@@ -35710,7 +35712,7 @@ var import_fs_extra33 = __toESM(require_lib(), 1);
35710
35712
  import { readdirSync, rmSync } from "node:fs";
35711
35713
  import { dirname as dirname8, join as join63 } from "node:path";
35712
35714
  init_logger();
35713
- var import_picocolors15 = __toESM(require_picocolors(), 1);
35715
+ var import_picocolors16 = __toESM(require_picocolors(), 1);
35714
35716
  function classifyFileByOwnership(ownership, forceOverwrite, deleteReason) {
35715
35717
  if (ownership === "ck") {
35716
35718
  return { action: "delete", reason: deleteReason };
@@ -35801,27 +35803,27 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
35801
35803
  }
35802
35804
  function displayDryRunPreview(analysis, installationType) {
35803
35805
  console.log("");
35804
- log.info(import_picocolors15.default.bold(`DRY RUN - Preview for ${installationType} installation:`));
35806
+ log.info(import_picocolors16.default.bold(`DRY RUN - Preview for ${installationType} installation:`));
35805
35807
  console.log("");
35806
35808
  if (analysis.toDelete.length > 0) {
35807
- console.log(import_picocolors15.default.red(import_picocolors15.default.bold(`Files to DELETE (${analysis.toDelete.length}):`)));
35809
+ console.log(import_picocolors16.default.red(import_picocolors16.default.bold(`Files to DELETE (${analysis.toDelete.length}):`)));
35808
35810
  const showDelete = analysis.toDelete.slice(0, 10);
35809
35811
  for (const item of showDelete) {
35810
- console.log(` ${import_picocolors15.default.red("✖")} ${item.path}`);
35812
+ console.log(` ${import_picocolors16.default.red("✖")} ${item.path}`);
35811
35813
  }
35812
35814
  if (analysis.toDelete.length > 10) {
35813
- console.log(import_picocolors15.default.gray(` ... and ${analysis.toDelete.length - 10} more`));
35815
+ console.log(import_picocolors16.default.gray(` ... and ${analysis.toDelete.length - 10} more`));
35814
35816
  }
35815
35817
  console.log("");
35816
35818
  }
35817
35819
  if (analysis.toPreserve.length > 0) {
35818
- console.log(import_picocolors15.default.green(import_picocolors15.default.bold(`Files to PRESERVE (${analysis.toPreserve.length}):`)));
35820
+ console.log(import_picocolors16.default.green(import_picocolors16.default.bold(`Files to PRESERVE (${analysis.toPreserve.length}):`)));
35819
35821
  const showPreserve = analysis.toPreserve.slice(0, 10);
35820
35822
  for (const item of showPreserve) {
35821
- console.log(` ${import_picocolors15.default.green("✓")} ${item.path} ${import_picocolors15.default.gray(`(${item.reason})`)}`);
35823
+ console.log(` ${import_picocolors16.default.green("✓")} ${item.path} ${import_picocolors16.default.gray(`(${item.reason})`)}`);
35822
35824
  }
35823
35825
  if (analysis.toPreserve.length > 10) {
35824
- console.log(import_picocolors15.default.gray(` ... and ${analysis.toPreserve.length - 10} more`));
35826
+ console.log(import_picocolors16.default.gray(` ... and ${analysis.toPreserve.length - 10} more`));
35825
35827
  }
35826
35828
  console.log("");
35827
35829
  }
@@ -35969,10 +35971,10 @@ async function uninstallCommand(options) {
35969
35971
  }
35970
35972
  displayInstallations(installations, scope);
35971
35973
  if (validOptions.kit) {
35972
- log.info(import_picocolors16.default.cyan(`Kit-scoped uninstall: ${validOptions.kit} kit only`));
35974
+ log.info(import_picocolors17.default.cyan(`Kit-scoped uninstall: ${validOptions.kit} kit only`));
35973
35975
  }
35974
35976
  if (validOptions.dryRun) {
35975
- log.info(import_picocolors16.default.yellow("DRY RUN MODE - No files will be deleted"));
35977
+ log.info(import_picocolors17.default.yellow("DRY RUN MODE - No files will be deleted"));
35976
35978
  await removeInstallations(installations, {
35977
35979
  dryRun: true,
35978
35980
  forceOverwrite: validOptions.forceOverwrite,
@@ -35982,8 +35984,8 @@ async function uninstallCommand(options) {
35982
35984
  return;
35983
35985
  }
35984
35986
  if (validOptions.forceOverwrite) {
35985
- log.warn(`${import_picocolors16.default.yellow(import_picocolors16.default.bold("FORCE MODE ENABLED"))}
35986
- ${import_picocolors16.default.yellow("User modifications will be permanently deleted!")}`);
35987
+ log.warn(`${import_picocolors17.default.yellow(import_picocolors17.default.bold("FORCE MODE ENABLED"))}
35988
+ ${import_picocolors17.default.yellow("User modifications will be permanently deleted!")}`);
35987
35989
  }
35988
35990
  if (!validOptions.yes) {
35989
35991
  const kitLabel = validOptions.kit ? ` (${validOptions.kit} kit only)` : "";
@@ -36144,206 +36146,534 @@ class NpmRegistryClient {
36144
36146
  }
36145
36147
  }
36146
36148
 
36147
- // src/commands/update-cli.ts
36148
- init_logger();
36149
- init_types2();
36150
- init_types2();
36149
+ // src/domains/versioning/checking/version-utils.ts
36151
36150
  var import_compare_versions2 = __toESM(require_umd(), 1);
36152
- // package.json
36153
- var package_default = {
36154
- name: "claudekit-cli",
36155
- version: "3.13.2",
36156
- description: "CLI tool for bootstrapping and updating ClaudeKit projects",
36157
- type: "module",
36158
- repository: {
36159
- type: "git",
36160
- url: "git+https://github.com/mrgoonie/claudekit-cli.git"
36161
- },
36162
- publishConfig: {
36163
- access: "public",
36164
- registry: "https://registry.npmjs.org"
36165
- },
36166
- bin: {
36167
- ck: "bin/ck.js"
36168
- },
36169
- files: [
36170
- "bin/ck.js",
36171
- "dist/index.js"
36172
- ],
36173
- scripts: {
36174
- dev: "bun run src/index.ts",
36175
- build: "bun build src/index.ts --outdir dist --target node --external @octokit/rest",
36176
- compile: "bun build src/index.ts --compile --outfile ck",
36177
- "compile:binary": "bun build src/index.ts --compile --outfile bin/ck",
36178
- "compile:binaries": "node scripts/build-all-binaries.js",
36179
- "check-version-sync": "node scripts/check-binary-version-sync.js",
36180
- "build:platform-binaries": "bun run scripts/build-platform-binaries.js",
36181
- test: "bun test",
36182
- "test:watch": "bun test --watch",
36183
- "test:quick": "./scripts/dev-quick-start.sh test",
36184
- lint: "biome check .",
36185
- "lint:fix": "biome check --fix .",
36186
- "lint:fix-unsafe": "biome check --fix --unsafe .",
36187
- format: "biome format --write .",
36188
- typecheck: "tsc --noEmit",
36189
- "dev:quick": "./scripts/dev-quick-start.sh",
36190
- "dev:all": "./scripts/dev-quick-start.sh all",
36191
- metrics: "bun run scripts/workflow-metrics.ts",
36192
- "install:hooks": "./.githooks/install.sh"
36193
- },
36194
- keywords: [
36195
- "cli",
36196
- "claudekit",
36197
- "boilerplate",
36198
- "bootstrap",
36199
- "template"
36200
- ],
36201
- author: "ClaudeKit",
36202
- license: "MIT",
36203
- engines: {
36204
- bun: ">=1.3.2",
36205
- node: ">=18.0.0"
36206
- },
36207
- dependencies: {
36208
- "@clack/prompts": "^0.7.0",
36209
- "@octokit/rest": "^22.0.0",
36210
- cac: "^6.7.14",
36211
- "cli-progress": "^3.12.0",
36212
- "compare-versions": "^6.1.1",
36213
- "extract-zip": "^2.0.1",
36214
- "fs-extra": "^11.2.0",
36215
- ignore: "^5.3.2",
36216
- minimatch: "^10.1.1",
36217
- ora: "^8.0.0",
36218
- "p-limit": "^7.2.0",
36219
- picocolors: "^1.1.1",
36220
- "proper-lockfile": "^4.1.2",
36221
- tar: "^7.4.3",
36222
- tmp: "^0.2.3",
36223
- zod: "^3.23.8"
36224
- },
36225
- devDependencies: {
36226
- "@biomejs/biome": "^1.9.4",
36227
- "@semantic-release/changelog": "^6.0.3",
36228
- "@semantic-release/git": "^10.0.1",
36229
- "@types/bun": "latest",
36230
- "@types/cli-progress": "^3.11.6",
36231
- "@types/fs-extra": "^11.0.4",
36232
- "@types/node": "^22.10.1",
36233
- "@types/proper-lockfile": "^4.1.4",
36234
- "@types/tar": "^6.1.13",
36235
- "@types/tmp": "^0.2.6",
36236
- "semantic-release": "^24.2.0",
36237
- typescript: "^5.7.2"
36151
+ function isUpdateCheckDisabled() {
36152
+ return process.env.NO_UPDATE_NOTIFIER === "1" || process.env.NO_UPDATE_NOTIFIER === "true" || !process.stdout.isTTY;
36153
+ }
36154
+ function normalizeVersion(version) {
36155
+ return version.replace(/^v/, "");
36156
+ }
36157
+ function isNewerVersion(currentVersion, latestVersion) {
36158
+ try {
36159
+ const current = normalizeVersion(currentVersion);
36160
+ const latest = normalizeVersion(latestVersion);
36161
+ return import_compare_versions2.compareVersions(latest, current) > 0;
36162
+ } catch {
36163
+ return false;
36238
36164
  }
36239
- };
36240
-
36241
- // src/commands/update-cli.ts
36242
- var execAsync7 = promisify7(exec7);
36165
+ }
36166
+ // src/domains/versioning/checking/kit-version-checker.ts
36167
+ init_logger();
36168
+ init_types2();
36243
36169
 
36244
- class CliUpdateError extends ClaudeKitError {
36245
- constructor(message) {
36246
- super(message, "CLI_UPDATE_ERROR");
36247
- this.name = "CliUpdateError";
36170
+ // src/domains/versioning/version-cache.ts
36171
+ init_logger();
36172
+ import { existsSync as existsSync16 } from "node:fs";
36173
+ import { mkdir as mkdir18, readFile as readFile20, writeFile as writeFile17 } from "node:fs/promises";
36174
+ import { join as join65 } from "node:path";
36175
+ class VersionCacheManager {
36176
+ static CACHE_FILENAME = "version-check.json";
36177
+ static CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
36178
+ static getCacheFile() {
36179
+ const cacheDir = PathResolver.getCacheDir(false);
36180
+ return join65(cacheDir, VersionCacheManager.CACHE_FILENAME);
36248
36181
  }
36249
- }
36250
- var PACKAGE_NAME = "claudekit-cli";
36251
- async function updateCliCommand(options) {
36252
- const s = de();
36253
- intro("[>] ClaudeKit CLI - Update");
36254
- try {
36255
- const opts = UpdateCliOptionsSchema.parse(options);
36256
- const currentVersion = package_default.version;
36257
- logger.info(`Current CLI version: ${currentVersion}`);
36258
- s.start("Detecting package manager...");
36259
- const pm = await PackageManagerDetector.detect();
36260
- const pmVersion = await PackageManagerDetector.getVersion(pm);
36261
- s.stop(`Using ${PackageManagerDetector.getDisplayName(pm)}${pmVersion ? ` v${pmVersion}` : ""}`);
36262
- logger.verbose(`Detected package manager: ${pm}`);
36263
- s.start("Checking for updates...");
36264
- let targetVersion = null;
36265
- if (opts.release && opts.release !== "latest") {
36266
- const exists = await NpmRegistryClient.versionExists(PACKAGE_NAME, opts.release, opts.registry);
36267
- if (!exists) {
36268
- s.stop("Version not found");
36269
- throw new CliUpdateError(`Version ${opts.release} does not exist on npm registry. Run 'ck versions' to see available versions.`);
36182
+ static async load() {
36183
+ const cacheFile = VersionCacheManager.getCacheFile();
36184
+ try {
36185
+ if (!existsSync16(cacheFile)) {
36186
+ logger.debug("Version check cache not found");
36187
+ return null;
36270
36188
  }
36271
- targetVersion = opts.release;
36272
- s.stop(`Target version: ${targetVersion}`);
36273
- } else if (opts.beta) {
36274
- targetVersion = await NpmRegistryClient.getBetaVersion(PACKAGE_NAME, opts.registry);
36275
- if (!targetVersion) {
36276
- s.stop("No beta version available");
36277
- logger.warning("No beta version found. Using latest stable version instead.");
36278
- targetVersion = await NpmRegistryClient.getLatestVersion(PACKAGE_NAME, opts.registry);
36279
- } else {
36280
- s.stop(`Latest beta version: ${targetVersion}`);
36189
+ const content = await readFile20(cacheFile, "utf-8");
36190
+ const cache2 = JSON.parse(content);
36191
+ if (!cache2.lastCheck || !cache2.currentVersion || !cache2.latestVersion) {
36192
+ logger.debug("Invalid cache structure, ignoring");
36193
+ return null;
36281
36194
  }
36282
- } else {
36283
- targetVersion = await NpmRegistryClient.getLatestVersion(PACKAGE_NAME, opts.registry);
36284
- s.stop(`Latest version: ${targetVersion || "unknown"}`);
36285
- }
36286
- if (!targetVersion) {
36287
- throw new CliUpdateError(`Failed to fetch version information from npm registry. Check your internet connection and try again. Manual update: ${PackageManagerDetector.getUpdateCommand(pm, PACKAGE_NAME)}`);
36288
- }
36289
- const comparison = import_compare_versions2.compareVersions(currentVersion, targetVersion);
36290
- if (comparison === 0) {
36291
- outro(`[+] Already on the latest version (${currentVersion})`);
36292
- return;
36293
- }
36294
- if (comparison > 0 && !opts.release) {
36295
- outro(`[+] Current version (${currentVersion}) is newer than latest (${targetVersion})`);
36296
- return;
36297
- }
36298
- const isUpgrade = comparison < 0;
36299
- const changeType = isUpgrade ? "upgrade" : "downgrade";
36300
- logger.info(`${isUpgrade ? "[^]" : "[v]"} ${changeType}: ${currentVersion} -> ${targetVersion}`);
36301
- if (opts.check) {
36302
- note(`Update available: ${currentVersion} -> ${targetVersion}
36303
-
36304
- Run 'ck update' to install`, "Update Check");
36305
- outro("Check complete");
36306
- return;
36195
+ logger.debug(`Version check cache loaded: ${JSON.stringify(cache2)}`);
36196
+ return cache2;
36197
+ } catch (error) {
36198
+ logger.debug(`Failed to load version check cache: ${error}`);
36199
+ return null;
36307
36200
  }
36308
- if (!opts.yes) {
36309
- const shouldUpdate = await se({
36310
- message: `${isUpgrade ? "Update" : "Downgrade"} CLI from ${currentVersion} to ${targetVersion}?`
36311
- });
36312
- if (lD(shouldUpdate) || !shouldUpdate) {
36313
- outro("Update cancelled");
36314
- return;
36201
+ }
36202
+ static async save(cache2) {
36203
+ const cacheFile = VersionCacheManager.getCacheFile();
36204
+ const cacheDir = PathResolver.getCacheDir(false);
36205
+ try {
36206
+ if (!existsSync16(cacheDir)) {
36207
+ await mkdir18(cacheDir, { recursive: true, mode: 448 });
36315
36208
  }
36209
+ await writeFile17(cacheFile, JSON.stringify(cache2, null, 2), "utf-8");
36210
+ logger.debug(`Version check cache saved to ${cacheFile}`);
36211
+ } catch (error) {
36212
+ logger.debug(`Failed to save version check cache: ${error}`);
36316
36213
  }
36317
- const updateCmd = PackageManagerDetector.getUpdateCommand(pm, PACKAGE_NAME, targetVersion);
36318
- logger.info(`Running: ${updateCmd}`);
36319
- s.start("Updating CLI...");
36214
+ }
36215
+ static isCacheValid(cache2) {
36216
+ if (!cache2)
36217
+ return false;
36218
+ const now = Date.now();
36219
+ const age = now - cache2.lastCheck;
36220
+ const isValid2 = age < VersionCacheManager.CACHE_TTL_MS;
36221
+ const ageDays = (age / 1000 / 60 / 60 / 24).toFixed(1);
36222
+ logger.debug(`Cache validity check: age=${ageDays} days, valid=${isValid2}`);
36223
+ return isValid2;
36224
+ }
36225
+ static async clear() {
36226
+ const cacheFile = VersionCacheManager.getCacheFile();
36320
36227
  try {
36321
- await execAsync7(updateCmd, {
36322
- timeout: 120000
36323
- });
36324
- s.stop("Update completed");
36325
- } catch (error) {
36326
- s.stop("Update failed");
36327
- const errorMessage = error instanceof Error ? error.message : "Unknown error";
36328
- if (errorMessage.includes("EACCES") || errorMessage.includes("EPERM") || errorMessage.includes("permission") || errorMessage.includes("Access is denied")) {
36329
- throw new CliUpdateError(`Permission denied. Try: sudo ${updateCmd}
36330
-
36331
- Or fix npm permissions: https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally`);
36228
+ if (existsSync16(cacheFile)) {
36229
+ const fs12 = await import("node:fs/promises");
36230
+ await fs12.unlink(cacheFile);
36231
+ logger.debug("Version check cache cleared");
36332
36232
  }
36333
- throw new CliUpdateError(`Update failed: ${errorMessage}
36334
-
36335
- Manual update: ${updateCmd}`);
36233
+ } catch (error) {
36234
+ logger.debug(`Failed to clear version check cache: ${error}`);
36336
36235
  }
36337
- s.start("Verifying installation...");
36338
- try {
36339
- const { stdout } = await execAsync7("ck --version", { timeout: 5000 });
36340
- const newVersionMatch = stdout.match(/CLI Version:\s*(\S+)/);
36341
- const newVersion = newVersionMatch ? newVersionMatch[1] : targetVersion;
36342
- s.stop(`Installed version: ${newVersion}`);
36343
- outro(`[+] Successfully updated ClaudeKit CLI to ${newVersion}`);
36344
- } catch {
36345
- s.stop("Verification completed");
36236
+ }
36237
+ }
36238
+
36239
+ // src/domains/versioning/checking/kit-version-checker.ts
36240
+ async function fetchLatestRelease(currentVersion) {
36241
+ try {
36242
+ const githubClient = new GitHubClient;
36243
+ const kit = AVAILABLE_KITS.engineer;
36244
+ const timeoutPromise = new Promise((_3, reject) => setTimeout(() => reject(new Error("Timeout")), 5000));
36245
+ const releasePromise = githubClient.getLatestRelease(kit);
36246
+ const release = await Promise.race([releasePromise, timeoutPromise]);
36247
+ const latestVersion = release.tag_name;
36248
+ const updateAvailable = isNewerVersion(currentVersion, latestVersion);
36249
+ const releaseUrl = `https://github.com/${kit.owner}/${kit.repo}/releases/tag/${latestVersion}`;
36250
+ logger.debug(`Fetched latest release: current=${currentVersion}, latest=${latestVersion}, updateAvailable=${updateAvailable}`);
36251
+ return {
36252
+ currentVersion,
36253
+ latestVersion,
36254
+ updateAvailable,
36255
+ releaseUrl
36256
+ };
36257
+ } catch (error) {
36258
+ logger.debug(`Failed to fetch latest release: ${error}`);
36259
+ return null;
36260
+ }
36261
+ }
36262
+
36263
+ class VersionChecker {
36264
+ static async check(currentVersion) {
36265
+ if (isUpdateCheckDisabled()) {
36266
+ logger.debug("Update check disabled by environment");
36267
+ return null;
36268
+ }
36269
+ const cache2 = await VersionCacheManager.load();
36270
+ if (cache2 && VersionCacheManager.isCacheValid(cache2) && cache2.currentVersion === currentVersion) {
36271
+ logger.debug("Using cached version check result");
36272
+ return {
36273
+ currentVersion: cache2.currentVersion,
36274
+ latestVersion: cache2.latestVersion,
36275
+ updateAvailable: cache2.updateAvailable,
36276
+ releaseUrl: cache2.latestUrl
36277
+ };
36278
+ }
36279
+ logger.debug("Cache expired or invalid, fetching latest release");
36280
+ const result = await fetchLatestRelease(currentVersion);
36281
+ if (result) {
36282
+ await VersionCacheManager.save({
36283
+ lastCheck: Date.now(),
36284
+ currentVersion: result.currentVersion,
36285
+ latestVersion: result.latestVersion,
36286
+ latestUrl: result.releaseUrl,
36287
+ updateAvailable: result.updateAvailable
36288
+ });
36289
+ }
36290
+ return result;
36291
+ }
36292
+ }
36293
+ // src/domains/versioning/checking/cli-version-checker.ts
36294
+ init_logger();
36295
+ var import_compare_versions3 = __toESM(require_umd(), 1);
36296
+ var PACKAGE_NAME = "claudekit-cli";
36297
+
36298
+ class CliVersionChecker {
36299
+ static async check(currentVersion) {
36300
+ if (isUpdateCheckDisabled()) {
36301
+ logger.debug("CLI update check disabled by environment");
36302
+ return null;
36303
+ }
36304
+ try {
36305
+ const latestVersion = await NpmRegistryClient.getLatestVersion(PACKAGE_NAME);
36306
+ if (!latestVersion) {
36307
+ logger.debug("Failed to fetch latest CLI version from npm");
36308
+ return null;
36309
+ }
36310
+ const current = normalizeVersion(currentVersion);
36311
+ const latest = normalizeVersion(latestVersion);
36312
+ const updateAvailable = import_compare_versions3.compareVersions(latest, current) > 0;
36313
+ logger.debug(`CLI version check: current=${current}, latest=${latest}, updateAvailable=${updateAvailable}`);
36314
+ return {
36315
+ currentVersion: current,
36316
+ latestVersion: latest,
36317
+ updateAvailable,
36318
+ releaseUrl: `https://www.npmjs.com/package/${PACKAGE_NAME}`
36319
+ };
36320
+ } catch (error) {
36321
+ logger.debug(`CLI version check failed: ${error}`);
36322
+ return null;
36323
+ }
36324
+ }
36325
+ }
36326
+ // src/domains/versioning/checking/notification-display.ts
36327
+ var import_picocolors18 = __toESM(require_picocolors(), 1);
36328
+ function createNotificationBox(borderColor, boxWidth) {
36329
+ const contentWidth = boxWidth - 2;
36330
+ const topBorder = borderColor(`╭${"─".repeat(contentWidth)}╮`);
36331
+ const bottomBorder = borderColor(`╰${"─".repeat(contentWidth)}╯`);
36332
+ const emptyLine = borderColor("│") + " ".repeat(contentWidth) + borderColor("│");
36333
+ const padLine = (text, visibleLen) => {
36334
+ const len = visibleLen ?? text.length;
36335
+ const displayText = len > contentWidth ? `${text.slice(0, contentWidth - 3)}...` : text;
36336
+ const actualLen = visibleLen ?? displayText.length;
36337
+ const totalPadding = contentWidth - actualLen;
36338
+ const leftPadding = Math.max(0, Math.floor(totalPadding / 2));
36339
+ const rightPadding = Math.max(0, totalPadding - leftPadding);
36340
+ return borderColor("│") + " ".repeat(leftPadding) + displayText + " ".repeat(rightPadding) + borderColor("│");
36341
+ };
36342
+ return { topBorder, bottomBorder, emptyLine, padLine };
36343
+ }
36344
+ function displayKitNotification(result, options = {}) {
36345
+ if (!result.updateAvailable)
36346
+ return;
36347
+ const { currentVersion, latestVersion } = result;
36348
+ const { isGlobal = false } = options;
36349
+ const displayCurrent = normalizeVersion(currentVersion);
36350
+ const displayLatest = normalizeVersion(latestVersion);
36351
+ const boxWidth = 52;
36352
+ const { topBorder, bottomBorder, emptyLine, padLine } = createNotificationBox(import_picocolors18.default.cyan, boxWidth);
36353
+ const headerText = import_picocolors18.default.bold(import_picocolors18.default.yellow("⬆ Kit Update Available"));
36354
+ const headerLen = "⬆ Kit Update Available".length;
36355
+ const versionText = `${import_picocolors18.default.dim(displayCurrent)} ${import_picocolors18.default.white("→")} ${import_picocolors18.default.green(import_picocolors18.default.bold(displayLatest))}`;
36356
+ const versionLen = displayCurrent.length + 3 + displayLatest.length;
36357
+ const updateCmd = isGlobal ? "ck init -g" : "ck init";
36358
+ const commandText = `Run: ${import_picocolors18.default.cyan(import_picocolors18.default.bold(updateCmd))}`;
36359
+ const commandLen = `Run: ${updateCmd}`.length;
36360
+ console.log("");
36361
+ console.log(topBorder);
36362
+ console.log(emptyLine);
36363
+ console.log(padLine(headerText, headerLen));
36364
+ console.log(padLine(versionText, versionLen));
36365
+ console.log(emptyLine);
36366
+ console.log(padLine(commandText, commandLen));
36367
+ console.log(emptyLine);
36368
+ console.log(bottomBorder);
36369
+ console.log("");
36370
+ }
36371
+ function displayCliNotification(result) {
36372
+ if (!result.updateAvailable)
36373
+ return;
36374
+ const { currentVersion, latestVersion } = result;
36375
+ const boxWidth = 52;
36376
+ const { topBorder, bottomBorder, emptyLine, padLine } = createNotificationBox(import_picocolors18.default.magenta, boxWidth);
36377
+ const headerText = import_picocolors18.default.bold(import_picocolors18.default.yellow("⬆ CLI Update Available"));
36378
+ const headerLen = "⬆ CLI Update Available".length;
36379
+ const versionText = `${import_picocolors18.default.dim(currentVersion)} ${import_picocolors18.default.white("→")} ${import_picocolors18.default.green(import_picocolors18.default.bold(latestVersion))}`;
36380
+ const versionLen = currentVersion.length + 3 + latestVersion.length;
36381
+ const commandText = `Run: ${import_picocolors18.default.magenta(import_picocolors18.default.bold("ck update"))}`;
36382
+ const commandLen = "Run: ck update".length;
36383
+ console.log("");
36384
+ console.log(topBorder);
36385
+ console.log(emptyLine);
36386
+ console.log(padLine(headerText, headerLen));
36387
+ console.log(padLine(versionText, versionLen));
36388
+ console.log(emptyLine);
36389
+ console.log(padLine(commandText, commandLen));
36390
+ console.log(emptyLine);
36391
+ console.log(bottomBorder);
36392
+ console.log("");
36393
+ }
36394
+ // src/domains/versioning/version-checker.ts
36395
+ class VersionChecker2 {
36396
+ static async check(currentVersion) {
36397
+ return VersionChecker.check(currentVersion);
36398
+ }
36399
+ static displayNotification(result, options = {}) {
36400
+ displayKitNotification(result, options);
36401
+ }
36402
+ }
36403
+
36404
+ class CliVersionChecker2 {
36405
+ static async check(currentVersion) {
36406
+ return CliVersionChecker.check(currentVersion);
36407
+ }
36408
+ static displayNotification(result) {
36409
+ displayCliNotification(result);
36410
+ }
36411
+ }
36412
+
36413
+ // src/commands/update-cli.ts
36414
+ init_logger();
36415
+ init_types2();
36416
+ init_types2();
36417
+ var import_compare_versions4 = __toESM(require_umd(), 1);
36418
+ var import_picocolors19 = __toESM(require_picocolors(), 1);
36419
+ // package.json
36420
+ var package_default = {
36421
+ name: "claudekit-cli",
36422
+ version: "3.14.0",
36423
+ description: "CLI tool for bootstrapping and updating ClaudeKit projects",
36424
+ type: "module",
36425
+ repository: {
36426
+ type: "git",
36427
+ url: "git+https://github.com/mrgoonie/claudekit-cli.git"
36428
+ },
36429
+ publishConfig: {
36430
+ access: "public",
36431
+ registry: "https://registry.npmjs.org"
36432
+ },
36433
+ bin: {
36434
+ ck: "bin/ck.js"
36435
+ },
36436
+ files: [
36437
+ "bin/ck.js",
36438
+ "dist/index.js"
36439
+ ],
36440
+ scripts: {
36441
+ dev: "bun run src/index.ts",
36442
+ build: "bun build src/index.ts --outdir dist --target node --external @octokit/rest",
36443
+ compile: "bun build src/index.ts --compile --outfile ck",
36444
+ "compile:binary": "bun build src/index.ts --compile --outfile bin/ck",
36445
+ "compile:binaries": "node scripts/build-all-binaries.js",
36446
+ "check-version-sync": "node scripts/check-binary-version-sync.js",
36447
+ "build:platform-binaries": "bun run scripts/build-platform-binaries.js",
36448
+ test: "bun test",
36449
+ "test:watch": "bun test --watch",
36450
+ "test:quick": "./scripts/dev-quick-start.sh test",
36451
+ lint: "biome check .",
36452
+ "lint:fix": "biome check --fix .",
36453
+ "lint:fix-unsafe": "biome check --fix --unsafe .",
36454
+ format: "biome format --write .",
36455
+ typecheck: "tsc --noEmit",
36456
+ "dev:quick": "./scripts/dev-quick-start.sh",
36457
+ "dev:all": "./scripts/dev-quick-start.sh all",
36458
+ metrics: "bun run scripts/workflow-metrics.ts",
36459
+ "install:hooks": "./.githooks/install.sh"
36460
+ },
36461
+ keywords: [
36462
+ "cli",
36463
+ "claudekit",
36464
+ "boilerplate",
36465
+ "bootstrap",
36466
+ "template"
36467
+ ],
36468
+ author: "ClaudeKit",
36469
+ license: "MIT",
36470
+ engines: {
36471
+ bun: ">=1.3.2",
36472
+ node: ">=18.0.0"
36473
+ },
36474
+ dependencies: {
36475
+ "@clack/prompts": "^0.7.0",
36476
+ "@octokit/rest": "^22.0.0",
36477
+ cac: "^6.7.14",
36478
+ "cli-progress": "^3.12.0",
36479
+ "compare-versions": "^6.1.1",
36480
+ "extract-zip": "^2.0.1",
36481
+ "fs-extra": "^11.2.0",
36482
+ ignore: "^5.3.2",
36483
+ minimatch: "^10.1.1",
36484
+ ora: "^8.0.0",
36485
+ "p-limit": "^7.2.0",
36486
+ picocolors: "^1.1.1",
36487
+ "proper-lockfile": "^4.1.2",
36488
+ tar: "^7.4.3",
36489
+ tmp: "^0.2.3",
36490
+ zod: "^3.23.8"
36491
+ },
36492
+ devDependencies: {
36493
+ "@biomejs/biome": "^1.9.4",
36494
+ "@semantic-release/changelog": "^6.0.3",
36495
+ "@semantic-release/git": "^10.0.1",
36496
+ "@types/bun": "latest",
36497
+ "@types/cli-progress": "^3.11.6",
36498
+ "@types/fs-extra": "^11.0.4",
36499
+ "@types/node": "^22.10.1",
36500
+ "@types/proper-lockfile": "^4.1.4",
36501
+ "@types/tar": "^6.1.13",
36502
+ "@types/tmp": "^0.2.6",
36503
+ "semantic-release": "^24.2.0",
36504
+ typescript: "^5.7.2"
36505
+ }
36506
+ };
36507
+
36508
+ // src/commands/update-cli.ts
36509
+ var execAsync7 = promisify7(exec7);
36510
+
36511
+ class CliUpdateError extends ClaudeKitError {
36512
+ constructor(message) {
36513
+ super(message, "CLI_UPDATE_ERROR");
36514
+ this.name = "CliUpdateError";
36515
+ }
36516
+ }
36517
+ var PACKAGE_NAME2 = "claudekit-cli";
36518
+ var KIT_UPDATE_REMINDER_HEADER = "Note: 'ck update' only updates the CLI tool itself.";
36519
+ async function displayKitUpdateReminder() {
36520
+ try {
36521
+ const setup = await getClaudeKitSetup();
36522
+ const hasLocal = !!setup.project.metadata;
36523
+ const hasGlobal = !!setup.global.metadata;
36524
+ const localVersion = setup.project.metadata?.version;
36525
+ const globalVersion = setup.global.metadata?.version;
36526
+ const versionsToCheck = new Set;
36527
+ if (localVersion)
36528
+ versionsToCheck.add(localVersion);
36529
+ if (globalVersion)
36530
+ versionsToCheck.add(globalVersion);
36531
+ const versionCheckResults = new Map;
36532
+ if (versionsToCheck.size > 0) {
36533
+ const checkPromises = [...versionsToCheck].map(async (version) => {
36534
+ const result = await VersionChecker2.check(version).catch(() => null);
36535
+ return { version, result };
36536
+ });
36537
+ const results = await Promise.all(checkPromises);
36538
+ for (const { version, result } of results) {
36539
+ versionCheckResults.set(version, result);
36540
+ }
36541
+ }
36542
+ const cmdLocal = "ck init";
36543
+ const cmdGlobal = "ck init -g";
36544
+ const maxCmdLen = Math.max(cmdLocal.length, cmdGlobal.length);
36545
+ const pad = (cmd) => cmd.padEnd(maxCmdLen);
36546
+ const lines = [];
36547
+ lines.push(import_picocolors19.default.yellow(KIT_UPDATE_REMINDER_HEADER));
36548
+ lines.push("");
36549
+ lines.push("To update your ClaudeKit content (skills, commands, workflows):");
36550
+ if (hasLocal && localVersion) {
36551
+ lines.push(` ${import_picocolors19.default.cyan(pad(cmdLocal))} Update local project (v${localVersion})`);
36552
+ const localCheck = versionCheckResults.get(localVersion);
36553
+ if (localCheck?.updateAvailable) {
36554
+ const indent = " ".repeat(maxCmdLen + 4);
36555
+ lines.push(`${indent}${import_picocolors19.default.green(`→ v${localCheck.latestVersion} available!`)}`);
36556
+ }
36557
+ } else {
36558
+ lines.push(` ${import_picocolors19.default.cyan(pad(cmdLocal))} Initialize in current project`);
36559
+ }
36560
+ if (hasGlobal && globalVersion) {
36561
+ lines.push(` ${import_picocolors19.default.cyan(pad(cmdGlobal))} Update global ~/.claude (v${globalVersion})`);
36562
+ const globalCheck = versionCheckResults.get(globalVersion);
36563
+ if (globalCheck?.updateAvailable) {
36564
+ const indent = " ".repeat(maxCmdLen + 4);
36565
+ lines.push(`${indent}${import_picocolors19.default.green(`→ v${globalCheck.latestVersion} available!`)}`);
36566
+ }
36567
+ } else {
36568
+ lines.push(` ${import_picocolors19.default.cyan(pad(cmdGlobal))} Initialize global ~/.claude`);
36569
+ }
36570
+ logger.info("");
36571
+ log.info(lines.join(`
36572
+ `));
36573
+ } catch (error) {
36574
+ logger.verbose(`Failed to display kit update reminder: ${error instanceof Error ? error.message : "unknown error"}`);
36575
+ }
36576
+ }
36577
+ async function updateCliCommand(options) {
36578
+ const s = de();
36579
+ intro("[>] ClaudeKit CLI - Update");
36580
+ try {
36581
+ const opts = UpdateCliOptionsSchema.parse(options);
36582
+ const currentVersion = package_default.version;
36583
+ logger.info(`Current CLI version: ${currentVersion}`);
36584
+ s.start("Detecting package manager...");
36585
+ const pm = await PackageManagerDetector.detect();
36586
+ const pmVersion = await PackageManagerDetector.getVersion(pm);
36587
+ s.stop(`Using ${PackageManagerDetector.getDisplayName(pm)}${pmVersion ? ` v${pmVersion}` : ""}`);
36588
+ logger.verbose(`Detected package manager: ${pm}`);
36589
+ s.start("Checking for updates...");
36590
+ let targetVersion = null;
36591
+ if (opts.release && opts.release !== "latest") {
36592
+ const exists = await NpmRegistryClient.versionExists(PACKAGE_NAME2, opts.release, opts.registry);
36593
+ if (!exists) {
36594
+ s.stop("Version not found");
36595
+ throw new CliUpdateError(`Version ${opts.release} does not exist on npm registry. Run 'ck versions' to see available versions.`);
36596
+ }
36597
+ targetVersion = opts.release;
36598
+ s.stop(`Target version: ${targetVersion}`);
36599
+ } else if (opts.beta) {
36600
+ targetVersion = await NpmRegistryClient.getBetaVersion(PACKAGE_NAME2, opts.registry);
36601
+ if (!targetVersion) {
36602
+ s.stop("No beta version available");
36603
+ logger.warning("No beta version found. Using latest stable version instead.");
36604
+ targetVersion = await NpmRegistryClient.getLatestVersion(PACKAGE_NAME2, opts.registry);
36605
+ } else {
36606
+ s.stop(`Latest beta version: ${targetVersion}`);
36607
+ }
36608
+ } else {
36609
+ targetVersion = await NpmRegistryClient.getLatestVersion(PACKAGE_NAME2, opts.registry);
36610
+ s.stop(`Latest version: ${targetVersion || "unknown"}`);
36611
+ }
36612
+ if (!targetVersion) {
36613
+ throw new CliUpdateError(`Failed to fetch version information from npm registry. Check your internet connection and try again. Manual update: ${PackageManagerDetector.getUpdateCommand(pm, PACKAGE_NAME2)}`);
36614
+ }
36615
+ const comparison = import_compare_versions4.compareVersions(currentVersion, targetVersion);
36616
+ if (comparison === 0) {
36617
+ outro(`[+] Already on the latest CLI version (${currentVersion})`);
36618
+ await displayKitUpdateReminder();
36619
+ return;
36620
+ }
36621
+ if (comparison > 0 && !opts.release) {
36622
+ outro(`[+] Current version (${currentVersion}) is newer than latest (${targetVersion})`);
36623
+ return;
36624
+ }
36625
+ const isUpgrade = comparison < 0;
36626
+ const changeType = isUpgrade ? "upgrade" : "downgrade";
36627
+ logger.info(`${isUpgrade ? "[^]" : "[v]"} ${changeType}: ${currentVersion} -> ${targetVersion}`);
36628
+ if (opts.check) {
36629
+ note(`CLI update available: ${currentVersion} -> ${targetVersion}
36630
+
36631
+ Run 'ck update' to install`, "Update Check");
36632
+ await displayKitUpdateReminder();
36633
+ outro("Check complete");
36634
+ return;
36635
+ }
36636
+ if (!opts.yes) {
36637
+ const shouldUpdate = await se({
36638
+ message: `${isUpgrade ? "Update" : "Downgrade"} CLI from ${currentVersion} to ${targetVersion}?`
36639
+ });
36640
+ if (lD(shouldUpdate) || !shouldUpdate) {
36641
+ outro("Update cancelled");
36642
+ return;
36643
+ }
36644
+ }
36645
+ const updateCmd = PackageManagerDetector.getUpdateCommand(pm, PACKAGE_NAME2, targetVersion);
36646
+ logger.info(`Running: ${updateCmd}`);
36647
+ s.start("Updating CLI...");
36648
+ try {
36649
+ await execAsync7(updateCmd, {
36650
+ timeout: 120000
36651
+ });
36652
+ s.stop("Update completed");
36653
+ } catch (error) {
36654
+ s.stop("Update failed");
36655
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
36656
+ if (errorMessage.includes("EACCES") || errorMessage.includes("EPERM") || errorMessage.includes("permission") || errorMessage.includes("Access is denied")) {
36657
+ throw new CliUpdateError(`Permission denied. Try: sudo ${updateCmd}
36658
+
36659
+ Or fix npm permissions: https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally`);
36660
+ }
36661
+ throw new CliUpdateError(`Update failed: ${errorMessage}
36662
+
36663
+ Manual update: ${updateCmd}`);
36664
+ }
36665
+ s.start("Verifying installation...");
36666
+ try {
36667
+ const { stdout } = await execAsync7("ck --version", { timeout: 5000 });
36668
+ const newVersionMatch = stdout.match(/CLI Version:\s*(\S+)/);
36669
+ const newVersion = newVersionMatch ? newVersionMatch[1] : targetVersion;
36670
+ s.stop(`Installed version: ${newVersion}`);
36671
+ outro(`[+] Successfully updated ClaudeKit CLI to ${newVersion}`);
36672
+ await displayKitUpdateReminder();
36673
+ } catch {
36674
+ s.stop("Verification completed");
36346
36675
  outro(`[+] Update completed. Please restart your terminal to use CLI ${targetVersion}`);
36676
+ await displayKitUpdateReminder();
36347
36677
  }
36348
36678
  } catch (error) {
36349
36679
  if (error instanceof CliUpdateError) {
@@ -36359,7 +36689,7 @@ Manual update: ${updateCmd}`);
36359
36689
  // src/commands/version.ts
36360
36690
  init_logger();
36361
36691
  init_types2();
36362
- var import_picocolors17 = __toESM(require_picocolors(), 1);
36692
+ var import_picocolors20 = __toESM(require_picocolors(), 1);
36363
36693
  function formatRelativeTime(dateString) {
36364
36694
  if (!dateString)
36365
36695
  return "Unknown";
@@ -36381,402 +36711,136 @@ function formatRelativeTime(dateString) {
36381
36711
  }
36382
36712
  function displayKitReleases(kitName, releases) {
36383
36713
  console.log(`
36384
- ${import_picocolors17.default.bold(import_picocolors17.default.cyan(kitName))} - Available Versions:
36714
+ ${import_picocolors20.default.bold(import_picocolors20.default.cyan(kitName))} - Available Versions:
36385
36715
  `);
36386
36716
  if (releases.length === 0) {
36387
- console.log(import_picocolors17.default.dim(" No releases found"));
36717
+ console.log(import_picocolors20.default.dim(" No releases found"));
36388
36718
  return;
36389
36719
  }
36390
36720
  for (const release of releases) {
36391
- const version = import_picocolors17.default.green(release.tag_name);
36721
+ const version = import_picocolors20.default.green(release.tag_name);
36392
36722
  const name2 = release.name || "No title";
36393
36723
  const publishedAt = formatRelativeTime(release.published_at);
36394
- const assetCount = release.assets.length;
36395
- const badges = [];
36396
- if (release.prerelease)
36397
- badges.push(import_picocolors17.default.yellow("[prerelease]"));
36398
- if (release.draft)
36399
- badges.push(import_picocolors17.default.gray("[draft]"));
36400
- const badgeStr = badges.length > 0 ? ` ${badges.join(" ")}` : "";
36401
- const versionPart = version.padEnd(20);
36402
- const namePart = name2.length > 40 ? `${name2.slice(0, 37)}...` : name2.padEnd(40);
36403
- const timePart = import_picocolors17.default.dim(publishedAt.padEnd(20));
36404
- const assetPart = import_picocolors17.default.dim(`(${assetCount} ${assetCount === 1 ? "asset" : "assets"})`);
36405
- console.log(` ${versionPart} ${namePart} ${timePart} ${assetPart}${badgeStr}`);
36406
- }
36407
- console.log(import_picocolors17.default.dim(`
36408
- Showing ${releases.length} ${releases.length === 1 ? "release" : "releases"}`));
36409
- }
36410
- async function versionCommand(options) {
36411
- const prompts2 = new PromptsManager;
36412
- prompts2.intro("\uD83D\uDCE6 ClaudeKit - Available Versions");
36413
- try {
36414
- const validOptions = VersionCommandOptionsSchema.parse(options);
36415
- const kitsToFetch = validOptions.kit ? [validOptions.kit] : Object.keys(AVAILABLE_KITS);
36416
- const github = new GitHubClient;
36417
- const limit = validOptions.limit || 30;
36418
- const releasePromises = kitsToFetch.map(async (kitType) => {
36419
- const kitConfig = AVAILABLE_KITS[kitType];
36420
- try {
36421
- const releases = await github.listReleases(kitConfig, limit);
36422
- const filteredReleases = validOptions.all ? releases : releases.filter((r2) => !r2.draft && !r2.prerelease);
36423
- return {
36424
- kitType,
36425
- kitConfig,
36426
- releases: filteredReleases,
36427
- error: null
36428
- };
36429
- } catch (error) {
36430
- return {
36431
- kitType,
36432
- kitConfig,
36433
- releases: [],
36434
- error: error instanceof Error ? error.message : "Unknown error"
36435
- };
36436
- }
36437
- });
36438
- const results = await Promise.all(releasePromises);
36439
- for (const result of results) {
36440
- if (result.error) {
36441
- console.log(`
36442
- ${import_picocolors17.default.bold(import_picocolors17.default.cyan(result.kitConfig.name))} - ${import_picocolors17.default.red("Error")}`);
36443
- console.log(import_picocolors17.default.dim(` ${result.error}`));
36444
- } else {
36445
- displayKitReleases(result.kitConfig.name, result.releases);
36446
- }
36447
- }
36448
- prompts2.outro("✨ Done");
36449
- } catch (error) {
36450
- logger.error(error instanceof Error ? error.message : "Unknown error occurred");
36451
- process.exit(1);
36452
- }
36453
- }
36454
-
36455
- // src/cli/command-registry.ts
36456
- init_logger();
36457
- function registerCommands(cli) {
36458
- cli.command("new", "Bootstrap a new ClaudeKit project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit to use (engineer, marketing)").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--force", "Overwrite existing files without confirmation").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--opencode", "Install OpenCode CLI package (non-interactive mode)").option("--gemini", "Install Google Gemini CLI package (non-interactive mode)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--with-sudo", "Include system packages requiring sudo (Linux: ffmpeg, imagemagick)").option("--prefix", "Add /ck: prefix to all slash commands by moving them to commands/ck/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--docs-dir <name>", "Custom docs folder name (default: docs)").option("--plans-dir <name>", "Custom plans folder name (default: plans)").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").action(async (options) => {
36459
- if (options.exclude && !Array.isArray(options.exclude)) {
36460
- options.exclude = [options.exclude];
36461
- }
36462
- await newCommand(options);
36463
- });
36464
- cli.command("init", "Initialize or update ClaudeKit project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit to use (engineer, marketing)").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--only <pattern>", "Include only files matching glob pattern (can be used multiple times)").option("-g, --global", "Use platform-specific user configuration directory").option("--fresh", "Completely remove .claude directory before downloading (requires confirmation)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--with-sudo", "Include system packages requiring sudo (Linux: ffmpeg, imagemagick)").option("--prefix", "Add /ck: prefix to all slash commands by moving them to commands/ck/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--dry-run", "Preview changes without applying them (requires --prefix)").option("--force-overwrite", "Override ownership protections and delete user-modified files (requires --prefix)").option("--force-overwrite-settings", "Fully replace settings.json instead of selective merge (destroys user customizations)").option("--skip-setup", "Skip interactive configuration wizard").option("--docs-dir <name>", "Custom docs folder name (default: docs)").option("--plans-dir <name>", "Custom plans folder name (default: plans)").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").action(async (options) => {
36465
- if (options.exclude && !Array.isArray(options.exclude)) {
36466
- options.exclude = [options.exclude];
36467
- }
36468
- if (options.only && !Array.isArray(options.only)) {
36469
- options.only = [options.only];
36470
- }
36471
- await initCommand(options);
36472
- });
36473
- cli.command("update", "Update ClaudeKit CLI to the latest version").option("-r, --release <version>", "Update to a specific version").option("--check", "Check for updates without installing").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").option("--beta", "Update to the latest beta version").option("--registry <url>", "Custom npm registry URL").option("--kit <kit>", "[DEPRECATED] Use 'ck init --kit <kit>' instead").option("-g, --global", "[DEPRECATED] Use 'ck init --global' instead").action(async (options) => {
36474
- if (options.kit || options.global) {
36475
- console.log();
36476
- const deprecatedFlags = [options.kit && "--kit", options.global && "--global"].filter(Boolean).join(" and ");
36477
- logger.warning(`The ${deprecatedFlags} option${options.kit && options.global ? "s are" : " is"} no longer supported with 'ck update'`);
36478
- console.log();
36479
- console.log(" 'ck update' now only updates the ClaudeKit CLI itself.");
36480
- console.log();
36481
- console.log(" To update a kit installation, use:");
36482
- const suggestedCmd = ["ck init"];
36483
- if (options.kit)
36484
- suggestedCmd.push(`--kit ${options.kit}`);
36485
- if (options.global)
36486
- suggestedCmd.push("--global");
36487
- console.log(` ${suggestedCmd.join(" ")}`);
36488
- console.log();
36489
- process.exit(0);
36490
- }
36491
- try {
36492
- await updateCliCommand(options);
36493
- } catch (error) {
36494
- process.exit(1);
36495
- }
36496
- });
36497
- cli.command("versions", "List available versions of ClaudeKit repositories").option("--kit <kit>", "Filter by specific kit (engineer, marketing)").option("--limit <limit>", "Number of releases to show (default: 30)").option("--all", "Show all releases including prereleases").action(async (options) => {
36498
- await versionCommand(options);
36499
- });
36500
- cli.command("doctor", "Comprehensive health check for ClaudeKit").option("--report", "Generate shareable diagnostic report").option("--fix", "Auto-fix all fixable issues").option("--check-only", "CI mode: no prompts, exit 1 on failures").option("--json", "Output JSON format").option("--full", "Include extended priority checks (slower)").action(async (options) => {
36501
- await doctorCommand(options);
36502
- });
36503
- cli.command("uninstall", "Remove ClaudeKit installations").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").option("-l, --local", "Uninstall only local installation (current project)").option("-g, --global", "Uninstall only global installation (~/.claude/)").option("-A, --all", "Uninstall from both local and global locations").option("-k, --kit <type>", "Uninstall specific kit only (engineer, marketing)").option("--dry-run", "Preview what would be removed without deleting").option("--force-overwrite", "Delete even user-modified files (requires confirmation)").action(async (options) => {
36504
- await uninstallCommand(options);
36505
- });
36506
- cli.command("easter-egg", "\uD83E\uDD5A Roll for a random discount code (Code Hunt 2025)").action(async () => {
36507
- await easterEggCommand();
36508
- });
36509
- }
36510
-
36511
- // src/cli/version-display.ts
36512
- import { existsSync as existsSync17, readFileSync as readFileSync5 } from "node:fs";
36513
- import { join as join66 } from "node:path";
36514
-
36515
- // src/domains/versioning/checking/version-utils.ts
36516
- var import_compare_versions3 = __toESM(require_umd(), 1);
36517
- function isUpdateCheckDisabled() {
36518
- return process.env.NO_UPDATE_NOTIFIER === "1" || process.env.NO_UPDATE_NOTIFIER === "true" || !process.stdout.isTTY;
36519
- }
36520
- function normalizeVersion(version) {
36521
- return version.replace(/^v/, "");
36522
- }
36523
- function isNewerVersion(currentVersion, latestVersion) {
36524
- try {
36525
- const current = normalizeVersion(currentVersion);
36526
- const latest = normalizeVersion(latestVersion);
36527
- return import_compare_versions3.compareVersions(latest, current) > 0;
36528
- } catch {
36529
- return false;
36530
- }
36531
- }
36532
- // src/domains/versioning/checking/kit-version-checker.ts
36533
- init_logger();
36534
- init_types2();
36535
-
36536
- // src/domains/versioning/version-cache.ts
36537
- init_logger();
36538
- import { existsSync as existsSync16 } from "node:fs";
36539
- import { mkdir as mkdir18, readFile as readFile20, writeFile as writeFile17 } from "node:fs/promises";
36540
- import { join as join65 } from "node:path";
36541
- class VersionCacheManager {
36542
- static CACHE_FILENAME = "version-check.json";
36543
- static CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
36544
- static getCacheFile() {
36545
- const cacheDir = PathResolver.getCacheDir(false);
36546
- return join65(cacheDir, VersionCacheManager.CACHE_FILENAME);
36547
- }
36548
- static async load() {
36549
- const cacheFile = VersionCacheManager.getCacheFile();
36550
- try {
36551
- if (!existsSync16(cacheFile)) {
36552
- logger.debug("Version check cache not found");
36553
- return null;
36554
- }
36555
- const content = await readFile20(cacheFile, "utf-8");
36556
- const cache2 = JSON.parse(content);
36557
- if (!cache2.lastCheck || !cache2.currentVersion || !cache2.latestVersion) {
36558
- logger.debug("Invalid cache structure, ignoring");
36559
- return null;
36560
- }
36561
- logger.debug(`Version check cache loaded: ${JSON.stringify(cache2)}`);
36562
- return cache2;
36563
- } catch (error) {
36564
- logger.debug(`Failed to load version check cache: ${error}`);
36565
- return null;
36566
- }
36567
- }
36568
- static async save(cache2) {
36569
- const cacheFile = VersionCacheManager.getCacheFile();
36570
- const cacheDir = PathResolver.getCacheDir(false);
36571
- try {
36572
- if (!existsSync16(cacheDir)) {
36573
- await mkdir18(cacheDir, { recursive: true, mode: 448 });
36574
- }
36575
- await writeFile17(cacheFile, JSON.stringify(cache2, null, 2), "utf-8");
36576
- logger.debug(`Version check cache saved to ${cacheFile}`);
36577
- } catch (error) {
36578
- logger.debug(`Failed to save version check cache: ${error}`);
36579
- }
36580
- }
36581
- static isCacheValid(cache2) {
36582
- if (!cache2)
36583
- return false;
36584
- const now = Date.now();
36585
- const age = now - cache2.lastCheck;
36586
- const isValid2 = age < VersionCacheManager.CACHE_TTL_MS;
36587
- const ageDays = (age / 1000 / 60 / 60 / 24).toFixed(1);
36588
- logger.debug(`Cache validity check: age=${ageDays} days, valid=${isValid2}`);
36589
- return isValid2;
36590
- }
36591
- static async clear() {
36592
- const cacheFile = VersionCacheManager.getCacheFile();
36593
- try {
36594
- if (existsSync16(cacheFile)) {
36595
- const fs12 = await import("node:fs/promises");
36596
- await fs12.unlink(cacheFile);
36597
- logger.debug("Version check cache cleared");
36598
- }
36599
- } catch (error) {
36600
- logger.debug(`Failed to clear version check cache: ${error}`);
36601
- }
36724
+ const assetCount = release.assets.length;
36725
+ const badges = [];
36726
+ if (release.prerelease)
36727
+ badges.push(import_picocolors20.default.yellow("[prerelease]"));
36728
+ if (release.draft)
36729
+ badges.push(import_picocolors20.default.gray("[draft]"));
36730
+ const badgeStr = badges.length > 0 ? ` ${badges.join(" ")}` : "";
36731
+ const versionPart = version.padEnd(20);
36732
+ const namePart = name2.length > 40 ? `${name2.slice(0, 37)}...` : name2.padEnd(40);
36733
+ const timePart = import_picocolors20.default.dim(publishedAt.padEnd(20));
36734
+ const assetPart = import_picocolors20.default.dim(`(${assetCount} ${assetCount === 1 ? "asset" : "assets"})`);
36735
+ console.log(` ${versionPart} ${namePart} ${timePart} ${assetPart}${badgeStr}`);
36602
36736
  }
36737
+ console.log(import_picocolors20.default.dim(`
36738
+ Showing ${releases.length} ${releases.length === 1 ? "release" : "releases"}`));
36603
36739
  }
36604
-
36605
- // src/domains/versioning/checking/kit-version-checker.ts
36606
- async function fetchLatestRelease(currentVersion) {
36740
+ async function versionCommand(options) {
36741
+ const prompts2 = new PromptsManager;
36742
+ prompts2.intro("\uD83D\uDCE6 ClaudeKit - Available Versions");
36607
36743
  try {
36608
- const githubClient = new GitHubClient;
36609
- const kit = AVAILABLE_KITS.engineer;
36610
- const timeoutPromise = new Promise((_3, reject) => setTimeout(() => reject(new Error("Timeout")), 5000));
36611
- const releasePromise = githubClient.getLatestRelease(kit);
36612
- const release = await Promise.race([releasePromise, timeoutPromise]);
36613
- const latestVersion = release.tag_name;
36614
- const updateAvailable = isNewerVersion(currentVersion, latestVersion);
36615
- const releaseUrl = `https://github.com/${kit.owner}/${kit.repo}/releases/tag/${latestVersion}`;
36616
- logger.debug(`Fetched latest release: current=${currentVersion}, latest=${latestVersion}, updateAvailable=${updateAvailable}`);
36617
- return {
36618
- currentVersion,
36619
- latestVersion,
36620
- updateAvailable,
36621
- releaseUrl
36622
- };
36744
+ const validOptions = VersionCommandOptionsSchema.parse(options);
36745
+ const kitsToFetch = validOptions.kit ? [validOptions.kit] : Object.keys(AVAILABLE_KITS);
36746
+ const github = new GitHubClient;
36747
+ const limit = validOptions.limit || 30;
36748
+ const releasePromises = kitsToFetch.map(async (kitType) => {
36749
+ const kitConfig = AVAILABLE_KITS[kitType];
36750
+ try {
36751
+ const releases = await github.listReleases(kitConfig, limit);
36752
+ const filteredReleases = validOptions.all ? releases : releases.filter((r2) => !r2.draft && !r2.prerelease);
36753
+ return {
36754
+ kitType,
36755
+ kitConfig,
36756
+ releases: filteredReleases,
36757
+ error: null
36758
+ };
36759
+ } catch (error) {
36760
+ return {
36761
+ kitType,
36762
+ kitConfig,
36763
+ releases: [],
36764
+ error: error instanceof Error ? error.message : "Unknown error"
36765
+ };
36766
+ }
36767
+ });
36768
+ const results = await Promise.all(releasePromises);
36769
+ for (const result of results) {
36770
+ if (result.error) {
36771
+ console.log(`
36772
+ ${import_picocolors20.default.bold(import_picocolors20.default.cyan(result.kitConfig.name))} - ${import_picocolors20.default.red("Error")}`);
36773
+ console.log(import_picocolors20.default.dim(` ${result.error}`));
36774
+ } else {
36775
+ displayKitReleases(result.kitConfig.name, result.releases);
36776
+ }
36777
+ }
36778
+ prompts2.outro("✨ Done");
36623
36779
  } catch (error) {
36624
- logger.debug(`Failed to fetch latest release: ${error}`);
36625
- return null;
36780
+ logger.error(error instanceof Error ? error.message : "Unknown error occurred");
36781
+ process.exit(1);
36626
36782
  }
36627
36783
  }
36628
36784
 
36629
- class VersionChecker {
36630
- static async check(currentVersion) {
36631
- if (isUpdateCheckDisabled()) {
36632
- logger.debug("Update check disabled by environment");
36633
- return null;
36785
+ // src/cli/command-registry.ts
36786
+ init_logger();
36787
+ function registerCommands(cli) {
36788
+ cli.command("new", "Bootstrap a new ClaudeKit project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit to use (engineer, marketing)").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--force", "Overwrite existing files without confirmation").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--opencode", "Install OpenCode CLI package (non-interactive mode)").option("--gemini", "Install Google Gemini CLI package (non-interactive mode)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--with-sudo", "Include system packages requiring sudo (Linux: ffmpeg, imagemagick)").option("--prefix", "Add /ck: prefix to all slash commands by moving them to commands/ck/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--docs-dir <name>", "Custom docs folder name (default: docs)").option("--plans-dir <name>", "Custom plans folder name (default: plans)").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").action(async (options) => {
36789
+ if (options.exclude && !Array.isArray(options.exclude)) {
36790
+ options.exclude = [options.exclude];
36634
36791
  }
36635
- const cache2 = await VersionCacheManager.load();
36636
- if (cache2 && VersionCacheManager.isCacheValid(cache2) && cache2.currentVersion === currentVersion) {
36637
- logger.debug("Using cached version check result");
36638
- return {
36639
- currentVersion: cache2.currentVersion,
36640
- latestVersion: cache2.latestVersion,
36641
- updateAvailable: cache2.updateAvailable,
36642
- releaseUrl: cache2.latestUrl
36643
- };
36792
+ await newCommand(options);
36793
+ });
36794
+ cli.command("init", "Initialize or update ClaudeKit project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit to use (engineer, marketing)").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--only <pattern>", "Include only files matching glob pattern (can be used multiple times)").option("-g, --global", "Use platform-specific user configuration directory").option("--fresh", "Completely remove .claude directory before downloading (requires confirmation)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--with-sudo", "Include system packages requiring sudo (Linux: ffmpeg, imagemagick)").option("--prefix", "Add /ck: prefix to all slash commands by moving them to commands/ck/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--dry-run", "Preview changes without applying them (requires --prefix)").option("--force-overwrite", "Override ownership protections and delete user-modified files (requires --prefix)").option("--force-overwrite-settings", "Fully replace settings.json instead of selective merge (destroys user customizations)").option("--skip-setup", "Skip interactive configuration wizard").option("--docs-dir <name>", "Custom docs folder name (default: docs)").option("--plans-dir <name>", "Custom plans folder name (default: plans)").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").action(async (options) => {
36795
+ if (options.exclude && !Array.isArray(options.exclude)) {
36796
+ options.exclude = [options.exclude];
36644
36797
  }
36645
- logger.debug("Cache expired or invalid, fetching latest release");
36646
- const result = await fetchLatestRelease(currentVersion);
36647
- if (result) {
36648
- await VersionCacheManager.save({
36649
- lastCheck: Date.now(),
36650
- currentVersion: result.currentVersion,
36651
- latestVersion: result.latestVersion,
36652
- latestUrl: result.releaseUrl,
36653
- updateAvailable: result.updateAvailable
36654
- });
36798
+ if (options.only && !Array.isArray(options.only)) {
36799
+ options.only = [options.only];
36655
36800
  }
36656
- return result;
36657
- }
36658
- }
36659
- // src/domains/versioning/checking/cli-version-checker.ts
36660
- init_logger();
36661
- var import_compare_versions4 = __toESM(require_umd(), 1);
36662
- var PACKAGE_NAME2 = "claudekit-cli";
36663
-
36664
- class CliVersionChecker {
36665
- static async check(currentVersion) {
36666
- if (isUpdateCheckDisabled()) {
36667
- logger.debug("CLI update check disabled by environment");
36668
- return null;
36801
+ await initCommand(options);
36802
+ });
36803
+ cli.command("update", "Update ClaudeKit CLI to the latest version").option("-r, --release <version>", "Update to a specific version").option("--check", "Check for updates without installing").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").option("--beta", "Update to the latest beta version").option("--registry <url>", "Custom npm registry URL").option("--kit <kit>", "[DEPRECATED] Use 'ck init --kit <kit>' instead").option("-g, --global", "[DEPRECATED] Use 'ck init --global' instead").action(async (options) => {
36804
+ if (options.kit || options.global) {
36805
+ console.log();
36806
+ const deprecatedFlags = [options.kit && "--kit", options.global && "--global"].filter(Boolean).join(" and ");
36807
+ logger.warning(`The ${deprecatedFlags} option${options.kit && options.global ? "s are" : " is"} no longer supported with 'ck update'`);
36808
+ console.log();
36809
+ console.log(" 'ck update' now only updates the ClaudeKit CLI itself.");
36810
+ console.log();
36811
+ console.log(" To update a kit installation, use:");
36812
+ const suggestedCmd = ["ck init"];
36813
+ if (options.kit)
36814
+ suggestedCmd.push(`--kit ${options.kit}`);
36815
+ if (options.global)
36816
+ suggestedCmd.push("--global");
36817
+ console.log(` ${suggestedCmd.join(" ")}`);
36818
+ console.log();
36819
+ process.exit(0);
36669
36820
  }
36670
36821
  try {
36671
- const latestVersion = await NpmRegistryClient.getLatestVersion(PACKAGE_NAME2);
36672
- if (!latestVersion) {
36673
- logger.debug("Failed to fetch latest CLI version from npm");
36674
- return null;
36675
- }
36676
- const current = normalizeVersion(currentVersion);
36677
- const latest = normalizeVersion(latestVersion);
36678
- const updateAvailable = import_compare_versions4.compareVersions(latest, current) > 0;
36679
- logger.debug(`CLI version check: current=${current}, latest=${latest}, updateAvailable=${updateAvailable}`);
36680
- return {
36681
- currentVersion: current,
36682
- latestVersion: latest,
36683
- updateAvailable,
36684
- releaseUrl: `https://www.npmjs.com/package/${PACKAGE_NAME2}`
36685
- };
36822
+ await updateCliCommand(options);
36686
36823
  } catch (error) {
36687
- logger.debug(`CLI version check failed: ${error}`);
36688
- return null;
36824
+ process.exit(1);
36689
36825
  }
36690
- }
36691
- }
36692
- // src/domains/versioning/checking/notification-display.ts
36693
- var import_picocolors18 = __toESM(require_picocolors(), 1);
36694
- function createNotificationBox(borderColor, boxWidth) {
36695
- const contentWidth = boxWidth - 2;
36696
- const topBorder = borderColor(`╭${"─".repeat(contentWidth)}╮`);
36697
- const bottomBorder = borderColor(`╰${"".repeat(contentWidth)}╯`);
36698
- const emptyLine = borderColor("│") + " ".repeat(contentWidth) + borderColor("│");
36699
- const padLine = (text, visibleLen) => {
36700
- const len = visibleLen ?? text.length;
36701
- const displayText = len > contentWidth ? `${text.slice(0, contentWidth - 3)}...` : text;
36702
- const actualLen = visibleLen ?? displayText.length;
36703
- const totalPadding = contentWidth - actualLen;
36704
- const leftPadding = Math.max(0, Math.floor(totalPadding / 2));
36705
- const rightPadding = Math.max(0, totalPadding - leftPadding);
36706
- return borderColor("│") + " ".repeat(leftPadding) + displayText + " ".repeat(rightPadding) + borderColor("│");
36707
- };
36708
- return { topBorder, bottomBorder, emptyLine, padLine };
36709
- }
36710
- function displayKitNotification(result, options = {}) {
36711
- if (!result.updateAvailable)
36712
- return;
36713
- const { currentVersion, latestVersion } = result;
36714
- const { isGlobal = false } = options;
36715
- const displayCurrent = normalizeVersion(currentVersion);
36716
- const displayLatest = normalizeVersion(latestVersion);
36717
- const boxWidth = 52;
36718
- const { topBorder, bottomBorder, emptyLine, padLine } = createNotificationBox(import_picocolors18.default.cyan, boxWidth);
36719
- const headerText = import_picocolors18.default.bold(import_picocolors18.default.yellow("⬆ Kit Update Available"));
36720
- const headerLen = "⬆ Kit Update Available".length;
36721
- const versionText = `${import_picocolors18.default.dim(displayCurrent)} ${import_picocolors18.default.white("→")} ${import_picocolors18.default.green(import_picocolors18.default.bold(displayLatest))}`;
36722
- const versionLen = displayCurrent.length + 3 + displayLatest.length;
36723
- const updateCmd = isGlobal ? "ck init -g" : "ck init";
36724
- const commandText = `Run: ${import_picocolors18.default.cyan(import_picocolors18.default.bold(updateCmd))}`;
36725
- const commandLen = `Run: ${updateCmd}`.length;
36726
- console.log("");
36727
- console.log(topBorder);
36728
- console.log(emptyLine);
36729
- console.log(padLine(headerText, headerLen));
36730
- console.log(padLine(versionText, versionLen));
36731
- console.log(emptyLine);
36732
- console.log(padLine(commandText, commandLen));
36733
- console.log(emptyLine);
36734
- console.log(bottomBorder);
36735
- console.log("");
36736
- }
36737
- function displayCliNotification(result) {
36738
- if (!result.updateAvailable)
36739
- return;
36740
- const { currentVersion, latestVersion } = result;
36741
- const boxWidth = 52;
36742
- const { topBorder, bottomBorder, emptyLine, padLine } = createNotificationBox(import_picocolors18.default.magenta, boxWidth);
36743
- const headerText = import_picocolors18.default.bold(import_picocolors18.default.yellow("⬆ CLI Update Available"));
36744
- const headerLen = "⬆ CLI Update Available".length;
36745
- const versionText = `${import_picocolors18.default.dim(currentVersion)} ${import_picocolors18.default.white("→")} ${import_picocolors18.default.green(import_picocolors18.default.bold(latestVersion))}`;
36746
- const versionLen = currentVersion.length + 3 + latestVersion.length;
36747
- const commandText = `Run: ${import_picocolors18.default.magenta(import_picocolors18.default.bold("ck update"))}`;
36748
- const commandLen = "Run: ck update".length;
36749
- console.log("");
36750
- console.log(topBorder);
36751
- console.log(emptyLine);
36752
- console.log(padLine(headerText, headerLen));
36753
- console.log(padLine(versionText, versionLen));
36754
- console.log(emptyLine);
36755
- console.log(padLine(commandText, commandLen));
36756
- console.log(emptyLine);
36757
- console.log(bottomBorder);
36758
- console.log("");
36759
- }
36760
- // src/domains/versioning/version-checker.ts
36761
- class VersionChecker2 {
36762
- static async check(currentVersion) {
36763
- return VersionChecker.check(currentVersion);
36764
- }
36765
- static displayNotification(result, options = {}) {
36766
- displayKitNotification(result, options);
36767
- }
36768
- }
36769
-
36770
- class CliVersionChecker2 {
36771
- static async check(currentVersion) {
36772
- return CliVersionChecker.check(currentVersion);
36773
- }
36774
- static displayNotification(result) {
36775
- displayCliNotification(result);
36776
- }
36826
+ });
36827
+ cli.command("versions", "List available versions of ClaudeKit repositories").option("--kit <kit>", "Filter by specific kit (engineer, marketing)").option("--limit <limit>", "Number of releases to show (default: 30)").option("--all", "Show all releases including prereleases").action(async (options) => {
36828
+ await versionCommand(options);
36829
+ });
36830
+ cli.command("doctor", "Comprehensive health check for ClaudeKit").option("--report", "Generate shareable diagnostic report").option("--fix", "Auto-fix all fixable issues").option("--check-only", "CI mode: no prompts, exit 1 on failures").option("--json", "Output JSON format").option("--full", "Include extended priority checks (slower)").action(async (options) => {
36831
+ await doctorCommand(options);
36832
+ });
36833
+ cli.command("uninstall", "Remove ClaudeKit installations").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").option("-l, --local", "Uninstall only local installation (current project)").option("-g, --global", "Uninstall only global installation (~/.claude/)").option("-A, --all", "Uninstall from both local and global locations").option("-k, --kit <type>", "Uninstall specific kit only (engineer, marketing)").option("--dry-run", "Preview what would be removed without deleting").option("--force-overwrite", "Delete even user-modified files (requires confirmation)").action(async (options) => {
36834
+ await uninstallCommand(options);
36835
+ });
36836
+ cli.command("easter-egg", "\uD83E\uDD5A Roll for a random discount code (Code Hunt 2025)").action(async () => {
36837
+ await easterEggCommand();
36838
+ });
36777
36839
  }
36778
36840
 
36779
36841
  // src/cli/version-display.ts
36842
+ import { existsSync as existsSync17, readFileSync as readFileSync5 } from "node:fs";
36843
+ import { join as join66 } from "node:path";
36780
36844
  init_logger();
36781
36845
  init_types2();
36782
36846
  var packageVersion = package_default.version;
@@ -36823,6 +36887,8 @@ async function displayVersion() {
36823
36887
  }
36824
36888
  if (!foundAnyKit) {
36825
36889
  console.log("No ClaudeKit installation found");
36890
+ console.log(`
36891
+ To get started: ck new (local project) or ck init -g (global)`);
36826
36892
  }
36827
36893
  try {
36828
36894
  const cliUpdateCheck = await CliVersionChecker2.check(packageVersion);
@@ -36849,7 +36915,7 @@ function getPackageVersion2() {
36849
36915
 
36850
36916
  // src/shared/logger.ts
36851
36917
  init_output_manager();
36852
- var import_picocolors19 = __toESM(require_picocolors(), 1);
36918
+ var import_picocolors21 = __toESM(require_picocolors(), 1);
36853
36919
  import { createWriteStream as createWriteStream3 } from "node:fs";
36854
36920
 
36855
36921
  class Logger2 {
@@ -36858,23 +36924,23 @@ class Logger2 {
36858
36924
  exitHandlerRegistered = false;
36859
36925
  info(message) {
36860
36926
  const symbols = output.getSymbols();
36861
- console.log(import_picocolors19.default.blue(symbols.info), message);
36927
+ console.log(import_picocolors21.default.blue(symbols.info), message);
36862
36928
  }
36863
36929
  success(message) {
36864
36930
  const symbols = output.getSymbols();
36865
- console.log(import_picocolors19.default.green(symbols.success), message);
36931
+ console.log(import_picocolors21.default.green(symbols.success), message);
36866
36932
  }
36867
36933
  warning(message) {
36868
36934
  const symbols = output.getSymbols();
36869
- console.log(import_picocolors19.default.yellow(symbols.warning), message);
36935
+ console.log(import_picocolors21.default.yellow(symbols.warning), message);
36870
36936
  }
36871
36937
  error(message) {
36872
36938
  const symbols = output.getSymbols();
36873
- console.error(import_picocolors19.default.red(symbols.error), message);
36939
+ console.error(import_picocolors21.default.red(symbols.error), message);
36874
36940
  }
36875
36941
  debug(message) {
36876
36942
  if (process.env.DEBUG) {
36877
- console.log(import_picocolors19.default.gray("[DEBUG]"), message);
36943
+ console.log(import_picocolors21.default.gray("[DEBUG]"), message);
36878
36944
  }
36879
36945
  }
36880
36946
  verbose(message, context) {
@@ -36883,7 +36949,7 @@ class Logger2 {
36883
36949
  const timestamp = this.getTimestamp();
36884
36950
  const sanitizedMessage = this.sanitize(message);
36885
36951
  const formattedContext = context ? this.formatContext(context) : "";
36886
- const logLine = `${timestamp} ${import_picocolors19.default.gray("[VERBOSE]")} ${sanitizedMessage}${formattedContext}`;
36952
+ const logLine = `${timestamp} ${import_picocolors21.default.gray("[VERBOSE]")} ${sanitizedMessage}${formattedContext}`;
36887
36953
  console.error(logLine);
36888
36954
  if (this.logFileStream) {
36889
36955
  const plainLogLine = `${timestamp} [VERBOSE] ${sanitizedMessage}${formattedContext}`;
@@ -36986,7 +37052,7 @@ var logger3 = new Logger2;
36986
37052
 
36987
37053
  // src/shared/output-manager.ts
36988
37054
  init_terminal_utils();
36989
- var import_picocolors20 = __toESM(require_picocolors(), 1);
37055
+ var import_picocolors22 = __toESM(require_picocolors(), 1);
36990
37056
  var SYMBOLS2 = {
36991
37057
  unicode: {
36992
37058
  prompt: "◇",
@@ -37065,7 +37131,7 @@ class OutputManager2 {
37065
37131
  if (this.config.quiet)
37066
37132
  return;
37067
37133
  const symbol = this.getSymbols().success;
37068
- console.log(import_picocolors20.default.green(`${symbol} ${message}`));
37134
+ console.log(import_picocolors22.default.green(`${symbol} ${message}`));
37069
37135
  }
37070
37136
  error(message, data) {
37071
37137
  if (this.config.json) {
@@ -37073,7 +37139,7 @@ class OutputManager2 {
37073
37139
  return;
37074
37140
  }
37075
37141
  const symbol = this.getSymbols().error;
37076
- console.error(import_picocolors20.default.red(`${symbol} ${message}`));
37142
+ console.error(import_picocolors22.default.red(`${symbol} ${message}`));
37077
37143
  }
37078
37144
  warning(message, data) {
37079
37145
  if (this.config.json) {
@@ -37083,7 +37149,7 @@ class OutputManager2 {
37083
37149
  if (this.config.quiet)
37084
37150
  return;
37085
37151
  const symbol = this.getSymbols().warning;
37086
- console.log(import_picocolors20.default.yellow(`${symbol} ${message}`));
37152
+ console.log(import_picocolors22.default.yellow(`${symbol} ${message}`));
37087
37153
  }
37088
37154
  info(message, data) {
37089
37155
  if (this.config.json) {
@@ -37093,7 +37159,7 @@ class OutputManager2 {
37093
37159
  if (this.config.quiet)
37094
37160
  return;
37095
37161
  const symbol = this.getSymbols().info;
37096
- console.log(import_picocolors20.default.blue(`${symbol} ${message}`));
37162
+ console.log(import_picocolors22.default.blue(`${symbol} ${message}`));
37097
37163
  }
37098
37164
  verbose(message, data) {
37099
37165
  if (!this.config.verbose)
@@ -37102,7 +37168,7 @@ class OutputManager2 {
37102
37168
  this.addJsonEntry({ type: "info", message, data });
37103
37169
  return;
37104
37170
  }
37105
- console.log(import_picocolors20.default.dim(` ${message}`));
37171
+ console.log(import_picocolors22.default.dim(` ${message}`));
37106
37172
  }
37107
37173
  indent(message) {
37108
37174
  if (this.config.json)
@@ -37127,7 +37193,7 @@ class OutputManager2 {
37127
37193
  return;
37128
37194
  const symbols = this.getSymbols();
37129
37195
  console.log();
37130
- console.log(import_picocolors20.default.bold(import_picocolors20.default.cyan(`${symbols.line} ${title}`)));
37196
+ console.log(import_picocolors22.default.bold(import_picocolors22.default.cyan(`${symbols.line} ${title}`)));
37131
37197
  }
37132
37198
  addJsonEntry(entry) {
37133
37199
  this.jsonBuffer.push({