claudekit-cli 3.35.0-dev.16 → 3.35.0-dev.18

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 +412 -186
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1006,6 +1006,13 @@ var init_dist2 = __esm(() => {
1006
1006
  function supportsUnicode() {
1007
1007
  if (process.env.WT_SESSION)
1008
1008
  return true;
1009
+ const ci = (process.env.CI || "").trim().toLowerCase();
1010
+ if (ci === "true" || ci === "1")
1011
+ return true;
1012
+ if (process.env.TERM === "dumb")
1013
+ return false;
1014
+ if (!process.stdout.isTTY)
1015
+ return false;
1009
1016
  if (process.env.TERM_PROGRAM === "iTerm.app")
1010
1017
  return true;
1011
1018
  if (process.env.TERM_PROGRAM === "Apple_Terminal")
@@ -1014,12 +1021,6 @@ function supportsUnicode() {
1014
1021
  return true;
1015
1022
  if (process.env.KONSOLE_VERSION)
1016
1023
  return true;
1017
- if (process.env.CI)
1018
- return true;
1019
- if (process.env.TERM === "dumb")
1020
- return false;
1021
- if (!process.stdout.isTTY)
1022
- return false;
1023
1024
  const locale = process.env.LANG || process.env.LC_ALL || "";
1024
1025
  if (locale.toLowerCase().includes("utf"))
1025
1026
  return true;
@@ -1089,6 +1090,8 @@ class OutputManager {
1089
1090
  shouldShowProgress() {
1090
1091
  if (this.config.json)
1091
1092
  return false;
1093
+ if (this.config.quiet)
1094
+ return false;
1092
1095
  if (!isTTY())
1093
1096
  return false;
1094
1097
  return true;
@@ -38560,11 +38563,40 @@ var init_ck_config_manager = __esm(() => {
38560
38563
  });
38561
38564
 
38562
38565
  // src/shared/environment.ts
38566
+ function normalizeEnvValue(value) {
38567
+ return value?.trim().toLowerCase() ?? "";
38568
+ }
38569
+ function isTruthyEnv(value) {
38570
+ return TRUTHY_ENV_VALUES.has(normalizeEnvValue(value));
38571
+ }
38572
+ function isTestEnvironment() {
38573
+ return normalizeEnvValue("development") === "test" || isTruthyEnv(process.env.VITEST) || isTruthyEnv(process.env.BUN_TEST);
38574
+ }
38563
38575
  function isCIEnvironment() {
38564
- return process.env.CI === "true" || process.env.CI_SAFE_MODE === "true";
38576
+ return isTruthyEnv(process.env.CI) || isTruthyEnv(process.env.CI_SAFE_MODE);
38577
+ }
38578
+ function isIsolatedTestEnvironment() {
38579
+ const normalizedValue = normalizeEnvValue(process.env.CK_TEST_HOME);
38580
+ if (!normalizedValue) {
38581
+ return false;
38582
+ }
38583
+ return !FALSY_ENV_VALUES.has(normalizedValue);
38584
+ }
38585
+ function shouldSkipExpensiveOperations() {
38586
+ if (isIsolatedTestEnvironment()) {
38587
+ return false;
38588
+ }
38589
+ return isCIEnvironment();
38590
+ }
38591
+ function getHomeDirectoryFromEnv(platformName = process.platform) {
38592
+ const value = platformName === "win32" ? process.env.USERPROFILE || process.env.HOME : process.env.HOME || process.env.USERPROFILE;
38593
+ if (!value || value.trim() === "") {
38594
+ return null;
38595
+ }
38596
+ return value.trim();
38565
38597
  }
38566
38598
  function isNonInteractive() {
38567
- return !process.stdin.isTTY || process.env.CI === "true" || process.env.NON_INTERACTIVE === "true";
38599
+ return !process.stdin.isTTY || isCIEnvironment() || isTruthyEnv(process.env.NON_INTERACTIVE);
38568
38600
  }
38569
38601
  function isMacOS() {
38570
38602
  return process.platform === "darwin";
@@ -38579,13 +38611,34 @@ function getOptimalConcurrency() {
38579
38611
  return PLATFORM_CONCURRENCY.WINDOWS;
38580
38612
  return PLATFORM_CONCURRENCY.LINUX;
38581
38613
  }
38582
- var PLATFORM_CONCURRENCY;
38614
+ var PLATFORM_CONCURRENCY, TRUTHY_ENV_VALUES, FALSY_ENV_VALUES;
38583
38615
  var init_environment = __esm(() => {
38584
38616
  PLATFORM_CONCURRENCY = {
38585
38617
  MACOS: 10,
38586
38618
  WINDOWS: 15,
38587
38619
  LINUX: 20
38588
38620
  };
38621
+ TRUTHY_ENV_VALUES = new Set(["1", "true", "yes", "on"]);
38622
+ FALSY_ENV_VALUES = new Set(["0", "false", "no", "off"]);
38623
+ });
38624
+
38625
+ // src/shared/claudekit-constants.ts
38626
+ function getCliVersion2() {
38627
+ return process.env.CLAUDEKIT_CLI_VERSION?.trim() || process.env.npm_package_version?.trim() || "unknown";
38628
+ }
38629
+ function getCliUserAgent() {
38630
+ return `${CLAUDEKIT_CLI_NPM_PACKAGE_NAME}/${getCliVersion2()}`;
38631
+ }
38632
+ var CLAUDEKIT_CLI_NPM_PACKAGE_NAME = "claudekit-cli", CLAUDEKIT_CLI_NPM_PACKAGE_URL, CLAUDEKIT_CLI_GLOBAL_INSTALL_COMMAND, CLAUDEKIT_CLI_INSTALL_COMMANDS, DEFAULT_NETWORK_TIMEOUT_MS = 3000;
38633
+ var init_claudekit_constants = __esm(() => {
38634
+ CLAUDEKIT_CLI_NPM_PACKAGE_URL = `https://www.npmjs.com/package/${CLAUDEKIT_CLI_NPM_PACKAGE_NAME}`;
38635
+ CLAUDEKIT_CLI_GLOBAL_INSTALL_COMMAND = `npm install -g ${CLAUDEKIT_CLI_NPM_PACKAGE_NAME}`;
38636
+ CLAUDEKIT_CLI_INSTALL_COMMANDS = [
38637
+ CLAUDEKIT_CLI_GLOBAL_INSTALL_COMMAND,
38638
+ `pnpm add -g ${CLAUDEKIT_CLI_NPM_PACKAGE_NAME}`,
38639
+ `yarn global add ${CLAUDEKIT_CLI_NPM_PACKAGE_NAME}`,
38640
+ `bun add -g ${CLAUDEKIT_CLI_NPM_PACKAGE_NAME}`
38641
+ ];
38589
38642
  });
38590
38643
 
38591
38644
  // node_modules/chalk/source/vendor/ansi-styles/index.js
@@ -41758,10 +41811,29 @@ function normalizeCommand(cmd) {
41758
41811
  return normalized;
41759
41812
  }
41760
41813
 
41814
+ // src/shared/parse-timeout.ts
41815
+ function parseTimeoutMs(rawValue, fallback2, min = 500, max = 60000) {
41816
+ if (!rawValue) {
41817
+ return fallback2;
41818
+ }
41819
+ const parsed = Number.parseInt(rawValue, 10);
41820
+ if (Number.isNaN(parsed)) {
41821
+ return fallback2;
41822
+ }
41823
+ if (parsed < min) {
41824
+ return min;
41825
+ }
41826
+ if (parsed > max) {
41827
+ return max;
41828
+ }
41829
+ return parsed;
41830
+ }
41831
+
41761
41832
  // src/shared/index.ts
41762
41833
  var init_shared = __esm(() => {
41763
41834
  init_logger();
41764
41835
  init_environment();
41836
+ init_claudekit_constants();
41765
41837
  init_terminal_utils();
41766
41838
  init_path_resolver();
41767
41839
  init_safe_spinner();
@@ -51522,7 +51594,7 @@ import { existsSync as existsSync25 } from "node:fs";
51522
51594
  import { mkdir as mkdir7, readFile as readFile20, writeFile as writeFile9 } from "node:fs/promises";
51523
51595
  import { homedir as homedir22 } from "node:os";
51524
51596
  import { dirname as dirname9, join as join31 } from "node:path";
51525
- function getCliVersion2() {
51597
+ function getCliVersion3() {
51526
51598
  try {
51527
51599
  if (process.env.npm_package_version) {
51528
51600
  return process.env.npm_package_version;
@@ -51570,7 +51642,7 @@ async function addInstallation(skill, agent, global3, path4, sourcePath) {
51570
51642
  path: path4,
51571
51643
  installedAt: new Date().toISOString(),
51572
51644
  sourcePath,
51573
- cliVersion: getCliVersion2()
51645
+ cliVersion: getCliVersion3()
51574
51646
  });
51575
51647
  await writeRegistry(registry);
51576
51648
  }
@@ -52098,6 +52170,16 @@ var init_npm_registry = __esm(() => {
52098
52170
  init_logger();
52099
52171
  });
52100
52172
 
52173
+ // src/domains/installation/package-managers/constants.ts
52174
+ function getPmVersionCommandTimeoutMs() {
52175
+ return parseTimeoutMs(process.env.CK_PM_VERSION_TIMEOUT_MS, DEFAULT_PM_VERSION_COMMAND_TIMEOUT_MS);
52176
+ }
52177
+ function getPmQueryTimeoutMs() {
52178
+ return parseTimeoutMs(process.env.CK_PM_QUERY_TIMEOUT_MS, DEFAULT_PM_QUERY_TIMEOUT_MS);
52179
+ }
52180
+ var DEFAULT_PM_VERSION_COMMAND_TIMEOUT_MS = 3000, DEFAULT_PM_QUERY_TIMEOUT_MS = 5000;
52181
+ var init_constants = () => {};
52182
+
52101
52183
  // src/domains/installation/package-managers/detector-base.ts
52102
52184
  import { exec } from "node:child_process";
52103
52185
  import { promisify as promisify7 } from "node:util";
@@ -52116,13 +52198,13 @@ var init_detector_base = __esm(() => {
52116
52198
  function getNpmQuery() {
52117
52199
  return {
52118
52200
  pm: "npm",
52119
- cmd: isWindows() ? "npm.cmd ls -g claudekit-cli --depth=0 --json" : "npm ls -g claudekit-cli --depth=0 --json",
52201
+ cmd: isWindows() ? `npm.cmd ls -g ${CLAUDEKIT_CLI_NPM_PACKAGE_NAME} --depth=0 --json` : `npm ls -g ${CLAUDEKIT_CLI_NPM_PACKAGE_NAME} --depth=0 --json`,
52120
52202
  checkFn: (stdout) => {
52121
52203
  try {
52122
52204
  const data = JSON.parse(stdout);
52123
- return !!(data.dependencies?.["claudekit-cli"] || stdout.includes("claudekit-cli"));
52205
+ return !!(data.dependencies?.[CLAUDEKIT_CLI_NPM_PACKAGE_NAME] || stdout.includes(CLAUDEKIT_CLI_NPM_PACKAGE_NAME));
52124
52206
  } catch {
52125
- return stdout.includes("claudekit-cli");
52207
+ return stdout.includes(CLAUDEKIT_CLI_NPM_PACKAGE_NAME);
52126
52208
  }
52127
52209
  }
52128
52210
  };
@@ -52132,7 +52214,9 @@ function getNpmVersionCommand() {
52132
52214
  }
52133
52215
  async function getNpmVersion() {
52134
52216
  try {
52135
- const { stdout } = await execAsync(getNpmVersionCommand(), { timeout: 3000 });
52217
+ const { stdout } = await execAsync(getNpmVersionCommand(), {
52218
+ timeout: getPmVersionCommandTimeoutMs()
52219
+ });
52136
52220
  return stdout.trim();
52137
52221
  } catch {
52138
52222
  return null;
@@ -52149,7 +52233,9 @@ function getNpmUpdateCommand(packageName, version) {
52149
52233
  return isWindows() ? `npm.cmd install -g ${packageName}${versionSuffix}` : `npm install -g ${packageName}${versionSuffix}`;
52150
52234
  }
52151
52235
  var init_npm_detector = __esm(() => {
52236
+ init_claudekit_constants();
52152
52237
  init_environment();
52238
+ init_constants();
52153
52239
  init_detector_base();
52154
52240
  });
52155
52241
 
@@ -52158,7 +52244,7 @@ function getBunQuery() {
52158
52244
  return {
52159
52245
  pm: "bun",
52160
52246
  cmd: "bun pm ls -g",
52161
- checkFn: (stdout) => stdout.includes("claudekit-cli")
52247
+ checkFn: (stdout) => stdout.includes(CLAUDEKIT_CLI_NPM_PACKAGE_NAME)
52162
52248
  };
52163
52249
  }
52164
52250
  function getBunVersionCommand() {
@@ -52166,7 +52252,9 @@ function getBunVersionCommand() {
52166
52252
  }
52167
52253
  async function getBunVersion() {
52168
52254
  try {
52169
- const { stdout } = await execAsync(getBunVersionCommand(), { timeout: 3000 });
52255
+ const { stdout } = await execAsync(getBunVersionCommand(), {
52256
+ timeout: getPmVersionCommandTimeoutMs()
52257
+ });
52170
52258
  return stdout.trim();
52171
52259
  } catch {
52172
52260
  return null;
@@ -52183,6 +52271,8 @@ function getBunUpdateCommand(packageName, version) {
52183
52271
  return `bun add -g ${packageName}${versionSuffix}`;
52184
52272
  }
52185
52273
  var init_bun_detector = __esm(() => {
52274
+ init_claudekit_constants();
52275
+ init_constants();
52186
52276
  init_detector_base();
52187
52277
  });
52188
52278
 
@@ -52190,8 +52280,8 @@ var init_bun_detector = __esm(() => {
52190
52280
  function getYarnQuery() {
52191
52281
  return {
52192
52282
  pm: "yarn",
52193
- cmd: isWindows() ? "yarn.cmd global list --pattern claudekit-cli" : "yarn global list --pattern claudekit-cli",
52194
- checkFn: (stdout) => stdout.includes("claudekit-cli")
52283
+ cmd: isWindows() ? `yarn.cmd global list --pattern ${CLAUDEKIT_CLI_NPM_PACKAGE_NAME}` : `yarn global list --pattern ${CLAUDEKIT_CLI_NPM_PACKAGE_NAME}`,
52284
+ checkFn: (stdout) => stdout.includes(CLAUDEKIT_CLI_NPM_PACKAGE_NAME)
52195
52285
  };
52196
52286
  }
52197
52287
  function getYarnVersionCommand() {
@@ -52199,7 +52289,9 @@ function getYarnVersionCommand() {
52199
52289
  }
52200
52290
  async function getYarnVersion() {
52201
52291
  try {
52202
- const { stdout } = await execAsync(getYarnVersionCommand(), { timeout: 3000 });
52292
+ const { stdout } = await execAsync(getYarnVersionCommand(), {
52293
+ timeout: getPmVersionCommandTimeoutMs()
52294
+ });
52203
52295
  return stdout.trim();
52204
52296
  } catch {
52205
52297
  return null;
@@ -52216,7 +52308,9 @@ function getYarnUpdateCommand(packageName, version) {
52216
52308
  return isWindows() ? `yarn.cmd global add ${packageName}${versionSuffix}` : `yarn global add ${packageName}${versionSuffix}`;
52217
52309
  }
52218
52310
  var init_yarn_detector = __esm(() => {
52311
+ init_claudekit_constants();
52219
52312
  init_environment();
52313
+ init_constants();
52220
52314
  init_detector_base();
52221
52315
  });
52222
52316
 
@@ -52224,8 +52318,8 @@ var init_yarn_detector = __esm(() => {
52224
52318
  function getPnpmQuery() {
52225
52319
  return {
52226
52320
  pm: "pnpm",
52227
- cmd: isWindows() ? "pnpm.cmd ls -g claudekit-cli" : "pnpm ls -g claudekit-cli",
52228
- checkFn: (stdout) => stdout.includes("claudekit-cli")
52321
+ cmd: isWindows() ? `pnpm.cmd ls -g ${CLAUDEKIT_CLI_NPM_PACKAGE_NAME}` : `pnpm ls -g ${CLAUDEKIT_CLI_NPM_PACKAGE_NAME}`,
52322
+ checkFn: (stdout) => stdout.includes(CLAUDEKIT_CLI_NPM_PACKAGE_NAME)
52229
52323
  };
52230
52324
  }
52231
52325
  function getPnpmVersionCommand() {
@@ -52233,7 +52327,9 @@ function getPnpmVersionCommand() {
52233
52327
  }
52234
52328
  async function getPnpmVersion() {
52235
52329
  try {
52236
- const { stdout } = await execAsync(getPnpmVersionCommand(), { timeout: 3000 });
52330
+ const { stdout } = await execAsync(getPnpmVersionCommand(), {
52331
+ timeout: getPmVersionCommandTimeoutMs()
52332
+ });
52237
52333
  return stdout.trim();
52238
52334
  } catch {
52239
52335
  return null;
@@ -52250,7 +52346,9 @@ function getPnpmUpdateCommand(packageName, version) {
52250
52346
  return isWindows() ? `pnpm.cmd add -g ${packageName}${versionSuffix}` : `pnpm add -g ${packageName}${versionSuffix}`;
52251
52347
  }
52252
52348
  var init_pnpm_detector = __esm(() => {
52349
+ init_claudekit_constants();
52253
52350
  init_environment();
52351
+ init_constants();
52254
52352
  init_detector_base();
52255
52353
  });
52256
52354
 
@@ -52304,13 +52402,19 @@ function detectFromEnv() {
52304
52402
  if (execPath) {
52305
52403
  logger.debug(`Detected exec path: ${execPath}`);
52306
52404
  const normalizedExec = execPath.replace(/\\/g, "/").toLowerCase();
52307
- if (/\/bun([/.]|$)/.test(normalizedExec) || normalizedExec.startsWith("bun"))
52405
+ const matchesPmExecPath = (pm) => {
52406
+ if (new RegExp(`(?:^|/)${pm}(?:[/.]|$)`).test(normalizedExec)) {
52407
+ return true;
52408
+ }
52409
+ return normalizedExec === pm || normalizedExec === `${pm}.cmd` || normalizedExec === `${pm}.exe` || normalizedExec === `${pm}.js` || normalizedExec === `${pm}.cjs` || normalizedExec === `${pm}.mjs`;
52410
+ };
52411
+ if (matchesPmExecPath("bun"))
52308
52412
  return "bun";
52309
- if (/\/yarn([/.]|$)/.test(normalizedExec) || normalizedExec.startsWith("yarn"))
52413
+ if (matchesPmExecPath("yarn"))
52310
52414
  return "yarn";
52311
- if (/\/pnpm([/.]|$)/.test(normalizedExec) || normalizedExec.startsWith("pnpm"))
52415
+ if (matchesPmExecPath("pnpm"))
52312
52416
  return "pnpm";
52313
- if (/\/npm([/.]|$)/.test(normalizedExec) || normalizedExec.startsWith("npm"))
52417
+ if (matchesPmExecPath("npm"))
52314
52418
  return "npm";
52315
52419
  }
52316
52420
  return "unknown";
@@ -52373,16 +52477,16 @@ async function saveCachedPm(pm, getVersion) {
52373
52477
  async function findOwningPm() {
52374
52478
  const queries = [getBunQuery(), getNpmQuery(), getPnpmQuery(), getYarnQuery()];
52375
52479
  logger.verbose("PackageManagerDetector: Querying all PMs in parallel");
52376
- logger.debug("Querying package managers for claudekit-cli ownership...");
52480
+ logger.debug(`Querying package managers for ${CLAUDEKIT_CLI_NPM_PACKAGE_NAME} ownership...`);
52377
52481
  const results = await Promise.allSettled(queries.map(async ({ pm, cmd, checkFn }) => {
52378
52482
  try {
52379
52483
  logger.verbose(`PackageManagerDetector: Querying ${pm}`);
52380
52484
  const { stdout } = await execAsync(cmd, {
52381
- timeout: QUERY_TIMEOUT
52485
+ timeout: getPmQueryTimeoutMs()
52382
52486
  });
52383
52487
  if (checkFn(stdout)) {
52384
52488
  logger.verbose(`PackageManagerDetector: Found via ${pm}`);
52385
- logger.debug(`Found claudekit-cli installed via ${pm}`);
52489
+ logger.debug(`Found ${CLAUDEKIT_CLI_NPM_PACKAGE_NAME} installed via ${pm}`);
52386
52490
  return pm;
52387
52491
  }
52388
52492
  logger.verbose(`PackageManagerDetector: Not found via ${pm}`);
@@ -52392,12 +52496,20 @@ async function findOwningPm() {
52392
52496
  return null;
52393
52497
  }));
52394
52498
  logger.verbose("PackageManagerDetector: All PM queries complete");
52499
+ const detectedPms = [];
52395
52500
  for (const result of results) {
52396
- if (result.status === "fulfilled" && result.value) {
52397
- return result.value;
52501
+ if (result.status === "fulfilled" && result.value && !detectedPms.includes(result.value)) {
52502
+ detectedPms.push(result.value);
52398
52503
  }
52399
52504
  }
52400
- logger.debug("Could not determine which package manager installed claudekit-cli");
52505
+ if (detectedPms.length === 1) {
52506
+ return detectedPms[0];
52507
+ }
52508
+ if (detectedPms.length > 1) {
52509
+ logger.warning(`Ambiguous package manager ownership for ${CLAUDEKIT_CLI_NPM_PACKAGE_NAME}: ${detectedPms.join(", ")}. Falling back to default detection.`);
52510
+ return null;
52511
+ }
52512
+ logger.debug(`Could not determine which package manager installed ${CLAUDEKIT_CLI_NPM_PACKAGE_NAME}`);
52401
52513
  return null;
52402
52514
  }
52403
52515
  async function clearCache() {
@@ -52412,10 +52524,12 @@ async function clearCache() {
52412
52524
  logger.debug(`Failed to clear cache: ${error instanceof Error ? error.message : "Unknown error"}`);
52413
52525
  }
52414
52526
  }
52415
- var CACHE_FILE = "install-info.json", CACHE_TTL, QUERY_TIMEOUT = 5000;
52527
+ var CACHE_FILE = "install-info.json", CACHE_TTL;
52416
52528
  var init_detection_core = __esm(() => {
52529
+ init_claudekit_constants();
52417
52530
  init_logger();
52418
52531
  init_path_resolver();
52532
+ init_constants();
52419
52533
  init_package_managers();
52420
52534
  CACHE_TTL = 30 * 24 * 60 * 60 * 1000;
52421
52535
  });
@@ -52433,7 +52547,9 @@ var init_package_managers = __esm(() => {
52433
52547
  // src/domains/installation/package-manager-detector.ts
52434
52548
  var PackageManagerDetector;
52435
52549
  var init_package_manager_detector = __esm(() => {
52550
+ init_claudekit_constants();
52436
52551
  init_logger();
52552
+ init_constants();
52437
52553
  init_package_managers();
52438
52554
  PackageManagerDetector = class PackageManagerDetector {
52439
52555
  static async detect() {
@@ -52469,7 +52585,7 @@ var init_package_manager_detector = __esm(() => {
52469
52585
  return owningPm;
52470
52586
  }
52471
52587
  logger.verbose("PackageManagerDetector: Defaulting to npm");
52472
- logger.warning("Could not detect package manager that installed claudekit-cli, defaulting to npm");
52588
+ logger.warning(`Could not detect package manager that installed ${CLAUDEKIT_CLI_NPM_PACKAGE_NAME}, defaulting to npm`);
52473
52589
  return "npm";
52474
52590
  }
52475
52591
  static readCachedPm = readCachedPm;
@@ -52481,7 +52597,9 @@ var init_package_manager_detector = __esm(() => {
52481
52597
  if (pm === "unknown")
52482
52598
  return false;
52483
52599
  try {
52484
- await execAsync(PackageManagerDetector.getVersionCommand(pm), { timeout: 3000 });
52600
+ await execAsync(PackageManagerDetector.getVersionCommand(pm), {
52601
+ timeout: getPmVersionCommandTimeoutMs()
52602
+ });
52485
52603
  return true;
52486
52604
  } catch {
52487
52605
  return false;
@@ -52947,7 +53065,7 @@ var package_default;
52947
53065
  var init_package = __esm(() => {
52948
53066
  package_default = {
52949
53067
  name: "claudekit-cli",
52950
- version: "3.35.0-dev.16",
53068
+ version: "3.35.0-dev.18",
52951
53069
  description: "CLI tool for bootstrapping and updating ClaudeKit projects",
52952
53070
  type: "module",
52953
53071
  repository: {
@@ -53188,7 +53306,7 @@ async function updateCliCommand(options2) {
53188
53306
  s.start("Checking for updates...");
53189
53307
  let targetVersion = null;
53190
53308
  if (opts.release && opts.release !== "latest") {
53191
- const exists = await NpmRegistryClient.versionExists(PACKAGE_NAME, opts.release, opts.registry);
53309
+ const exists = await NpmRegistryClient.versionExists(CLAUDEKIT_CLI_NPM_PACKAGE_NAME, opts.release, opts.registry);
53192
53310
  if (!exists) {
53193
53311
  s.stop("Version not found");
53194
53312
  throw new CliUpdateError(`Version ${opts.release} does not exist on npm registry. Run 'ck versions' to see available versions.`);
@@ -53196,20 +53314,20 @@ async function updateCliCommand(options2) {
53196
53314
  targetVersion = opts.release;
53197
53315
  s.stop(`Target version: ${targetVersion}`);
53198
53316
  } else if (opts.dev || opts.beta) {
53199
- targetVersion = await NpmRegistryClient.getDevVersion(PACKAGE_NAME, opts.registry);
53317
+ targetVersion = await NpmRegistryClient.getDevVersion(CLAUDEKIT_CLI_NPM_PACKAGE_NAME, opts.registry);
53200
53318
  if (!targetVersion) {
53201
53319
  s.stop("No dev version available");
53202
53320
  logger.warning("No dev version found. Using latest stable version instead.");
53203
- targetVersion = await NpmRegistryClient.getLatestVersion(PACKAGE_NAME, opts.registry);
53321
+ targetVersion = await NpmRegistryClient.getLatestVersion(CLAUDEKIT_CLI_NPM_PACKAGE_NAME, opts.registry);
53204
53322
  } else {
53205
53323
  s.stop(`Latest dev version: ${targetVersion}`);
53206
53324
  }
53207
53325
  } else {
53208
- targetVersion = await NpmRegistryClient.getLatestVersion(PACKAGE_NAME, opts.registry);
53326
+ targetVersion = await NpmRegistryClient.getLatestVersion(CLAUDEKIT_CLI_NPM_PACKAGE_NAME, opts.registry);
53209
53327
  s.stop(`Latest version: ${targetVersion || "unknown"}`);
53210
53328
  }
53211
53329
  if (!targetVersion) {
53212
- 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)}`);
53330
+ 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)}`);
53213
53331
  }
53214
53332
  const comparison = import_compare_versions.compareVersions(currentVersion, targetVersion);
53215
53333
  if (comparison === 0) {
@@ -53242,7 +53360,7 @@ Run 'ck update' to install`, "Update Check");
53242
53360
  return;
53243
53361
  }
53244
53362
  }
53245
- const updateCmd = PackageManagerDetector.getUpdateCommand(pm, PACKAGE_NAME, targetVersion);
53363
+ const updateCmd = PackageManagerDetector.getUpdateCommand(pm, CLAUDEKIT_CLI_NPM_PACKAGE_NAME, targetVersion);
53246
53364
  logger.info(`Running: ${updateCmd}`);
53247
53365
  s.start("Updating CLI...");
53248
53366
  try {
@@ -53298,12 +53416,13 @@ Manual update: ${updateCmd}`);
53298
53416
  throw new CliUpdateError(errorMessage);
53299
53417
  }
53300
53418
  }
53301
- var import_compare_versions, import_fs_extra5, execAsync2, CliUpdateError, PACKAGE_NAME = "claudekit-cli";
53419
+ var import_compare_versions, import_fs_extra5, execAsync2, CliUpdateError;
53302
53420
  var init_update_cli = __esm(() => {
53303
53421
  init_npm_registry();
53304
53422
  init_package_manager_detector();
53305
53423
  init_metadata_migration();
53306
53424
  init_claudekit_scanner();
53425
+ init_claudekit_constants();
53307
53426
  init_logger();
53308
53427
  init_safe_prompts();
53309
53428
  init_types3();
@@ -53519,7 +53638,7 @@ async function getAuthenticatedClient() {
53519
53638
  const { token } = await AuthManager.getToken();
53520
53639
  cachedOctokit = new Octokit({
53521
53640
  auth: token,
53522
- userAgent: "claudekit-cli",
53641
+ userAgent: getCliUserAgent(),
53523
53642
  request: {
53524
53643
  timeout: 30000
53525
53644
  }
@@ -53533,6 +53652,7 @@ async function invalidateAuth() {
53533
53652
  }
53534
53653
  var cachedOctokit = null;
53535
53654
  var init_auth_api = __esm(() => {
53655
+ init_claudekit_constants();
53536
53656
  init_logger();
53537
53657
  init_github_auth();
53538
53658
  });
@@ -54488,7 +54608,7 @@ function isUpdateCheckDisabled() {
54488
54608
  return process.env.NO_UPDATE_NOTIFIER === "1" || process.env.NO_UPDATE_NOTIFIER === "true" || !process.stdout.isTTY;
54489
54609
  }
54490
54610
  function normalizeVersion(version) {
54491
- return version.replace(/^v/, "");
54611
+ return version.replace(/^v/i, "");
54492
54612
  }
54493
54613
  function parseVersionParts(version) {
54494
54614
  const normalized = normalizeVersion(version);
@@ -54667,7 +54787,7 @@ class CliVersionChecker {
54667
54787
  return null;
54668
54788
  }
54669
54789
  try {
54670
- const latestVersion = await NpmRegistryClient.getLatestVersion(PACKAGE_NAME2);
54790
+ const latestVersion = await NpmRegistryClient.getLatestVersion(CLAUDEKIT_CLI_NPM_PACKAGE_NAME);
54671
54791
  if (!latestVersion) {
54672
54792
  logger.debug("Failed to fetch latest CLI version from npm");
54673
54793
  return null;
@@ -54684,7 +54804,7 @@ class CliVersionChecker {
54684
54804
  currentVersion: current,
54685
54805
  latestVersion: latest,
54686
54806
  updateAvailable,
54687
- releaseUrl: `https://www.npmjs.com/package/${PACKAGE_NAME2}`
54807
+ releaseUrl: CLAUDEKIT_CLI_NPM_PACKAGE_URL
54688
54808
  };
54689
54809
  } catch (error) {
54690
54810
  logger.debug(`CLI version check failed: ${error}`);
@@ -54692,9 +54812,10 @@ class CliVersionChecker {
54692
54812
  }
54693
54813
  }
54694
54814
  }
54695
- var import_compare_versions4, PACKAGE_NAME2 = "claudekit-cli";
54815
+ var import_compare_versions4;
54696
54816
  var init_cli_version_checker = __esm(() => {
54697
54817
  init_npm_registry();
54818
+ init_claudekit_constants();
54698
54819
  init_logger();
54699
54820
  init_version_utils();
54700
54821
  import_compare_versions4 = __toESM(require_umd(), 1);
@@ -54806,29 +54927,45 @@ import { spawn as spawn2 } from "node:child_process";
54806
54927
  import { existsSync as existsSync31 } from "node:fs";
54807
54928
  import { readFile as readFile27 } from "node:fs/promises";
54808
54929
  import { join as join39 } from "node:path";
54930
+ function hasCliUpdate(currentVersion, latestVersion) {
54931
+ if (!latestVersion) {
54932
+ return false;
54933
+ }
54934
+ try {
54935
+ return import_compare_versions5.compareVersions(normalizeVersion(latestVersion), normalizeVersion(currentVersion)) > 0;
54936
+ } catch (error) {
54937
+ logger.debug(`Version comparison failed for "${currentVersion}" vs "${latestVersion}": ${error}`);
54938
+ return latestVersion !== currentVersion;
54939
+ }
54940
+ }
54809
54941
  function registerSystemRoutes(app) {
54810
54942
  app.get("/api/system/check-updates", async (req, res) => {
54811
54943
  const { target, kit, channel = "stable" } = req.query;
54944
+ const normalizedChannel = typeof channel === "string" ? channel.toLowerCase() : "stable";
54812
54945
  if (!target || target !== "cli" && target !== "kit") {
54813
54946
  res.status(400).json({ error: "Missing or invalid target param (cli|kit)" });
54814
54947
  return;
54815
54948
  }
54949
+ if (normalizedChannel !== "stable" && normalizedChannel !== "beta") {
54950
+ res.status(400).json({ error: "Invalid channel param (stable|beta)" });
54951
+ return;
54952
+ }
54816
54953
  try {
54817
54954
  if (target === "cli") {
54818
54955
  const packageJson = await getPackageJson();
54819
54956
  const currentVersion = packageJson?.version ?? "0.0.0";
54820
54957
  let latestVersion = null;
54821
- if (channel === "beta") {
54822
- latestVersion = await NpmRegistryClient.getDevVersion("claudekit-cli");
54958
+ if (normalizedChannel === "beta") {
54959
+ latestVersion = await NpmRegistryClient.getDevVersion(CLAUDEKIT_CLI_NPM_PACKAGE_NAME);
54823
54960
  } else {
54824
- latestVersion = await NpmRegistryClient.getLatestVersion("claudekit-cli");
54961
+ latestVersion = await NpmRegistryClient.getLatestVersion(CLAUDEKIT_CLI_NPM_PACKAGE_NAME);
54825
54962
  }
54826
- const updateAvailable = latestVersion ? latestVersion !== currentVersion : false;
54963
+ const updateAvailable = hasCliUpdate(currentVersion, latestVersion);
54827
54964
  const response = {
54828
54965
  current: currentVersion,
54829
54966
  latest: latestVersion,
54830
54967
  updateAvailable,
54831
- releaseUrl: updateAvailable ? "https://www.npmjs.com/package/claudekit" : undefined
54968
+ releaseUrl: CLAUDEKIT_CLI_NPM_PACKAGE_URL
54832
54969
  };
54833
54970
  res.json(response);
54834
54971
  } else {
@@ -54840,7 +54977,7 @@ function registerSystemRoutes(app) {
54840
54977
  current: currentVersion,
54841
54978
  latest: result?.latestVersion ?? null,
54842
54979
  updateAvailable: result?.updateAvailable ?? false,
54843
- releaseUrl: result?.updateAvailable ? `https://github.com/anthropics/claudekit-${kitName}/releases` : undefined
54980
+ releaseUrl: `https://github.com/anthropics/claudekit-${kitName}/releases`
54844
54981
  };
54845
54982
  res.json(response);
54846
54983
  }
@@ -54870,7 +55007,7 @@ function registerSystemRoutes(app) {
54870
55007
  }
54871
55008
  let versions = [];
54872
55009
  if (target === "cli") {
54873
- const packageInfo = await NpmRegistryClient.getPackageInfo("claudekit-cli");
55010
+ const packageInfo = await NpmRegistryClient.getPackageInfo(CLAUDEKIT_CLI_NPM_PACKAGE_NAME);
54874
55011
  if (packageInfo) {
54875
55012
  const allVersions = Object.keys(packageInfo.versions);
54876
55013
  const latestStable = packageInfo["dist-tags"]?.latest;
@@ -54928,8 +55065,15 @@ function registerSystemRoutes(app) {
54928
55065
  res.status(400).json({ error: "Missing or invalid target param (cli|kit)" });
54929
55066
  return;
54930
55067
  }
54931
- if (target === "kit" && !kit) {
54932
- res.status(400).json({ error: "Missing kit param for kit update" });
55068
+ if (target === "kit") {
55069
+ const kitName = kit;
55070
+ if (!kitName || !AVAILABLE_KITS[kitName]) {
55071
+ res.status(400).json({ error: "Missing or invalid kit param" });
55072
+ return;
55073
+ }
55074
+ }
55075
+ if (version && typeof version === "string" && !/^[a-zA-Z0-9._-]+$/.test(version)) {
55076
+ res.status(400).json({ error: "Invalid version format" });
54933
55077
  return;
54934
55078
  }
54935
55079
  res.setHeader("Content-Type", "text/event-stream");
@@ -54939,34 +55083,27 @@ function registerSystemRoutes(app) {
54939
55083
  res.write(`data: ${JSON.stringify({ type: "start", message: "Starting update..." })}
54940
55084
 
54941
55085
  `);
54942
- let command;
54943
- let args;
55086
+ let commandLine;
54944
55087
  if (target === "cli") {
54945
55088
  const pm = await PackageManagerDetector.detect();
54946
55089
  const targetVersion = version || "latest";
54947
- const fullCmd = PackageManagerDetector.getUpdateCommand(pm, "claudekit-cli", targetVersion);
54948
- const parts = fullCmd.split(" ");
54949
- command = parts[0];
54950
- args = parts.slice(1);
55090
+ commandLine = PackageManagerDetector.getUpdateCommand(pm, CLAUDEKIT_CLI_NPM_PACKAGE_NAME, targetVersion);
54951
55091
  res.write(`data: ${JSON.stringify({ type: "phase", name: "downloading" })}
54952
55092
 
54953
55093
  `);
54954
- logger.debug(`CLI update using ${pm}: ${fullCmd}`);
55094
+ logger.debug(`CLI update using ${pm}: ${commandLine}`);
54955
55095
  } else {
54956
55096
  const kitName = kit;
54957
55097
  const metadata = await getKitMetadata2(kitName);
54958
55098
  const isBeta = isBetaVersion(metadata?.version);
54959
- const initCmd = buildInitCommand(true, kitName, isBeta);
54960
- const parts = initCmd.split(" ");
54961
- command = parts[0];
54962
- args = parts.slice(1);
54963
- logger.debug(`Updating kit ${kitName} (beta: ${isBeta}): ${initCmd}`);
55099
+ commandLine = buildInitCommand(true, kitName, isBeta);
55100
+ logger.debug(`Updating kit ${kitName} (beta: ${isBeta}): ${commandLine}`);
54964
55101
  res.write(`data: ${JSON.stringify({ type: "phase", name: "installing" })}
54965
55102
 
54966
55103
  `);
54967
55104
  }
54968
- logger.debug(`Spawning update command: ${command} ${args.join(" ")}`);
54969
- const childProcess4 = spawn2(command, args, {
55105
+ logger.debug(`Spawning update command: ${commandLine}`);
55106
+ const childProcess4 = spawn2(commandLine, {
54970
55107
  shell: true,
54971
55108
  env: { ...process.env }
54972
55109
  });
@@ -55048,17 +55185,20 @@ async function getKitMetadata2(kitName) {
55048
55185
  return null;
55049
55186
  }
55050
55187
  }
55051
- var versionCache, CACHE_TTL_MS;
55188
+ var import_compare_versions5, versionCache, CACHE_TTL_MS;
55052
55189
  var init_system_routes = __esm(() => {
55053
55190
  init_update_cli();
55054
55191
  init_github_client();
55055
55192
  init_npm_registry();
55056
55193
  init_package_manager_detector();
55194
+ init_version_utils();
55057
55195
  init_version_checker();
55196
+ init_claudekit_constants();
55058
55197
  init_logger();
55059
55198
  init_path_resolver();
55060
55199
  init_kit();
55061
55200
  init_package();
55201
+ import_compare_versions5 = __toESM(require_umd(), 1);
55062
55202
  versionCache = new Map;
55063
55203
  CACHE_TTL_MS = 5 * 60 * 1000;
55064
55204
  });
@@ -60034,35 +60174,46 @@ var init_validators = __esm(() => {
60034
60174
  });
60035
60175
 
60036
60176
  // src/services/package-installer/npm-package-manager.ts
60177
+ function getNpmLookupTimeoutMs() {
60178
+ return parseTimeoutMs(process.env.CK_NPM_LOOKUP_TIMEOUT_MS, DEFAULT_NPM_LOOKUP_TIMEOUT_MS, MIN_NPM_TIMEOUT_MS, MAX_NPM_TIMEOUT_MS);
60179
+ }
60180
+ function getNpmInstallTimeoutMs() {
60181
+ return parseTimeoutMs(process.env.CK_NPM_INSTALL_TIMEOUT_MS, DEFAULT_NPM_INSTALL_TIMEOUT_MS, MIN_NPM_TIMEOUT_MS, MAX_NPM_TIMEOUT_MS);
60182
+ }
60183
+ function escapeRegex(value) {
60184
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
60185
+ }
60037
60186
  async function isPackageInstalled(packageName) {
60038
60187
  validatePackageName(packageName);
60039
- if (isCIEnvironment()) {
60040
- logger.info(`CI environment detected: skipping network check for ${packageName}`);
60188
+ if (shouldSkipExpensiveOperations()) {
60189
+ logger.info(`Expensive checks disabled: skipping global package check for ${packageName}`);
60041
60190
  return false;
60042
60191
  }
60043
60192
  if (packageName === "npm") {
60044
60193
  try {
60045
- await execAsync7(`${getNpmCommand()} --version`, { timeout: 3000 });
60194
+ await execAsync7(`${getNpmCommand()} --version`, { timeout: getNpmLookupTimeoutMs() });
60046
60195
  return true;
60047
60196
  } catch {
60048
60197
  return false;
60049
60198
  }
60050
60199
  }
60051
60200
  try {
60052
- await execAsync7(`${getNpmCommand()} view ${packageName} version`, { timeout: 3000 });
60201
+ await execAsync7(`${getNpmCommand()} view ${packageName} version`, {
60202
+ timeout: getNpmLookupTimeoutMs()
60203
+ });
60053
60204
  try {
60054
- const { stdout: stdout2 } = await execAsync7(`${getNpmCommand()} list -g ${packageName} --depth=0`, {
60055
- timeout: 3000
60205
+ const { stdout: jsonOutput } = await execAsync7(`${getNpmCommand()} list -g ${packageName} --depth=0 --json`, {
60206
+ timeout: getNpmLookupTimeoutMs()
60056
60207
  });
60057
- const caseInsensitiveMatch = stdout2.toLowerCase().includes(packageName.toLowerCase());
60058
- if (caseInsensitiveMatch) {
60208
+ const packageList = JSON.parse(jsonOutput);
60209
+ if (packageList.dependencies?.[packageName]) {
60059
60210
  return true;
60060
60211
  }
60061
- const { stdout: jsonOutput } = await execAsync7(`${getNpmCommand()} list -g ${packageName} --depth=0 --json`, {
60062
- timeout: 3000
60212
+ const { stdout: stdout2 } = await execAsync7(`${getNpmCommand()} list -g ${packageName} --depth=0`, {
60213
+ timeout: getNpmLookupTimeoutMs()
60063
60214
  });
60064
- const packageList = JSON.parse(jsonOutput);
60065
- return packageList.dependencies?.[packageName] || false;
60215
+ const exactPattern = new RegExp(`(?:^|\\s|[├└│─]+)${escapeRegex(packageName)}@([^\\s\\n]+)(?:\\s|$)`, "m");
60216
+ return exactPattern.test(stdout2);
60066
60217
  } catch {
60067
60218
  return false;
60068
60219
  }
@@ -60072,26 +60223,30 @@ async function isPackageInstalled(packageName) {
60072
60223
  }
60073
60224
  async function getPackageVersion(packageName) {
60074
60225
  validatePackageName(packageName);
60075
- if (isCIEnvironment()) {
60076
- logger.info(`CI environment detected: skipping version check for ${packageName}`);
60226
+ if (shouldSkipExpensiveOperations()) {
60227
+ logger.info(`Expensive checks disabled: skipping package version check for ${packageName}`);
60077
60228
  return null;
60078
60229
  }
60079
60230
  if (packageName === "npm") {
60080
60231
  try {
60081
- const { stdout: stdout2 } = await execAsync7(`${getNpmCommand()} --version`, { timeout: 3000 });
60232
+ const { stdout: stdout2 } = await execAsync7(`${getNpmCommand()} --version`, {
60233
+ timeout: getNpmLookupTimeoutMs()
60234
+ });
60082
60235
  return stdout2.trim();
60083
60236
  } catch {
60084
60237
  return null;
60085
60238
  }
60086
60239
  }
60087
60240
  try {
60088
- await execAsync7(`${getNpmCommand()} view ${packageName} version`, { timeout: 3000 });
60241
+ await execAsync7(`${getNpmCommand()} view ${packageName} version`, {
60242
+ timeout: getNpmLookupTimeoutMs()
60243
+ });
60089
60244
  } catch {
60090
60245
  return null;
60091
60246
  }
60092
60247
  try {
60093
60248
  const { stdout: jsonOutput } = await execAsync7(`${getNpmCommand()} list -g ${packageName} --depth=0 --json`, {
60094
- timeout: 3000
60249
+ timeout: getNpmLookupTimeoutMs()
60095
60250
  });
60096
60251
  const packageList = JSON.parse(jsonOutput);
60097
60252
  if (packageList.dependencies?.[packageName]) {
@@ -60100,11 +60255,11 @@ async function getPackageVersion(packageName) {
60100
60255
  } catch {}
60101
60256
  try {
60102
60257
  const { stdout: stdout2 } = await execAsync7(`${getNpmCommand()} list -g ${packageName} --depth=0`, {
60103
- timeout: 3000
60258
+ timeout: getNpmLookupTimeoutMs()
60104
60259
  });
60105
60260
  const patterns = [
60106
- new RegExp(`${packageName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}@([^\\s\\n]+)`),
60107
- new RegExp(`${packageName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}@([0-9]+\\.[0-9]+\\.[0-9]+(?:-[\\w.-]+)?)`)
60261
+ new RegExp(`${escapeRegex(packageName)}@([^\\s\\n]+)`),
60262
+ new RegExp(`${escapeRegex(packageName)}@([0-9]+\\.[0-9]+\\.[0-9]+(?:-[\\w.-]+)?)`)
60108
60263
  ];
60109
60264
  for (const pattern of patterns) {
60110
60265
  const match = stdout2.match(pattern);
@@ -60123,8 +60278,15 @@ async function installPackageGlobally(packageName, packageDisplayName) {
60123
60278
  try {
60124
60279
  logger.info(`Installing ${displayName} globally...`);
60125
60280
  await execAsync7(`${getNpmCommand()} install -g ${packageName}`, {
60126
- timeout: 120000
60281
+ timeout: getNpmInstallTimeoutMs()
60127
60282
  });
60283
+ if (shouldSkipExpensiveOperations()) {
60284
+ logger.info(`Expensive checks disabled: skipping post-install verification for ${displayName}`);
60285
+ return {
60286
+ success: true,
60287
+ package: displayName
60288
+ };
60289
+ }
60128
60290
  const isInstalled = await isPackageInstalled(packageName);
60129
60291
  if (!isInstalled) {
60130
60292
  return {
@@ -60150,6 +60312,7 @@ async function installPackageGlobally(packageName, packageDisplayName) {
60150
60312
  };
60151
60313
  }
60152
60314
  }
60315
+ var DEFAULT_NPM_LOOKUP_TIMEOUT_MS = 3000, DEFAULT_NPM_INSTALL_TIMEOUT_MS = 120000, MIN_NPM_TIMEOUT_MS = 500, MAX_NPM_TIMEOUT_MS = 300000;
60153
60316
  var init_npm_package_manager = __esm(() => {
60154
60317
  init_environment();
60155
60318
  init_logger();
@@ -60909,37 +61072,54 @@ __export(exports_package_installer, {
60909
61072
  async function processPackageInstallations(shouldInstallOpenCode, shouldInstallGemini, projectDir) {
60910
61073
  const results = {};
60911
61074
  if (shouldInstallOpenCode) {
60912
- const alreadyInstalled = await isOpenCodeInstalled();
60913
- if (alreadyInstalled) {
60914
- logger.info("OpenCode CLI already installed");
61075
+ if (isTestEnvironment()) {
60915
61076
  results.opencode = {
60916
61077
  success: true,
60917
- package: "OpenCode CLI"
61078
+ package: "OpenCode CLI",
61079
+ skipped: true
60918
61080
  };
60919
61081
  } else {
60920
- results.opencode = await installOpenCode();
61082
+ const alreadyInstalled = await isOpenCodeInstalled();
61083
+ if (alreadyInstalled) {
61084
+ logger.info("OpenCode CLI already installed");
61085
+ results.opencode = {
61086
+ success: true,
61087
+ package: "OpenCode CLI"
61088
+ };
61089
+ } else {
61090
+ results.opencode = await installOpenCode();
61091
+ }
60921
61092
  }
60922
61093
  }
60923
61094
  if (shouldInstallGemini) {
60924
- const alreadyInstalled = await isGeminiInstalled();
60925
- if (alreadyInstalled) {
60926
- logger.info("Google Gemini CLI already installed");
61095
+ if (isTestEnvironment()) {
60927
61096
  results.gemini = {
60928
61097
  success: true,
60929
- package: "Google Gemini CLI"
61098
+ package: "Google Gemini CLI",
61099
+ skipped: true
60930
61100
  };
60931
61101
  } else {
60932
- results.gemini = await installGemini();
60933
- }
60934
- const geminiAvailable = alreadyInstalled || results.gemini?.success;
60935
- if (projectDir && geminiAvailable) {
60936
- const { processGeminiMcpLinking: processGeminiMcpLinking2 } = await Promise.resolve().then(() => (init_gemini_mcp_linker(), exports_gemini_mcp_linker));
60937
- await processGeminiMcpLinking2(projectDir);
61102
+ const alreadyInstalled = await isGeminiInstalled();
61103
+ if (alreadyInstalled) {
61104
+ logger.info("Google Gemini CLI already installed");
61105
+ results.gemini = {
61106
+ success: true,
61107
+ package: "Google Gemini CLI"
61108
+ };
61109
+ } else {
61110
+ results.gemini = await installGemini();
61111
+ }
61112
+ const geminiAvailable = alreadyInstalled || results.gemini?.success;
61113
+ if (projectDir && geminiAvailable) {
61114
+ const { processGeminiMcpLinking: processGeminiMcpLinking2 } = await Promise.resolve().then(() => (init_gemini_mcp_linker(), exports_gemini_mcp_linker));
61115
+ await processGeminiMcpLinking2(projectDir);
61116
+ }
60938
61117
  }
60939
61118
  }
60940
61119
  return results;
60941
61120
  }
60942
61121
  var init_package_installer = __esm(() => {
61122
+ init_environment();
60943
61123
  init_logger();
60944
61124
  init_gemini_installer();
60945
61125
  init_opencode_installer();
@@ -66866,11 +67046,12 @@ import { exec as exec6 } from "node:child_process";
66866
67046
  import { promisify as promisify12 } from "node:util";
66867
67047
 
66868
67048
  // src/domains/github/gh-cli-utils.ts
67049
+ init_environment();
66869
67050
  init_logger();
66870
67051
  import { readFileSync as readFileSync4 } from "node:fs";
66871
67052
  var MIN_GH_CLI_VERSION = "2.20.0";
66872
67053
  var GH_COMMAND_TIMEOUT_MS = 1e4;
66873
- function compareVersions5(a3, b3) {
67054
+ function compareVersions6(a3, b3) {
66874
67055
  const partsA = a3.split(".").map(Number);
66875
67056
  const partsB = b3.split(".").map(Number);
66876
67057
  const maxLen = Math.max(partsA.length, partsB.length);
@@ -66895,11 +67076,8 @@ function isWSL2() {
66895
67076
  return false;
66896
67077
  }
66897
67078
  }
66898
- function shouldSkipExpensiveOperations() {
66899
- if (process.env.CK_TEST_HOME) {
66900
- return false;
66901
- }
66902
- return process.env.CI === "true" || process.env.CI_SAFE_MODE === "true";
67079
+ function shouldSkipExpensiveOperations2() {
67080
+ return shouldSkipExpensiveOperations();
66903
67081
  }
66904
67082
  function getGhUpgradeInstructions(currentVersion) {
66905
67083
  const platform5 = process.platform;
@@ -66930,16 +67108,11 @@ function getGhUpgradeInstructions(currentVersion) {
66930
67108
  }
66931
67109
 
66932
67110
  // src/services/package-installer/dependency-checker.ts
67111
+ init_environment();
66933
67112
  init_logger();
66934
67113
  import { exec as exec3 } from "node:child_process";
66935
67114
  import { promisify as promisify9 } from "node:util";
66936
67115
  var execAsync3 = promisify9(exec3);
66937
- function shouldSkipExpensiveOperations2() {
66938
- if (process.env.CK_TEST_HOME) {
66939
- return false;
66940
- }
66941
- return process.env.CI === "true" || process.env.CI_SAFE_MODE === "true";
66942
- }
66943
67116
  function getOSInfo() {
66944
67117
  const platform5 = process.platform;
66945
67118
  const arch2 = process.arch;
@@ -67028,10 +67201,14 @@ var DEPENDENCIES = {
67028
67201
  }
67029
67202
  };
67030
67203
  async function commandExists(command) {
67031
- if (shouldSkipExpensiveOperations2()) {
67204
+ if (shouldSkipExpensiveOperations()) {
67032
67205
  const supportedCommands = ["node", "python", "python3", "pip", "pip3", "claude"];
67033
67206
  return supportedCommands.includes(command);
67034
67207
  }
67208
+ if (!/^[a-zA-Z0-9_-]+$/.test(command)) {
67209
+ logger.verbose(`Invalid command name rejected: ${command}`);
67210
+ return false;
67211
+ }
67035
67212
  try {
67036
67213
  const whichCmd = process.platform === "win32" ? "where" : "which";
67037
67214
  logger.verbose(`Checking if command exists: ${command}`);
@@ -67044,11 +67221,14 @@ async function commandExists(command) {
67044
67221
  }
67045
67222
  }
67046
67223
  async function getCommandPath(command) {
67047
- if (shouldSkipExpensiveOperations2()) {
67224
+ if (shouldSkipExpensiveOperations()) {
67048
67225
  const ciPath = getCICommandPath(command);
67049
67226
  if (ciPath)
67050
67227
  return ciPath;
67051
67228
  }
67229
+ if (!/^[a-zA-Z0-9_-]+$/.test(command)) {
67230
+ return null;
67231
+ }
67052
67232
  try {
67053
67233
  const whichCmd = process.platform === "win32" ? "where" : "which";
67054
67234
  logger.verbose(`Getting path for command: ${command}`);
@@ -67063,7 +67243,7 @@ async function getCommandPath(command) {
67063
67243
  }
67064
67244
  }
67065
67245
  async function getCommandVersion(command, versionFlag, versionRegex) {
67066
- if (shouldSkipExpensiveOperations2()) {
67246
+ if (shouldSkipExpensiveOperations()) {
67067
67247
  const mockVersions = {
67068
67248
  npm: "10.0.0",
67069
67249
  node: "20.0.0",
@@ -67075,6 +67255,9 @@ async function getCommandVersion(command, versionFlag, versionRegex) {
67075
67255
  };
67076
67256
  return mockVersions[command] || null;
67077
67257
  }
67258
+ if (!/^[a-zA-Z0-9_-]+$/.test(command) || !/^--?[a-zA-Z0-9_-]+$/.test(versionFlag)) {
67259
+ return null;
67260
+ }
67078
67261
  try {
67079
67262
  logger.verbose(`Getting version for: ${command} ${versionFlag}`);
67080
67263
  const { stdout, stderr } = await execAsync3(`${command} ${versionFlag}`);
@@ -67089,7 +67272,7 @@ async function getCommandVersion(command, versionFlag, versionRegex) {
67089
67272
  return null;
67090
67273
  }
67091
67274
  }
67092
- function compareVersions6(current, required) {
67275
+ function compareVersions7(current, required) {
67093
67276
  const parseCurrent = current.split(".").map((n) => Number.parseInt(n, 10));
67094
67277
  const parseRequired = required.split(".").map((n) => Number.parseInt(n, 10));
67095
67278
  for (let i = 0;i < 3; i++) {
@@ -67113,7 +67296,7 @@ async function checkDependency(config) {
67113
67296
  let meetsRequirements = true;
67114
67297
  let message;
67115
67298
  if (config.minVersion && version) {
67116
- meetsRequirements = compareVersions6(version, config.minVersion);
67299
+ meetsRequirements = compareVersions7(version, config.minVersion);
67117
67300
  if (!meetsRequirements) {
67118
67301
  message = `Version ${version} is below minimum ${config.minVersion}`;
67119
67302
  }
@@ -67386,7 +67569,7 @@ class SystemChecker {
67386
67569
  logger.verbose(`SystemChecker: Processing ${dep.name}`);
67387
67570
  results.push(await this.mapDependencyToCheck(dep));
67388
67571
  }
67389
- if (!shouldSkipExpensiveOperations()) {
67572
+ if (!shouldSkipExpensiveOperations2()) {
67390
67573
  logger.verbose("SystemChecker: Checking git");
67391
67574
  results.push(await this.checkGit());
67392
67575
  logger.verbose("SystemChecker: Checking GitHub CLI");
@@ -67508,7 +67691,7 @@ class SystemChecker {
67508
67691
  const { stdout } = await execAsync6("gh --version");
67509
67692
  const match = stdout.match(/(\d+\.\d+\.\d+)/);
67510
67693
  const version = match?.[1];
67511
- if (version && compareVersions5(version, MIN_GH_CLI_VERSION) < 0) {
67694
+ if (version && compareVersions6(version, MIN_GH_CLI_VERSION) < 0) {
67512
67695
  return {
67513
67696
  id: "gh-cli-version",
67514
67697
  name: "GitHub CLI",
@@ -67630,6 +67813,7 @@ function checkProjectInstall(setup) {
67630
67813
  }
67631
67814
  // src/domains/health-checks/checkers/cli-install-checker.ts
67632
67815
  init_package_manager_detector();
67816
+ init_claudekit_constants();
67633
67817
  init_logger();
67634
67818
  async function checkCliInstallMethod() {
67635
67819
  if (false) {}
@@ -67643,7 +67827,7 @@ async function checkCliInstallMethod() {
67643
67827
  priority: "standard",
67644
67828
  status: pm !== "unknown" ? "pass" : "warn",
67645
67829
  message: pmVersion ? `${displayName} (v${pmVersion})` : displayName,
67646
- suggestion: pm === "unknown" ? "Run: npm install -g claudekit-cli" : undefined,
67830
+ suggestion: pm === "unknown" ? `Install with one of: ${CLAUDEKIT_CLI_INSTALL_COMMANDS.join(" | ")}` : undefined,
67647
67831
  autoFixable: false
67648
67832
  };
67649
67833
  }
@@ -67832,11 +68016,9 @@ import { constants as constants2, access as access2, unlink as unlink6, writeFil
67832
68016
  import { join as join44 } from "node:path";
67833
68017
 
67834
68018
  // src/domains/health-checks/checkers/shared.ts
68019
+ init_environment();
67835
68020
  function shouldSkipExpensiveOperations3() {
67836
- if (process.env.CK_TEST_HOME) {
67837
- return false;
67838
- }
67839
- return process.env.CI === "true" || process.env.CI_SAFE_MODE === "true";
68021
+ return shouldSkipExpensiveOperations();
67840
68022
  }
67841
68023
  var HOOK_EXTENSIONS = [".js", ".cjs", ".mjs", ".ts", ".sh", ".ps1"];
67842
68024
 
@@ -68538,6 +68720,7 @@ async function checkEnvKeys(setup) {
68538
68720
  return results;
68539
68721
  }
68540
68722
  // src/domains/health-checks/checkers/hook-health-checker.ts
68723
+ init_claudekit_constants();
68541
68724
  init_logger();
68542
68725
  init_path_resolver();
68543
68726
  import { spawnSync as spawnSync2 } from "node:child_process";
@@ -69165,7 +69348,7 @@ async function checkCliVersion() {
69165
69348
  autoFixable: false
69166
69349
  };
69167
69350
  }
69168
- const npmResult = spawnSync2("npm", ["view", "claudekit-cli", "version"], {
69351
+ const npmResult = spawnSync2("npm", ["view", CLAUDEKIT_CLI_NPM_PACKAGE_NAME, "version"], {
69169
69352
  timeout: HOOK_CHECK_TIMEOUT_MS,
69170
69353
  encoding: "utf-8"
69171
69354
  });
@@ -69730,16 +69913,13 @@ class AuthChecker {
69730
69913
  import { platform as platform6 } from "node:os";
69731
69914
 
69732
69915
  // src/domains/health-checks/platform/environment-checker.ts
69916
+ init_environment();
69733
69917
  init_path_resolver();
69734
69918
  import { constants as constants3, access as access3, mkdir as mkdir12, readFile as readFile31, unlink as unlink7, writeFile as writeFile15 } from "node:fs/promises";
69735
69919
  import { arch as arch2, homedir as homedir24, platform as platform5 } from "node:os";
69736
69920
  import { join as join53, normalize as normalize6 } from "node:path";
69737
- var IS_WINDOWS = platform5() === "win32";
69738
69921
  function shouldSkipExpensiveOperations4() {
69739
- if (process.env.CK_TEST_HOME) {
69740
- return false;
69741
- }
69742
- return process.env.CI === "true" || process.env.CI_SAFE_MODE === "true";
69922
+ return shouldSkipExpensiveOperations();
69743
69923
  }
69744
69924
  async function checkPlatformDetect() {
69745
69925
  const os5 = platform5();
@@ -69760,7 +69940,8 @@ async function checkPlatformDetect() {
69760
69940
  }
69761
69941
  async function checkHomeDirResolution() {
69762
69942
  const nodeHome = normalize6(homedir24());
69763
- const envHome = normalize6(IS_WINDOWS ? process.env.USERPROFILE || "" : process.env.HOME || "");
69943
+ const rawEnvHome = getHomeDirectoryFromEnv(platform5());
69944
+ const envHome = rawEnvHome ? normalize6(rawEnvHome) : "";
69764
69945
  const match = nodeHome === envHome && envHome !== "";
69765
69946
  return {
69766
69947
  id: "home-dir-resolution",
@@ -69994,7 +70175,7 @@ async function checkSymlinkSupport() {
69994
70175
  }
69995
70176
 
69996
70177
  // src/domains/health-checks/platform-checker.ts
69997
- var IS_WINDOWS2 = platform6() === "win32";
70178
+ var IS_WINDOWS = platform6() === "win32";
69998
70179
 
69999
70180
  class PlatformChecker {
70000
70181
  group = "platform";
@@ -70002,7 +70183,7 @@ class PlatformChecker {
70002
70183
  const results = [];
70003
70184
  results.push(await checkPlatformDetect());
70004
70185
  results.push(await checkHomeDirResolution());
70005
- if (IS_WINDOWS2) {
70186
+ if (IS_WINDOWS) {
70006
70187
  results.push(await checkEnvVarExpansion());
70007
70188
  }
70008
70189
  results.push(await checkGlobalDirAccess());
@@ -70010,7 +70191,7 @@ class PlatformChecker {
70010
70191
  if (this.isWSL()) {
70011
70192
  results.push(await checkWSLBoundary());
70012
70193
  }
70013
- if (IS_WINDOWS2) {
70194
+ if (IS_WINDOWS) {
70014
70195
  results.push(await checkLongPathSupport());
70015
70196
  results.push(await checkSymlinkSupport());
70016
70197
  }
@@ -70021,13 +70202,21 @@ class PlatformChecker {
70021
70202
  }
70022
70203
  }
70023
70204
  // src/domains/health-checks/network-checker.ts
70205
+ init_claudekit_constants();
70206
+ init_environment();
70024
70207
  init_logger();
70025
- var NETWORK_TIMEOUT = Number.parseInt(process.env.CLAUDEKIT_NETWORK_TIMEOUT || "3000", 10);
70208
+ function getNetworkTimeoutMs() {
70209
+ const raw = process.env.CLAUDEKIT_NETWORK_TIMEOUT;
70210
+ if (raw && Number.isNaN(Number.parseInt(raw, 10))) {
70211
+ logger.warning(`Invalid CLAUDEKIT_NETWORK_TIMEOUT value "${raw}", using default ${DEFAULT_NETWORK_TIMEOUT_MS}ms`);
70212
+ }
70213
+ return parseTimeoutMs(raw, DEFAULT_NETWORK_TIMEOUT_MS);
70214
+ }
70026
70215
 
70027
70216
  class NetworkChecker {
70028
70217
  group = "network";
70029
70218
  async run() {
70030
- if (this.isCI()) {
70219
+ if (this.shouldSkipChecks()) {
70031
70220
  logger.verbose("NetworkChecker: Skipping in CI environment");
70032
70221
  return [];
70033
70222
  }
@@ -70037,8 +70226,8 @@ class NetworkChecker {
70037
70226
  results.push(await this.checkApiGitHub());
70038
70227
  return results;
70039
70228
  }
70040
- isCI() {
70041
- return process.env.CI === "true" || process.env.CI_SAFE_MODE === "true" || false || process.env.VITEST === "true" || process.env.JEST_WORKER_ID !== undefined || process.env.TEST === "true";
70229
+ shouldSkipChecks() {
70230
+ return isCIEnvironment() || isTestEnvironment();
70042
70231
  }
70043
70232
  checkProxyDetected() {
70044
70233
  const httpProxy = process.env.HTTP_PROXY || process.env.http_proxy;
@@ -70080,7 +70269,7 @@ class NetworkChecker {
70080
70269
  try {
70081
70270
  const response = await fetch("https://github.com", {
70082
70271
  method: "HEAD",
70083
- signal: AbortSignal.timeout(NETWORK_TIMEOUT)
70272
+ signal: AbortSignal.timeout(getNetworkTimeoutMs())
70084
70273
  });
70085
70274
  const latency = Date.now() - startTime;
70086
70275
  if (response.ok || response.status === 301 || response.status === 302) {
@@ -70112,7 +70301,7 @@ class NetworkChecker {
70112
70301
  group: "network",
70113
70302
  priority: "standard",
70114
70303
  status: "fail",
70115
- message: isTimeout ? `Timeout (>${NETWORK_TIMEOUT}ms)` : "Connection failed",
70304
+ message: isTimeout ? `Timeout (>${getNetworkTimeoutMs()}ms)` : "Connection failed",
70116
70305
  suggestion: "Check internet connection or proxy settings",
70117
70306
  autoFixable: false
70118
70307
  };
@@ -70125,9 +70314,9 @@ class NetworkChecker {
70125
70314
  method: "GET",
70126
70315
  headers: {
70127
70316
  Accept: "application/vnd.github.v3+json",
70128
- "User-Agent": "claudekit-cli"
70317
+ "User-Agent": getCliUserAgent()
70129
70318
  },
70130
- signal: AbortSignal.timeout(NETWORK_TIMEOUT)
70319
+ signal: AbortSignal.timeout(getNetworkTimeoutMs())
70131
70320
  });
70132
70321
  const latency = Date.now() - startTime;
70133
70322
  if (response.ok) {
@@ -70159,7 +70348,7 @@ class NetworkChecker {
70159
70348
  group: "network",
70160
70349
  priority: "standard",
70161
70350
  status: "fail",
70162
- message: isTimeout ? `Timeout (>${NETWORK_TIMEOUT}ms)` : "Connection failed",
70351
+ message: isTimeout ? `Timeout (>${getNetworkTimeoutMs()}ms)` : "Connection failed",
70163
70352
  suggestion: "Check internet connection or proxy settings for api.github.com",
70164
70353
  autoFixable: false
70165
70354
  };
@@ -70249,7 +70438,7 @@ import { fileURLToPath as fileURLToPath3 } from "node:url";
70249
70438
  init_environment();
70250
70439
  init_logger();
70251
70440
  init_dist2();
70252
- function getCliVersion3() {
70441
+ function getCliVersion4() {
70253
70442
  try {
70254
70443
  const __dirname4 = dirname13(fileURLToPath3(import.meta.url));
70255
70444
  const pkgPath = join55(__dirname4, "../../../package.json");
@@ -70419,7 +70608,7 @@ class ReportGenerator {
70419
70608
  osVersion: osInfo.details,
70420
70609
  node: process.version,
70421
70610
  cwd: this.scrubPath(process.cwd()),
70422
- cliVersion: getCliVersion3()
70611
+ cliVersion: getCliVersion4()
70423
70612
  };
70424
70613
  }
70425
70614
  scrubPath(path5) {
@@ -70712,9 +70901,10 @@ async function easterEggCommand() {
70712
70901
  init_github_client();
70713
70902
 
70714
70903
  // src/domains/sync/config-version-checker.ts
70904
+ init_claudekit_constants();
70715
70905
  init_logger();
70716
70906
  init_path_resolver();
70717
- var import_compare_versions5 = __toESM(require_umd(), 1);
70907
+ var import_compare_versions6 = __toESM(require_umd(), 1);
70718
70908
  import { mkdir as mkdir14, readFile as readFile32, unlink as unlink9, writeFile as writeFile17 } from "node:fs/promises";
70719
70909
  import { join as join56 } from "node:path";
70720
70910
  var CACHE_TTL_HOURS = 24;
@@ -70790,7 +70980,7 @@ class ConfigVersionChecker {
70790
70980
  try {
70791
70981
  const headers = {
70792
70982
  Accept: "application/vnd.github.v3+json",
70793
- "User-Agent": "claudekit-cli"
70983
+ "User-Agent": getCliUserAgent()
70794
70984
  };
70795
70985
  const githubToken = process.env.GITHUB_TOKEN;
70796
70986
  if (githubToken) {
@@ -70850,7 +71040,7 @@ class ConfigVersionChecker {
70850
71040
  const cache3 = await ConfigVersionChecker.loadCache(kitType, global3);
70851
71041
  const now = Date.now();
70852
71042
  if (cache3 && now - cache3.lastCheck < CACHE_TTL_MS2) {
70853
- const hasUpdates = import_compare_versions5.compareVersions(cache3.latestVersion, normalizedCurrent) > 0;
71043
+ const hasUpdates = import_compare_versions6.compareVersions(cache3.latestVersion, normalizedCurrent) > 0;
70854
71044
  return {
70855
71045
  hasUpdates,
70856
71046
  currentVersion: normalizedCurrent,
@@ -70864,7 +71054,7 @@ class ConfigVersionChecker {
70864
71054
  ...cache3,
70865
71055
  lastCheck: now
70866
71056
  });
70867
- const hasUpdates = import_compare_versions5.compareVersions(cache3.latestVersion, normalizedCurrent) > 0;
71057
+ const hasUpdates = import_compare_versions6.compareVersions(cache3.latestVersion, normalizedCurrent) > 0;
70868
71058
  return {
70869
71059
  hasUpdates,
70870
71060
  currentVersion: normalizedCurrent,
@@ -70878,7 +71068,7 @@ class ConfigVersionChecker {
70878
71068
  latestVersion: result.version,
70879
71069
  etag: result.etag
70880
71070
  });
70881
- const hasUpdates = import_compare_versions5.compareVersions(result.version, normalizedCurrent) > 0;
71071
+ const hasUpdates = import_compare_versions6.compareVersions(result.version, normalizedCurrent) > 0;
70882
71072
  return {
70883
71073
  hasUpdates,
70884
71074
  currentVersion: normalizedCurrent,
@@ -70887,7 +71077,7 @@ class ConfigVersionChecker {
70887
71077
  };
70888
71078
  }
70889
71079
  if (cache3) {
70890
- const hasUpdates = import_compare_versions5.compareVersions(cache3.latestVersion, normalizedCurrent) > 0;
71080
+ const hasUpdates = import_compare_versions6.compareVersions(cache3.latestVersion, normalizedCurrent) > 0;
70891
71081
  return {
70892
71082
  hasUpdates,
70893
71083
  currentVersion: normalizedCurrent,
@@ -86829,7 +87019,7 @@ init_logger();
86829
87019
  import { readFile as readFile45, readdir as readdir30, writeFile as writeFile26 } from "node:fs/promises";
86830
87020
  import { platform as platform12 } from "node:os";
86831
87021
  import { extname as extname4, join as join97 } from "node:path";
86832
- var IS_WINDOWS3 = platform12() === "win32";
87022
+ var IS_WINDOWS2 = platform12() === "win32";
86833
87023
  function getOpenCodeGlobalPath() {
86834
87024
  return "$HOME/.config/opencode/";
86835
87025
  }
@@ -87049,16 +87239,7 @@ async function handlePostInstall(ctx) {
87049
87239
  return ctx;
87050
87240
  }
87051
87241
  if (ctx.options.global) {
87052
- const claudeMdSource = join99(ctx.extractDir, "CLAUDE.md");
87053
- const claudeMdDest = join99(ctx.resolvedDir, "CLAUDE.md");
87054
- if (await import_fs_extra30.pathExists(claudeMdSource)) {
87055
- if (!await import_fs_extra30.pathExists(claudeMdDest)) {
87056
- await import_fs_extra30.copy(claudeMdSource, claudeMdDest);
87057
- logger.success("Copied CLAUDE.md to global directory");
87058
- } else {
87059
- logger.debug("CLAUDE.md already exists in global directory (preserved)");
87060
- }
87061
- }
87242
+ await handleGlobalClaudeMd(ctx);
87062
87243
  }
87063
87244
  let installSkills = ctx.options.installSkills;
87064
87245
  if (!ctx.isNonInteractive && !installSkills) {
@@ -87118,6 +87299,49 @@ async function handlePostInstall(ctx) {
87118
87299
  installSkills
87119
87300
  };
87120
87301
  }
87302
+ function normalizeLineEndings(content) {
87303
+ return content.replace(/\r\n/g, `
87304
+ `);
87305
+ }
87306
+ async function handleGlobalClaudeMd(ctx) {
87307
+ if (!ctx.extractDir || !ctx.resolvedDir)
87308
+ return;
87309
+ const claudeMdSource = join99(ctx.extractDir, "CLAUDE.md");
87310
+ const claudeMdDest = join99(ctx.resolvedDir, "CLAUDE.md");
87311
+ if (!await import_fs_extra30.pathExists(claudeMdSource))
87312
+ return;
87313
+ const destExists = await import_fs_extra30.pathExists(claudeMdDest);
87314
+ if (!destExists) {
87315
+ await import_fs_extra30.copy(claudeMdSource, claudeMdDest);
87316
+ logger.success("Copied CLAUDE.md to global directory");
87317
+ return;
87318
+ }
87319
+ if (ctx.options.fresh || ctx.options.forceOverwrite) {
87320
+ await import_fs_extra30.copy(claudeMdSource, claudeMdDest);
87321
+ logger.success("Updated CLAUDE.md in global directory");
87322
+ return;
87323
+ }
87324
+ const [srcContent, destContent] = await Promise.all([
87325
+ import_fs_extra30.readFile(claudeMdSource, "utf-8"),
87326
+ import_fs_extra30.readFile(claudeMdDest, "utf-8")
87327
+ ]);
87328
+ if (normalizeLineEndings(srcContent) === normalizeLineEndings(destContent)) {
87329
+ logger.debug("CLAUDE.md already up to date");
87330
+ return;
87331
+ }
87332
+ if (!ctx.isNonInteractive) {
87333
+ const shouldOverwrite = await ctx.prompts.confirm(`CLAUDE.md has changed in the new version. Update it?
87334
+ (Your customizations will be replaced)`);
87335
+ if (!shouldOverwrite) {
87336
+ logger.info("CLAUDE.md preserved (user chose to keep existing)");
87337
+ return;
87338
+ }
87339
+ } else {
87340
+ logger.warning("Updating CLAUDE.md (content differs from new version)");
87341
+ }
87342
+ await import_fs_extra30.copy(claudeMdSource, claudeMdDest);
87343
+ logger.success("Updated CLAUDE.md (new version detected)");
87344
+ }
87121
87345
  // src/commands/init/phases/selection-handler.ts
87122
87346
  init_config_manager();
87123
87347
  init_github_client();
@@ -87175,7 +87399,7 @@ function isTimeoutError(error) {
87175
87399
  }
87176
87400
  async function runPreflightChecks() {
87177
87401
  logger.debug("Running GitHub CLI pre-flight checks");
87178
- if (shouldSkipExpensiveOperations()) {
87402
+ if (shouldSkipExpensiveOperations2()) {
87179
87403
  logger.debug("Skipping preflight checks in test/CI environment");
87180
87404
  return createSuccessfulPreflightResult();
87181
87405
  }
@@ -87217,7 +87441,7 @@ async function runPreflightChecks() {
87217
87441
  return result;
87218
87442
  }
87219
87443
  if (result.ghVersion) {
87220
- const comparison = compareVersions5(result.ghVersion, MIN_GH_CLI_VERSION);
87444
+ const comparison = compareVersions6(result.ghVersion, MIN_GH_CLI_VERSION);
87221
87445
  result.ghVersionOk = comparison >= 0;
87222
87446
  if (!result.ghVersionOk) {
87223
87447
  logger.debug(`GitHub CLI version ${result.ghVersion} is below minimum ${MIN_GH_CLI_VERSION}`);
@@ -87779,7 +88003,7 @@ async function handleSelection(ctx) {
87779
88003
  };
87780
88004
  }
87781
88005
  // src/commands/init/phases/sync-handler.ts
87782
- import { copyFile as copyFile7, mkdir as mkdir29, open as open4, readFile as readFile47, rename as rename5, stat as stat17, unlink as unlink10, writeFile as writeFile28 } from "node:fs/promises";
88006
+ import { copyFile as copyFile7, mkdir as mkdir29, open as open4, readFile as readFile48, rename as rename5, stat as stat17, unlink as unlink10, writeFile as writeFile28 } from "node:fs/promises";
87783
88007
  import { dirname as dirname21, join as join102, resolve as resolve20 } from "node:path";
87784
88008
  init_logger();
87785
88009
  init_path_resolver();
@@ -87947,7 +88171,7 @@ async function executeSyncMerge(ctx) {
87947
88171
  try {
87948
88172
  const sourceMetadataPath = join102(upstreamDir, "metadata.json");
87949
88173
  if (await import_fs_extra33.pathExists(sourceMetadataPath)) {
87950
- const content = await readFile47(sourceMetadataPath, "utf-8");
88174
+ const content = await readFile48(sourceMetadataPath, "utf-8");
87951
88175
  const sourceMetadata = JSON.parse(content);
87952
88176
  deletions = sourceMetadata.deletions || [];
87953
88177
  }
@@ -88245,7 +88469,7 @@ async function renameFolders(dirsToRename, extractDir, options2) {
88245
88469
  // src/services/transformers/folder-transform/path-replacer.ts
88246
88470
  init_logger();
88247
88471
  init_types3();
88248
- import { readFile as readFile48, readdir as readdir32, writeFile as writeFile29 } from "node:fs/promises";
88472
+ import { readFile as readFile49, readdir as readdir32, writeFile as writeFile29 } from "node:fs/promises";
88249
88473
  import { join as join104, relative as relative18 } from "node:path";
88250
88474
  var TRANSFORMABLE_FILE_PATTERNS = [
88251
88475
  ".md",
@@ -88312,7 +88536,7 @@ async function transformFileContents(dir, compiledReplacements, options2) {
88312
88536
  if (!shouldTransform)
88313
88537
  continue;
88314
88538
  try {
88315
- const content = await readFile48(fullPath, "utf-8");
88539
+ const content = await readFile49(fullPath, "utf-8");
88316
88540
  let newContent = content;
88317
88541
  let changeCount = 0;
88318
88542
  for (const { regex: regex2, replacement } of compiledReplacements) {
@@ -88434,11 +88658,11 @@ async function transformFolderPaths(extractDir, folders, options2 = {}) {
88434
88658
 
88435
88659
  // src/services/transformers/global-path-transformer.ts
88436
88660
  init_logger();
88437
- import { readFile as readFile49, readdir as readdir33, writeFile as writeFile30 } from "node:fs/promises";
88661
+ import { readFile as readFile50, readdir as readdir33, writeFile as writeFile30 } from "node:fs/promises";
88438
88662
  import { platform as platform13 } from "node:os";
88439
88663
  import { extname as extname5, join as join105 } from "node:path";
88440
- var IS_WINDOWS4 = platform13() === "win32";
88441
- var HOME_PREFIX = IS_WINDOWS4 ? "%USERPROFILE%" : "$HOME";
88664
+ var IS_WINDOWS3 = platform13() === "win32";
88665
+ var HOME_PREFIX = IS_WINDOWS3 ? "%USERPROFILE%" : "$HOME";
88442
88666
  function getHomeDirPrefix() {
88443
88667
  return HOME_PREFIX;
88444
88668
  }
@@ -88459,7 +88683,7 @@ function transformContent(content) {
88459
88683
  let transformed = content;
88460
88684
  const homePrefix = getHomeDirPrefix();
88461
88685
  const claudePath = `${homePrefix}/.claude/`;
88462
- if (IS_WINDOWS4) {
88686
+ if (IS_WINDOWS3) {
88463
88687
  transformed = transformed.replace(/\$HOME\/\.claude\//g, () => {
88464
88688
  changes++;
88465
88689
  return claudePath;
@@ -88489,7 +88713,7 @@ function transformContent(content) {
88489
88713
  changes++;
88490
88714
  return claudePath;
88491
88715
  });
88492
- if (IS_WINDOWS4) {
88716
+ if (IS_WINDOWS3) {
88493
88717
  transformed = transformed.replace(/%CLAUDE_PROJECT_DIR%\/\.claude\//g, () => {
88494
88718
  changes++;
88495
88719
  return claudePath;
@@ -88554,7 +88778,7 @@ async function transformPathsForGlobalInstall(directory, options2 = {}) {
88554
88778
  await processDirectory2(fullPath);
88555
88779
  } else if (entry.isFile() && shouldTransformFile3(entry.name)) {
88556
88780
  try {
88557
- const content = await readFile49(fullPath, "utf-8");
88781
+ const content = await readFile50(fullPath, "utf-8");
88558
88782
  const { transformed, changes } = transformContent(content);
88559
88783
  if (changes > 0) {
88560
88784
  await writeFile30(fullPath, transformed, "utf-8");
@@ -88816,7 +89040,7 @@ init_checksum_utils();
88816
89040
  init_config_discovery();
88817
89041
  var import_picocolors25 = __toESM(require_picocolors(), 1);
88818
89042
  import { existsSync as existsSync50 } from "node:fs";
88819
- import { readFile as readFile50, rm as rm12, unlink as unlink11 } from "node:fs/promises";
89043
+ import { readFile as readFile51, rm as rm12, unlink as unlink11 } from "node:fs/promises";
88820
89044
  import { resolve as resolve21 } from "node:path";
88821
89045
 
88822
89046
  // src/commands/portable/conflict-resolver.ts
@@ -89390,7 +89614,7 @@ async function migrateCommand(options2) {
89390
89614
  for (const action of conflictActions) {
89391
89615
  if (!action.diff && action.targetPath && existsSync50(action.targetPath)) {
89392
89616
  try {
89393
- const targetContent = await readFile50(action.targetPath, "utf-8");
89617
+ const targetContent = await readFile51(action.targetPath, "utf-8");
89394
89618
  const sourceItem = agents2.find((a3) => a3.name === action.item) || commands.find((c2) => c2.name === action.item) || (configItem?.name === action.item ? configItem : null) || ruleItems.find((r2) => r2.name === action.item);
89395
89619
  if (sourceItem) {
89396
89620
  const providerConfig = providers[action.provider];
@@ -89584,7 +89808,7 @@ async function computeTargetStates(selectedProviders, global3) {
89584
89808
  continue;
89585
89809
  try {
89586
89810
  if (existsSync50(entry.path)) {
89587
- const content = await readFile50(entry.path, "utf-8");
89811
+ const content = await readFile51(entry.path, "utf-8");
89588
89812
  states.set(entry.path, {
89589
89813
  path: entry.path,
89590
89814
  exists: true,
@@ -91888,6 +92112,8 @@ class OutputManager2 {
91888
92112
  shouldShowProgress() {
91889
92113
  if (this.config.json)
91890
92114
  return false;
92115
+ if (this.config.quiet)
92116
+ return false;
91891
92117
  if (!isTTY())
91892
92118
  return false;
91893
92119
  return true;