claudekit-cli 3.34.1-dev.4 → 3.35.0-dev.1

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 +1254 -408
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -44585,10 +44585,38 @@ var init_pnpm_detector = __esm(() => {
44585
44585
  });
44586
44586
 
44587
44587
  // src/domains/installation/package-managers/detection-core.ts
44588
- import { existsSync as existsSync17 } from "node:fs";
44588
+ import { existsSync as existsSync17, realpathSync } from "node:fs";
44589
44589
  import { chmod as chmod2, mkdir as mkdir6, readFile as readFile13, writeFile as writeFile7 } from "node:fs/promises";
44590
44590
  import { platform as platform4 } from "node:os";
44591
- import { join as join23 } from "node:path";
44591
+ import { join as join23, sep } from "node:path";
44592
+ function detectFromBinaryPath() {
44593
+ try {
44594
+ const scriptPath = process.argv[1];
44595
+ if (!scriptPath)
44596
+ return "unknown";
44597
+ let resolvedPath;
44598
+ try {
44599
+ resolvedPath = realpathSync(scriptPath);
44600
+ } catch {
44601
+ resolvedPath = scriptPath;
44602
+ }
44603
+ const normalized = resolvedPath.split(sep).join("/").toLowerCase();
44604
+ logger.verbose(`Binary path resolved: ${normalized}`);
44605
+ if (normalized.includes("/.bun/install/") || normalized.includes("/bun/install/global/")) {
44606
+ return "bun";
44607
+ }
44608
+ if (normalized.includes("/pnpm/global/") || normalized.includes("/.local/share/pnpm/")) {
44609
+ return "pnpm";
44610
+ }
44611
+ if (normalized.includes("/yarn/global/") || normalized.includes("/.config/yarn/")) {
44612
+ return "yarn";
44613
+ }
44614
+ if (normalized.includes("/npm/node_modules/") || normalized.includes("/usr/local/lib/node_modules/") || normalized.includes("/usr/lib/node_modules/") || normalized.includes("/opt/homebrew/lib/node_modules/") || normalized.includes("/.nvm/versions/node/") || normalized.includes("/n/versions/node/") || normalized.includes("/appdata/roaming/npm/")) {
44615
+ return "npm";
44616
+ }
44617
+ } catch {}
44618
+ return "unknown";
44619
+ }
44592
44620
  function detectFromEnv() {
44593
44621
  const userAgent = process.env.npm_config_user_agent;
44594
44622
  if (userAgent) {
@@ -44605,13 +44633,14 @@ function detectFromEnv() {
44605
44633
  const execPath = process.env.npm_execpath;
44606
44634
  if (execPath) {
44607
44635
  logger.debug(`Detected exec path: ${execPath}`);
44608
- if (execPath.includes("bun"))
44636
+ const normalizedExec = execPath.replace(/\\/g, "/").toLowerCase();
44637
+ if (/\/bun([/.]|$)/.test(normalizedExec) || normalizedExec.startsWith("bun"))
44609
44638
  return "bun";
44610
- if (execPath.includes("yarn"))
44639
+ if (/\/yarn([/.]|$)/.test(normalizedExec) || normalizedExec.startsWith("yarn"))
44611
44640
  return "yarn";
44612
- if (execPath.includes("pnpm"))
44641
+ if (/\/pnpm([/.]|$)/.test(normalizedExec) || normalizedExec.startsWith("pnpm"))
44613
44642
  return "pnpm";
44614
- if (execPath.includes("npm"))
44643
+ if (/\/npm([/.]|$)/.test(normalizedExec) || normalizedExec.startsWith("npm"))
44615
44644
  return "npm";
44616
44645
  }
44617
44646
  return "unknown";
@@ -44629,8 +44658,8 @@ async function readCachedPm() {
44629
44658
  return null;
44630
44659
  }
44631
44660
  const age = Date.now() - data.detectedAt;
44632
- if (age > CACHE_TTL) {
44633
- logger.debug("Cache expired, will re-detect");
44661
+ if (age < 0 || age > CACHE_TTL) {
44662
+ logger.debug(age < 0 ? "Cache timestamp in future, ignoring" : "Cache expired, will re-detect");
44634
44663
  return null;
44635
44664
  }
44636
44665
  const validPms = ["npm", "bun", "yarn", "pnpm"];
@@ -44739,6 +44768,18 @@ var init_package_manager_detector = __esm(() => {
44739
44768
  PackageManagerDetector = class PackageManagerDetector {
44740
44769
  static async detect() {
44741
44770
  logger.verbose("PackageManagerDetector: Starting detection");
44771
+ const binaryPm = detectFromBinaryPath();
44772
+ if (binaryPm !== "unknown") {
44773
+ logger.verbose(`PackageManagerDetector: Detected from binary path: ${binaryPm}`);
44774
+ const cachedPm2 = await readCachedPm();
44775
+ if (cachedPm2 && cachedPm2 !== binaryPm) {
44776
+ logger.verbose(`PackageManagerDetector: Cache says ${cachedPm2}, binary says ${binaryPm} — updating cache`);
44777
+ await saveCachedPm(binaryPm, PackageManagerDetector.getVersion);
44778
+ } else if (!cachedPm2) {
44779
+ await saveCachedPm(binaryPm, PackageManagerDetector.getVersion);
44780
+ }
44781
+ return binaryPm;
44782
+ }
44742
44783
  const envPm = detectFromEnv();
44743
44784
  if (envPm !== "unknown") {
44744
44785
  logger.verbose(`PackageManagerDetector: Detected from env: ${envPm}`);
@@ -45236,7 +45277,7 @@ var package_default;
45236
45277
  var init_package = __esm(() => {
45237
45278
  package_default = {
45238
45279
  name: "claudekit-cli",
45239
- version: "3.34.1-dev.4",
45280
+ version: "3.35.0-dev.1",
45240
45281
  description: "CLI tool for bootstrapping and updating ClaudeKit projects",
45241
45282
  type: "module",
45242
45283
  repository: {
@@ -45551,12 +45592,15 @@ Run 'ck update' to install`, "Update Check");
45551
45592
  s.stop("Update failed");
45552
45593
  const errorMessage = error instanceof Error ? error.message : "Unknown error";
45553
45594
  if (errorMessage.includes("EACCES") || errorMessage.includes("EPERM") || errorMessage.includes("permission") || errorMessage.includes("Access is denied")) {
45554
- throw new CliUpdateError(`Permission denied. Try: sudo ${updateCmd}
45595
+ const permHint = pm === "npm" ? `
45555
45596
 
45556
- Or fix npm permissions: https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally`);
45597
+ Or fix npm permissions: https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally` : "";
45598
+ const isWindows3 = process.platform === "win32";
45599
+ const elevationHint = isWindows3 ? `Run your terminal as Administrator and retry: ${updateCmd}` : `sudo ${updateCmd}`;
45600
+ throw new CliUpdateError(`Permission denied. Try: ${elevationHint}${permHint}`);
45557
45601
  }
45558
45602
  logger.error(`Update failed: ${errorMessage}`);
45559
- logger.info("Try running: npm install -g claudekit-cli@latest");
45603
+ logger.info(`Try running: ${updateCmd}`);
45560
45604
  throw new CliUpdateError(`Update failed: ${errorMessage}
45561
45605
 
45562
45606
  Manual update: ${updateCmd}`);
@@ -50573,7 +50617,7 @@ __export(exports_github_api_checker, {
50573
50617
  checkRepositoryAccess: () => checkRepositoryAccess,
50574
50618
  checkRateLimit: () => checkRateLimit
50575
50619
  });
50576
- import { spawnSync } from "node:child_process";
50620
+ import { spawnSync as spawnSync2 } from "node:child_process";
50577
50621
  async function checkRateLimit() {
50578
50622
  if (false) {}
50579
50623
  const apiEndpoint = "api.github.com/rate_limit";
@@ -50668,7 +50712,7 @@ async function checkTokenScopes() {
50668
50712
  if (false) {}
50669
50713
  const checkCommand = "gh auth status -h github.com";
50670
50714
  try {
50671
- const result = spawnSync("gh", ["auth", "status", "-h", "github.com"], {
50715
+ const result = spawnSync2("gh", ["auth", "status", "-h", "github.com"], {
50672
50716
  encoding: "utf8",
50673
50717
  timeout: COMMAND_TIMEOUT_MS
50674
50718
  });
@@ -52236,7 +52280,7 @@ var require_picomatch2 = __commonJS((exports, module) => {
52236
52280
  import { exec as exec7, execFile as execFile7, spawn as spawn3 } from "node:child_process";
52237
52281
  import { promisify as promisify13 } from "node:util";
52238
52282
  function executeInteractiveScript(command, args, options2) {
52239
- return new Promise((resolve8, reject) => {
52283
+ return new Promise((resolve9, reject) => {
52240
52284
  const child = spawn3(command, args, {
52241
52285
  stdio: ["ignore", "inherit", "inherit"],
52242
52286
  cwd: options2?.cwd,
@@ -52257,7 +52301,7 @@ function executeInteractiveScript(command, args, options2) {
52257
52301
  } else if (code !== 0) {
52258
52302
  reject(new Error(`Command exited with code ${code}`));
52259
52303
  } else {
52260
- resolve8();
52304
+ resolve9();
52261
52305
  }
52262
52306
  });
52263
52307
  child.on("error", (error) => {
@@ -52278,7 +52322,7 @@ var init_process_executor = __esm(() => {
52278
52322
  });
52279
52323
 
52280
52324
  // src/services/package-installer/validators.ts
52281
- import { resolve as resolve8 } from "node:path";
52325
+ import { resolve as resolve9 } from "node:path";
52282
52326
  function validatePackageName(packageName) {
52283
52327
  if (!packageName || typeof packageName !== "string") {
52284
52328
  throw new Error("Package name must be a non-empty string");
@@ -52291,8 +52335,8 @@ function validatePackageName(packageName) {
52291
52335
  }
52292
52336
  }
52293
52337
  function validateScriptPath(skillsDir2, scriptPath) {
52294
- const skillsDirResolved = resolve8(skillsDir2);
52295
- const scriptPathResolved = resolve8(scriptPath);
52338
+ const skillsDirResolved = resolve9(skillsDir2);
52339
+ const scriptPathResolved = resolve9(scriptPath);
52296
52340
  const skillsDirNormalized = isWindows() ? skillsDirResolved.toLowerCase() : skillsDirResolved;
52297
52341
  const scriptPathNormalized = isWindows() ? scriptPathResolved.toLowerCase() : scriptPathResolved;
52298
52342
  if (!scriptPathNormalized.startsWith(skillsDirNormalized)) {
@@ -52456,7 +52500,7 @@ var init_gemini_installer = __esm(() => {
52456
52500
  });
52457
52501
 
52458
52502
  // src/services/package-installer/opencode-installer.ts
52459
- import { join as join47 } from "node:path";
52503
+ import { join as join48 } from "node:path";
52460
52504
  async function isOpenCodeInstalled() {
52461
52505
  try {
52462
52506
  await execAsync7("opencode --version", { timeout: 5000 });
@@ -52478,8 +52522,8 @@ async function installOpenCode() {
52478
52522
  try {
52479
52523
  logger.info(`Installing ${displayName}...`);
52480
52524
  const { unlink: unlink8 } = await import("node:fs/promises");
52481
- const { tmpdir: tmpdir3 } = await import("node:os");
52482
- const tempScriptPath = join47(tmpdir3(), "opencode-install.sh");
52525
+ const { tmpdir: tmpdir4 } = await import("node:os");
52526
+ const tempScriptPath = join48(tmpdir4(), "opencode-install.sh");
52483
52527
  try {
52484
52528
  logger.info("Downloading OpenCode installation script...");
52485
52529
  await execFileAsync5("curl", ["-fsSL", "https://opencode.ai/install", "-o", tempScriptPath], {
@@ -52530,8 +52574,8 @@ var init_opencode_installer = __esm(() => {
52530
52574
  var PARTIAL_INSTALL_VERSION = "partial", EXIT_CODE_CRITICAL_FAILURE = 1, EXIT_CODE_PARTIAL_SUCCESS = 2;
52531
52575
 
52532
52576
  // src/services/package-installer/install-error-handler.ts
52533
- import { existsSync as existsSync31, readFileSync as readFileSync7, unlinkSync as unlinkSync2 } from "node:fs";
52534
- import { join as join48 } from "node:path";
52577
+ import { existsSync as existsSync32, readFileSync as readFileSync8, unlinkSync as unlinkSync2 } from "node:fs";
52578
+ import { join as join49 } from "node:path";
52535
52579
  function parseNameReason(str2) {
52536
52580
  const colonIndex = str2.indexOf(":");
52537
52581
  if (colonIndex === -1) {
@@ -52540,14 +52584,14 @@ function parseNameReason(str2) {
52540
52584
  return [str2.slice(0, colonIndex).trim(), str2.slice(colonIndex + 1).trim()];
52541
52585
  }
52542
52586
  function displayInstallErrors(skillsDir2) {
52543
- const summaryPath = join48(skillsDir2, ".install-error-summary.json");
52544
- if (!existsSync31(summaryPath)) {
52587
+ const summaryPath = join49(skillsDir2, ".install-error-summary.json");
52588
+ if (!existsSync32(summaryPath)) {
52545
52589
  logger.error("Skills installation failed. Run with --verbose for details.");
52546
52590
  return;
52547
52591
  }
52548
52592
  let summary;
52549
52593
  try {
52550
- summary = JSON.parse(readFileSync7(summaryPath, "utf-8"));
52594
+ summary = JSON.parse(readFileSync8(summaryPath, "utf-8"));
52551
52595
  } catch (parseError) {
52552
52596
  logger.error("Failed to parse error summary. File may be corrupted.");
52553
52597
  logger.debug(`Parse error: ${parseError instanceof Error ? parseError.message : String(parseError)}`);
@@ -52631,8 +52675,8 @@ async function checkNeedsSudoPackages() {
52631
52675
  }
52632
52676
  }
52633
52677
  function hasInstallState(skillsDir2) {
52634
- const stateFilePath = join48(skillsDir2, ".install-state.json");
52635
- return existsSync31(stateFilePath);
52678
+ const stateFilePath = join49(skillsDir2, ".install-state.json");
52679
+ return existsSync32(stateFilePath);
52636
52680
  }
52637
52681
  var WHICH_COMMAND_TIMEOUT_MS = 5000;
52638
52682
  var init_install_error_handler = __esm(() => {
@@ -52640,7 +52684,7 @@ var init_install_error_handler = __esm(() => {
52640
52684
  });
52641
52685
 
52642
52686
  // src/services/package-installer/skills-installer.ts
52643
- import { join as join49 } from "node:path";
52687
+ import { join as join50 } from "node:path";
52644
52688
  async function installSkillsDependencies(skillsDir2, options2 = {}) {
52645
52689
  const { skipConfirm = false, withSudo = false } = options2;
52646
52690
  const displayName = "Skills Dependencies";
@@ -52662,11 +52706,11 @@ async function installSkillsDependencies(skillsDir2, options2 = {}) {
52662
52706
  };
52663
52707
  }
52664
52708
  try {
52665
- const { existsSync: existsSync32 } = await import("node:fs");
52709
+ const { existsSync: existsSync33 } = await import("node:fs");
52666
52710
  const clack = await Promise.resolve().then(() => (init_dist2(), exports_dist));
52667
52711
  const platform7 = process.platform;
52668
52712
  const scriptName = platform7 === "win32" ? "install.ps1" : "install.sh";
52669
- const scriptPath = join49(skillsDir2, scriptName);
52713
+ const scriptPath = join50(skillsDir2, scriptName);
52670
52714
  try {
52671
52715
  validateScriptPath(skillsDir2, scriptPath);
52672
52716
  } catch (error) {
@@ -52678,11 +52722,11 @@ async function installSkillsDependencies(skillsDir2, options2 = {}) {
52678
52722
  error: `Path validation failed: ${errorMessage}`
52679
52723
  };
52680
52724
  }
52681
- if (!existsSync32(scriptPath)) {
52725
+ if (!existsSync33(scriptPath)) {
52682
52726
  logger.warning(`Skills installation script not found: ${scriptPath}`);
52683
52727
  logger.info("");
52684
52728
  logger.info("\uD83D\uDCD6 Manual Installation Instructions:");
52685
- logger.info(` See: ${join49(skillsDir2, "INSTALLATION.md")}`);
52729
+ logger.info(` See: ${join50(skillsDir2, "INSTALLATION.md")}`);
52686
52730
  logger.info("");
52687
52731
  logger.info("Quick start:");
52688
52732
  logger.info(" cd .claude/skills/ai-multimodal/scripts");
@@ -52729,7 +52773,7 @@ async function installSkillsDependencies(skillsDir2, options2 = {}) {
52729
52773
  logger.info(` ${platform7 === "win32" ? `powershell -File "${scriptPath}"` : `bash ${scriptPath}`}`);
52730
52774
  logger.info("");
52731
52775
  logger.info("Or see complete guide:");
52732
- logger.info(` ${join49(skillsDir2, "INSTALLATION.md")}`);
52776
+ logger.info(` ${join50(skillsDir2, "INSTALLATION.md")}`);
52733
52777
  return {
52734
52778
  success: false,
52735
52779
  package: displayName,
@@ -52850,7 +52894,7 @@ async function installSkillsDependencies(skillsDir2, options2 = {}) {
52850
52894
  logger.info("\uD83D\uDCD6 Manual Installation Instructions:");
52851
52895
  logger.info("");
52852
52896
  logger.info("See complete guide:");
52853
- logger.info(` cat ${join49(skillsDir2, "INSTALLATION.md")}`);
52897
+ logger.info(` cat ${join50(skillsDir2, "INSTALLATION.md")}`);
52854
52898
  logger.info("");
52855
52899
  logger.info("Quick start:");
52856
52900
  logger.info(" cd .claude/skills/ai-multimodal/scripts");
@@ -52894,9 +52938,9 @@ var init_skills_installer2 = __esm(() => {
52894
52938
  });
52895
52939
 
52896
52940
  // src/services/package-installer/gemini-mcp/config-manager.ts
52897
- import { existsSync as existsSync32 } from "node:fs";
52941
+ import { existsSync as existsSync33 } from "node:fs";
52898
52942
  import { mkdir as mkdir12, readFile as readFile26, writeFile as writeFile15 } from "node:fs/promises";
52899
- import { dirname as dirname11, join as join50 } from "node:path";
52943
+ import { dirname as dirname11, join as join51 } from "node:path";
52900
52944
  async function readJsonFile(filePath) {
52901
52945
  try {
52902
52946
  const content = await readFile26(filePath, "utf-8");
@@ -52908,11 +52952,11 @@ async function readJsonFile(filePath) {
52908
52952
  }
52909
52953
  }
52910
52954
  async function addGeminiToGitignore(projectDir) {
52911
- const gitignorePath = join50(projectDir, ".gitignore");
52955
+ const gitignorePath = join51(projectDir, ".gitignore");
52912
52956
  const geminiPattern = ".gemini/";
52913
52957
  try {
52914
52958
  let content = "";
52915
- if (existsSync32(gitignorePath)) {
52959
+ if (existsSync33(gitignorePath)) {
52916
52960
  content = await readFile26(gitignorePath, "utf-8");
52917
52961
  const lines = content.split(`
52918
52962
  `).map((line) => line.trim()).filter((line) => !line.startsWith("#"));
@@ -52937,7 +52981,7 @@ ${geminiPattern}
52937
52981
  }
52938
52982
  async function createNewSettingsWithMerge(geminiSettingsPath, mcpConfigPath) {
52939
52983
  const linkDir = dirname11(geminiSettingsPath);
52940
- if (!existsSync32(linkDir)) {
52984
+ if (!existsSync33(linkDir)) {
52941
52985
  await mkdir12(linkDir, { recursive: true });
52942
52986
  logger.debug(`Created directory: ${linkDir}`);
52943
52987
  }
@@ -52998,23 +53042,23 @@ var init_config_manager2 = __esm(() => {
52998
53042
  });
52999
53043
 
53000
53044
  // src/services/package-installer/gemini-mcp/validation.ts
53001
- import { existsSync as existsSync33, lstatSync, readlinkSync } from "node:fs";
53045
+ import { existsSync as existsSync34, lstatSync, readlinkSync } from "node:fs";
53002
53046
  import { homedir as homedir17 } from "node:os";
53003
- import { join as join51 } from "node:path";
53047
+ import { join as join52 } from "node:path";
53004
53048
  function getGlobalMcpConfigPath() {
53005
- return join51(homedir17(), ".claude", ".mcp.json");
53049
+ return join52(homedir17(), ".claude", ".mcp.json");
53006
53050
  }
53007
53051
  function getLocalMcpConfigPath(projectDir) {
53008
- return join51(projectDir, ".mcp.json");
53052
+ return join52(projectDir, ".mcp.json");
53009
53053
  }
53010
53054
  function findMcpConfigPath(projectDir) {
53011
53055
  const localPath = getLocalMcpConfigPath(projectDir);
53012
- if (existsSync33(localPath)) {
53056
+ if (existsSync34(localPath)) {
53013
53057
  logger.debug(`Found local MCP config: ${localPath}`);
53014
53058
  return localPath;
53015
53059
  }
53016
53060
  const globalPath = getGlobalMcpConfigPath();
53017
- if (existsSync33(globalPath)) {
53061
+ if (existsSync34(globalPath)) {
53018
53062
  logger.debug(`Found global MCP config: ${globalPath}`);
53019
53063
  return globalPath;
53020
53064
  }
@@ -53023,13 +53067,13 @@ function findMcpConfigPath(projectDir) {
53023
53067
  }
53024
53068
  function getGeminiSettingsPath(projectDir, isGlobal) {
53025
53069
  if (isGlobal) {
53026
- return join51(homedir17(), ".gemini", "settings.json");
53070
+ return join52(homedir17(), ".gemini", "settings.json");
53027
53071
  }
53028
- return join51(projectDir, ".gemini", "settings.json");
53072
+ return join52(projectDir, ".gemini", "settings.json");
53029
53073
  }
53030
53074
  function checkExistingGeminiConfig(projectDir, isGlobal = false) {
53031
53075
  const geminiSettingsPath = getGeminiSettingsPath(projectDir, isGlobal);
53032
- if (!existsSync33(geminiSettingsPath)) {
53076
+ if (!existsSync34(geminiSettingsPath)) {
53033
53077
  return { exists: false, isSymlink: false, settingsPath: geminiSettingsPath };
53034
53078
  }
53035
53079
  try {
@@ -53053,12 +53097,12 @@ var init_validation = __esm(() => {
53053
53097
  });
53054
53098
 
53055
53099
  // src/services/package-installer/gemini-mcp/linker-core.ts
53056
- import { existsSync as existsSync34 } from "node:fs";
53100
+ import { existsSync as existsSync35 } from "node:fs";
53057
53101
  import { mkdir as mkdir13, symlink as symlink2 } from "node:fs/promises";
53058
- import { dirname as dirname12, join as join52 } from "node:path";
53102
+ import { dirname as dirname12, join as join53 } from "node:path";
53059
53103
  async function createSymlink(targetPath, linkPath, projectDir, isGlobal) {
53060
53104
  const linkDir = dirname12(linkPath);
53061
- if (!existsSync34(linkDir)) {
53105
+ if (!existsSync35(linkDir)) {
53062
53106
  await mkdir13(linkDir, { recursive: true });
53063
53107
  logger.debug(`Created directory: ${linkDir}`);
53064
53108
  }
@@ -53066,7 +53110,7 @@ async function createSymlink(targetPath, linkPath, projectDir, isGlobal) {
53066
53110
  if (isGlobal) {
53067
53111
  symlinkTarget = getGlobalMcpConfigPath();
53068
53112
  } else {
53069
- const localMcpPath = join52(projectDir, ".mcp.json");
53113
+ const localMcpPath = join53(projectDir, ".mcp.json");
53070
53114
  const isLocalConfig = targetPath === localMcpPath;
53071
53115
  symlinkTarget = isLocalConfig ? "../.mcp.json" : targetPath;
53072
53116
  }
@@ -53099,10 +53143,10 @@ __export(exports_gemini_mcp_linker, {
53099
53143
  checkExistingGeminiConfig: () => checkExistingGeminiConfig,
53100
53144
  addGeminiToGitignore: () => addGeminiToGitignore
53101
53145
  });
53102
- import { resolve as resolve9 } from "node:path";
53146
+ import { resolve as resolve10 } from "node:path";
53103
53147
  async function linkGeminiMcpConfig(projectDir, options2 = {}) {
53104
53148
  const { skipGitignore = false, isGlobal = false } = options2;
53105
- const resolvedProjectDir = resolve9(projectDir);
53149
+ const resolvedProjectDir = resolve10(projectDir);
53106
53150
  const geminiSettingsPath = getGeminiSettingsPath(resolvedProjectDir, isGlobal);
53107
53151
  const mcpConfigPath = findMcpConfigPath(resolvedProjectDir);
53108
53152
  if (!mcpConfigPath) {
@@ -53900,12 +53944,12 @@ var require_adapter = __commonJS((exports, module) => {
53900
53944
  return newFs;
53901
53945
  }
53902
53946
  function toPromise(method) {
53903
- return (...args) => new Promise((resolve10, reject) => {
53947
+ return (...args) => new Promise((resolve11, reject) => {
53904
53948
  args.push((err, result) => {
53905
53949
  if (err) {
53906
53950
  reject(err);
53907
53951
  } else {
53908
- resolve10(result);
53952
+ resolve11(result);
53909
53953
  }
53910
53954
  });
53911
53955
  method(...args);
@@ -54475,7 +54519,7 @@ var require_get_stream = __commonJS((exports, module) => {
54475
54519
  };
54476
54520
  const { maxBuffer } = options2;
54477
54521
  let stream;
54478
- await new Promise((resolve11, reject) => {
54522
+ await new Promise((resolve12, reject) => {
54479
54523
  const rejectPromise = (error) => {
54480
54524
  if (error && stream.getBufferedLength() <= BufferConstants.MAX_LENGTH) {
54481
54525
  error.bufferedData = stream.getBufferedValue();
@@ -54487,7 +54531,7 @@ var require_get_stream = __commonJS((exports, module) => {
54487
54531
  rejectPromise(error);
54488
54532
  return;
54489
54533
  }
54490
- resolve11();
54534
+ resolve12();
54491
54535
  });
54492
54536
  stream.on("data", () => {
54493
54537
  if (stream.getBufferedLength() > maxBuffer) {
@@ -55848,7 +55892,7 @@ var require_extract_zip = __commonJS((exports, module) => {
55848
55892
  debug("opening", this.zipPath, "with opts", this.opts);
55849
55893
  this.zipfile = await openZip(this.zipPath, { lazyEntries: true });
55850
55894
  this.canceled = false;
55851
- return new Promise((resolve11, reject) => {
55895
+ return new Promise((resolve12, reject) => {
55852
55896
  this.zipfile.on("error", (err) => {
55853
55897
  this.canceled = true;
55854
55898
  reject(err);
@@ -55857,7 +55901,7 @@ var require_extract_zip = __commonJS((exports, module) => {
55857
55901
  this.zipfile.on("close", () => {
55858
55902
  if (!this.canceled) {
55859
55903
  debug("zip extraction complete");
55860
- resolve11();
55904
+ resolve12();
55861
55905
  }
55862
55906
  });
55863
55907
  this.zipfile.on("entry", async (entry) => {
@@ -58565,7 +58609,7 @@ function getPagerArgs(pagerCmd) {
58565
58609
  return [];
58566
58610
  }
58567
58611
  async function trySystemPager(content) {
58568
- return new Promise((resolve20) => {
58612
+ return new Promise((resolve21) => {
58569
58613
  const pagerCmd = process.env.PAGER || "less";
58570
58614
  const pagerArgs = getPagerArgs(pagerCmd);
58571
58615
  try {
@@ -58575,20 +58619,20 @@ async function trySystemPager(content) {
58575
58619
  });
58576
58620
  const timeout2 = setTimeout(() => {
58577
58621
  pager.kill();
58578
- resolve20(false);
58622
+ resolve21(false);
58579
58623
  }, 30000);
58580
58624
  pager.stdin.write(content);
58581
58625
  pager.stdin.end();
58582
58626
  pager.on("close", (code2) => {
58583
58627
  clearTimeout(timeout2);
58584
- resolve20(code2 === 0);
58628
+ resolve21(code2 === 0);
58585
58629
  });
58586
58630
  pager.on("error", () => {
58587
58631
  clearTimeout(timeout2);
58588
- resolve20(false);
58632
+ resolve21(false);
58589
58633
  });
58590
58634
  } catch {
58591
- resolve20(false);
58635
+ resolve21(false);
58592
58636
  }
58593
58637
  });
58594
58638
  }
@@ -58615,16 +58659,16 @@ async function basicPager(content) {
58615
58659
  break;
58616
58660
  }
58617
58661
  const remaining = lines.length - currentLine;
58618
- await new Promise((resolve20) => {
58662
+ await new Promise((resolve21) => {
58619
58663
  rl.question(`-- More (${remaining} lines) [Enter/q] --`, (answer) => {
58620
58664
  if (answer.toLowerCase() === "q") {
58621
58665
  rl.close();
58622
58666
  process.exitCode = 0;
58623
- resolve20();
58667
+ resolve21();
58624
58668
  return;
58625
58669
  }
58626
58670
  process.stdout.write("\x1B[1A\x1B[2K");
58627
- resolve20();
58671
+ resolve21();
58628
58672
  });
58629
58673
  });
58630
58674
  }
@@ -61572,6 +61616,794 @@ async function checkEnvKeys(setup) {
61572
61616
  }
61573
61617
  return results;
61574
61618
  }
61619
+ // src/domains/health-checks/checkers/hook-health-checker.ts
61620
+ init_logger();
61621
+ init_path_resolver();
61622
+ import { spawnSync } from "node:child_process";
61623
+ import { existsSync as existsSync30, readFileSync as readFileSync6, statSync as statSync5, writeFileSync } from "node:fs";
61624
+ import { readdir as readdir9 } from "node:fs/promises";
61625
+ import { tmpdir } from "node:os";
61626
+ import { join as join41, resolve as resolve8 } from "node:path";
61627
+ var HOOK_CHECK_TIMEOUT_MS = 5000;
61628
+ var PYTHON_CHECK_TIMEOUT_MS = 3000;
61629
+ var MAX_LOG_FILE_SIZE_BYTES = 10 * 1024 * 1024;
61630
+ function getHooksDir(projectDir) {
61631
+ const projectHooksDir = resolve8(projectDir, ".claude", "hooks");
61632
+ const globalHooksDir = resolve8(PathResolver.getGlobalKitDir(), "hooks");
61633
+ if (existsSync30(projectHooksDir))
61634
+ return projectHooksDir;
61635
+ if (existsSync30(globalHooksDir))
61636
+ return globalHooksDir;
61637
+ return null;
61638
+ }
61639
+ function isPathWithin(filePath, parentDir) {
61640
+ return resolve8(filePath).startsWith(resolve8(parentDir));
61641
+ }
61642
+ async function checkHookSyntax(projectDir) {
61643
+ const hooksDir = getHooksDir(projectDir);
61644
+ if (!hooksDir) {
61645
+ return {
61646
+ id: "hook-syntax",
61647
+ name: "Hook Syntax",
61648
+ group: "claudekit",
61649
+ priority: "critical",
61650
+ status: "info",
61651
+ message: "No hooks directory",
61652
+ autoFixable: false
61653
+ };
61654
+ }
61655
+ try {
61656
+ const files = await readdir9(hooksDir);
61657
+ const cjsFiles = files.filter((f3) => f3.endsWith(".cjs"));
61658
+ if (cjsFiles.length === 0) {
61659
+ return {
61660
+ id: "hook-syntax",
61661
+ name: "Hook Syntax",
61662
+ group: "claudekit",
61663
+ priority: "critical",
61664
+ status: "info",
61665
+ message: "No .cjs hooks found",
61666
+ autoFixable: false
61667
+ };
61668
+ }
61669
+ const errors2 = [];
61670
+ for (const file of cjsFiles) {
61671
+ const filePath = join41(hooksDir, file);
61672
+ if (!isPathWithin(filePath, hooksDir))
61673
+ continue;
61674
+ const result = spawnSync("node", ["--check", filePath], {
61675
+ timeout: HOOK_CHECK_TIMEOUT_MS,
61676
+ encoding: "utf-8"
61677
+ });
61678
+ if (result.status !== 0) {
61679
+ errors2.push(`${file}: ${result.stderr?.trim() || "syntax error"}`);
61680
+ }
61681
+ }
61682
+ if (errors2.length > 0) {
61683
+ return {
61684
+ id: "hook-syntax",
61685
+ name: "Hook Syntax",
61686
+ group: "claudekit",
61687
+ priority: "critical",
61688
+ status: "fail",
61689
+ message: `${errors2.length} hook(s) with syntax errors`,
61690
+ details: errors2.join(`
61691
+ `),
61692
+ suggestion: "Run: ck init",
61693
+ autoFixable: true,
61694
+ fix: {
61695
+ id: "fix-hook-syntax",
61696
+ description: "Reinstall hooks via ck init",
61697
+ execute: async () => ({
61698
+ success: false,
61699
+ message: "Manual fix required: run 'ck init'"
61700
+ })
61701
+ }
61702
+ };
61703
+ }
61704
+ return {
61705
+ id: "hook-syntax",
61706
+ name: "Hook Syntax",
61707
+ group: "claudekit",
61708
+ priority: "critical",
61709
+ status: "pass",
61710
+ message: `${cjsFiles.length} hook(s) valid`,
61711
+ autoFixable: false
61712
+ };
61713
+ } catch (error) {
61714
+ logger.debug(`Hook syntax check failed: ${error}`);
61715
+ return {
61716
+ id: "hook-syntax",
61717
+ name: "Hook Syntax",
61718
+ group: "claudekit",
61719
+ priority: "critical",
61720
+ status: "fail",
61721
+ message: "Failed to check hook syntax",
61722
+ details: error instanceof Error ? error.message : String(error),
61723
+ autoFixable: false
61724
+ };
61725
+ }
61726
+ }
61727
+ async function checkHookDeps(projectDir) {
61728
+ const hooksDir = getHooksDir(projectDir);
61729
+ if (!hooksDir) {
61730
+ return {
61731
+ id: "hook-deps",
61732
+ name: "Hook Dependencies",
61733
+ group: "claudekit",
61734
+ priority: "critical",
61735
+ status: "info",
61736
+ message: "No hooks directory",
61737
+ autoFixable: false
61738
+ };
61739
+ }
61740
+ try {
61741
+ const files = await readdir9(hooksDir);
61742
+ const cjsFiles = files.filter((f3) => f3.endsWith(".cjs"));
61743
+ if (cjsFiles.length === 0) {
61744
+ return {
61745
+ id: "hook-deps",
61746
+ name: "Hook Dependencies",
61747
+ group: "claudekit",
61748
+ priority: "critical",
61749
+ status: "info",
61750
+ message: "No .cjs hooks found",
61751
+ autoFixable: false
61752
+ };
61753
+ }
61754
+ const missingDeps = [];
61755
+ const requireRegex = /require\(['"]([^'"]+)['"]\)/g;
61756
+ for (const file of cjsFiles) {
61757
+ const filePath = join41(hooksDir, file);
61758
+ if (!isPathWithin(filePath, hooksDir))
61759
+ continue;
61760
+ const content = readFileSync6(filePath, "utf-8");
61761
+ for (let match = requireRegex.exec(content);match !== null; match = requireRegex.exec(content)) {
61762
+ const depPath = match[1];
61763
+ if (depPath.startsWith("node:") || isNodeBuiltin(depPath)) {
61764
+ continue;
61765
+ }
61766
+ if (depPath.startsWith(".")) {
61767
+ const resolvedPath = join41(hooksDir, depPath);
61768
+ const extensions = [".js", ".cjs", ".mjs", ".json"];
61769
+ const indexFiles = ["index.js", "index.cjs", "index.mjs"];
61770
+ const exists = existsSync30(resolvedPath) || extensions.some((ext) => existsSync30(resolvedPath + ext)) || indexFiles.some((idx) => existsSync30(join41(resolvedPath, idx)));
61771
+ if (!exists) {
61772
+ missingDeps.push(`${file}: ${depPath}`);
61773
+ }
61774
+ }
61775
+ }
61776
+ }
61777
+ if (missingDeps.length > 0) {
61778
+ return {
61779
+ id: "hook-deps",
61780
+ name: "Hook Dependencies",
61781
+ group: "claudekit",
61782
+ priority: "critical",
61783
+ status: "fail",
61784
+ message: `${missingDeps.length} missing dependency(ies)`,
61785
+ details: missingDeps.join(`
61786
+ `),
61787
+ suggestion: "Run: ck init",
61788
+ autoFixable: true,
61789
+ fix: {
61790
+ id: "fix-hook-deps",
61791
+ description: "Reinstall hooks via ck init",
61792
+ execute: async () => ({
61793
+ success: false,
61794
+ message: "Manual fix required: run 'ck init'"
61795
+ })
61796
+ }
61797
+ };
61798
+ }
61799
+ return {
61800
+ id: "hook-deps",
61801
+ name: "Hook Dependencies",
61802
+ group: "claudekit",
61803
+ priority: "critical",
61804
+ status: "pass",
61805
+ message: "All dependencies resolved",
61806
+ autoFixable: false
61807
+ };
61808
+ } catch (error) {
61809
+ logger.debug(`Hook deps check failed: ${error}`);
61810
+ return {
61811
+ id: "hook-deps",
61812
+ name: "Hook Dependencies",
61813
+ group: "claudekit",
61814
+ priority: "critical",
61815
+ status: "fail",
61816
+ message: "Failed to check dependencies",
61817
+ details: error instanceof Error ? error.message : String(error),
61818
+ autoFixable: false
61819
+ };
61820
+ }
61821
+ }
61822
+ function isNodeBuiltin(mod) {
61823
+ try {
61824
+ const { builtinModules } = __require("node:module");
61825
+ return builtinModules.includes(mod);
61826
+ } catch {
61827
+ const builtins = [
61828
+ "fs",
61829
+ "path",
61830
+ "os",
61831
+ "child_process",
61832
+ "util",
61833
+ "stream",
61834
+ "events",
61835
+ "crypto",
61836
+ "http",
61837
+ "https",
61838
+ "net",
61839
+ "dns",
61840
+ "url",
61841
+ "querystring",
61842
+ "readline",
61843
+ "process",
61844
+ "buffer",
61845
+ "console",
61846
+ "timers",
61847
+ "assert",
61848
+ "zlib",
61849
+ "worker_threads",
61850
+ "perf_hooks",
61851
+ "v8",
61852
+ "vm",
61853
+ "tls"
61854
+ ];
61855
+ return builtins.includes(mod);
61856
+ }
61857
+ }
61858
+ async function checkHookRuntime(projectDir) {
61859
+ const hooksDir = getHooksDir(projectDir);
61860
+ if (!hooksDir) {
61861
+ return {
61862
+ id: "hook-runtime",
61863
+ name: "Hook Runtime",
61864
+ group: "claudekit",
61865
+ priority: "standard",
61866
+ status: "info",
61867
+ message: "No hooks directory",
61868
+ autoFixable: false
61869
+ };
61870
+ }
61871
+ try {
61872
+ const files = await readdir9(hooksDir);
61873
+ const cjsFiles = files.filter((f3) => f3.endsWith(".cjs"));
61874
+ if (cjsFiles.length === 0) {
61875
+ return {
61876
+ id: "hook-runtime",
61877
+ name: "Hook Runtime",
61878
+ group: "claudekit",
61879
+ priority: "standard",
61880
+ status: "info",
61881
+ message: "No .cjs hooks found",
61882
+ autoFixable: false
61883
+ };
61884
+ }
61885
+ const syntheticPayload = JSON.stringify({
61886
+ tool_name: "Read",
61887
+ tool_input: { file_path: join41(tmpdir(), "ck-doctor-test.txt") }
61888
+ });
61889
+ const failures = [];
61890
+ for (const file of cjsFiles) {
61891
+ const filePath = join41(hooksDir, file);
61892
+ if (!isPathWithin(filePath, hooksDir))
61893
+ continue;
61894
+ const result = spawnSync("node", [filePath], {
61895
+ input: syntheticPayload,
61896
+ timeout: HOOK_CHECK_TIMEOUT_MS,
61897
+ encoding: "utf-8"
61898
+ });
61899
+ if (result.status !== null && result.status !== 0 && result.status !== 2) {
61900
+ const error = result.error?.message || result.stderr?.trim() || `exit code ${result.status}`;
61901
+ failures.push(`${file}: ${error}`);
61902
+ } else if (result.status === null && result.error) {
61903
+ const error = result.error.message || "failed to execute";
61904
+ failures.push(`${file}: ${error}`);
61905
+ }
61906
+ }
61907
+ if (failures.length > 0) {
61908
+ return {
61909
+ id: "hook-runtime",
61910
+ name: "Hook Runtime",
61911
+ group: "claudekit",
61912
+ priority: "standard",
61913
+ status: "fail",
61914
+ message: `${failures.length} hook(s) failed dry-run`,
61915
+ details: failures.join(`
61916
+ `),
61917
+ suggestion: "Run: ck init",
61918
+ autoFixable: true,
61919
+ fix: {
61920
+ id: "fix-hook-runtime",
61921
+ description: "Reinstall hooks via ck init",
61922
+ execute: async () => ({
61923
+ success: false,
61924
+ message: "Manual fix required: run 'ck init'"
61925
+ })
61926
+ }
61927
+ };
61928
+ }
61929
+ return {
61930
+ id: "hook-runtime",
61931
+ name: "Hook Runtime",
61932
+ group: "claudekit",
61933
+ priority: "standard",
61934
+ status: "pass",
61935
+ message: `${cjsFiles.length} hook(s) passed dry-run`,
61936
+ autoFixable: false
61937
+ };
61938
+ } catch (error) {
61939
+ logger.debug(`Hook runtime check failed: ${error}`);
61940
+ return {
61941
+ id: "hook-runtime",
61942
+ name: "Hook Runtime",
61943
+ group: "claudekit",
61944
+ priority: "standard",
61945
+ status: "fail",
61946
+ message: "Failed to check hook runtime",
61947
+ details: error instanceof Error ? error.message : String(error),
61948
+ autoFixable: false
61949
+ };
61950
+ }
61951
+ }
61952
+ async function checkHookConfig(projectDir) {
61953
+ const projectConfigPath = join41(projectDir, ".claude", ".ck.json");
61954
+ const globalConfigPath = join41(PathResolver.getGlobalKitDir(), ".ck.json");
61955
+ const configPath = existsSync30(projectConfigPath) ? projectConfigPath : existsSync30(globalConfigPath) ? globalConfigPath : null;
61956
+ if (!configPath) {
61957
+ return {
61958
+ id: "hook-config",
61959
+ name: "Hook Config",
61960
+ group: "claudekit",
61961
+ priority: "standard",
61962
+ status: "info",
61963
+ message: "No .ck.json config",
61964
+ autoFixable: false
61965
+ };
61966
+ }
61967
+ const hooksDir = getHooksDir(projectDir);
61968
+ if (!hooksDir) {
61969
+ return {
61970
+ id: "hook-config",
61971
+ name: "Hook Config",
61972
+ group: "claudekit",
61973
+ priority: "standard",
61974
+ status: "info",
61975
+ message: "No hooks directory",
61976
+ autoFixable: false
61977
+ };
61978
+ }
61979
+ try {
61980
+ const configContent = readFileSync6(configPath, "utf-8");
61981
+ const config = JSON.parse(configContent);
61982
+ if (!config.hooks || typeof config.hooks !== "object") {
61983
+ return {
61984
+ id: "hook-config",
61985
+ name: "Hook Config",
61986
+ group: "claudekit",
61987
+ priority: "standard",
61988
+ status: "pass",
61989
+ message: "No hooks configured",
61990
+ autoFixable: false
61991
+ };
61992
+ }
61993
+ const files = await readdir9(hooksDir);
61994
+ const hookBaseNames = new Set(files.filter((f3) => HOOK_EXTENSIONS.some((ext) => f3.endsWith(ext))).map((f3) => {
61995
+ for (const ext of HOOK_EXTENSIONS) {
61996
+ if (f3.endsWith(ext))
61997
+ return f3.slice(0, -ext.length);
61998
+ }
61999
+ return f3;
62000
+ }));
62001
+ const orphanedEntries = [];
62002
+ for (const hookName of Object.keys(config.hooks)) {
62003
+ if (!hookBaseNames.has(hookName)) {
62004
+ orphanedEntries.push(hookName);
62005
+ }
62006
+ }
62007
+ if (orphanedEntries.length > 0) {
62008
+ return {
62009
+ id: "hook-config",
62010
+ name: "Hook Config",
62011
+ group: "claudekit",
62012
+ priority: "standard",
62013
+ status: "warn",
62014
+ message: `${orphanedEntries.length} orphaned config entry(ies)`,
62015
+ details: orphanedEntries.join(", "),
62016
+ suggestion: "Remove orphaned entries from .ck.json",
62017
+ autoFixable: true,
62018
+ fix: {
62019
+ id: "fix-hook-config",
62020
+ description: "Remove orphaned entries from .ck.json",
62021
+ execute: async () => {
62022
+ try {
62023
+ for (const entry of orphanedEntries) {
62024
+ delete config.hooks[entry];
62025
+ }
62026
+ const updatedConfig = JSON.stringify(config, null, 2);
62027
+ writeFileSync(configPath, updatedConfig, "utf-8");
62028
+ return {
62029
+ success: true,
62030
+ message: `Removed ${orphanedEntries.length} orphaned entry(ies)`
62031
+ };
62032
+ } catch (err) {
62033
+ return {
62034
+ success: false,
62035
+ message: `Failed to update .ck.json: ${err}`
62036
+ };
62037
+ }
62038
+ }
62039
+ }
62040
+ };
62041
+ }
62042
+ return {
62043
+ id: "hook-config",
62044
+ name: "Hook Config",
62045
+ group: "claudekit",
62046
+ priority: "standard",
62047
+ status: "pass",
62048
+ message: "All config entries valid",
62049
+ autoFixable: false
62050
+ };
62051
+ } catch (error) {
62052
+ logger.debug(`Hook config check failed: ${error}`);
62053
+ return {
62054
+ id: "hook-config",
62055
+ name: "Hook Config",
62056
+ group: "claudekit",
62057
+ priority: "standard",
62058
+ status: "fail",
62059
+ message: "Failed to validate config",
62060
+ details: error instanceof Error ? error.message : String(error),
62061
+ autoFixable: false
62062
+ };
62063
+ }
62064
+ }
62065
+ async function checkHookLogs(projectDir) {
62066
+ const hooksDir = getHooksDir(projectDir);
62067
+ if (!hooksDir) {
62068
+ return {
62069
+ id: "hook-logs",
62070
+ name: "Hook Crash Logs",
62071
+ group: "claudekit",
62072
+ priority: "standard",
62073
+ status: "info",
62074
+ message: "No hooks directory",
62075
+ autoFixable: false
62076
+ };
62077
+ }
62078
+ const logPath = join41(hooksDir, ".logs", "hook-log.jsonl");
62079
+ if (!existsSync30(logPath)) {
62080
+ return {
62081
+ id: "hook-logs",
62082
+ name: "Hook Crash Logs",
62083
+ group: "claudekit",
62084
+ priority: "standard",
62085
+ status: "pass",
62086
+ message: "No crash logs",
62087
+ autoFixable: false
62088
+ };
62089
+ }
62090
+ try {
62091
+ const logStats = statSync5(logPath);
62092
+ if (logStats.size > MAX_LOG_FILE_SIZE_BYTES) {
62093
+ return {
62094
+ id: "hook-logs",
62095
+ name: "Hook Crash Logs",
62096
+ group: "claudekit",
62097
+ priority: "standard",
62098
+ status: "warn",
62099
+ message: `Log file too large (${Math.round(logStats.size / 1024 / 1024)}MB)`,
62100
+ suggestion: "Delete .claude/hooks/.logs/hook-log.jsonl and run: ck init",
62101
+ autoFixable: true,
62102
+ fix: {
62103
+ id: "fix-hook-logs",
62104
+ description: "Clear oversized log file",
62105
+ execute: async () => {
62106
+ try {
62107
+ writeFileSync(logPath, "", "utf-8");
62108
+ return { success: true, message: "Cleared oversized log file" };
62109
+ } catch (err) {
62110
+ return { success: false, message: `Failed to clear log: ${err}` };
62111
+ }
62112
+ }
62113
+ }
62114
+ };
62115
+ }
62116
+ const logContent = readFileSync6(logPath, "utf-8");
62117
+ const lines = logContent.trim().split(`
62118
+ `).filter(Boolean);
62119
+ const now = Date.now();
62120
+ const oneDayAgo = now - 24 * 60 * 60 * 1000;
62121
+ const crashes = [];
62122
+ for (const line of lines) {
62123
+ try {
62124
+ const entry = JSON.parse(line);
62125
+ const timestamp = new Date(entry.ts || entry.timestamp).getTime();
62126
+ if (timestamp >= oneDayAgo && entry.status === "crash") {
62127
+ crashes.push({
62128
+ hook: entry.hook || "unknown",
62129
+ error: entry.error || "unknown error"
62130
+ });
62131
+ }
62132
+ } catch {}
62133
+ }
62134
+ if (crashes.length === 0) {
62135
+ return {
62136
+ id: "hook-logs",
62137
+ name: "Hook Crash Logs",
62138
+ group: "claudekit",
62139
+ priority: "standard",
62140
+ status: "pass",
62141
+ message: "No crashes in last 24h",
62142
+ autoFixable: false
62143
+ };
62144
+ }
62145
+ if (crashes.length <= 5) {
62146
+ const hookList = crashes.map((c2) => `${c2.hook}: ${c2.error}`).join(`
62147
+ `);
62148
+ return {
62149
+ id: "hook-logs",
62150
+ name: "Hook Crash Logs",
62151
+ group: "claudekit",
62152
+ priority: "standard",
62153
+ status: "warn",
62154
+ message: `${crashes.length} crash(es) in last 24h`,
62155
+ details: hookList,
62156
+ suggestion: "Run: ck init",
62157
+ autoFixable: true,
62158
+ fix: {
62159
+ id: "fix-hook-logs",
62160
+ description: "Clear log file",
62161
+ execute: async () => {
62162
+ try {
62163
+ writeFileSync(logPath, "", "utf-8");
62164
+ return {
62165
+ success: true,
62166
+ message: "Cleared crash log file"
62167
+ };
62168
+ } catch (err) {
62169
+ return {
62170
+ success: false,
62171
+ message: `Failed to clear log: ${err}`
62172
+ };
62173
+ }
62174
+ }
62175
+ }
62176
+ };
62177
+ }
62178
+ const hookCounts = crashes.reduce((acc, c2) => {
62179
+ acc[c2.hook] = (acc[c2.hook] || 0) + 1;
62180
+ return acc;
62181
+ }, {});
62182
+ const topCrashers = Object.entries(hookCounts).sort((a3, b3) => b3[1] - a3[1]).slice(0, 5).map(([hook, count]) => `${hook} (${count}x)`).join(", ");
62183
+ return {
62184
+ id: "hook-logs",
62185
+ name: "Hook Crash Logs",
62186
+ group: "claudekit",
62187
+ priority: "standard",
62188
+ status: "fail",
62189
+ message: `${crashes.length} crashes in last 24h`,
62190
+ details: `Most frequent: ${topCrashers}`,
62191
+ suggestion: "Run: ck init",
62192
+ autoFixable: true,
62193
+ fix: {
62194
+ id: "fix-hook-logs",
62195
+ description: "Clear log file and suggest reinstall",
62196
+ execute: async () => {
62197
+ try {
62198
+ writeFileSync(logPath, "", "utf-8");
62199
+ return {
62200
+ success: true,
62201
+ message: "Cleared crash log. Run 'ck init' to reinstall hooks."
62202
+ };
62203
+ } catch (err) {
62204
+ return {
62205
+ success: false,
62206
+ message: `Failed to clear log: ${err}`
62207
+ };
62208
+ }
62209
+ }
62210
+ }
62211
+ };
62212
+ } catch (error) {
62213
+ logger.debug(`Hook logs check failed: ${error}`);
62214
+ return {
62215
+ id: "hook-logs",
62216
+ name: "Hook Crash Logs",
62217
+ group: "claudekit",
62218
+ priority: "standard",
62219
+ status: "fail",
62220
+ message: "Failed to check crash logs",
62221
+ details: error instanceof Error ? error.message : String(error),
62222
+ autoFixable: false
62223
+ };
62224
+ }
62225
+ }
62226
+ async function checkCliVersion() {
62227
+ try {
62228
+ const versionResult = spawnSync("ck", ["-V"], {
62229
+ timeout: HOOK_CHECK_TIMEOUT_MS,
62230
+ encoding: "utf-8"
62231
+ });
62232
+ let installedVersion = "unknown";
62233
+ if (versionResult.status === 0 && versionResult.stdout) {
62234
+ installedVersion = versionResult.stdout.trim();
62235
+ }
62236
+ if (installedVersion === "unknown") {
62237
+ return {
62238
+ id: "cli-version",
62239
+ name: "CLI Version",
62240
+ group: "claudekit",
62241
+ priority: "critical",
62242
+ status: "warn",
62243
+ message: "Cannot determine installed version",
62244
+ autoFixable: false
62245
+ };
62246
+ }
62247
+ const npmResult = spawnSync("npm", ["view", "claudekit-cli", "version"], {
62248
+ timeout: HOOK_CHECK_TIMEOUT_MS,
62249
+ encoding: "utf-8"
62250
+ });
62251
+ if (npmResult.status !== 0) {
62252
+ return {
62253
+ id: "cli-version",
62254
+ name: "CLI Version",
62255
+ group: "claudekit",
62256
+ priority: "critical",
62257
+ status: "warn",
62258
+ message: `v${installedVersion} (unable to check for updates)`,
62259
+ autoFixable: false
62260
+ };
62261
+ }
62262
+ const latestVersion = npmResult.stdout?.trim() || installedVersion;
62263
+ const parseVersion = (v2) => v2.replace(/-.*$/, "").split(".").map(Number);
62264
+ const [installedMajor, installedMinor] = parseVersion(installedVersion);
62265
+ const [latestMajor, latestMinor] = parseVersion(latestVersion);
62266
+ if (installedMajor < latestMajor) {
62267
+ return {
62268
+ id: "cli-version",
62269
+ name: "CLI Version",
62270
+ group: "claudekit",
62271
+ priority: "critical",
62272
+ status: "fail",
62273
+ message: `v${installedVersion} (latest: v${latestVersion})`,
62274
+ details: "Major version behind",
62275
+ suggestion: "Run: ck update",
62276
+ autoFixable: true,
62277
+ fix: {
62278
+ id: "fix-cli-version",
62279
+ description: "Update CLI to latest version",
62280
+ execute: async () => ({
62281
+ success: false,
62282
+ message: "Manual fix required: run 'ck update'"
62283
+ })
62284
+ }
62285
+ };
62286
+ }
62287
+ if (installedMajor === latestMajor && installedMinor < latestMinor) {
62288
+ return {
62289
+ id: "cli-version",
62290
+ name: "CLI Version",
62291
+ group: "claudekit",
62292
+ priority: "critical",
62293
+ status: "warn",
62294
+ message: `v${installedVersion} (latest: v${latestVersion})`,
62295
+ details: "Minor version behind",
62296
+ suggestion: "Run: ck update",
62297
+ autoFixable: true,
62298
+ fix: {
62299
+ id: "fix-cli-version",
62300
+ description: "Update CLI to latest version",
62301
+ execute: async () => ({
62302
+ success: false,
62303
+ message: "Manual fix required: run 'ck update'"
62304
+ })
62305
+ }
62306
+ };
62307
+ }
62308
+ return {
62309
+ id: "cli-version",
62310
+ name: "CLI Version",
62311
+ group: "claudekit",
62312
+ priority: "critical",
62313
+ status: "pass",
62314
+ message: `v${installedVersion} (up to date)`,
62315
+ autoFixable: false
62316
+ };
62317
+ } catch (error) {
62318
+ logger.debug(`CLI version check failed: ${error}`);
62319
+ return {
62320
+ id: "cli-version",
62321
+ name: "CLI Version",
62322
+ group: "claudekit",
62323
+ priority: "critical",
62324
+ status: "warn",
62325
+ message: "Failed to check version",
62326
+ details: error instanceof Error ? error.message : String(error),
62327
+ autoFixable: false
62328
+ };
62329
+ }
62330
+ }
62331
+ async function checkPythonVenv(projectDir) {
62332
+ const isWindows3 = process.platform === "win32";
62333
+ const venvBin = isWindows3 ? join41("Scripts", "python.exe") : join41("bin", "python3");
62334
+ const projectVenvPath = join41(projectDir, ".claude", "skills", ".venv", venvBin);
62335
+ const globalVenvPath = join41(PathResolver.getGlobalKitDir(), "skills", ".venv", venvBin);
62336
+ const venvPath = existsSync30(projectVenvPath) ? projectVenvPath : existsSync30(globalVenvPath) ? globalVenvPath : null;
62337
+ if (!venvPath) {
62338
+ return {
62339
+ id: "python-venv",
62340
+ name: "Python Venv",
62341
+ group: "claudekit",
62342
+ priority: "standard",
62343
+ status: "warn",
62344
+ message: "Virtual environment not found",
62345
+ suggestion: "Delete .venv and run install.sh",
62346
+ autoFixable: true,
62347
+ fix: {
62348
+ id: "fix-python-venv",
62349
+ description: "Delete .venv and suggest reinstall",
62350
+ execute: async () => ({
62351
+ success: false,
62352
+ message: "Manual fix required: delete .venv and run install.sh"
62353
+ })
62354
+ }
62355
+ };
62356
+ }
62357
+ try {
62358
+ const result = spawnSync(venvPath, ["--version"], {
62359
+ timeout: PYTHON_CHECK_TIMEOUT_MS,
62360
+ encoding: "utf-8"
62361
+ });
62362
+ if (result.status !== 0) {
62363
+ return {
62364
+ id: "python-venv",
62365
+ name: "Python Venv",
62366
+ group: "claudekit",
62367
+ priority: "standard",
62368
+ status: "fail",
62369
+ message: "Python venv exists but broken",
62370
+ details: result.stderr?.trim() || "Failed to run python3 --version",
62371
+ suggestion: "Delete .venv and run install.sh",
62372
+ autoFixable: true,
62373
+ fix: {
62374
+ id: "fix-python-venv",
62375
+ description: "Delete .venv",
62376
+ execute: async () => ({
62377
+ success: false,
62378
+ message: "Manual fix required: delete .venv and run install.sh"
62379
+ })
62380
+ }
62381
+ };
62382
+ }
62383
+ const version = result.stdout?.trim() || "unknown";
62384
+ return {
62385
+ id: "python-venv",
62386
+ name: "Python Venv",
62387
+ group: "claudekit",
62388
+ priority: "standard",
62389
+ status: "pass",
62390
+ message: version,
62391
+ autoFixable: false
62392
+ };
62393
+ } catch (error) {
62394
+ logger.debug(`Python venv check failed: ${error}`);
62395
+ return {
62396
+ id: "python-venv",
62397
+ name: "Python Venv",
62398
+ group: "claudekit",
62399
+ priority: "standard",
62400
+ status: "fail",
62401
+ message: "Failed to check venv",
62402
+ details: error instanceof Error ? error.message : String(error),
62403
+ autoFixable: false
62404
+ };
62405
+ }
62406
+ }
61575
62407
  // src/domains/health-checks/claudekit-checker.ts
61576
62408
  class ClaudekitChecker {
61577
62409
  group = "claudekit";
@@ -61586,6 +62418,8 @@ class ClaudekitChecker {
61586
62418
  const setup = await getClaudeKitSetup(this.projectDir);
61587
62419
  logger.verbose("ClaudekitChecker: Setup scan complete");
61588
62420
  const results = [];
62421
+ logger.verbose("ClaudekitChecker: Checking CLI version");
62422
+ results.push(await checkCliVersion());
61589
62423
  logger.verbose("ClaudekitChecker: Checking CLI install method");
61590
62424
  results.push(await checkCliInstallMethod());
61591
62425
  logger.verbose("ClaudekitChecker: Checking global install");
@@ -61608,6 +62442,18 @@ class ClaudekitChecker {
61608
62442
  results.push(await checkGlobalDirWritable());
61609
62443
  logger.verbose("ClaudekitChecker: Checking hooks directory");
61610
62444
  results.push(await checkHooksExist(this.projectDir));
62445
+ logger.verbose("ClaudekitChecker: Checking hook syntax");
62446
+ results.push(await checkHookSyntax(this.projectDir));
62447
+ logger.verbose("ClaudekitChecker: Checking hook dependencies");
62448
+ results.push(await checkHookDeps(this.projectDir));
62449
+ logger.verbose("ClaudekitChecker: Checking hook runtime");
62450
+ results.push(await checkHookRuntime(this.projectDir));
62451
+ logger.verbose("ClaudekitChecker: Checking hook config");
62452
+ results.push(await checkHookConfig(this.projectDir));
62453
+ logger.verbose("ClaudekitChecker: Checking hook crash logs");
62454
+ results.push(await checkHookLogs(this.projectDir));
62455
+ logger.verbose("ClaudekitChecker: Checking Python venv");
62456
+ results.push(await checkPythonVenv(this.projectDir));
61611
62457
  logger.verbose("ClaudekitChecker: Checking settings.json validity");
61612
62458
  results.push(await checkSettingsValid(this.projectDir));
61613
62459
  logger.verbose("ClaudekitChecker: Checking path references");
@@ -61620,7 +62466,7 @@ class ClaudekitChecker {
61620
62466
  }
61621
62467
  // src/domains/health-checks/auth-checker.ts
61622
62468
  init_github_auth();
61623
- import { spawnSync as spawnSync2 } from "node:child_process";
62469
+ import { spawnSync as spawnSync3 } from "node:child_process";
61624
62470
 
61625
62471
  // src/domains/installation/git-clone-manager.ts
61626
62472
  init_logger();
@@ -61887,7 +62733,7 @@ class AuthChecker {
61887
62733
  if (false) {}
61888
62734
  try {
61889
62735
  logger.verbose("AuthChecker: Running 'gh auth status -h github.com' command");
61890
- const result = spawnSync2("gh", ["auth", "status", "-h", "github.com"], {
62736
+ const result = spawnSync3("gh", ["auth", "status", "-h", "github.com"], {
61891
62737
  encoding: "utf8",
61892
62738
  timeout: COMMAND_TIMEOUT_MS2
61893
62739
  });
@@ -61966,7 +62812,7 @@ import { platform as platform6 } from "node:os";
61966
62812
  init_path_resolver();
61967
62813
  import { constants as constants3, access as access3, mkdir as mkdir9, readFile as readFile23, unlink as unlink5, writeFile as writeFile12 } from "node:fs/promises";
61968
62814
  import { arch as arch2, homedir as homedir16, platform as platform5 } from "node:os";
61969
- import { join as join42, normalize as normalize6 } from "node:path";
62815
+ import { join as join43, normalize as normalize6 } from "node:path";
61970
62816
  var IS_WINDOWS = platform5() === "win32";
61971
62817
  function shouldSkipExpensiveOperations4() {
61972
62818
  if (process.env.CK_TEST_HOME) {
@@ -62060,7 +62906,7 @@ async function checkGlobalDirAccess() {
62060
62906
  autoFixable: false
62061
62907
  };
62062
62908
  }
62063
- const testFile = join42(globalDir, ".ck-doctor-access-test");
62909
+ const testFile = join43(globalDir, ".ck-doctor-access-test");
62064
62910
  try {
62065
62911
  await mkdir9(globalDir, { recursive: true });
62066
62912
  await writeFile12(testFile, "test", "utf-8");
@@ -62138,7 +62984,7 @@ async function checkWSLBoundary() {
62138
62984
  // src/domains/health-checks/platform/windows-checker.ts
62139
62985
  init_path_resolver();
62140
62986
  import { mkdir as mkdir10, symlink, unlink as unlink6, writeFile as writeFile13 } from "node:fs/promises";
62141
- import { join as join43 } from "node:path";
62987
+ import { join as join44 } from "node:path";
62142
62988
  async function checkLongPathSupport() {
62143
62989
  if (shouldSkipExpensiveOperations4()) {
62144
62990
  return {
@@ -62190,8 +63036,8 @@ async function checkSymlinkSupport() {
62190
63036
  };
62191
63037
  }
62192
63038
  const testDir = PathResolver.getGlobalKitDir();
62193
- const target = join43(testDir, ".ck-symlink-test-target");
62194
- const link = join43(testDir, ".ck-symlink-test-link");
63039
+ const target = join44(testDir, ".ck-symlink-test-target");
63040
+ const link = join44(testDir, ".ck-symlink-test-link");
62195
63041
  try {
62196
63042
  await mkdir10(testDir, { recursive: true });
62197
63043
  await writeFile13(target, "test", "utf-8");
@@ -62474,10 +63320,10 @@ class AutoHealer {
62474
63320
  }
62475
63321
  }
62476
63322
  // src/domains/health-checks/report-generator.ts
62477
- import { execSync as execSync3, spawnSync as spawnSync3 } from "node:child_process";
62478
- import { readFileSync as readFileSync6, unlinkSync, writeFileSync } from "node:fs";
62479
- import { tmpdir as tmpdir2 } from "node:os";
62480
- import { dirname as dirname10, join as join44 } from "node:path";
63323
+ import { execSync as execSync3, spawnSync as spawnSync4 } from "node:child_process";
63324
+ import { readFileSync as readFileSync7, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
63325
+ import { tmpdir as tmpdir3 } from "node:os";
63326
+ import { dirname as dirname10, join as join45 } from "node:path";
62481
63327
  import { fileURLToPath as fileURLToPath3 } from "node:url";
62482
63328
  init_environment();
62483
63329
  init_logger();
@@ -62485,8 +63331,8 @@ init_dist2();
62485
63331
  function getCliVersion2() {
62486
63332
  try {
62487
63333
  const __dirname4 = dirname10(fileURLToPath3(import.meta.url));
62488
- const pkgPath = join44(__dirname4, "../../../package.json");
62489
- const pkg = JSON.parse(readFileSync6(pkgPath, "utf-8"));
63334
+ const pkgPath = join45(__dirname4, "../../../package.json");
63335
+ const pkg = JSON.parse(readFileSync7(pkgPath, "utf-8"));
62490
63336
  return pkg.version || "unknown";
62491
63337
  } catch (err) {
62492
63338
  logger.debug(`Failed to read CLI version: ${err}`);
@@ -62624,10 +63470,10 @@ class ReportGenerator {
62624
63470
  return null;
62625
63471
  }
62626
63472
  }
62627
- const tmpFile = join44(tmpdir2(), `ck-report-${Date.now()}.txt`);
62628
- writeFileSync(tmpFile, report);
63473
+ const tmpFile = join45(tmpdir3(), `ck-report-${Date.now()}.txt`);
63474
+ writeFileSync2(tmpFile, report);
62629
63475
  try {
62630
- const result = spawnSync3("gh", ["gist", "create", tmpFile, "--desc", "ClaudeKit Diagnostic Report"], {
63476
+ const result = spawnSync4("gh", ["gist", "create", tmpFile, "--desc", "ClaudeKit Diagnostic Report"], {
62631
63477
  encoding: "utf-8"
62632
63478
  });
62633
63479
  if (result.status !== 0) {
@@ -62949,7 +63795,7 @@ init_logger();
62949
63795
  init_path_resolver();
62950
63796
  var import_compare_versions5 = __toESM(require_umd(), 1);
62951
63797
  import { mkdir as mkdir11, readFile as readFile24, unlink as unlink7, writeFile as writeFile14 } from "node:fs/promises";
62952
- import { join as join45 } from "node:path";
63798
+ import { join as join46 } from "node:path";
62953
63799
  var CACHE_TTL_HOURS = 24;
62954
63800
  var DEFAULT_CACHE_TTL_MS = CACHE_TTL_HOURS * 60 * 60 * 1000;
62955
63801
  var MIN_CACHE_TTL_MS = 60 * 1000;
@@ -62986,7 +63832,7 @@ var KIT_REPOS = {
62986
63832
  class ConfigVersionChecker {
62987
63833
  static getCacheFilePath(kitType, global3) {
62988
63834
  const cacheDir = PathResolver.getCacheDir(global3);
62989
- return join45(cacheDir, `${kitType}-${CACHE_FILENAME}`);
63835
+ return join46(cacheDir, `${kitType}-${CACHE_FILENAME}`);
62990
63836
  }
62991
63837
  static async loadCache(kitType, global3) {
62992
63838
  try {
@@ -63073,7 +63919,7 @@ class ConfigVersionChecker {
63073
63919
  return null;
63074
63920
  }
63075
63921
  const delay = baseBackoff * 2 ** attempt;
63076
- await new Promise((resolve8) => setTimeout(resolve8, delay));
63922
+ await new Promise((resolve9) => setTimeout(resolve9, delay));
63077
63923
  }
63078
63924
  }
63079
63925
  return null;
@@ -63149,7 +63995,7 @@ class ConfigVersionChecker {
63149
63995
  }
63150
63996
  // src/domains/sync/sync-engine.ts
63151
63997
  import { lstat as lstat3, readFile as readFile25, readlink, realpath as realpath2, stat as stat9 } from "node:fs/promises";
63152
- import { isAbsolute as isAbsolute2, join as join46, normalize as normalize7, relative as relative4 } from "node:path";
63998
+ import { isAbsolute as isAbsolute2, join as join47, normalize as normalize7, relative as relative4 } from "node:path";
63153
63999
 
63154
64000
  // src/services/file-operations/ownership-checker.ts
63155
64001
  init_metadata_migration();
@@ -63240,24 +64086,24 @@ function pLimit(concurrency) {
63240
64086
  activeCount--;
63241
64087
  resumeNext();
63242
64088
  };
63243
- const run = async (function_, resolve8, arguments_) => {
64089
+ const run = async (function_, resolve9, arguments_) => {
63244
64090
  const result = (async () => function_(...arguments_))();
63245
- resolve8(result);
64091
+ resolve9(result);
63246
64092
  try {
63247
64093
  await result;
63248
64094
  } catch {}
63249
64095
  next();
63250
64096
  };
63251
- const enqueue = (function_, resolve8, arguments_) => {
64097
+ const enqueue = (function_, resolve9, arguments_) => {
63252
64098
  new Promise((internalResolve) => {
63253
64099
  queue.enqueue(internalResolve);
63254
- }).then(run.bind(undefined, function_, resolve8, arguments_));
64100
+ }).then(run.bind(undefined, function_, resolve9, arguments_));
63255
64101
  if (activeCount < concurrency) {
63256
64102
  resumeNext();
63257
64103
  }
63258
64104
  };
63259
- const generator = (function_, ...arguments_) => new Promise((resolve8) => {
63260
- enqueue(function_, resolve8, arguments_);
64105
+ const generator = (function_, ...arguments_) => new Promise((resolve9) => {
64106
+ enqueue(function_, resolve9, arguments_);
63261
64107
  });
63262
64108
  Object.defineProperties(generator, {
63263
64109
  activeCount: {
@@ -63308,12 +64154,12 @@ async function mapWithLimit(items, fn, concurrency = DEFAULT_CONCURRENCY) {
63308
64154
  // src/services/file-operations/ownership-checker.ts
63309
64155
  class OwnershipChecker {
63310
64156
  static async calculateChecksum(filePath) {
63311
- return new Promise((resolve8, reject) => {
64157
+ return new Promise((resolve9, reject) => {
63312
64158
  const hash = createHash("sha256");
63313
64159
  const stream = createReadStream2(filePath);
63314
64160
  stream.on("data", (chunk) => hash.update(chunk));
63315
64161
  stream.on("end", () => {
63316
- resolve8(hash.digest("hex"));
64162
+ resolve9(hash.digest("hex"));
63317
64163
  });
63318
64164
  stream.on("error", (err) => {
63319
64165
  stream.destroy();
@@ -64437,7 +65283,7 @@ async function validateSymlinkChain(path3, basePath, maxDepth = MAX_SYMLINK_DEPT
64437
65283
  if (!stats.isSymbolicLink())
64438
65284
  break;
64439
65285
  const target = await readlink(current);
64440
- const resolvedTarget = isAbsolute2(target) ? target : join46(current, "..", target);
65286
+ const resolvedTarget = isAbsolute2(target) ? target : join47(current, "..", target);
64441
65287
  const normalizedTarget = normalize7(resolvedTarget);
64442
65288
  const rel = relative4(basePath, normalizedTarget);
64443
65289
  if (rel.startsWith("..") || isAbsolute2(rel)) {
@@ -64473,7 +65319,7 @@ async function validateSyncPath(basePath, filePath) {
64473
65319
  if (normalized.startsWith("..") || normalized.includes("/../")) {
64474
65320
  throw new Error(`Path traversal not allowed: ${filePath}`);
64475
65321
  }
64476
- const fullPath = join46(basePath, normalized);
65322
+ const fullPath = join47(basePath, normalized);
64477
65323
  const rel = relative4(basePath, fullPath);
64478
65324
  if (rel.startsWith("..") || isAbsolute2(rel)) {
64479
65325
  throw new Error(`Path escapes base directory: ${filePath}`);
@@ -64488,7 +65334,7 @@ async function validateSyncPath(basePath, filePath) {
64488
65334
  }
64489
65335
  } catch (error) {
64490
65336
  if (error.code === "ENOENT") {
64491
- const parentPath = join46(fullPath, "..");
65337
+ const parentPath = join47(fullPath, "..");
64492
65338
  try {
64493
65339
  const resolvedBase = await realpath2(basePath);
64494
65340
  const resolvedParent = await realpath2(parentPath);
@@ -65670,7 +66516,7 @@ init_logger();
65670
66516
  var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
65671
66517
  import { mkdir as mkdir14 } from "node:fs/promises";
65672
66518
  import os5 from "node:os";
65673
- import { join as join53 } from "node:path";
66519
+ import { join as join54 } from "node:path";
65674
66520
  var LOCK_CONFIG = {
65675
66521
  stale: 60000,
65676
66522
  retries: 0
@@ -65678,12 +66524,12 @@ var LOCK_CONFIG = {
65678
66524
  var activeLocks = new Set;
65679
66525
  var cleanupRegistered = false;
65680
66526
  function getLocksDir() {
65681
- return join53(os5.homedir(), ".claudekit", "locks");
66527
+ return join54(os5.homedir(), ".claudekit", "locks");
65682
66528
  }
65683
66529
  function cleanupLocks() {
65684
66530
  for (const name of activeLocks) {
65685
66531
  try {
65686
- const lockPath = join53(getLocksDir(), `${name}.lock`);
66532
+ const lockPath = join54(getLocksDir(), `${name}.lock`);
65687
66533
  import_proper_lockfile.default.unlockSync(lockPath, { realpath: false });
65688
66534
  } catch {
65689
66535
  try {
@@ -65706,7 +66552,7 @@ async function ensureLocksDir() {
65706
66552
  async function withProcessLock(lockName, fn) {
65707
66553
  registerCleanupHandlers();
65708
66554
  await ensureLocksDir();
65709
- const lockPath = join53(getLocksDir(), `${lockName}.lock`);
66555
+ const lockPath = join54(getLocksDir(), `${lockName}.lock`);
65710
66556
  let release;
65711
66557
  try {
65712
66558
  release = await import_proper_lockfile.default.lock(lockPath, { ...LOCK_CONFIG, realpath: false });
@@ -65737,7 +66583,7 @@ init_logger();
65737
66583
  init_logger();
65738
66584
  init_path_resolver();
65739
66585
  var import_fs_extra7 = __toESM(require_lib3(), 1);
65740
- import { join as join54 } from "node:path";
66586
+ import { join as join55 } from "node:path";
65741
66587
  async function handleConflicts(ctx) {
65742
66588
  if (ctx.cancelled)
65743
66589
  return ctx;
@@ -65746,7 +66592,7 @@ async function handleConflicts(ctx) {
65746
66592
  if (PathResolver.isLocalSameAsGlobal()) {
65747
66593
  return ctx;
65748
66594
  }
65749
- const localSettingsPath = join54(process.cwd(), ".claude", "settings.json");
66595
+ const localSettingsPath = join55(process.cwd(), ".claude", "settings.json");
65750
66596
  if (!await import_fs_extra7.pathExists(localSettingsPath)) {
65751
66597
  return ctx;
65752
66598
  }
@@ -65761,7 +66607,7 @@ async function handleConflicts(ctx) {
65761
66607
  return { ...ctx, cancelled: true };
65762
66608
  }
65763
66609
  if (choice === "remove") {
65764
- const localClaudeDir = join54(process.cwd(), ".claude");
66610
+ const localClaudeDir = join55(process.cwd(), ".claude");
65765
66611
  try {
65766
66612
  await import_fs_extra7.remove(localClaudeDir);
65767
66613
  logger.success("Removed local .claude/ directory");
@@ -65857,8 +66703,8 @@ init_environment();
65857
66703
  init_logger();
65858
66704
  init_safe_spinner();
65859
66705
  import { mkdir as mkdir20, stat as stat12 } from "node:fs/promises";
65860
- import { tmpdir as tmpdir3 } from "node:os";
65861
- import { join as join61 } from "node:path";
66706
+ import { tmpdir as tmpdir4 } from "node:os";
66707
+ import { join as join62 } from "node:path";
65862
66708
 
65863
66709
  // src/shared/temp-cleanup.ts
65864
66710
  init_logger();
@@ -65877,7 +66723,7 @@ init_logger();
65877
66723
  init_output_manager();
65878
66724
  import { createWriteStream as createWriteStream2, rmSync } from "node:fs";
65879
66725
  import { mkdir as mkdir15 } from "node:fs/promises";
65880
- import { join as join55 } from "node:path";
66726
+ import { join as join56 } from "node:path";
65881
66727
 
65882
66728
  // src/shared/progress-bar.ts
65883
66729
  init_output_manager();
@@ -66041,21 +66887,21 @@ init_types2();
66041
66887
 
66042
66888
  // src/domains/installation/utils/path-security.ts
66043
66889
  init_types2();
66044
- import { lstatSync as lstatSync2, realpathSync } from "node:fs";
66045
- import { relative as relative5, resolve as resolve10 } from "node:path";
66890
+ import { lstatSync as lstatSync2, realpathSync as realpathSync2 } from "node:fs";
66891
+ import { relative as relative5, resolve as resolve11 } from "node:path";
66046
66892
  var MAX_EXTRACTION_SIZE = 500 * 1024 * 1024;
66047
66893
  function isPathSafe(basePath, targetPath) {
66048
- const resolvedBase = resolve10(basePath);
66894
+ const resolvedBase = resolve11(basePath);
66049
66895
  try {
66050
66896
  const stat10 = lstatSync2(targetPath);
66051
66897
  if (stat10.isSymbolicLink()) {
66052
- const realTarget = realpathSync(targetPath);
66898
+ const realTarget = realpathSync2(targetPath);
66053
66899
  if (!realTarget.startsWith(resolvedBase)) {
66054
66900
  return false;
66055
66901
  }
66056
66902
  }
66057
66903
  } catch {}
66058
- const resolvedTarget = resolve10(targetPath);
66904
+ const resolvedTarget = resolve11(targetPath);
66059
66905
  const relativePath = relative5(resolvedBase, resolvedTarget);
66060
66906
  return !relativePath.startsWith("..") && !relativePath.startsWith("/") && resolvedTarget.startsWith(resolvedBase);
66061
66907
  }
@@ -66087,7 +66933,7 @@ var MAX_DOWNLOAD_SIZE = 500 * 1024 * 1024;
66087
66933
  class FileDownloader {
66088
66934
  async downloadAsset(asset, destDir) {
66089
66935
  try {
66090
- const destPath = join55(destDir, asset.name);
66936
+ const destPath = join56(destDir, asset.name);
66091
66937
  await mkdir15(destDir, { recursive: true });
66092
66938
  output.info(`Downloading ${asset.name} (${formatBytes(asset.size)})...`);
66093
66939
  logger.verbose("Download details", {
@@ -66143,7 +66989,7 @@ class FileDownloader {
66143
66989
  }
66144
66990
  if (downloadedSize !== totalSize) {
66145
66991
  fileStream.end();
66146
- await new Promise((resolve11) => fileStream.once("close", resolve11));
66992
+ await new Promise((resolve12) => fileStream.once("close", resolve12));
66147
66993
  try {
66148
66994
  rmSync(destPath, { force: true });
66149
66995
  } catch (cleanupError) {
@@ -66157,7 +67003,7 @@ class FileDownloader {
66157
67003
  return destPath;
66158
67004
  } catch (error) {
66159
67005
  fileStream.end();
66160
- await new Promise((resolve11) => fileStream.once("close", resolve11));
67006
+ await new Promise((resolve12) => fileStream.once("close", resolve12));
66161
67007
  try {
66162
67008
  rmSync(destPath, { force: true });
66163
67009
  } catch (cleanupError) {
@@ -66172,7 +67018,7 @@ class FileDownloader {
66172
67018
  }
66173
67019
  async downloadFile(params) {
66174
67020
  const { url, name, size, destDir, token } = params;
66175
- const destPath = join55(destDir, name);
67021
+ const destPath = join56(destDir, name);
66176
67022
  await mkdir15(destDir, { recursive: true });
66177
67023
  output.info(`Downloading ${name}${size ? ` (${formatBytes(size)})` : ""}...`);
66178
67024
  const headers = {};
@@ -66223,7 +67069,7 @@ class FileDownloader {
66223
67069
  const expectedSize = Number(response.headers.get("content-length"));
66224
67070
  if (expectedSize > 0 && downloadedSize !== expectedSize) {
66225
67071
  fileStream.end();
66226
- await new Promise((resolve11) => fileStream.once("close", resolve11));
67072
+ await new Promise((resolve12) => fileStream.once("close", resolve12));
66227
67073
  try {
66228
67074
  rmSync(destPath, { force: true });
66229
67075
  } catch (cleanupError) {
@@ -66241,7 +67087,7 @@ class FileDownloader {
66241
67087
  return destPath;
66242
67088
  } catch (error) {
66243
67089
  fileStream.end();
66244
- await new Promise((resolve11) => fileStream.once("close", resolve11));
67090
+ await new Promise((resolve12) => fileStream.once("close", resolve12));
66245
67091
  try {
66246
67092
  rmSync(destPath, { force: true });
66247
67093
  } catch (cleanupError) {
@@ -66257,11 +67103,11 @@ class FileDownloader {
66257
67103
  init_logger();
66258
67104
  init_types2();
66259
67105
  import { constants as constants4 } from "node:fs";
66260
- import { access as access4, readdir as readdir9 } from "node:fs/promises";
66261
- import { join as join56 } from "node:path";
67106
+ import { access as access4, readdir as readdir10 } from "node:fs/promises";
67107
+ import { join as join57 } from "node:path";
66262
67108
  async function validateExtraction(extractDir) {
66263
67109
  try {
66264
- const entries = await readdir9(extractDir, { encoding: "utf8" });
67110
+ const entries = await readdir10(extractDir, { encoding: "utf8" });
66265
67111
  logger.debug(`Extracted files: ${entries.join(", ")}`);
66266
67112
  if (entries.length === 0) {
66267
67113
  throw new ExtractionError("Extraction resulted in no files");
@@ -66270,7 +67116,7 @@ async function validateExtraction(extractDir) {
66270
67116
  const missingPaths = [];
66271
67117
  for (const path3 of criticalPaths) {
66272
67118
  try {
66273
- await access4(join56(extractDir, path3), constants4.F_OK);
67119
+ await access4(join57(extractDir, path3), constants4.F_OK);
66274
67120
  logger.debug(`Found: ${path3}`);
66275
67121
  } catch {
66276
67122
  logger.warning(`Expected path not found: ${path3}`);
@@ -66291,8 +67137,8 @@ async function validateExtraction(extractDir) {
66291
67137
 
66292
67138
  // src/domains/installation/extraction/tar-extractor.ts
66293
67139
  init_logger();
66294
- import { copyFile as copyFile3, mkdir as mkdir18, readdir as readdir11, rm as rm3, stat as stat10 } from "node:fs/promises";
66295
- import { join as join59 } from "node:path";
67140
+ import { copyFile as copyFile3, mkdir as mkdir18, readdir as readdir12, rm as rm3, stat as stat10 } from "node:fs/promises";
67141
+ import { join as join60 } from "node:path";
66296
67142
 
66297
67143
  // node_modules/@isaacs/fs-minipass/dist/esm/index.js
66298
67144
  import EE from "events";
@@ -66840,10 +67686,10 @@ class Minipass extends EventEmitter3 {
66840
67686
  return this[ENCODING] ? buf.join("") : Buffer.concat(buf, buf.dataLength);
66841
67687
  }
66842
67688
  async promise() {
66843
- return new Promise((resolve11, reject) => {
67689
+ return new Promise((resolve12, reject) => {
66844
67690
  this.on(DESTROYED, () => reject(new Error("stream destroyed")));
66845
67691
  this.on("error", (er) => reject(er));
66846
- this.on("end", () => resolve11());
67692
+ this.on("end", () => resolve12());
66847
67693
  });
66848
67694
  }
66849
67695
  [Symbol.asyncIterator]() {
@@ -66862,7 +67708,7 @@ class Minipass extends EventEmitter3 {
66862
67708
  return Promise.resolve({ done: false, value: res });
66863
67709
  if (this[EOF])
66864
67710
  return stop();
66865
- let resolve11;
67711
+ let resolve12;
66866
67712
  let reject;
66867
67713
  const onerr = (er) => {
66868
67714
  this.off("data", ondata);
@@ -66876,19 +67722,19 @@ class Minipass extends EventEmitter3 {
66876
67722
  this.off("end", onend);
66877
67723
  this.off(DESTROYED, ondestroy);
66878
67724
  this.pause();
66879
- resolve11({ value, done: !!this[EOF] });
67725
+ resolve12({ value, done: !!this[EOF] });
66880
67726
  };
66881
67727
  const onend = () => {
66882
67728
  this.off("error", onerr);
66883
67729
  this.off("data", ondata);
66884
67730
  this.off(DESTROYED, ondestroy);
66885
67731
  stop();
66886
- resolve11({ done: true, value: undefined });
67732
+ resolve12({ done: true, value: undefined });
66887
67733
  };
66888
67734
  const ondestroy = () => onerr(new Error("stream destroyed"));
66889
67735
  return new Promise((res2, rej) => {
66890
67736
  reject = rej;
66891
- resolve11 = res2;
67737
+ resolve12 = res2;
66892
67738
  this.once(DESTROYED, ondestroy);
66893
67739
  this.once("error", onerr);
66894
67740
  this.once("end", onend);
@@ -67994,10 +68840,10 @@ class Minipass2 extends EventEmitter4 {
67994
68840
  return this[ENCODING2] ? buf.join("") : Buffer.concat(buf, buf.dataLength);
67995
68841
  }
67996
68842
  async promise() {
67997
- return new Promise((resolve11, reject) => {
68843
+ return new Promise((resolve12, reject) => {
67998
68844
  this.on(DESTROYED2, () => reject(new Error("stream destroyed")));
67999
68845
  this.on("error", (er) => reject(er));
68000
- this.on("end", () => resolve11());
68846
+ this.on("end", () => resolve12());
68001
68847
  });
68002
68848
  }
68003
68849
  [Symbol.asyncIterator]() {
@@ -68016,7 +68862,7 @@ class Minipass2 extends EventEmitter4 {
68016
68862
  return Promise.resolve({ done: false, value: res });
68017
68863
  if (this[EOF2])
68018
68864
  return stop();
68019
- let resolve11;
68865
+ let resolve12;
68020
68866
  let reject;
68021
68867
  const onerr = (er) => {
68022
68868
  this.off("data", ondata);
@@ -68030,19 +68876,19 @@ class Minipass2 extends EventEmitter4 {
68030
68876
  this.off("end", onend);
68031
68877
  this.off(DESTROYED2, ondestroy);
68032
68878
  this.pause();
68033
- resolve11({ value, done: !!this[EOF2] });
68879
+ resolve12({ value, done: !!this[EOF2] });
68034
68880
  };
68035
68881
  const onend = () => {
68036
68882
  this.off("error", onerr);
68037
68883
  this.off("data", ondata);
68038
68884
  this.off(DESTROYED2, ondestroy);
68039
68885
  stop();
68040
- resolve11({ done: true, value: undefined });
68886
+ resolve12({ done: true, value: undefined });
68041
68887
  };
68042
68888
  const ondestroy = () => onerr(new Error("stream destroyed"));
68043
68889
  return new Promise((res2, rej) => {
68044
68890
  reject = rej;
68045
- resolve11 = res2;
68891
+ resolve12 = res2;
68046
68892
  this.once(DESTROYED2, ondestroy);
68047
68893
  this.once("error", onerr);
68048
68894
  this.once("end", onend);
@@ -69470,10 +70316,10 @@ class Minipass3 extends EventEmitter5 {
69470
70316
  return this[ENCODING3] ? buf.join("") : Buffer.concat(buf, buf.dataLength);
69471
70317
  }
69472
70318
  async promise() {
69473
- return new Promise((resolve11, reject) => {
70319
+ return new Promise((resolve12, reject) => {
69474
70320
  this.on(DESTROYED3, () => reject(new Error("stream destroyed")));
69475
70321
  this.on("error", (er) => reject(er));
69476
- this.on("end", () => resolve11());
70322
+ this.on("end", () => resolve12());
69477
70323
  });
69478
70324
  }
69479
70325
  [Symbol.asyncIterator]() {
@@ -69492,7 +70338,7 @@ class Minipass3 extends EventEmitter5 {
69492
70338
  return Promise.resolve({ done: false, value: res });
69493
70339
  if (this[EOF3])
69494
70340
  return stop();
69495
- let resolve11;
70341
+ let resolve12;
69496
70342
  let reject;
69497
70343
  const onerr = (er) => {
69498
70344
  this.off("data", ondata);
@@ -69506,19 +70352,19 @@ class Minipass3 extends EventEmitter5 {
69506
70352
  this.off("end", onend);
69507
70353
  this.off(DESTROYED3, ondestroy);
69508
70354
  this.pause();
69509
- resolve11({ value, done: !!this[EOF3] });
70355
+ resolve12({ value, done: !!this[EOF3] });
69510
70356
  };
69511
70357
  const onend = () => {
69512
70358
  this.off("error", onerr);
69513
70359
  this.off("data", ondata);
69514
70360
  this.off(DESTROYED3, ondestroy);
69515
70361
  stop();
69516
- resolve11({ done: true, value: undefined });
70362
+ resolve12({ done: true, value: undefined });
69517
70363
  };
69518
70364
  const ondestroy = () => onerr(new Error("stream destroyed"));
69519
70365
  return new Promise((res2, rej) => {
69520
70366
  reject = rej;
69521
- resolve11 = res2;
70367
+ resolve12 = res2;
69522
70368
  this.once(DESTROYED3, ondestroy);
69523
70369
  this.once("error", onerr);
69524
70370
  this.once("end", onend);
@@ -70289,9 +71135,9 @@ var listFile = (opt, _files) => {
70289
71135
  const parse4 = new Parser(opt);
70290
71136
  const readSize = opt.maxReadSize || 16 * 1024 * 1024;
70291
71137
  const file = opt.file;
70292
- const p = new Promise((resolve11, reject) => {
71138
+ const p = new Promise((resolve12, reject) => {
70293
71139
  parse4.on("error", reject);
70294
- parse4.on("end", resolve11);
71140
+ parse4.on("end", resolve12);
70295
71141
  fs9.stat(file, (er, stat10) => {
70296
71142
  if (er) {
70297
71143
  reject(er);
@@ -72054,7 +72900,7 @@ var mkdirSync = (dir, opt) => {
72054
72900
  };
72055
72901
 
72056
72902
  // node_modules/tar/dist/esm/path-reservations.js
72057
- import { join as join57 } from "node:path";
72903
+ import { join as join58 } from "node:path";
72058
72904
 
72059
72905
  // node_modules/tar/dist/esm/normalize-unicode.js
72060
72906
  var normalizeCache = Object.create(null);
@@ -72087,7 +72933,7 @@ var getDirs = (path8) => {
72087
72933
  const dirs = path8.split("/").slice(0, -1).reduce((set, path9) => {
72088
72934
  const s = set[set.length - 1];
72089
72935
  if (s !== undefined) {
72090
- path9 = join57(s, path9);
72936
+ path9 = join58(s, path9);
72091
72937
  }
72092
72938
  set.push(path9 || "/");
72093
72939
  return set;
@@ -72101,7 +72947,7 @@ class PathReservations {
72101
72947
  #running = new Set;
72102
72948
  reserve(paths, fn) {
72103
72949
  paths = isWindows4 ? ["win32 parallelization disabled"] : paths.map((p) => {
72104
- return stripTrailingSlashes(join57(normalizeUnicode(p))).toLowerCase();
72950
+ return stripTrailingSlashes(join58(normalizeUnicode(p))).toLowerCase();
72105
72951
  });
72106
72952
  const dirs = new Set(paths.map((path8) => getDirs(path8)).reduce((a3, b3) => a3.concat(b3)));
72107
72953
  this.#reservations.set(fn, { dirs, paths });
@@ -72871,9 +73717,9 @@ var extractFile = (opt, _3) => {
72871
73717
  const u = new Unpack(opt);
72872
73718
  const readSize = opt.maxReadSize || 16 * 1024 * 1024;
72873
73719
  const file = opt.file;
72874
- const p = new Promise((resolve11, reject) => {
73720
+ const p = new Promise((resolve12, reject) => {
72875
73721
  u.on("error", reject);
72876
- u.on("close", resolve11);
73722
+ u.on("close", resolve12);
72877
73723
  fs16.stat(file, (er, stat10) => {
72878
73724
  if (er) {
72879
73725
  reject(er);
@@ -73006,7 +73852,7 @@ var replaceAsync = (opt, files) => {
73006
73852
  };
73007
73853
  fs17.read(fd, headBuf, 0, 512, position, onread);
73008
73854
  };
73009
- const promise = new Promise((resolve11, reject) => {
73855
+ const promise = new Promise((resolve12, reject) => {
73010
73856
  p.on("error", reject);
73011
73857
  let flag = "r+";
73012
73858
  const onopen = (er, fd) => {
@@ -73031,7 +73877,7 @@ var replaceAsync = (opt, files) => {
73031
73877
  });
73032
73878
  p.pipe(stream);
73033
73879
  stream.on("error", reject);
73034
- stream.on("close", resolve11);
73880
+ stream.on("close", resolve12);
73035
73881
  addFilesAsync2(p, files);
73036
73882
  });
73037
73883
  });
@@ -73160,8 +74006,8 @@ function decodeFilePath(path10) {
73160
74006
  // src/domains/installation/utils/file-utils.ts
73161
74007
  init_logger();
73162
74008
  init_types2();
73163
- import { copyFile as copyFile2, lstat as lstat4, mkdir as mkdir17, readdir as readdir10 } from "node:fs/promises";
73164
- import { join as join58, relative as relative6 } from "node:path";
74009
+ import { copyFile as copyFile2, lstat as lstat4, mkdir as mkdir17, readdir as readdir11 } from "node:fs/promises";
74010
+ import { join as join59, relative as relative6 } from "node:path";
73165
74011
  async function withRetry(fn, retries = 3) {
73166
74012
  for (let i = 0;i < retries; i++) {
73167
74013
  try {
@@ -73181,10 +74027,10 @@ var isRetryable = (e2) => {
73181
74027
  var delay = (ms) => new Promise((r2) => setTimeout(r2, ms));
73182
74028
  async function moveDirectoryContents(sourceDir, destDir, shouldExclude, sizeTracker) {
73183
74029
  await mkdir17(destDir, { recursive: true });
73184
- const entries = await readdir10(sourceDir, { encoding: "utf8" });
74030
+ const entries = await readdir11(sourceDir, { encoding: "utf8" });
73185
74031
  for (const entry of entries) {
73186
- const sourcePath = join58(sourceDir, entry);
73187
- const destPath = join58(destDir, entry);
74032
+ const sourcePath = join59(sourceDir, entry);
74033
+ const destPath = join59(destDir, entry);
73188
74034
  const relativePath = relative6(sourceDir, sourcePath);
73189
74035
  if (!isPathSafe(destDir, destPath)) {
73190
74036
  logger.warning(`Skipping unsafe path: ${relativePath}`);
@@ -73209,10 +74055,10 @@ async function moveDirectoryContents(sourceDir, destDir, shouldExclude, sizeTrac
73209
74055
  }
73210
74056
  async function copyDirectory(sourceDir, destDir, shouldExclude, sizeTracker) {
73211
74057
  await mkdir17(destDir, { recursive: true });
73212
- const entries = await readdir10(sourceDir, { encoding: "utf8" });
74058
+ const entries = await readdir11(sourceDir, { encoding: "utf8" });
73213
74059
  for (const entry of entries) {
73214
- const sourcePath = join58(sourceDir, entry);
73215
- const destPath = join58(destDir, entry);
74060
+ const sourcePath = join59(sourceDir, entry);
74061
+ const destPath = join59(destDir, entry);
73216
74062
  const relativePath = relative6(sourceDir, sourcePath);
73217
74063
  if (!isPathSafe(destDir, destPath)) {
73218
74064
  logger.warning(`Skipping unsafe path: ${relativePath}`);
@@ -73256,14 +74102,14 @@ class TarExtractor {
73256
74102
  }
73257
74103
  });
73258
74104
  logger.debug(`Extracted TAR.GZ to temp: ${tempExtractDir}`);
73259
- const entries = await readdir11(tempExtractDir, { encoding: "utf8" });
74105
+ const entries = await readdir12(tempExtractDir, { encoding: "utf8" });
73260
74106
  logger.debug(`Root entries: ${entries.join(", ")}`);
73261
74107
  if (entries.length === 1) {
73262
74108
  const rootEntry = entries[0];
73263
- const rootPath = join59(tempExtractDir, rootEntry);
74109
+ const rootPath = join60(tempExtractDir, rootEntry);
73264
74110
  const rootStat = await stat10(rootPath);
73265
74111
  if (rootStat.isDirectory()) {
73266
- const rootContents = await readdir11(rootPath, { encoding: "utf8" });
74112
+ const rootContents = await readdir12(rootPath, { encoding: "utf8" });
73267
74113
  logger.debug(`Root directory '${rootEntry}' contains: ${rootContents.join(", ")}`);
73268
74114
  const isWrapper = isWrapperDirectory(rootEntry);
73269
74115
  logger.debug(`Is wrapper directory: ${isWrapper}`);
@@ -73276,7 +74122,7 @@ class TarExtractor {
73276
74122
  }
73277
74123
  } else {
73278
74124
  await mkdir18(destDir, { recursive: true });
73279
- await copyFile3(rootPath, join59(destDir, rootEntry));
74125
+ await copyFile3(rootPath, join60(destDir, rootEntry));
73280
74126
  }
73281
74127
  } else {
73282
74128
  logger.debug("Multiple root entries - moving all");
@@ -73298,27 +74144,27 @@ init_environment();
73298
74144
  init_logger();
73299
74145
  var import_extract_zip = __toESM(require_extract_zip(), 1);
73300
74146
  import { execFile as execFile8 } from "node:child_process";
73301
- import { copyFile as copyFile4, mkdir as mkdir19, readdir as readdir12, rm as rm4, stat as stat11 } from "node:fs/promises";
73302
- import { join as join60 } from "node:path";
74147
+ import { copyFile as copyFile4, mkdir as mkdir19, readdir as readdir13, rm as rm4, stat as stat11 } from "node:fs/promises";
74148
+ import { join as join61 } from "node:path";
73303
74149
  class ZipExtractor {
73304
74150
  async tryNativeUnzip(archivePath, destDir) {
73305
74151
  if (!isMacOS()) {
73306
74152
  return false;
73307
74153
  }
73308
- return new Promise((resolve11) => {
74154
+ return new Promise((resolve12) => {
73309
74155
  mkdir19(destDir, { recursive: true }).then(() => {
73310
74156
  execFile8("unzip", ["-o", "-q", archivePath, "-d", destDir], (error, _stdout, stderr) => {
73311
74157
  if (error) {
73312
74158
  logger.debug(`Native unzip failed: ${stderr || error.message}`);
73313
- resolve11(false);
74159
+ resolve12(false);
73314
74160
  return;
73315
74161
  }
73316
74162
  logger.debug("Native unzip succeeded");
73317
- resolve11(true);
74163
+ resolve12(true);
73318
74164
  });
73319
74165
  }).catch((err) => {
73320
74166
  logger.debug(`Failed to create directory for native unzip: ${err.message}`);
73321
- resolve11(false);
74167
+ resolve12(false);
73322
74168
  });
73323
74169
  });
73324
74170
  }
@@ -73343,14 +74189,14 @@ class ZipExtractor {
73343
74189
  logger.verbose(`Extracted ${extractedCount} files`);
73344
74190
  }
73345
74191
  logger.debug(`Extracted ZIP to temp: ${tempExtractDir}`);
73346
- const entries = await readdir12(tempExtractDir, { encoding: "utf8" });
74192
+ const entries = await readdir13(tempExtractDir, { encoding: "utf8" });
73347
74193
  logger.debug(`Root entries: ${entries.join(", ")}`);
73348
74194
  if (entries.length === 1) {
73349
74195
  const rootEntry = entries[0];
73350
- const rootPath = join60(tempExtractDir, rootEntry);
74196
+ const rootPath = join61(tempExtractDir, rootEntry);
73351
74197
  const rootStat = await stat11(rootPath);
73352
74198
  if (rootStat.isDirectory()) {
73353
- const rootContents = await readdir12(rootPath, { encoding: "utf8" });
74199
+ const rootContents = await readdir13(rootPath, { encoding: "utf8" });
73354
74200
  logger.debug(`Root directory '${rootEntry}' contains: ${rootContents.join(", ")}`);
73355
74201
  const isWrapper = isWrapperDirectory(rootEntry);
73356
74202
  logger.debug(`Is wrapper directory: ${isWrapper}`);
@@ -73363,7 +74209,7 @@ class ZipExtractor {
73363
74209
  }
73364
74210
  } else {
73365
74211
  await mkdir19(destDir, { recursive: true });
73366
- await copyFile4(rootPath, join60(destDir, rootEntry));
74212
+ await copyFile4(rootPath, join61(destDir, rootEntry));
73367
74213
  }
73368
74214
  } else {
73369
74215
  logger.debug("Multiple root entries - moving all");
@@ -73462,7 +74308,7 @@ class DownloadManager {
73462
74308
  async createTempDir() {
73463
74309
  const timestamp = Date.now();
73464
74310
  const counter = DownloadManager.tempDirCounter++;
73465
- const primaryTempDir = join61(tmpdir3(), `claudekit-${timestamp}-${counter}`);
74311
+ const primaryTempDir = join62(tmpdir4(), `claudekit-${timestamp}-${counter}`);
73466
74312
  try {
73467
74313
  await mkdir20(primaryTempDir, { recursive: true });
73468
74314
  logger.debug(`Created temp directory: ${primaryTempDir}`);
@@ -73479,7 +74325,7 @@ Solutions:
73479
74325
  2. Set HOME environment variable
73480
74326
  3. Try running from a different directory`);
73481
74327
  }
73482
- const fallbackTempDir = join61(homeDir, ".claudekit", "tmp", `claudekit-${timestamp}-${counter}`);
74328
+ const fallbackTempDir = join62(homeDir, ".claudekit", "tmp", `claudekit-${timestamp}-${counter}`);
73483
74329
  try {
73484
74330
  await mkdir20(fallbackTempDir, { recursive: true });
73485
74331
  logger.debug(`Created temp directory (fallback): ${fallbackTempDir}`);
@@ -73828,20 +74674,20 @@ async function handleDownload(ctx) {
73828
74674
  };
73829
74675
  }
73830
74676
  // src/commands/init/phases/merge-handler.ts
73831
- import { join as join77 } from "node:path";
74677
+ import { join as join78 } from "node:path";
73832
74678
 
73833
74679
  // src/domains/installation/deletion-handler.ts
73834
- import { existsSync as existsSync35, lstatSync as lstatSync3, readdirSync as readdirSync2, rmSync as rmSync2, rmdirSync, unlinkSync as unlinkSync3 } from "node:fs";
73835
- import { dirname as dirname14, join as join64, relative as relative7, resolve as resolve12, sep } from "node:path";
74680
+ import { existsSync as existsSync36, lstatSync as lstatSync3, readdirSync as readdirSync2, rmSync as rmSync2, rmdirSync, unlinkSync as unlinkSync3 } from "node:fs";
74681
+ import { dirname as dirname14, join as join65, relative as relative7, resolve as resolve13, sep as sep2 } from "node:path";
73836
74682
 
73837
74683
  // src/services/file-operations/manifest/manifest-reader.ts
73838
74684
  init_metadata_migration();
73839
74685
  init_logger();
73840
74686
  init_types2();
73841
74687
  var import_fs_extra8 = __toESM(require_lib3(), 1);
73842
- import { join as join63 } from "node:path";
74688
+ import { join as join64 } from "node:path";
73843
74689
  async function readManifest(claudeDir2) {
73844
- const metadataPath = join63(claudeDir2, "metadata.json");
74690
+ const metadataPath = join64(claudeDir2, "metadata.json");
73845
74691
  if (!await import_fs_extra8.pathExists(metadataPath)) {
73846
74692
  return null;
73847
74693
  }
@@ -74014,12 +74860,12 @@ function shouldDeletePath(path11, metadata) {
74014
74860
  }
74015
74861
  function collectFilesRecursively(dir, baseDir) {
74016
74862
  const results = [];
74017
- if (!existsSync35(dir))
74863
+ if (!existsSync36(dir))
74018
74864
  return results;
74019
74865
  try {
74020
74866
  const entries = readdirSync2(dir, { withFileTypes: true });
74021
74867
  for (const entry of entries) {
74022
- const fullPath = join64(dir, entry.name);
74868
+ const fullPath = join65(dir, entry.name);
74023
74869
  const relativePath = relative7(baseDir, fullPath);
74024
74870
  if (entry.isDirectory()) {
74025
74871
  results.push(...collectFilesRecursively(fullPath, baseDir));
@@ -74049,8 +74895,8 @@ function expandGlobPatterns(patterns, claudeDir2) {
74049
74895
  }
74050
74896
  var MAX_CLEANUP_ITERATIONS = 50;
74051
74897
  function cleanupEmptyDirectories(filePath, claudeDir2) {
74052
- const normalizedClaudeDir = resolve12(claudeDir2);
74053
- let currentDir = resolve12(dirname14(filePath));
74898
+ const normalizedClaudeDir = resolve13(claudeDir2);
74899
+ let currentDir = resolve13(dirname14(filePath));
74054
74900
  let iterations = 0;
74055
74901
  while (currentDir !== normalizedClaudeDir && currentDir.startsWith(normalizedClaudeDir) && iterations < MAX_CLEANUP_ITERATIONS) {
74056
74902
  iterations++;
@@ -74059,7 +74905,7 @@ function cleanupEmptyDirectories(filePath, claudeDir2) {
74059
74905
  if (entries.length === 0) {
74060
74906
  rmdirSync(currentDir);
74061
74907
  logger.debug(`Removed empty directory: ${currentDir}`);
74062
- currentDir = resolve12(dirname14(currentDir));
74908
+ currentDir = resolve13(dirname14(currentDir));
74063
74909
  } else {
74064
74910
  break;
74065
74911
  }
@@ -74069,9 +74915,9 @@ function cleanupEmptyDirectories(filePath, claudeDir2) {
74069
74915
  }
74070
74916
  }
74071
74917
  function deletePath(fullPath, claudeDir2) {
74072
- const normalizedPath = resolve12(fullPath);
74073
- const normalizedClaudeDir = resolve12(claudeDir2);
74074
- if (!normalizedPath.startsWith(`${normalizedClaudeDir}${sep}`) && normalizedPath !== normalizedClaudeDir) {
74918
+ const normalizedPath = resolve13(fullPath);
74919
+ const normalizedClaudeDir = resolve13(claudeDir2);
74920
+ if (!normalizedPath.startsWith(`${normalizedClaudeDir}${sep2}`) && normalizedPath !== normalizedClaudeDir) {
74075
74921
  throw new Error(`Path traversal detected: ${fullPath}`);
74076
74922
  }
74077
74923
  try {
@@ -74087,7 +74933,7 @@ function deletePath(fullPath, claudeDir2) {
74087
74933
  }
74088
74934
  }
74089
74935
  async function updateMetadataAfterDeletion(claudeDir2, deletedPaths) {
74090
- const metadataPath = join64(claudeDir2, "metadata.json");
74936
+ const metadataPath = join65(claudeDir2, "metadata.json");
74091
74937
  if (!await import_fs_extra9.pathExists(metadataPath)) {
74092
74938
  return;
74093
74939
  }
@@ -74142,10 +74988,10 @@ async function handleDeletions(sourceMetadata, claudeDir2) {
74142
74988
  const userMetadata = await readManifest(claudeDir2);
74143
74989
  const result = { deletedPaths: [], preservedPaths: [], errors: [] };
74144
74990
  for (const path11 of deletions) {
74145
- const fullPath = join64(claudeDir2, path11);
74146
- const normalizedPath = resolve12(fullPath);
74147
- const normalizedClaudeDir = resolve12(claudeDir2);
74148
- if (!normalizedPath.startsWith(`${normalizedClaudeDir}${sep}`)) {
74991
+ const fullPath = join65(claudeDir2, path11);
74992
+ const normalizedPath = resolve13(fullPath);
74993
+ const normalizedClaudeDir = resolve13(claudeDir2);
74994
+ if (!normalizedPath.startsWith(`${normalizedClaudeDir}${sep2}`)) {
74149
74995
  logger.warning(`Skipping invalid path: ${path11}`);
74150
74996
  result.errors.push(path11);
74151
74997
  continue;
@@ -74155,7 +75001,7 @@ async function handleDeletions(sourceMetadata, claudeDir2) {
74155
75001
  logger.verbose(`Preserved user file: ${path11}`);
74156
75002
  continue;
74157
75003
  }
74158
- if (existsSync35(fullPath)) {
75004
+ if (existsSync36(fullPath)) {
74159
75005
  try {
74160
75006
  deletePath(fullPath, claudeDir2);
74161
75007
  result.deletedPaths.push(path11);
@@ -74182,7 +75028,7 @@ init_logger();
74182
75028
  init_types2();
74183
75029
  var import_fs_extra12 = __toESM(require_lib3(), 1);
74184
75030
  var import_ignore3 = __toESM(require_ignore(), 1);
74185
- import { dirname as dirname16, join as join67, relative as relative9 } from "node:path";
75031
+ import { dirname as dirname16, join as join68, relative as relative9 } from "node:path";
74186
75032
 
74187
75033
  // src/domains/installation/selective-merger.ts
74188
75034
  import { stat as stat13 } from "node:fs/promises";
@@ -74361,7 +75207,7 @@ init_logger();
74361
75207
  var import_fs_extra10 = __toESM(require_lib3(), 1);
74362
75208
  var import_ignore2 = __toESM(require_ignore(), 1);
74363
75209
  import { relative as relative8 } from "node:path";
74364
- import { join as join65 } from "node:path";
75210
+ import { join as join66 } from "node:path";
74365
75211
 
74366
75212
  // node_modules/@isaacs/balanced-match/dist/esm/index.js
74367
75213
  var balanced = (a3, b3, str2) => {
@@ -75168,8 +76014,8 @@ var path11 = {
75168
76014
  win32: { sep: "\\" },
75169
76015
  posix: { sep: "/" }
75170
76016
  };
75171
- var sep2 = defaultPlatform === "win32" ? path11.win32.sep : path11.posix.sep;
75172
- minimatch.sep = sep2;
76017
+ var sep3 = defaultPlatform === "win32" ? path11.win32.sep : path11.posix.sep;
76018
+ minimatch.sep = sep3;
75173
76019
  var GLOBSTAR = Symbol("globstar **");
75174
76020
  minimatch.GLOBSTAR = GLOBSTAR;
75175
76021
  var qmark2 = "[^/]";
@@ -75817,7 +76663,7 @@ class FileScanner {
75817
76663
  const files = [];
75818
76664
  const entries = await import_fs_extra10.readdir(dir, { encoding: "utf8" });
75819
76665
  for (const entry of entries) {
75820
- const fullPath = join65(dir, entry);
76666
+ const fullPath = join66(dir, entry);
75821
76667
  const relativePath = relative8(baseDir, fullPath);
75822
76668
  const normalizedRelativePath = relativePath.replace(/\\/g, "/");
75823
76669
  const stats = await import_fs_extra10.lstat(fullPath);
@@ -75855,9 +76701,9 @@ import { execSync as execSync4 } from "node:child_process";
75855
76701
 
75856
76702
  // src/domains/config/installed-settings-tracker.ts
75857
76703
  init_shared();
75858
- import { existsSync as existsSync36 } from "node:fs";
76704
+ import { existsSync as existsSync37 } from "node:fs";
75859
76705
  import { mkdir as mkdir21, readFile as readFile29, writeFile as writeFile17 } from "node:fs/promises";
75860
- import { dirname as dirname15, join as join66 } from "node:path";
76706
+ import { dirname as dirname15, join as join67 } from "node:path";
75861
76707
  var CK_JSON_FILE = ".ck.json";
75862
76708
 
75863
76709
  class InstalledSettingsTracker {
@@ -75871,13 +76717,13 @@ class InstalledSettingsTracker {
75871
76717
  }
75872
76718
  getCkJsonPath() {
75873
76719
  if (this.isGlobal) {
75874
- return join66(this.projectDir, CK_JSON_FILE);
76720
+ return join67(this.projectDir, CK_JSON_FILE);
75875
76721
  }
75876
- return join66(this.projectDir, ".claude", CK_JSON_FILE);
76722
+ return join67(this.projectDir, ".claude", CK_JSON_FILE);
75877
76723
  }
75878
76724
  async loadInstalledSettings() {
75879
76725
  const ckJsonPath = this.getCkJsonPath();
75880
- if (!existsSync36(ckJsonPath)) {
76726
+ if (!existsSync37(ckJsonPath)) {
75881
76727
  return { hooks: [], mcpServers: [] };
75882
76728
  }
75883
76729
  try {
@@ -75897,7 +76743,7 @@ class InstalledSettingsTracker {
75897
76743
  const ckJsonPath = this.getCkJsonPath();
75898
76744
  try {
75899
76745
  let data = {};
75900
- if (existsSync36(ckJsonPath)) {
76746
+ if (existsSync37(ckJsonPath)) {
75901
76747
  const content = await readFile29(ckJsonPath, "utf-8");
75902
76748
  data = JSON.parse(content);
75903
76749
  }
@@ -76304,7 +77150,7 @@ class CopyExecutor {
76304
77150
  for (const file of files) {
76305
77151
  const relativePath = relative9(sourceDir, file);
76306
77152
  const normalizedRelativePath = relativePath.replace(/\\/g, "/");
76307
- const destPath = join67(destDir, relativePath);
77153
+ const destPath = join68(destDir, relativePath);
76308
77154
  if (await import_fs_extra12.pathExists(destPath)) {
76309
77155
  if (this.fileScanner.shouldNeverCopy(normalizedRelativePath)) {
76310
77156
  logger.debug(`Security-sensitive file exists but won't be overwritten: ${normalizedRelativePath}`);
@@ -76326,7 +77172,7 @@ class CopyExecutor {
76326
77172
  for (const file of files) {
76327
77173
  const relativePath = relative9(sourceDir, file);
76328
77174
  const normalizedRelativePath = relativePath.replace(/\\/g, "/");
76329
- const destPath = join67(destDir, relativePath);
77175
+ const destPath = join68(destDir, relativePath);
76330
77176
  if (this.fileScanner.shouldNeverCopy(normalizedRelativePath)) {
76331
77177
  logger.debug(`Skipping security-sensitive file: ${normalizedRelativePath}`);
76332
77178
  skippedCount++;
@@ -76495,16 +77341,16 @@ class FileMerger {
76495
77341
  }
76496
77342
 
76497
77343
  // src/domains/migration/legacy-migration.ts
76498
- import { readdir as readdir14, stat as stat14 } from "node:fs/promises";
76499
- import { join as join71, relative as relative10 } from "node:path";
77344
+ import { readdir as readdir15, stat as stat14 } from "node:fs/promises";
77345
+ import { join as join72, relative as relative10 } from "node:path";
76500
77346
  // src/services/file-operations/manifest/manifest-tracker.ts
76501
- import { join as join70 } from "node:path";
77347
+ import { join as join71 } from "node:path";
76502
77348
 
76503
77349
  // src/domains/migration/release-manifest.ts
76504
77350
  init_logger();
76505
77351
  init_zod();
76506
77352
  var import_fs_extra13 = __toESM(require_lib3(), 1);
76507
- import { join as join68 } from "node:path";
77353
+ import { join as join69 } from "node:path";
76508
77354
  var ReleaseManifestFileSchema = exports_external.object({
76509
77355
  path: exports_external.string(),
76510
77356
  checksum: exports_external.string().regex(/^[a-f0-9]{64}$/),
@@ -76519,7 +77365,7 @@ var ReleaseManifestSchema = exports_external.object({
76519
77365
 
76520
77366
  class ReleaseManifestLoader {
76521
77367
  static async load(extractDir) {
76522
- const manifestPath = join68(extractDir, "release-manifest.json");
77368
+ const manifestPath = join69(extractDir, "release-manifest.json");
76523
77369
  try {
76524
77370
  const content = await import_fs_extra13.readFile(manifestPath, "utf-8");
76525
77371
  const parsed = JSON.parse(content);
@@ -76545,9 +77391,9 @@ init_logger();
76545
77391
  init_types2();
76546
77392
  var import_fs_extra14 = __toESM(require_lib3(), 1);
76547
77393
  var import_proper_lockfile2 = __toESM(require_proper_lockfile(), 1);
76548
- import { join as join69 } from "node:path";
77394
+ import { join as join70 } from "node:path";
76549
77395
  async function writeManifest(claudeDir2, kitName, version, scope, kitType, trackedFiles, userConfigFiles) {
76550
- const metadataPath = join69(claudeDir2, "metadata.json");
77396
+ const metadataPath = join70(claudeDir2, "metadata.json");
76551
77397
  const kit = kitType || (/\bmarketing\b/i.test(kitName) ? "marketing" : "engineer");
76552
77398
  await import_fs_extra14.ensureFile(metadataPath);
76553
77399
  let release = null;
@@ -76603,7 +77449,7 @@ async function writeManifest(claudeDir2, kitName, version, scope, kitType, track
76603
77449
  }
76604
77450
  }
76605
77451
  async function removeKitFromManifest(claudeDir2, kit) {
76606
- const metadataPath = join69(claudeDir2, "metadata.json");
77452
+ const metadataPath = join70(claudeDir2, "metadata.json");
76607
77453
  if (!await import_fs_extra14.pathExists(metadataPath))
76608
77454
  return false;
76609
77455
  let release = null;
@@ -76733,7 +77579,7 @@ function buildFileTrackingList(options2) {
76733
77579
  if (!isGlobal && !installedPath.startsWith(".claude/"))
76734
77580
  continue;
76735
77581
  const relativePath = isGlobal ? installedPath : installedPath.replace(/^\.claude\//, "");
76736
- const filePath = join70(claudeDir2, relativePath);
77582
+ const filePath = join71(claudeDir2, relativePath);
76737
77583
  const manifestEntry = releaseManifest ? ReleaseManifestLoader.findFile(releaseManifest, installedPath) : null;
76738
77584
  const ownership = manifestEntry ? "ck" : "user";
76739
77585
  filesToTrack.push({
@@ -76823,7 +77669,7 @@ class LegacyMigration {
76823
77669
  const files = [];
76824
77670
  let entries;
76825
77671
  try {
76826
- entries = await readdir14(dir);
77672
+ entries = await readdir15(dir);
76827
77673
  } catch (err) {
76828
77674
  const error = err;
76829
77675
  if (error.code === "ENOENT") {
@@ -76840,7 +77686,7 @@ class LegacyMigration {
76840
77686
  continue;
76841
77687
  if (SKIP_DIRS_ALL.includes(entry))
76842
77688
  continue;
76843
- const fullPath = join71(dir, entry);
77689
+ const fullPath = join72(dir, entry);
76844
77690
  let stats;
76845
77691
  try {
76846
77692
  stats = await stat14(fullPath);
@@ -76942,7 +77788,7 @@ User-created files (sample):`);
76942
77788
  ];
76943
77789
  if (filesToChecksum.length > 0) {
76944
77790
  const checksumResults = await mapWithLimit(filesToChecksum, async ({ relativePath, ownership }) => {
76945
- const fullPath = join71(claudeDir2, relativePath);
77791
+ const fullPath = join72(claudeDir2, relativePath);
76946
77792
  const checksum = await OwnershipChecker.calculateChecksum(fullPath);
76947
77793
  return { relativePath, checksum, ownership };
76948
77794
  });
@@ -76963,7 +77809,7 @@ User-created files (sample):`);
76963
77809
  installedAt: new Date().toISOString(),
76964
77810
  files: trackedFiles
76965
77811
  };
76966
- const metadataPath = join71(claudeDir2, "metadata.json");
77812
+ const metadataPath = join72(claudeDir2, "metadata.json");
76967
77813
  await import_fs_extra15.writeFile(metadataPath, JSON.stringify(updatedMetadata, null, 2));
76968
77814
  logger.success(`Migration complete: tracked ${trackedFiles.length} files`);
76969
77815
  return true;
@@ -77069,7 +77915,7 @@ function buildConflictSummary(fileConflicts, hookConflicts, mcpConflicts) {
77069
77915
  init_logger();
77070
77916
  init_skip_directories();
77071
77917
  var import_fs_extra16 = __toESM(require_lib3(), 1);
77072
- import { join as join72, relative as relative11, resolve as resolve13 } from "node:path";
77918
+ import { join as join73, relative as relative11, resolve as resolve14 } from "node:path";
77073
77919
 
77074
77920
  class FileScanner2 {
77075
77921
  static async getFiles(dirPath, relativeTo) {
@@ -77085,7 +77931,7 @@ class FileScanner2 {
77085
77931
  logger.debug(`Skipping directory: ${entry}`);
77086
77932
  continue;
77087
77933
  }
77088
- const fullPath = join72(dirPath, entry);
77934
+ const fullPath = join73(dirPath, entry);
77089
77935
  if (!FileScanner2.isSafePath(basePath, fullPath)) {
77090
77936
  logger.warning(`Skipping potentially unsafe path: ${entry}`);
77091
77937
  continue;
@@ -77120,8 +77966,8 @@ class FileScanner2 {
77120
77966
  return files;
77121
77967
  }
77122
77968
  static async findCustomFiles(destDir, sourceDir, subPath) {
77123
- const destSubDir = join72(destDir, subPath);
77124
- const sourceSubDir = join72(sourceDir, subPath);
77969
+ const destSubDir = join73(destDir, subPath);
77970
+ const sourceSubDir = join73(sourceDir, subPath);
77125
77971
  logger.debug(`findCustomFiles - destDir: ${destDir}`);
77126
77972
  logger.debug(`findCustomFiles - sourceDir: ${sourceDir}`);
77127
77973
  logger.debug(`findCustomFiles - subPath: "${subPath}"`);
@@ -77149,8 +77995,8 @@ class FileScanner2 {
77149
77995
  return customFiles;
77150
77996
  }
77151
77997
  static isSafePath(basePath, targetPath) {
77152
- const resolvedBase = resolve13(basePath);
77153
- const resolvedTarget = resolve13(targetPath);
77998
+ const resolvedBase = resolve14(basePath);
77999
+ const resolvedTarget = resolve14(targetPath);
77154
78000
  return resolvedTarget.startsWith(resolvedBase);
77155
78001
  }
77156
78002
  static toPosixPath(path12) {
@@ -77161,13 +78007,13 @@ class FileScanner2 {
77161
78007
  // src/services/transformers/commands-prefix/prefix-applier.ts
77162
78008
  init_logger();
77163
78009
  var import_fs_extra17 = __toESM(require_lib3(), 1);
77164
- import { lstat as lstat7, mkdir as mkdir22, readdir as readdir17, stat as stat15 } from "node:fs/promises";
77165
- import { join as join74 } from "node:path";
78010
+ import { lstat as lstat7, mkdir as mkdir22, readdir as readdir18, stat as stat15 } from "node:fs/promises";
78011
+ import { join as join75 } from "node:path";
77166
78012
 
77167
78013
  // src/services/transformers/commands-prefix/content-transformer.ts
77168
78014
  init_logger();
77169
- import { readFile as readFile33, readdir as readdir16, writeFile as writeFile21 } from "node:fs/promises";
77170
- import { join as join73 } from "node:path";
78015
+ import { readFile as readFile33, readdir as readdir17, writeFile as writeFile21 } from "node:fs/promises";
78016
+ import { join as join74 } from "node:path";
77171
78017
  var TRANSFORMABLE_EXTENSIONS = new Set([
77172
78018
  ".md",
77173
78019
  ".txt",
@@ -77226,9 +78072,9 @@ async function transformCommandReferences(directory, options2 = {}) {
77226
78072
  let filesTransformed = 0;
77227
78073
  let totalReplacements = 0;
77228
78074
  async function processDirectory(dir) {
77229
- const entries = await readdir16(dir, { withFileTypes: true });
78075
+ const entries = await readdir17(dir, { withFileTypes: true });
77230
78076
  for (const entry of entries) {
77231
- const fullPath = join73(dir, entry.name);
78077
+ const fullPath = join74(dir, entry.name);
77232
78078
  if (entry.isDirectory()) {
77233
78079
  if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
77234
78080
  continue;
@@ -77303,22 +78149,22 @@ function shouldApplyPrefix(options2) {
77303
78149
  // src/services/transformers/commands-prefix/prefix-applier.ts
77304
78150
  async function applyPrefix(extractDir) {
77305
78151
  validatePath(extractDir, "extractDir");
77306
- const commandsDir = join74(extractDir, ".claude", "commands");
78152
+ const commandsDir = join75(extractDir, ".claude", "commands");
77307
78153
  if (!await import_fs_extra17.pathExists(commandsDir)) {
77308
78154
  logger.verbose("No commands directory found, skipping prefix application");
77309
78155
  return;
77310
78156
  }
77311
78157
  logger.info("Applying /ck: prefix to slash commands...");
77312
- const backupDir = join74(extractDir, ".commands-backup");
77313
- const tempDir = join74(extractDir, ".commands-prefix-temp");
78158
+ const backupDir = join75(extractDir, ".commands-backup");
78159
+ const tempDir = join75(extractDir, ".commands-prefix-temp");
77314
78160
  try {
77315
- const entries = await readdir17(commandsDir);
78161
+ const entries = await readdir18(commandsDir);
77316
78162
  if (entries.length === 0) {
77317
78163
  logger.verbose("Commands directory is empty, skipping prefix application");
77318
78164
  return;
77319
78165
  }
77320
78166
  if (entries.length === 1 && entries[0] === "ck") {
77321
- const ckDir2 = join74(commandsDir, "ck");
78167
+ const ckDir2 = join75(commandsDir, "ck");
77322
78168
  const ckStat = await stat15(ckDir2);
77323
78169
  if (ckStat.isDirectory()) {
77324
78170
  logger.verbose("Commands already have /ck: prefix, skipping");
@@ -77328,17 +78174,17 @@ async function applyPrefix(extractDir) {
77328
78174
  await import_fs_extra17.copy(commandsDir, backupDir);
77329
78175
  logger.verbose("Created backup of commands directory");
77330
78176
  await mkdir22(tempDir, { recursive: true });
77331
- const ckDir = join74(tempDir, "ck");
78177
+ const ckDir = join75(tempDir, "ck");
77332
78178
  await mkdir22(ckDir, { recursive: true });
77333
78179
  let processedCount = 0;
77334
78180
  for (const entry of entries) {
77335
- const sourcePath = join74(commandsDir, entry);
78181
+ const sourcePath = join75(commandsDir, entry);
77336
78182
  const stats = await lstat7(sourcePath);
77337
78183
  if (stats.isSymbolicLink()) {
77338
78184
  logger.warning(`Skipping symlink for security: ${entry}`);
77339
78185
  continue;
77340
78186
  }
77341
- const destPath = join74(ckDir, entry);
78187
+ const destPath = join75(ckDir, entry);
77342
78188
  await import_fs_extra17.copy(sourcePath, destPath, {
77343
78189
  overwrite: false,
77344
78190
  errorOnExist: true
@@ -77356,7 +78202,7 @@ async function applyPrefix(extractDir) {
77356
78202
  await import_fs_extra17.move(tempDir, commandsDir);
77357
78203
  await import_fs_extra17.remove(backupDir);
77358
78204
  logger.success("Successfully reorganized commands to /ck: prefix");
77359
- const claudeDir2 = join74(extractDir, ".claude");
78205
+ const claudeDir2 = join75(extractDir, ".claude");
77360
78206
  logger.info("Transforming command references in file contents...");
77361
78207
  const transformResult = await transformCommandReferences(claudeDir2, {
77362
78208
  verbose: logger.isVerbose()
@@ -77393,21 +78239,21 @@ async function applyPrefix(extractDir) {
77393
78239
 
77394
78240
  // src/services/transformers/commands-prefix/prefix-cleaner.ts
77395
78241
  init_metadata_migration();
77396
- import { lstat as lstat9, readdir as readdir19 } from "node:fs/promises";
77397
- import { join as join76 } from "node:path";
78242
+ import { lstat as lstat9, readdir as readdir20 } from "node:fs/promises";
78243
+ import { join as join77 } from "node:path";
77398
78244
  init_logger();
77399
78245
  var import_fs_extra19 = __toESM(require_lib3(), 1);
77400
78246
 
77401
78247
  // src/services/transformers/commands-prefix/file-processor.ts
77402
- import { lstat as lstat8, readdir as readdir18 } from "node:fs/promises";
77403
- import { join as join75 } from "node:path";
78248
+ import { lstat as lstat8, readdir as readdir19 } from "node:fs/promises";
78249
+ import { join as join76 } from "node:path";
77404
78250
  init_logger();
77405
78251
  var import_fs_extra18 = __toESM(require_lib3(), 1);
77406
78252
  async function scanDirectoryFiles(dir) {
77407
78253
  const files = [];
77408
- const entries = await readdir18(dir);
78254
+ const entries = await readdir19(dir);
77409
78255
  for (const entry of entries) {
77410
- const fullPath = join75(dir, entry);
78256
+ const fullPath = join76(dir, entry);
77411
78257
  const stats = await lstat8(fullPath);
77412
78258
  if (stats.isSymbolicLink()) {
77413
78259
  continue;
@@ -77535,8 +78381,8 @@ function isDifferentKitDirectory(dirName, currentKit) {
77535
78381
  async function cleanupCommandsDirectory(targetDir, isGlobal, options2 = {}) {
77536
78382
  const { dryRun = false } = options2;
77537
78383
  validatePath(targetDir, "targetDir");
77538
- const claudeDir2 = isGlobal ? targetDir : join76(targetDir, ".claude");
77539
- const commandsDir = join76(claudeDir2, "commands");
78384
+ const claudeDir2 = isGlobal ? targetDir : join77(targetDir, ".claude");
78385
+ const commandsDir = join77(claudeDir2, "commands");
77540
78386
  const accumulator = {
77541
78387
  results: [],
77542
78388
  deletedCount: 0,
@@ -77571,14 +78417,14 @@ async function cleanupCommandsDirectory(targetDir, isGlobal, options2 = {}) {
77571
78417
  if (options2.kitType) {
77572
78418
  logger.verbose(`Kit-aware cleanup: only cleaning files owned by '${options2.kitType}'`);
77573
78419
  }
77574
- const entries = await readdir19(commandsDir);
78420
+ const entries = await readdir20(commandsDir);
77575
78421
  if (entries.length === 0) {
77576
78422
  logger.verbose("Commands directory is empty");
77577
78423
  return result;
77578
78424
  }
77579
78425
  const metadataForChecks = options2.kitType ? createKitSpecificMetadata(metadata, options2.kitType) : metadata;
77580
78426
  for (const entry of entries) {
77581
- const entryPath = join76(commandsDir, entry);
78427
+ const entryPath = join77(commandsDir, entry);
77582
78428
  const stats = await lstat9(entryPath);
77583
78429
  if (stats.isSymbolicLink()) {
77584
78430
  addSymlinkSkip(entry, accumulator);
@@ -77635,7 +78481,7 @@ async function handleMerge(ctx) {
77635
78481
  let customClaudeFiles = [];
77636
78482
  if (!ctx.options.fresh) {
77637
78483
  logger.info("Scanning for custom .claude files...");
77638
- const scanSourceDir = ctx.options.global ? join77(ctx.extractDir, ".claude") : ctx.extractDir;
78484
+ const scanSourceDir = ctx.options.global ? join78(ctx.extractDir, ".claude") : ctx.extractDir;
77639
78485
  const scanTargetSubdir = ctx.options.global ? "" : ".claude";
77640
78486
  customClaudeFiles = await FileScanner2.findCustomFiles(ctx.resolvedDir, scanSourceDir, scanTargetSubdir);
77641
78487
  } else {
@@ -77700,7 +78546,7 @@ async function handleMerge(ctx) {
77700
78546
  return { ...ctx, cancelled: true };
77701
78547
  }
77702
78548
  }
77703
- const sourceDir = ctx.options.global ? join77(ctx.extractDir, ".claude") : ctx.extractDir;
78549
+ const sourceDir = ctx.options.global ? join78(ctx.extractDir, ".claude") : ctx.extractDir;
77704
78550
  await merger.merge(sourceDir, ctx.resolvedDir, ctx.isNonInteractive);
77705
78551
  const fileConflicts = merger.getFileConflicts();
77706
78552
  if (fileConflicts.length > 0 && !ctx.isNonInteractive) {
@@ -77708,7 +78554,7 @@ async function handleMerge(ctx) {
77708
78554
  displayConflictSummary(summary);
77709
78555
  }
77710
78556
  try {
77711
- const sourceMetadataPath = ctx.options.global ? join77(sourceDir, "metadata.json") : join77(sourceDir, ".claude", "metadata.json");
78557
+ const sourceMetadataPath = ctx.options.global ? join78(sourceDir, "metadata.json") : join78(sourceDir, ".claude", "metadata.json");
77712
78558
  if (await import_fs_extra20.pathExists(sourceMetadataPath)) {
77713
78559
  const metadataContent = await import_fs_extra20.readFile(sourceMetadataPath, "utf-8");
77714
78560
  const sourceMetadata = JSON.parse(metadataContent);
@@ -77752,7 +78598,7 @@ async function handleMerge(ctx) {
77752
78598
  };
77753
78599
  }
77754
78600
  // src/commands/init/phases/migration-handler.ts
77755
- import { join as join85 } from "node:path";
78601
+ import { join as join86 } from "node:path";
77756
78602
 
77757
78603
  // src/domains/skills/skills-detector.ts
77758
78604
  init_logger();
@@ -77767,8 +78613,8 @@ init_skip_directories();
77767
78613
  init_types2();
77768
78614
  var import_fs_extra21 = __toESM(require_lib3(), 1);
77769
78615
  import { createHash as createHash2 } from "node:crypto";
77770
- import { readFile as readFile35, readdir as readdir20, writeFile as writeFile22 } from "node:fs/promises";
77771
- import { join as join78, relative as relative12 } from "node:path";
78616
+ import { readFile as readFile35, readdir as readdir21, writeFile as writeFile22 } from "node:fs/promises";
78617
+ import { join as join79, relative as relative12 } from "node:path";
77772
78618
 
77773
78619
  class SkillsManifestManager {
77774
78620
  static MANIFEST_FILENAME = ".skills-manifest.json";
@@ -77790,12 +78636,12 @@ class SkillsManifestManager {
77790
78636
  return manifest;
77791
78637
  }
77792
78638
  static async writeManifest(skillsDir2, manifest) {
77793
- const manifestPath = join78(skillsDir2, SkillsManifestManager.MANIFEST_FILENAME);
78639
+ const manifestPath = join79(skillsDir2, SkillsManifestManager.MANIFEST_FILENAME);
77794
78640
  await writeFile22(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
77795
78641
  logger.debug(`Wrote manifest to: ${manifestPath}`);
77796
78642
  }
77797
78643
  static async readManifest(skillsDir2) {
77798
- const manifestPath = join78(skillsDir2, SkillsManifestManager.MANIFEST_FILENAME);
78644
+ const manifestPath = join79(skillsDir2, SkillsManifestManager.MANIFEST_FILENAME);
77799
78645
  if (!await import_fs_extra21.pathExists(manifestPath)) {
77800
78646
  logger.debug(`No manifest found at: ${manifestPath}`);
77801
78647
  return null;
@@ -77812,14 +78658,14 @@ class SkillsManifestManager {
77812
78658
  }
77813
78659
  }
77814
78660
  static async detectStructure(skillsDir2) {
77815
- const entries = await readdir20(skillsDir2, { withFileTypes: true });
78661
+ const entries = await readdir21(skillsDir2, { withFileTypes: true });
77816
78662
  const dirs = entries.filter((entry) => entry.isDirectory() && !BUILD_ARTIFACT_DIRS.includes(entry.name) && !entry.name.startsWith("."));
77817
78663
  if (dirs.length === 0) {
77818
78664
  return "flat";
77819
78665
  }
77820
78666
  for (const dir of dirs.slice(0, 3)) {
77821
- const dirPath = join78(skillsDir2, dir.name);
77822
- const subEntries = await readdir20(dirPath, { withFileTypes: true });
78667
+ const dirPath = join79(skillsDir2, dir.name);
78668
+ const subEntries = await readdir21(dirPath, { withFileTypes: true });
77823
78669
  const hasSubdirs = subEntries.some((entry) => entry.isDirectory());
77824
78670
  if (hasSubdirs) {
77825
78671
  return "categorized";
@@ -77834,10 +78680,10 @@ class SkillsManifestManager {
77834
78680
  static async scanSkills(skillsDir2, structure) {
77835
78681
  const skills = [];
77836
78682
  if (structure === "flat") {
77837
- const entries = await readdir20(skillsDir2, { withFileTypes: true });
78683
+ const entries = await readdir21(skillsDir2, { withFileTypes: true });
77838
78684
  for (const entry of entries) {
77839
78685
  if (entry.isDirectory() && !BUILD_ARTIFACT_DIRS.includes(entry.name) && !entry.name.startsWith(".")) {
77840
- const skillPath = join78(skillsDir2, entry.name);
78686
+ const skillPath = join79(skillsDir2, entry.name);
77841
78687
  const hash = await SkillsManifestManager.hashDirectory(skillPath);
77842
78688
  skills.push({
77843
78689
  name: entry.name,
@@ -77846,14 +78692,14 @@ class SkillsManifestManager {
77846
78692
  }
77847
78693
  }
77848
78694
  } else {
77849
- const categories = await readdir20(skillsDir2, { withFileTypes: true });
78695
+ const categories = await readdir21(skillsDir2, { withFileTypes: true });
77850
78696
  for (const category of categories) {
77851
78697
  if (category.isDirectory() && !BUILD_ARTIFACT_DIRS.includes(category.name) && !category.name.startsWith(".")) {
77852
- const categoryPath = join78(skillsDir2, category.name);
77853
- const skillEntries = await readdir20(categoryPath, { withFileTypes: true });
78698
+ const categoryPath = join79(skillsDir2, category.name);
78699
+ const skillEntries = await readdir21(categoryPath, { withFileTypes: true });
77854
78700
  for (const skillEntry of skillEntries) {
77855
78701
  if (skillEntry.isDirectory() && !skillEntry.name.startsWith(".")) {
77856
- const skillPath = join78(categoryPath, skillEntry.name);
78702
+ const skillPath = join79(categoryPath, skillEntry.name);
77857
78703
  const hash = await SkillsManifestManager.hashDirectory(skillPath);
77858
78704
  skills.push({
77859
78705
  name: skillEntry.name,
@@ -77881,9 +78727,9 @@ class SkillsManifestManager {
77881
78727
  }
77882
78728
  static async getAllFiles(dirPath) {
77883
78729
  const files = [];
77884
- const entries = await readdir20(dirPath, { withFileTypes: true });
78730
+ const entries = await readdir21(dirPath, { withFileTypes: true });
77885
78731
  for (const entry of entries) {
77886
- const fullPath = join78(dirPath, entry.name);
78732
+ const fullPath = join79(dirPath, entry.name);
77887
78733
  if (entry.name.startsWith(".") || BUILD_ARTIFACT_DIRS.includes(entry.name)) {
77888
78734
  continue;
77889
78735
  }
@@ -78004,13 +78850,13 @@ function getPathMapping(skillName, oldBasePath, newBasePath) {
78004
78850
 
78005
78851
  // src/domains/skills/detection/script-detector.ts
78006
78852
  var import_fs_extra22 = __toESM(require_lib3(), 1);
78007
- import { readdir as readdir21 } from "node:fs/promises";
78008
- import { join as join79 } from "node:path";
78853
+ import { readdir as readdir22 } from "node:fs/promises";
78854
+ import { join as join80 } from "node:path";
78009
78855
  async function scanDirectory(skillsDir2) {
78010
78856
  if (!await import_fs_extra22.pathExists(skillsDir2)) {
78011
78857
  return ["flat", []];
78012
78858
  }
78013
- const entries = await readdir21(skillsDir2, { withFileTypes: true });
78859
+ const entries = await readdir22(skillsDir2, { withFileTypes: true });
78014
78860
  const dirs = entries.filter((entry) => entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith("."));
78015
78861
  if (dirs.length === 0) {
78016
78862
  return ["flat", []];
@@ -78018,13 +78864,13 @@ async function scanDirectory(skillsDir2) {
78018
78864
  let totalSkillLikeCount = 0;
78019
78865
  const allSkills = [];
78020
78866
  for (const dir of dirs) {
78021
- const dirPath = join79(skillsDir2, dir.name);
78022
- const subEntries = await readdir21(dirPath, { withFileTypes: true });
78867
+ const dirPath = join80(skillsDir2, dir.name);
78868
+ const subEntries = await readdir22(dirPath, { withFileTypes: true });
78023
78869
  const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
78024
78870
  if (subdirs.length > 0) {
78025
78871
  for (const subdir of subdirs.slice(0, 3)) {
78026
- const subdirPath = join79(dirPath, subdir.name);
78027
- const subdirFiles = await readdir21(subdirPath, { withFileTypes: true });
78872
+ const subdirPath = join80(dirPath, subdir.name);
78873
+ const subdirFiles = await readdir22(subdirPath, { withFileTypes: true });
78028
78874
  const hasSkillMarker = subdirFiles.some((file) => file.isFile() && (file.name === "skill.md" || file.name === "README.md" || file.name === "readme.md" || file.name === "config.json" || file.name === "package.json"));
78029
78875
  if (hasSkillMarker) {
78030
78876
  totalSkillLikeCount++;
@@ -78180,12 +79026,12 @@ class SkillsMigrationDetector {
78180
79026
  // src/domains/skills/skills-migrator.ts
78181
79027
  init_logger();
78182
79028
  init_types2();
78183
- import { join as join84 } from "node:path";
79029
+ import { join as join85 } from "node:path";
78184
79030
 
78185
79031
  // src/domains/skills/migrator/migration-executor.ts
78186
79032
  init_logger();
78187
- import { copyFile as copyFile5, mkdir as mkdir23, readdir as readdir22, rm as rm5 } from "node:fs/promises";
78188
- import { join as join80 } from "node:path";
79033
+ import { copyFile as copyFile5, mkdir as mkdir23, readdir as readdir23, rm as rm5 } from "node:fs/promises";
79034
+ import { join as join81 } from "node:path";
78189
79035
  var import_fs_extra24 = __toESM(require_lib3(), 1);
78190
79036
 
78191
79037
  // src/domains/skills/skills-migration-prompts.ts
@@ -78348,10 +79194,10 @@ Detected changes:`;
78348
79194
  // src/domains/skills/migrator/migration-executor.ts
78349
79195
  async function copySkillDirectory(sourceDir, destDir) {
78350
79196
  await mkdir23(destDir, { recursive: true });
78351
- const entries = await readdir22(sourceDir, { withFileTypes: true });
79197
+ const entries = await readdir23(sourceDir, { withFileTypes: true });
78352
79198
  for (const entry of entries) {
78353
- const sourcePath = join80(sourceDir, entry.name);
78354
- const destPath = join80(destDir, entry.name);
79199
+ const sourcePath = join81(sourceDir, entry.name);
79200
+ const destPath = join81(destDir, entry.name);
78355
79201
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
78356
79202
  continue;
78357
79203
  }
@@ -78366,7 +79212,7 @@ async function executeInternal(mappings, customizations, currentSkillsDir, inter
78366
79212
  const migrated = [];
78367
79213
  const preserved = [];
78368
79214
  const errors2 = [];
78369
- const tempDir = join80(currentSkillsDir, "..", ".skills-migration-temp");
79215
+ const tempDir = join81(currentSkillsDir, "..", ".skills-migration-temp");
78370
79216
  await mkdir23(tempDir, { recursive: true });
78371
79217
  try {
78372
79218
  for (const mapping of mappings) {
@@ -78387,9 +79233,9 @@ async function executeInternal(mappings, customizations, currentSkillsDir, inter
78387
79233
  }
78388
79234
  }
78389
79235
  const category = mapping.category;
78390
- const targetPath = category ? join80(tempDir, category, skillName) : join80(tempDir, skillName);
79236
+ const targetPath = category ? join81(tempDir, category, skillName) : join81(tempDir, skillName);
78391
79237
  if (category) {
78392
- await mkdir23(join80(tempDir, category), { recursive: true });
79238
+ await mkdir23(join81(tempDir, category), { recursive: true });
78393
79239
  }
78394
79240
  await copySkillDirectory(currentSkillPath, targetPath);
78395
79241
  migrated.push(skillName);
@@ -78455,8 +79301,8 @@ function validateMigrationPath(path12, paramName) {
78455
79301
  init_logger();
78456
79302
  init_types2();
78457
79303
  var import_fs_extra25 = __toESM(require_lib3(), 1);
78458
- import { copyFile as copyFile6, mkdir as mkdir24, readdir as readdir23, rm as rm6, stat as stat16 } from "node:fs/promises";
78459
- import { basename as basename8, join as join81, normalize as normalize8 } from "node:path";
79304
+ import { copyFile as copyFile6, mkdir as mkdir24, readdir as readdir24, rm as rm6, stat as stat16 } from "node:fs/promises";
79305
+ import { basename as basename8, join as join82, normalize as normalize8 } from "node:path";
78460
79306
  function validatePath2(path12, paramName) {
78461
79307
  if (!path12 || typeof path12 !== "string") {
78462
79308
  throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
@@ -78482,7 +79328,7 @@ class SkillsBackupManager {
78482
79328
  const timestamp = Date.now();
78483
79329
  const randomSuffix = Math.random().toString(36).substring(2, 8);
78484
79330
  const backupDirName = `${SkillsBackupManager.BACKUP_PREFIX}${timestamp}-${randomSuffix}`;
78485
- const backupDir = parentDir ? join81(parentDir, backupDirName) : join81(skillsDir2, "..", backupDirName);
79331
+ const backupDir = parentDir ? join82(parentDir, backupDirName) : join82(skillsDir2, "..", backupDirName);
78486
79332
  logger.info(`Creating backup at: ${backupDir}`);
78487
79333
  try {
78488
79334
  await mkdir24(backupDir, { recursive: true });
@@ -78532,8 +79378,8 @@ class SkillsBackupManager {
78532
79378
  return [];
78533
79379
  }
78534
79380
  try {
78535
- const entries = await readdir23(parentDir, { withFileTypes: true });
78536
- const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) => join81(parentDir, entry.name));
79381
+ const entries = await readdir24(parentDir, { withFileTypes: true });
79382
+ const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) => join82(parentDir, entry.name));
78537
79383
  backups.sort().reverse();
78538
79384
  return backups;
78539
79385
  } catch (error) {
@@ -78559,10 +79405,10 @@ class SkillsBackupManager {
78559
79405
  return await SkillsBackupManager.getDirectorySize(backupDir);
78560
79406
  }
78561
79407
  static async copyDirectory(sourceDir, destDir) {
78562
- const entries = await readdir23(sourceDir, { withFileTypes: true });
79408
+ const entries = await readdir24(sourceDir, { withFileTypes: true });
78563
79409
  for (const entry of entries) {
78564
- const sourcePath = join81(sourceDir, entry.name);
78565
- const destPath = join81(destDir, entry.name);
79410
+ const sourcePath = join82(sourceDir, entry.name);
79411
+ const destPath = join82(destDir, entry.name);
78566
79412
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
78567
79413
  continue;
78568
79414
  }
@@ -78576,9 +79422,9 @@ class SkillsBackupManager {
78576
79422
  }
78577
79423
  static async getDirectorySize(dirPath) {
78578
79424
  let size = 0;
78579
- const entries = await readdir23(dirPath, { withFileTypes: true });
79425
+ const entries = await readdir24(dirPath, { withFileTypes: true });
78580
79426
  for (const entry of entries) {
78581
- const fullPath = join81(dirPath, entry.name);
79427
+ const fullPath = join82(dirPath, entry.name);
78582
79428
  if (entry.isSymbolicLink()) {
78583
79429
  continue;
78584
79430
  }
@@ -78613,13 +79459,13 @@ import { relative as relative14 } from "node:path";
78613
79459
  init_skip_directories();
78614
79460
  import { createHash as createHash3 } from "node:crypto";
78615
79461
  import { createReadStream as createReadStream3 } from "node:fs";
78616
- import { readFile as readFile36, readdir as readdir24 } from "node:fs/promises";
78617
- import { join as join82, relative as relative13 } from "node:path";
79462
+ import { readFile as readFile36, readdir as readdir25 } from "node:fs/promises";
79463
+ import { join as join83, relative as relative13 } from "node:path";
78618
79464
  async function getAllFiles(dirPath) {
78619
79465
  const files = [];
78620
- const entries = await readdir24(dirPath, { withFileTypes: true });
79466
+ const entries = await readdir25(dirPath, { withFileTypes: true });
78621
79467
  for (const entry of entries) {
78622
- const fullPath = join82(dirPath, entry.name);
79468
+ const fullPath = join83(dirPath, entry.name);
78623
79469
  if (entry.name.startsWith(".") || BUILD_ARTIFACT_DIRS.includes(entry.name) || entry.isSymbolicLink()) {
78624
79470
  continue;
78625
79471
  }
@@ -78633,12 +79479,12 @@ async function getAllFiles(dirPath) {
78633
79479
  return files;
78634
79480
  }
78635
79481
  async function hashFile(filePath) {
78636
- return new Promise((resolve14, reject) => {
79482
+ return new Promise((resolve15, reject) => {
78637
79483
  const hash = createHash3("sha256");
78638
79484
  const stream = createReadStream3(filePath);
78639
79485
  stream.on("data", (chunk) => hash.update(chunk));
78640
79486
  stream.on("end", () => {
78641
- resolve14(hash.digest("hex"));
79487
+ resolve15(hash.digest("hex"));
78642
79488
  });
78643
79489
  stream.on("error", (error) => {
78644
79490
  stream.destroy();
@@ -78745,8 +79591,8 @@ async function detectFileChanges(currentSkillPath, baselineSkillPath) {
78745
79591
  // src/domains/skills/customization/scan-reporter.ts
78746
79592
  init_types2();
78747
79593
  var import_fs_extra27 = __toESM(require_lib3(), 1);
78748
- import { readdir as readdir25 } from "node:fs/promises";
78749
- import { join as join83, normalize as normalize9 } from "node:path";
79594
+ import { readdir as readdir26 } from "node:fs/promises";
79595
+ import { join as join84, normalize as normalize9 } from "node:path";
78750
79596
  function validatePath3(path12, paramName) {
78751
79597
  if (!path12 || typeof path12 !== "string") {
78752
79598
  throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
@@ -78762,19 +79608,19 @@ async function scanSkillsDirectory(skillsDir2) {
78762
79608
  if (!await import_fs_extra27.pathExists(skillsDir2)) {
78763
79609
  return ["flat", []];
78764
79610
  }
78765
- const entries = await readdir25(skillsDir2, { withFileTypes: true });
79611
+ const entries = await readdir26(skillsDir2, { withFileTypes: true });
78766
79612
  const dirs = entries.filter((entry) => entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith("."));
78767
79613
  if (dirs.length === 0) {
78768
79614
  return ["flat", []];
78769
79615
  }
78770
- const firstDirPath = join83(skillsDir2, dirs[0].name);
78771
- const subEntries = await readdir25(firstDirPath, { withFileTypes: true });
79616
+ const firstDirPath = join84(skillsDir2, dirs[0].name);
79617
+ const subEntries = await readdir26(firstDirPath, { withFileTypes: true });
78772
79618
  const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
78773
79619
  if (subdirs.length > 0) {
78774
79620
  let skillLikeCount = 0;
78775
79621
  for (const subdir of subdirs.slice(0, 3)) {
78776
- const subdirPath = join83(firstDirPath, subdir.name);
78777
- const subdirFiles = await readdir25(subdirPath, { withFileTypes: true });
79622
+ const subdirPath = join84(firstDirPath, subdir.name);
79623
+ const subdirFiles = await readdir26(subdirPath, { withFileTypes: true });
78778
79624
  const hasSkillMarker = subdirFiles.some((file) => file.isFile() && (file.name === "skill.md" || file.name === "README.md" || file.name === "readme.md" || file.name === "config.json" || file.name === "package.json"));
78779
79625
  if (hasSkillMarker) {
78780
79626
  skillLikeCount++;
@@ -78783,8 +79629,8 @@ async function scanSkillsDirectory(skillsDir2) {
78783
79629
  if (skillLikeCount > 0) {
78784
79630
  const skills = [];
78785
79631
  for (const dir of dirs) {
78786
- const categoryPath = join83(skillsDir2, dir.name);
78787
- const skillDirs = await readdir25(categoryPath, { withFileTypes: true });
79632
+ const categoryPath = join84(skillsDir2, dir.name);
79633
+ const skillDirs = await readdir26(categoryPath, { withFileTypes: true });
78788
79634
  skills.push(...skillDirs.filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name));
78789
79635
  }
78790
79636
  return ["categorized", skills];
@@ -78793,17 +79639,17 @@ async function scanSkillsDirectory(skillsDir2) {
78793
79639
  return ["flat", dirs.map((dir) => dir.name)];
78794
79640
  }
78795
79641
  async function findSkillPath(skillsDir2, skillName) {
78796
- const flatPath = join83(skillsDir2, skillName);
79642
+ const flatPath = join84(skillsDir2, skillName);
78797
79643
  if (await import_fs_extra27.pathExists(flatPath)) {
78798
79644
  return { path: flatPath, category: undefined };
78799
79645
  }
78800
- const entries = await readdir25(skillsDir2, { withFileTypes: true });
79646
+ const entries = await readdir26(skillsDir2, { withFileTypes: true });
78801
79647
  for (const entry of entries) {
78802
79648
  if (!entry.isDirectory() || entry.name.startsWith(".") || entry.name === "node_modules") {
78803
79649
  continue;
78804
79650
  }
78805
- const categoryPath = join83(skillsDir2, entry.name);
78806
- const skillPath = join83(categoryPath, skillName);
79651
+ const categoryPath = join84(skillsDir2, entry.name);
79652
+ const skillPath = join84(categoryPath, skillName);
78807
79653
  if (await import_fs_extra27.pathExists(skillPath)) {
78808
79654
  return { path: skillPath, category: entry.name };
78809
79655
  }
@@ -78897,7 +79743,7 @@ class SkillsMigrator {
78897
79743
  }
78898
79744
  }
78899
79745
  if (options2.backup && !options2.dryRun) {
78900
- const claudeDir2 = join84(currentSkillsDir, "..");
79746
+ const claudeDir2 = join85(currentSkillsDir, "..");
78901
79747
  result.backupPath = await SkillsBackupManager.createBackup(currentSkillsDir, claudeDir2);
78902
79748
  logger.success(`Backup created at: ${result.backupPath}`);
78903
79749
  }
@@ -78958,7 +79804,7 @@ async function handleMigration(ctx) {
78958
79804
  logger.debug("Skipping skills migration (fresh installation)");
78959
79805
  return ctx;
78960
79806
  }
78961
- const newSkillsDir = join85(ctx.extractDir, ".claude", "skills");
79807
+ const newSkillsDir = join86(ctx.extractDir, ".claude", "skills");
78962
79808
  const currentSkillsDir = PathResolver.buildSkillsPath(ctx.resolvedDir, ctx.options.global);
78963
79809
  if (!await import_fs_extra28.pathExists(newSkillsDir) || !await import_fs_extra28.pathExists(currentSkillsDir)) {
78964
79810
  return ctx;
@@ -78981,14 +79827,14 @@ async function handleMigration(ctx) {
78981
79827
  return ctx;
78982
79828
  }
78983
79829
  // src/commands/init/phases/opencode-handler.ts
78984
- import { cp as cp2, readdir as readdir27, rm as rm7 } from "node:fs/promises";
78985
- import { join as join87 } from "node:path";
79830
+ import { cp as cp2, readdir as readdir28, rm as rm7 } from "node:fs/promises";
79831
+ import { join as join88 } from "node:path";
78986
79832
 
78987
79833
  // src/services/transformers/opencode-path-transformer.ts
78988
79834
  init_logger();
78989
- import { readFile as readFile37, readdir as readdir26, writeFile as writeFile23 } from "node:fs/promises";
79835
+ import { readFile as readFile37, readdir as readdir27, writeFile as writeFile23 } from "node:fs/promises";
78990
79836
  import { platform as platform12 } from "node:os";
78991
- import { extname as extname3, join as join86 } from "node:path";
79837
+ import { extname as extname3, join as join87 } from "node:path";
78992
79838
  var IS_WINDOWS3 = platform12() === "win32";
78993
79839
  function getOpenCodeGlobalPath() {
78994
79840
  return "$HOME/.config/opencode/";
@@ -79047,9 +79893,9 @@ async function transformPathsForGlobalOpenCode(directory, options2 = {}) {
79047
79893
  let totalChanges = 0;
79048
79894
  let filesSkipped = 0;
79049
79895
  async function processDirectory2(dir) {
79050
- const entries = await readdir26(dir, { withFileTypes: true });
79896
+ const entries = await readdir27(dir, { withFileTypes: true });
79051
79897
  for (const entry of entries) {
79052
- const fullPath = join86(dir, entry.name);
79898
+ const fullPath = join87(dir, entry.name);
79053
79899
  if (entry.isDirectory()) {
79054
79900
  if (entry.name === "node_modules" || entry.name.startsWith(".")) {
79055
79901
  continue;
@@ -79088,7 +79934,7 @@ async function handleOpenCode(ctx) {
79088
79934
  if (ctx.cancelled || !ctx.extractDir || !ctx.resolvedDir) {
79089
79935
  return ctx;
79090
79936
  }
79091
- const openCodeSource = join87(ctx.extractDir, ".opencode");
79937
+ const openCodeSource = join88(ctx.extractDir, ".opencode");
79092
79938
  if (!await import_fs_extra29.pathExists(openCodeSource)) {
79093
79939
  logger.debug("No .opencode directory in archive, skipping");
79094
79940
  return ctx;
@@ -79104,10 +79950,10 @@ async function handleOpenCode(ctx) {
79104
79950
  logger.success(`Transformed ${transformResult.totalChanges} OpenCode path(s) in ${transformResult.filesTransformed} file(s)`);
79105
79951
  }
79106
79952
  await import_fs_extra29.ensureDir(targetDir);
79107
- const entries = await readdir27(openCodeSource, { withFileTypes: true });
79953
+ const entries = await readdir28(openCodeSource, { withFileTypes: true });
79108
79954
  for (const entry of entries) {
79109
- const sourcePath = join87(openCodeSource, entry.name);
79110
- const targetPath = join87(targetDir, entry.name);
79955
+ const sourcePath = join88(openCodeSource, entry.name);
79956
+ const targetPath = join88(targetDir, entry.name);
79111
79957
  if (await import_fs_extra29.pathExists(targetPath)) {
79112
79958
  if (!ctx.options.forceOverwrite) {
79113
79959
  logger.verbose(`Skipping existing: ${entry.name}`);
@@ -79200,7 +80046,7 @@ Please use only one download method.`);
79200
80046
  }
79201
80047
  // src/commands/init/phases/post-install-handler.ts
79202
80048
  init_projects_registry();
79203
- import { join as join88 } from "node:path";
80049
+ import { join as join89 } from "node:path";
79204
80050
  init_logger();
79205
80051
  init_path_resolver();
79206
80052
  var import_fs_extra30 = __toESM(require_lib3(), 1);
@@ -79209,8 +80055,8 @@ async function handlePostInstall(ctx) {
79209
80055
  return ctx;
79210
80056
  }
79211
80057
  if (ctx.options.global) {
79212
- const claudeMdSource = join88(ctx.extractDir, "CLAUDE.md");
79213
- const claudeMdDest = join88(ctx.resolvedDir, "CLAUDE.md");
80058
+ const claudeMdSource = join89(ctx.extractDir, "CLAUDE.md");
80059
+ const claudeMdDest = join89(ctx.resolvedDir, "CLAUDE.md");
79214
80060
  if (await import_fs_extra30.pathExists(claudeMdSource)) {
79215
80061
  if (!await import_fs_extra30.pathExists(claudeMdDest)) {
79216
80062
  await import_fs_extra30.copy(claudeMdSource, claudeMdDest);
@@ -79258,7 +80104,7 @@ async function handlePostInstall(ctx) {
79258
80104
  }
79259
80105
  if (!ctx.options.skipSetup) {
79260
80106
  await promptSetupWizardIfNeeded({
79261
- envPath: join88(ctx.claudeDir, ".env"),
80107
+ envPath: join89(ctx.claudeDir, ".env"),
79262
80108
  claudeDir: ctx.claudeDir,
79263
80109
  isGlobal: ctx.options.global,
79264
80110
  isNonInteractive: ctx.isNonInteractive,
@@ -79282,7 +80128,7 @@ async function handlePostInstall(ctx) {
79282
80128
  init_config_manager();
79283
80129
  init_github_client();
79284
80130
  import { mkdir as mkdir25 } from "node:fs/promises";
79285
- import { join as join90, resolve as resolve15 } from "node:path";
80131
+ import { join as join91, resolve as resolve16 } from "node:path";
79286
80132
 
79287
80133
  // src/domains/github/kit-access-checker.ts
79288
80134
  init_logger();
@@ -79412,8 +80258,8 @@ async function runPreflightChecks() {
79412
80258
 
79413
80259
  // src/domains/installation/fresh-installer.ts
79414
80260
  init_metadata_migration();
79415
- import { existsSync as existsSync37, readdirSync as readdirSync3, rmSync as rmSync3, rmdirSync as rmdirSync2, unlinkSync as unlinkSync4 } from "node:fs";
79416
- import { dirname as dirname17, join as join89, resolve as resolve14 } from "node:path";
80261
+ import { existsSync as existsSync38, readdirSync as readdirSync3, rmSync as rmSync3, rmdirSync as rmdirSync2, unlinkSync as unlinkSync4 } from "node:fs";
80262
+ import { dirname as dirname17, join as join90, resolve as resolve15 } from "node:path";
79417
80263
  init_logger();
79418
80264
  init_safe_spinner();
79419
80265
  var import_fs_extra31 = __toESM(require_lib3(), 1);
@@ -79461,15 +80307,15 @@ async function analyzeFreshInstallation(claudeDir2) {
79461
80307
  };
79462
80308
  }
79463
80309
  function cleanupEmptyDirectories2(filePath, claudeDir2) {
79464
- const normalizedClaudeDir = resolve14(claudeDir2);
79465
- let currentDir = resolve14(dirname17(filePath));
80310
+ const normalizedClaudeDir = resolve15(claudeDir2);
80311
+ let currentDir = resolve15(dirname17(filePath));
79466
80312
  while (currentDir !== normalizedClaudeDir && currentDir.startsWith(normalizedClaudeDir)) {
79467
80313
  try {
79468
80314
  const entries = readdirSync3(currentDir);
79469
80315
  if (entries.length === 0) {
79470
80316
  rmdirSync2(currentDir);
79471
80317
  logger.debug(`Removed empty directory: ${currentDir}`);
79472
- currentDir = resolve14(dirname17(currentDir));
80318
+ currentDir = resolve15(dirname17(currentDir));
79473
80319
  } else {
79474
80320
  break;
79475
80321
  }
@@ -79486,9 +80332,9 @@ async function removeFilesByOwnership(claudeDir2, analysis, includeModified) {
79486
80332
  const filesToRemove = includeModified ? [...analysis.ckFiles, ...analysis.ckModifiedFiles] : analysis.ckFiles;
79487
80333
  const filesToPreserve = includeModified ? analysis.userFiles : [...analysis.ckModifiedFiles, ...analysis.userFiles];
79488
80334
  for (const file of filesToRemove) {
79489
- const fullPath = join89(claudeDir2, file.path);
80335
+ const fullPath = join90(claudeDir2, file.path);
79490
80336
  try {
79491
- if (existsSync37(fullPath)) {
80337
+ if (existsSync38(fullPath)) {
79492
80338
  unlinkSync4(fullPath);
79493
80339
  removedFiles.push(file.path);
79494
80340
  logger.debug(`Removed: ${file.path}`);
@@ -79511,7 +80357,7 @@ async function removeFilesByOwnership(claudeDir2, analysis, includeModified) {
79511
80357
  };
79512
80358
  }
79513
80359
  async function updateMetadataAfterFresh(claudeDir2, removedFiles) {
79514
- const metadataPath = join89(claudeDir2, "metadata.json");
80360
+ const metadataPath = join90(claudeDir2, "metadata.json");
79515
80361
  if (!await import_fs_extra31.pathExists(metadataPath)) {
79516
80362
  return;
79517
80363
  }
@@ -79554,7 +80400,7 @@ async function removeSubdirectoriesFallback(claudeDir2) {
79554
80400
  const removedFiles = [];
79555
80401
  let removedDirCount = 0;
79556
80402
  for (const subdir of CLAUDEKIT_SUBDIRECTORIES) {
79557
- const subdirPath = join89(claudeDir2, subdir);
80403
+ const subdirPath = join90(claudeDir2, subdir);
79558
80404
  if (await import_fs_extra31.pathExists(subdirPath)) {
79559
80405
  rmSync3(subdirPath, { recursive: true, force: true });
79560
80406
  removedDirCount++;
@@ -79562,7 +80408,7 @@ async function removeSubdirectoriesFallback(claudeDir2) {
79562
80408
  logger.debug(`Removed subdirectory: ${subdir}/`);
79563
80409
  }
79564
80410
  }
79565
- const metadataPath = join89(claudeDir2, "metadata.json");
80411
+ const metadataPath = join90(claudeDir2, "metadata.json");
79566
80412
  if (await import_fs_extra31.pathExists(metadataPath)) {
79567
80413
  unlinkSync4(metadataPath);
79568
80414
  removedFiles.push("metadata.json");
@@ -79780,7 +80626,7 @@ async function handleSelection(ctx) {
79780
80626
  }
79781
80627
  }
79782
80628
  }
79783
- const resolvedDir = resolve15(targetDir);
80629
+ const resolvedDir = resolve16(targetDir);
79784
80630
  logger.info(`Target directory: ${resolvedDir}`);
79785
80631
  if (!ctx.options.global && PathResolver.isLocalSameAsGlobal(resolvedDir)) {
79786
80632
  logger.warning("You're at HOME directory. Installing here modifies your GLOBAL ClaudeKit.");
@@ -79814,7 +80660,7 @@ async function handleSelection(ctx) {
79814
80660
  }
79815
80661
  if (!ctx.options.fresh) {
79816
80662
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
79817
- const claudeDir2 = prefix ? join90(resolvedDir, prefix) : resolvedDir;
80663
+ const claudeDir2 = prefix ? join91(resolvedDir, prefix) : resolvedDir;
79818
80664
  try {
79819
80665
  const existingMetadata = await readManifest(claudeDir2);
79820
80666
  if (existingMetadata?.kits) {
@@ -79846,7 +80692,7 @@ async function handleSelection(ctx) {
79846
80692
  }
79847
80693
  if (ctx.options.fresh) {
79848
80694
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
79849
- const claudeDir2 = prefix ? join90(resolvedDir, prefix) : resolvedDir;
80695
+ const claudeDir2 = prefix ? join91(resolvedDir, prefix) : resolvedDir;
79850
80696
  const canProceed = await handleFreshInstallation(claudeDir2, ctx.prompts);
79851
80697
  if (!canProceed) {
79852
80698
  return { ...ctx, cancelled: true };
@@ -79865,7 +80711,7 @@ async function handleSelection(ctx) {
79865
80711
  logger.info("Fetching available versions...");
79866
80712
  let currentVersion = null;
79867
80713
  try {
79868
- const metadataPath = ctx.options.global ? join90(PathResolver.getGlobalKitDir(), "metadata.json") : join90(resolvedDir, ".claude", "metadata.json");
80714
+ const metadataPath = ctx.options.global ? join91(PathResolver.getGlobalKitDir(), "metadata.json") : join91(resolvedDir, ".claude", "metadata.json");
79869
80715
  const metadata = await readClaudeKitMetadata(metadataPath);
79870
80716
  currentVersion = metadata?.version || null;
79871
80717
  if (currentVersion) {
@@ -79940,7 +80786,7 @@ async function handleSelection(ctx) {
79940
80786
  }
79941
80787
  // src/commands/init/phases/sync-handler.ts
79942
80788
  import { copyFile as copyFile7, mkdir as mkdir26, open as open4, readFile as readFile39, rename as rename3, stat as stat17, unlink as unlink8, writeFile as writeFile25 } from "node:fs/promises";
79943
- import { dirname as dirname18, join as join91, resolve as resolve16 } from "node:path";
80789
+ import { dirname as dirname18, join as join92, resolve as resolve17 } from "node:path";
79944
80790
  init_logger();
79945
80791
  init_path_resolver();
79946
80792
  var import_fs_extra33 = __toESM(require_lib3(), 1);
@@ -79949,14 +80795,14 @@ async function handleSync(ctx) {
79949
80795
  if (!ctx.options.sync) {
79950
80796
  return ctx;
79951
80797
  }
79952
- const resolvedDir = ctx.options.global ? PathResolver.getGlobalKitDir() : resolve16(ctx.options.dir || ".");
79953
- const claudeDir2 = ctx.options.global ? resolvedDir : join91(resolvedDir, ".claude");
80798
+ const resolvedDir = ctx.options.global ? PathResolver.getGlobalKitDir() : resolve17(ctx.options.dir || ".");
80799
+ const claudeDir2 = ctx.options.global ? resolvedDir : join92(resolvedDir, ".claude");
79954
80800
  if (!await import_fs_extra33.pathExists(claudeDir2)) {
79955
80801
  logger.error("Cannot sync: no .claude directory found");
79956
80802
  ctx.prompts.note("Run 'ck init' without --sync to install first.", "No Installation Found");
79957
80803
  return { ...ctx, cancelled: true };
79958
80804
  }
79959
- const metadataPath = join91(claudeDir2, "metadata.json");
80805
+ const metadataPath = join92(claudeDir2, "metadata.json");
79960
80806
  if (!await import_fs_extra33.pathExists(metadataPath)) {
79961
80807
  logger.error("Cannot sync: no metadata.json found");
79962
80808
  ctx.prompts.note(`Your installation may be from an older version.
@@ -80056,7 +80902,7 @@ function getLockTimeout() {
80056
80902
  var STALE_LOCK_THRESHOLD_MS = 5 * 60 * 1000;
80057
80903
  async function acquireSyncLock(global3) {
80058
80904
  const cacheDir = PathResolver.getCacheDir(global3);
80059
- const lockPath = join91(cacheDir, ".sync-lock");
80905
+ const lockPath = join92(cacheDir, ".sync-lock");
80060
80906
  const startTime = Date.now();
80061
80907
  const lockTimeout = getLockTimeout();
80062
80908
  await mkdir26(dirname18(lockPath), { recursive: true });
@@ -80083,7 +80929,7 @@ async function acquireSyncLock(global3) {
80083
80929
  }
80084
80930
  logger.debug(`Lock stat failed: ${statError}`);
80085
80931
  }
80086
- await new Promise((resolve17) => setTimeout(resolve17, 100));
80932
+ await new Promise((resolve18) => setTimeout(resolve18, 100));
80087
80933
  continue;
80088
80934
  }
80089
80935
  throw err;
@@ -80102,10 +80948,10 @@ async function executeSyncMerge(ctx) {
80102
80948
  const releaseLock = await acquireSyncLock(ctx.options.global);
80103
80949
  try {
80104
80950
  const trackedFiles = ctx.syncTrackedFiles;
80105
- const upstreamDir = ctx.options.global ? join91(ctx.extractDir, ".claude") : ctx.extractDir;
80951
+ const upstreamDir = ctx.options.global ? join92(ctx.extractDir, ".claude") : ctx.extractDir;
80106
80952
  let deletions = [];
80107
80953
  try {
80108
- const sourceMetadataPath = join91(upstreamDir, "metadata.json");
80954
+ const sourceMetadataPath = join92(upstreamDir, "metadata.json");
80109
80955
  if (await import_fs_extra33.pathExists(sourceMetadataPath)) {
80110
80956
  const content = await readFile39(sourceMetadataPath, "utf-8");
80111
80957
  const sourceMetadata = JSON.parse(content);
@@ -80137,7 +80983,7 @@ async function executeSyncMerge(ctx) {
80137
80983
  try {
80138
80984
  const sourcePath = await validateSyncPath(upstreamDir, file.path);
80139
80985
  const targetPath = await validateSyncPath(ctx.claudeDir, file.path);
80140
- const targetDir = join91(targetPath, "..");
80986
+ const targetDir = join92(targetPath, "..");
80141
80987
  try {
80142
80988
  await mkdir26(targetDir, { recursive: true });
80143
80989
  } catch (mkdirError) {
@@ -80308,7 +81154,7 @@ async function createBackup(claudeDir2, files, backupDir) {
80308
81154
  const sourcePath = await validateSyncPath(claudeDir2, file.path);
80309
81155
  if (await import_fs_extra33.pathExists(sourcePath)) {
80310
81156
  const targetPath = await validateSyncPath(backupDir, file.path);
80311
- const targetDir = join91(targetPath, "..");
81157
+ const targetDir = join92(targetPath, "..");
80312
81158
  await mkdir26(targetDir, { recursive: true });
80313
81159
  await copyFile7(sourcePath, targetPath);
80314
81160
  }
@@ -80323,7 +81169,7 @@ async function createBackup(claudeDir2, files, backupDir) {
80323
81169
  }
80324
81170
  // src/commands/init/phases/transform-handler.ts
80325
81171
  init_config_manager();
80326
- import { join as join95 } from "node:path";
81172
+ import { join as join96 } from "node:path";
80327
81173
 
80328
81174
  // src/services/transformers/folder-path-transformer.ts
80329
81175
  init_logger();
@@ -80334,38 +81180,38 @@ init_logger();
80334
81180
  init_types2();
80335
81181
  var import_fs_extra34 = __toESM(require_lib3(), 1);
80336
81182
  import { rename as rename4, rm as rm8 } from "node:fs/promises";
80337
- import { join as join92, relative as relative15 } from "node:path";
81183
+ import { join as join93, relative as relative15 } from "node:path";
80338
81184
  async function collectDirsToRename(extractDir, folders) {
80339
81185
  const dirsToRename = [];
80340
81186
  if (folders.docs !== DEFAULT_FOLDERS.docs) {
80341
- const docsPath = join92(extractDir, DEFAULT_FOLDERS.docs);
81187
+ const docsPath = join93(extractDir, DEFAULT_FOLDERS.docs);
80342
81188
  if (await import_fs_extra34.pathExists(docsPath)) {
80343
81189
  dirsToRename.push({
80344
81190
  from: docsPath,
80345
- to: join92(extractDir, folders.docs)
81191
+ to: join93(extractDir, folders.docs)
80346
81192
  });
80347
81193
  }
80348
- const claudeDocsPath = join92(extractDir, ".claude", DEFAULT_FOLDERS.docs);
81194
+ const claudeDocsPath = join93(extractDir, ".claude", DEFAULT_FOLDERS.docs);
80349
81195
  if (await import_fs_extra34.pathExists(claudeDocsPath)) {
80350
81196
  dirsToRename.push({
80351
81197
  from: claudeDocsPath,
80352
- to: join92(extractDir, ".claude", folders.docs)
81198
+ to: join93(extractDir, ".claude", folders.docs)
80353
81199
  });
80354
81200
  }
80355
81201
  }
80356
81202
  if (folders.plans !== DEFAULT_FOLDERS.plans) {
80357
- const plansPath = join92(extractDir, DEFAULT_FOLDERS.plans);
81203
+ const plansPath = join93(extractDir, DEFAULT_FOLDERS.plans);
80358
81204
  if (await import_fs_extra34.pathExists(plansPath)) {
80359
81205
  dirsToRename.push({
80360
81206
  from: plansPath,
80361
- to: join92(extractDir, folders.plans)
81207
+ to: join93(extractDir, folders.plans)
80362
81208
  });
80363
81209
  }
80364
- const claudePlansPath = join92(extractDir, ".claude", DEFAULT_FOLDERS.plans);
81210
+ const claudePlansPath = join93(extractDir, ".claude", DEFAULT_FOLDERS.plans);
80365
81211
  if (await import_fs_extra34.pathExists(claudePlansPath)) {
80366
81212
  dirsToRename.push({
80367
81213
  from: claudePlansPath,
80368
- to: join92(extractDir, ".claude", folders.plans)
81214
+ to: join93(extractDir, ".claude", folders.plans)
80369
81215
  });
80370
81216
  }
80371
81217
  }
@@ -80405,8 +81251,8 @@ async function renameFolders(dirsToRename, extractDir, options2) {
80405
81251
  // src/services/transformers/folder-transform/path-replacer.ts
80406
81252
  init_logger();
80407
81253
  init_types2();
80408
- import { readFile as readFile40, readdir as readdir28, writeFile as writeFile26 } from "node:fs/promises";
80409
- import { join as join93, relative as relative16 } from "node:path";
81254
+ import { readFile as readFile40, readdir as readdir29, writeFile as writeFile26 } from "node:fs/promises";
81255
+ import { join as join94, relative as relative16 } from "node:path";
80410
81256
  var TRANSFORMABLE_FILE_PATTERNS = [
80411
81257
  ".md",
80412
81258
  ".txt",
@@ -80457,9 +81303,9 @@ function compileReplacements(replacements) {
80457
81303
  async function transformFileContents(dir, compiledReplacements, options2) {
80458
81304
  let filesChanged = 0;
80459
81305
  let replacementsCount = 0;
80460
- const entries = await readdir28(dir, { withFileTypes: true });
81306
+ const entries = await readdir29(dir, { withFileTypes: true });
80461
81307
  for (const entry of entries) {
80462
- const fullPath = join93(dir, entry.name);
81308
+ const fullPath = join94(dir, entry.name);
80463
81309
  if (entry.isDirectory()) {
80464
81310
  if (entry.name === "node_modules" || entry.name === ".git") {
80465
81311
  continue;
@@ -80594,9 +81440,9 @@ async function transformFolderPaths(extractDir, folders, options2 = {}) {
80594
81440
 
80595
81441
  // src/services/transformers/global-path-transformer.ts
80596
81442
  init_logger();
80597
- import { readFile as readFile41, readdir as readdir29, writeFile as writeFile27 } from "node:fs/promises";
81443
+ import { readFile as readFile41, readdir as readdir30, writeFile as writeFile27 } from "node:fs/promises";
80598
81444
  import { platform as platform13 } from "node:os";
80599
- import { extname as extname4, join as join94 } from "node:path";
81445
+ import { extname as extname4, join as join95 } from "node:path";
80600
81446
  var IS_WINDOWS4 = platform13() === "win32";
80601
81447
  var HOME_PREFIX = IS_WINDOWS4 ? "%USERPROFILE%" : "$HOME";
80602
81448
  function getHomeDirPrefix() {
@@ -80704,9 +81550,9 @@ async function transformPathsForGlobalInstall(directory, options2 = {}) {
80704
81550
  let filesSkipped = 0;
80705
81551
  const skippedFiles = [];
80706
81552
  async function processDirectory2(dir) {
80707
- const entries = await readdir29(dir, { withFileTypes: true });
81553
+ const entries = await readdir30(dir, { withFileTypes: true });
80708
81554
  for (const entry of entries) {
80709
- const fullPath = join94(dir, entry.name);
81555
+ const fullPath = join95(dir, entry.name);
80710
81556
  if (entry.isDirectory()) {
80711
81557
  if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
80712
81558
  continue;
@@ -80782,7 +81628,7 @@ async function handleTransforms(ctx) {
80782
81628
  logger.debug(ctx.options.global ? "Saved folder configuration to ~/.claude/.ck.json" : "Saved folder configuration to .claude/.ck.json");
80783
81629
  }
80784
81630
  }
80785
- const claudeDir2 = ctx.options.global ? ctx.resolvedDir : join95(ctx.resolvedDir, ".claude");
81631
+ const claudeDir2 = ctx.options.global ? ctx.resolvedDir : join96(ctx.resolvedDir, ".claude");
80786
81632
  return {
80787
81633
  ...ctx,
80788
81634
  foldersConfig,
@@ -80975,7 +81821,7 @@ var import_picocolors22 = __toESM(require_picocolors(), 1);
80975
81821
 
80976
81822
  // src/commands/new/phases/directory-setup.ts
80977
81823
  init_config_manager();
80978
- import { resolve as resolve17 } from "node:path";
81824
+ import { resolve as resolve18 } from "node:path";
80979
81825
  init_logger();
80980
81826
  init_path_resolver();
80981
81827
  init_types2();
@@ -81060,7 +81906,7 @@ async function directorySetup(validOptions, prompts) {
81060
81906
  targetDir = await prompts.getDirectory(targetDir);
81061
81907
  }
81062
81908
  }
81063
- const resolvedDir = resolve17(targetDir);
81909
+ const resolvedDir = resolve18(targetDir);
81064
81910
  logger.info(`Target directory: ${resolvedDir}`);
81065
81911
  if (PathResolver.isLocalSameAsGlobal(resolvedDir)) {
81066
81912
  logger.warning("You're creating a project at HOME directory.");
@@ -81117,7 +81963,7 @@ async function handleDirectorySetup(ctx) {
81117
81963
  // src/commands/new/phases/project-creation.ts
81118
81964
  init_config_manager();
81119
81965
  init_github_client();
81120
- import { join as join96 } from "node:path";
81966
+ import { join as join97 } from "node:path";
81121
81967
  init_logger();
81122
81968
  init_output_manager();
81123
81969
  init_types2();
@@ -81243,7 +82089,7 @@ async function projectCreation(kit, resolvedDir, validOptions, isNonInteractive2
81243
82089
  output.section("Installing");
81244
82090
  logger.verbose("Installation target", { directory: resolvedDir });
81245
82091
  const merger = new FileMerger;
81246
- const claudeDir2 = join96(resolvedDir, ".claude");
82092
+ const claudeDir2 = join97(resolvedDir, ".claude");
81247
82093
  merger.setMultiKitContext(claudeDir2, kit);
81248
82094
  if (validOptions.exclude && validOptions.exclude.length > 0) {
81249
82095
  merger.addIgnorePatterns(validOptions.exclude);
@@ -81290,7 +82136,7 @@ async function handleProjectCreation(ctx) {
81290
82136
  }
81291
82137
  // src/commands/new/phases/post-setup.ts
81292
82138
  init_projects_registry();
81293
- import { join as join97 } from "node:path";
82139
+ import { join as join98 } from "node:path";
81294
82140
  init_package_installer();
81295
82141
  init_logger();
81296
82142
  init_path_resolver();
@@ -81322,9 +82168,9 @@ async function postSetup(resolvedDir, validOptions, isNonInteractive2, prompts)
81322
82168
  withSudo: validOptions.withSudo
81323
82169
  });
81324
82170
  }
81325
- const claudeDir2 = join97(resolvedDir, ".claude");
82171
+ const claudeDir2 = join98(resolvedDir, ".claude");
81326
82172
  await promptSetupWizardIfNeeded({
81327
- envPath: join97(claudeDir2, ".env"),
82173
+ envPath: join98(claudeDir2, ".env"),
81328
82174
  claudeDir: claudeDir2,
81329
82175
  isGlobal: false,
81330
82176
  isNonInteractive: isNonInteractive2,
@@ -81396,13 +82242,13 @@ init_claudekit_data2();
81396
82242
  init_logger();
81397
82243
  init_safe_prompts();
81398
82244
  var import_picocolors23 = __toESM(require_picocolors(), 1);
81399
- import { existsSync as existsSync38 } from "node:fs";
81400
- import { resolve as resolve18 } from "node:path";
82245
+ import { existsSync as existsSync39 } from "node:fs";
82246
+ import { resolve as resolve19 } from "node:path";
81401
82247
  async function handleAdd(projectPath, options2) {
81402
82248
  logger.debug(`Adding project: ${projectPath}, options: ${JSON.stringify(options2)}`);
81403
82249
  intro("Add Project");
81404
- const absolutePath = resolve18(projectPath);
81405
- if (!existsSync38(absolutePath)) {
82250
+ const absolutePath = resolve19(projectPath);
82251
+ if (!existsSync39(absolutePath)) {
81406
82252
  log.error(`Path does not exist: ${absolutePath}`);
81407
82253
  process.exitCode = 1;
81408
82254
  return;
@@ -82330,7 +83176,7 @@ async function detectInstallations() {
82330
83176
 
82331
83177
  // src/commands/uninstall/removal-handler.ts
82332
83178
  import { readdirSync as readdirSync5, rmSync as rmSync5 } from "node:fs";
82333
- import { join as join99, resolve as resolve19, sep as sep3 } from "node:path";
83179
+ import { join as join100, resolve as resolve20, sep as sep4 } from "node:path";
82334
83180
  init_logger();
82335
83181
  init_safe_prompts();
82336
83182
  init_safe_spinner();
@@ -82339,7 +83185,7 @@ var import_fs_extra37 = __toESM(require_lib3(), 1);
82339
83185
  // src/commands/uninstall/analysis-handler.ts
82340
83186
  init_metadata_migration();
82341
83187
  import { readdirSync as readdirSync4, rmSync as rmSync4 } from "node:fs";
82342
- import { dirname as dirname19, join as join98 } from "node:path";
83188
+ import { dirname as dirname19, join as join99 } from "node:path";
82343
83189
  init_logger();
82344
83190
  init_safe_prompts();
82345
83191
  var import_picocolors27 = __toESM(require_picocolors(), 1);
@@ -82387,7 +83233,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
82387
83233
  if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
82388
83234
  const kitFiles = metadata.kits[kit].files || [];
82389
83235
  for (const trackedFile of kitFiles) {
82390
- const filePath = join98(installation.path, trackedFile.path);
83236
+ const filePath = join99(installation.path, trackedFile.path);
82391
83237
  if (uninstallManifest.filesToPreserve.includes(trackedFile.path)) {
82392
83238
  result.toPreserve.push({ path: trackedFile.path, reason: "shared with other kit" });
82393
83239
  continue;
@@ -82417,7 +83263,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
82417
83263
  return result;
82418
83264
  }
82419
83265
  for (const trackedFile of allTrackedFiles) {
82420
- const filePath = join98(installation.path, trackedFile.path);
83266
+ const filePath = join99(installation.path, trackedFile.path);
82421
83267
  const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
82422
83268
  if (!ownershipResult.exists)
82423
83269
  continue;
@@ -82471,17 +83317,17 @@ async function isDirectory(filePath) {
82471
83317
  }
82472
83318
  async function isPathSafeToRemove(filePath, baseDir) {
82473
83319
  try {
82474
- const resolvedPath = resolve19(filePath);
82475
- const resolvedBase = resolve19(baseDir);
82476
- if (!resolvedPath.startsWith(resolvedBase + sep3) && resolvedPath !== resolvedBase) {
83320
+ const resolvedPath = resolve20(filePath);
83321
+ const resolvedBase = resolve20(baseDir);
83322
+ if (!resolvedPath.startsWith(resolvedBase + sep4) && resolvedPath !== resolvedBase) {
82477
83323
  logger.debug(`Path outside installation directory: ${filePath}`);
82478
83324
  return false;
82479
83325
  }
82480
83326
  const stats = await import_fs_extra37.lstat(filePath);
82481
83327
  if (stats.isSymbolicLink()) {
82482
83328
  const realPath = await import_fs_extra37.realpath(filePath);
82483
- const resolvedReal = resolve19(realPath);
82484
- if (!resolvedReal.startsWith(resolvedBase + sep3) && resolvedReal !== resolvedBase) {
83329
+ const resolvedReal = resolve20(realPath);
83330
+ if (!resolvedReal.startsWith(resolvedBase + sep4) && resolvedReal !== resolvedBase) {
82485
83331
  logger.debug(`Symlink points outside installation directory: ${filePath} -> ${realPath}`);
82486
83332
  return false;
82487
83333
  }
@@ -82514,7 +83360,7 @@ async function removeInstallations(installations, options2) {
82514
83360
  let removedCount = 0;
82515
83361
  let cleanedDirs = 0;
82516
83362
  for (const item of analysis.toDelete) {
82517
- const filePath = join99(installation.path, item.path);
83363
+ const filePath = join100(installation.path, item.path);
82518
83364
  if (!await import_fs_extra37.pathExists(filePath))
82519
83365
  continue;
82520
83366
  if (!await isPathSafeToRemove(filePath, installation.path)) {
@@ -82888,8 +83734,8 @@ init_version_checker();
82888
83734
  init_logger();
82889
83735
  init_path_resolver();
82890
83736
  init_types2();
82891
- import { existsSync as existsSync39, readFileSync as readFileSync8 } from "node:fs";
82892
- import { join as join100 } from "node:path";
83737
+ import { existsSync as existsSync40, readFileSync as readFileSync9 } from "node:fs";
83738
+ import { join as join101 } from "node:path";
82893
83739
  var packageVersion = package_default.version;
82894
83740
  function formatInstalledKits(metadata) {
82895
83741
  if (!metadata.kits || Object.keys(metadata.kits).length === 0) {
@@ -82921,13 +83767,13 @@ async function displayVersion() {
82921
83767
  let localKitVersion = null;
82922
83768
  let isGlobalOnlyKit = false;
82923
83769
  const globalKitDir = PathResolver.getGlobalKitDir();
82924
- const globalMetadataPath = join100(globalKitDir, "metadata.json");
83770
+ const globalMetadataPath = join101(globalKitDir, "metadata.json");
82925
83771
  const prefix = PathResolver.getPathPrefix(false);
82926
- const localMetadataPath = prefix ? join100(process.cwd(), prefix, "metadata.json") : join100(process.cwd(), "metadata.json");
83772
+ const localMetadataPath = prefix ? join101(process.cwd(), prefix, "metadata.json") : join101(process.cwd(), "metadata.json");
82927
83773
  const isLocalSameAsGlobal = localMetadataPath === globalMetadataPath;
82928
- if (!isLocalSameAsGlobal && existsSync39(localMetadataPath)) {
83774
+ if (!isLocalSameAsGlobal && existsSync40(localMetadataPath)) {
82929
83775
  try {
82930
- const rawMetadata = JSON.parse(readFileSync8(localMetadataPath, "utf-8"));
83776
+ const rawMetadata = JSON.parse(readFileSync9(localMetadataPath, "utf-8"));
82931
83777
  const metadata = MetadataSchema.parse(rawMetadata);
82932
83778
  const kitsDisplay = formatInstalledKits(metadata);
82933
83779
  if (kitsDisplay) {
@@ -82939,9 +83785,9 @@ async function displayVersion() {
82939
83785
  logger.verbose("Failed to parse local metadata.json", { error });
82940
83786
  }
82941
83787
  }
82942
- if (existsSync39(globalMetadataPath)) {
83788
+ if (existsSync40(globalMetadataPath)) {
82943
83789
  try {
82944
- const rawMetadata = JSON.parse(readFileSync8(globalMetadataPath, "utf-8"));
83790
+ const rawMetadata = JSON.parse(readFileSync9(globalMetadataPath, "utf-8"));
82945
83791
  const metadata = MetadataSchema.parse(rawMetadata);
82946
83792
  const kitsDisplay = formatInstalledKits(metadata);
82947
83793
  if (kitsDisplay) {