claudekit-cli 4.2.1 → 4.2.3-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.
package/cli-manifest.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "4.2.1",
3
- "generatedAt": "2026-05-12T16:32:49.942Z",
2
+ "version": "4.2.3-dev.1",
3
+ "generatedAt": "2026-05-12T22:38:53.023Z",
4
4
  "commands": {
5
5
  "agents": {
6
6
  "name": "agents",
package/dist/index.js CHANGED
@@ -45544,6 +45544,45 @@ function formatCanonicalClaudeCommand(nodePrefix, root, relativePath, suffix = "
45544
45544
  }
45545
45545
  return normalizedRoot === "$CLAUDE_PROJECT_DIR" ? `${nodePrefix}"${normalizedRoot}"/${normalizedRelativePath}${suffix}` : `${nodePrefix}"${normalizedRoot}/${normalizedRelativePath}"${suffix}`;
45546
45546
  }
45547
+ function resolveClaudePathArg(arg, root) {
45548
+ const normalizedArg = arg.replace(/\\/g, "/");
45549
+ const bareRelativeMatch = normalizedArg.match(/^(?:\.\/)?(\.claude\/.+)$/);
45550
+ if (bareRelativeMatch) {
45551
+ return { root, relativePath: bareRelativeMatch[1] };
45552
+ }
45553
+ const variableMatch = normalizedArg.match(/^(?:\$HOME|\$\{HOME\}|\$CLAUDE_PROJECT_DIR|\$\{CLAUDE_PROJECT_DIR\}|%USERPROFILE%|%CLAUDE_PROJECT_DIR%)\/(\.claude\/.+)$/);
45554
+ if (variableMatch) {
45555
+ return { root, relativePath: variableMatch[1] };
45556
+ }
45557
+ const tildeMatch = normalizedArg.match(/^~\/(\.claude\/.+)$/);
45558
+ if (tildeMatch) {
45559
+ return { root, relativePath: tildeMatch[1] };
45560
+ }
45561
+ const absoluteMatch = normalizedArg.match(/^((?:[A-Za-z]:\/|\/).*?\/\.claude\/.+)$/);
45562
+ if (absoluteMatch) {
45563
+ const absolutePath = absoluteMatch[1];
45564
+ const dotClaudeIdx = absolutePath.indexOf("/.claude/");
45565
+ if (dotClaudeIdx === -1) {
45566
+ return null;
45567
+ }
45568
+ const isWin2 = process.platform === "win32";
45569
+ const cmp = (s) => isWin2 ? s.toLowerCase() : s;
45570
+ const globalRoots = [
45571
+ `${homedir12().replace(/\\/g, "/").replace(/\/+$/, "")}/.claude/`,
45572
+ `${PathResolver.getGlobalKitDir().replace(/\\/g, "/").replace(/\/+$/, "")}/`
45573
+ ];
45574
+ const isUnderGlobal = globalRoots.some((g2) => cmp(absolutePath).startsWith(cmp(g2)));
45575
+ const resolvedRoot = isUnderGlobal ? "$HOME" : root;
45576
+ return {
45577
+ root: resolvedRoot,
45578
+ relativePath: absolutePath.slice(dotClaudeIdx + 1)
45579
+ };
45580
+ }
45581
+ return null;
45582
+ }
45583
+ function formatCanonicalClaudeArg(pathArg) {
45584
+ return formatCanonicalClaudeCommand("", pathArg.root, pathArg.relativePath);
45585
+ }
45547
45586
  function isNodeClaudeCommand(cmd) {
45548
45587
  if (!cmd)
45549
45588
  return false;
@@ -45611,6 +45650,39 @@ function repairClaudeNodeCommandPath(cmd, root) {
45611
45650
  }
45612
45651
  return { command: cmd, changed: false, issue: null };
45613
45652
  }
45653
+ function repairClaudeHookRunnerCommandPath(cmd, root) {
45654
+ if (!cmd) {
45655
+ return { command: cmd ?? "", changed: false, issue: null };
45656
+ }
45657
+ const runnerMatch = cmd.match(/^(\s*bash\s+)(?:"([^"]+)"|([^\s"]+))\s+(?:"([^"]+)"|([^\s"]+))(.*)$/);
45658
+ if (!runnerMatch) {
45659
+ return { command: cmd, changed: false, issue: null };
45660
+ }
45661
+ const [, bashPrefix, quotedRunner, unquotedRunner, quotedTarget, unquotedTarget, suffix] = runnerMatch;
45662
+ const runnerArg = quotedRunner ?? unquotedRunner;
45663
+ const targetArg = quotedTarget ?? unquotedTarget;
45664
+ const runnerPath = resolveClaudePathArg(runnerArg, root);
45665
+ if (!runnerPath || runnerPath.relativePath.replace(/\\/g, "/") !== ".claude/hooks/node-hook-runner.sh") {
45666
+ return { command: cmd, changed: false, issue: null };
45667
+ }
45668
+ const targetPath = resolveClaudePathArg(targetArg, root);
45669
+ if (!targetPath) {
45670
+ return { command: cmd, changed: false, issue: null };
45671
+ }
45672
+ const command = `${bashPrefix}${formatCanonicalClaudeArg(runnerPath)} ${formatCanonicalClaudeArg(targetPath)}${suffix}`;
45673
+ return {
45674
+ command,
45675
+ changed: command !== cmd,
45676
+ issue: command !== cmd ? "invalid-format" : null
45677
+ };
45678
+ }
45679
+ function repairClaudeHookCommandPath(cmd, root) {
45680
+ const nodeRepair = repairClaudeNodeCommandPath(cmd, root);
45681
+ if (nodeRepair.changed || nodeRepair.issue || isNodeClaudeCommand(cmd)) {
45682
+ return nodeRepair;
45683
+ }
45684
+ return repairClaudeHookRunnerCommandPath(cmd, root);
45685
+ }
45614
45686
  function normalizeCommand(cmd) {
45615
45687
  if (!cmd)
45616
45688
  return "";
@@ -51591,8 +51663,27 @@ var init_migrate_provider_scopes = __esm(() => {
51591
51663
 
51592
51664
  // src/commands/migrate/skill-directory-installer.ts
51593
51665
  import { existsSync as existsSync22 } from "node:fs";
51594
- import { cp, mkdir as mkdir10, rename as rename6, rm as rm5 } from "node:fs/promises";
51595
- import { join as join40, resolve as resolve15 } from "node:path";
51666
+ import { cp, mkdir as mkdir10, realpath as realpath5, rename as rename6, rm as rm5 } from "node:fs/promises";
51667
+ import { dirname as dirname11, join as join40, resolve as resolve15 } from "node:path";
51668
+ async function canonicalize(path3) {
51669
+ try {
51670
+ return await realpath5(path3);
51671
+ } catch {
51672
+ const parent = dirname11(path3);
51673
+ if (parent === path3) {
51674
+ return resolve15(path3);
51675
+ }
51676
+ try {
51677
+ const canonicalParent = await realpath5(parent);
51678
+ const absPath = resolve15(path3);
51679
+ const absParent = resolve15(parent);
51680
+ const basename13 = absPath.slice(absParent.length + 1) || "";
51681
+ return join40(canonicalParent, basename13);
51682
+ } catch {
51683
+ return resolve15(path3);
51684
+ }
51685
+ }
51686
+ }
51596
51687
  async function installSkillDirectories(skills, targetProviders, options2) {
51597
51688
  const results = [];
51598
51689
  for (const provider of targetProviders) {
@@ -51619,9 +51710,28 @@ async function installSkillDirectories(skills, targetProviders, options2) {
51619
51710
  });
51620
51711
  continue;
51621
51712
  }
51713
+ const sourceRoot = skills.length > 0 ? dirname11(skills[0].path) : null;
51714
+ const canonicalBase = existsSync22(basePath) ? await canonicalize(basePath) : null;
51715
+ const canonicalSourceRoot = sourceRoot ? await canonicalize(sourceRoot) : null;
51716
+ const basePathIsSymlinkedToSource = canonicalBase !== null && canonicalSourceRoot !== null && canonicalBase === canonicalSourceRoot && resolve15(basePath) !== resolve15(sourceRoot ?? "");
51717
+ if (basePathIsSymlinkedToSource) {
51718
+ for (const skill of skills) {
51719
+ results.push({
51720
+ provider,
51721
+ providerDisplayName: config.displayName,
51722
+ success: true,
51723
+ path: join40(basePath, skill.name),
51724
+ skipped: true,
51725
+ skipReason: `Skills directory ${basePath} is symlinked to source (${canonicalBase}); already in place`
51726
+ });
51727
+ }
51728
+ continue;
51729
+ }
51622
51730
  for (const skill of skills) {
51623
51731
  const targetDir = join40(basePath, skill.name);
51624
- if (resolve15(skill.path) === resolve15(targetDir)) {
51732
+ const canonicalSource = await canonicalize(skill.path);
51733
+ const canonicalTarget = await canonicalize(targetDir);
51734
+ if (canonicalSource === canonicalTarget) {
51625
51735
  results.push({
51626
51736
  provider,
51627
51737
  providerDisplayName: config.displayName,
@@ -53813,9 +53923,9 @@ var init_codex_capabilities = __esm(() => {
53813
53923
 
53814
53924
  // src/commands/portable/codex-path-safety.ts
53815
53925
  import { existsSync as existsSync24 } from "node:fs";
53816
- import { mkdir as mkdir12, realpath as realpath5 } from "node:fs/promises";
53926
+ import { mkdir as mkdir12, realpath as realpath6 } from "node:fs/promises";
53817
53927
  import { homedir as homedir25 } from "node:os";
53818
- import { dirname as dirname11, join as join42, resolve as resolve17, sep as sep7 } from "node:path";
53928
+ import { dirname as dirname12, join as join42, resolve as resolve17, sep as sep7 } from "node:path";
53819
53929
  function isPathWithinBoundary3(targetPath, boundaryPath) {
53820
53930
  const resolvedTarget = resolve17(targetPath);
53821
53931
  const resolvedBoundary = resolve17(boundaryPath);
@@ -53823,7 +53933,7 @@ function isPathWithinBoundary3(targetPath, boundaryPath) {
53823
53933
  }
53824
53934
  async function resolveRealPathSafe2(path3) {
53825
53935
  try {
53826
- return await realpath5(path3);
53936
+ return await realpath6(path3);
53827
53937
  } catch {
53828
53938
  return resolve17(path3);
53829
53939
  }
@@ -53834,11 +53944,11 @@ async function isCanonicalPathWithinBoundary2(targetPath, boundaryPath) {
53834
53944
  return isPathWithinBoundary3(canonicalTarget, canonicalBoundary);
53835
53945
  }
53836
53946
  function getCodexLockPath2(targetFilePath) {
53837
- return join42(dirname11(resolve17(targetFilePath)), ".config.toml.ck-codex.lock");
53947
+ return join42(dirname12(resolve17(targetFilePath)), ".config.toml.ck-codex.lock");
53838
53948
  }
53839
53949
  async function withCodexTargetLock2(targetFilePath, operation) {
53840
53950
  const resolvedTargetPath = resolve17(targetFilePath);
53841
- const dir = dirname11(resolvedTargetPath);
53951
+ const dir = dirname12(resolvedTargetPath);
53842
53952
  if (!existsSync24(dir)) {
53843
53953
  await mkdir12(dir, { recursive: true });
53844
53954
  }
@@ -53871,10 +53981,10 @@ var init_codex_path_safety = __esm(() => {
53871
53981
  // src/commands/portable/codex-features-flag.ts
53872
53982
  import { existsSync as existsSync25 } from "node:fs";
53873
53983
  import { readFile as readFile20, rename as rename7, unlink as unlink6, writeFile as writeFile11 } from "node:fs/promises";
53874
- import { dirname as dirname12, resolve as resolve18 } from "node:path";
53984
+ import { dirname as dirname13, resolve as resolve18 } from "node:path";
53875
53985
  async function ensureCodexHooksFeatureFlag(configTomlPath, isGlobal = false) {
53876
- const boundary = isGlobal ? getCodexGlobalBoundary() : dirname12(resolve18(configTomlPath));
53877
- if (!await isCanonicalPathWithinBoundary2(dirname12(resolve18(configTomlPath)), boundary)) {
53986
+ const boundary = isGlobal ? getCodexGlobalBoundary() : dirname13(resolve18(configTomlPath));
53987
+ if (!await isCanonicalPathWithinBoundary2(dirname13(resolve18(configTomlPath)), boundary)) {
53878
53988
  return {
53879
53989
  status: "failed",
53880
53990
  configPath: configTomlPath,
@@ -54040,7 +54150,7 @@ ${SENTINEL_END2}`;
54040
54150
  // src/commands/portable/codex-hook-wrapper.ts
54041
54151
  import { createHash as createHash5 } from "node:crypto";
54042
54152
  import { mkdirSync, writeFileSync as writeFileSync2 } from "node:fs";
54043
- import { dirname as dirname13, join as join43, resolve as resolve19 } from "node:path";
54153
+ import { dirname as dirname14, join as join43, resolve as resolve19 } from "node:path";
54044
54154
  function wrapperFilename(originalPath) {
54045
54155
  const abs = resolve19(originalPath);
54046
54156
  const hash = createHash5("sha256").update(abs).digest("hex").slice(0, 8);
@@ -54063,7 +54173,7 @@ function generateCodexHookWrappers(originalPaths, wrapperDir, capabilities, time
54063
54173
  continue;
54064
54174
  }
54065
54175
  try {
54066
- mkdirSync(dirname13(wrapperPath), { recursive: true });
54176
+ mkdirSync(dirname14(wrapperPath), { recursive: true });
54067
54177
  const resolvedPath = resolve19(originalPath);
54068
54178
  const hookTimeoutMs = timeoutsByPath?.[resolvedPath] ?? timeoutsByPath?.[originalPath];
54069
54179
  const content = buildWrapperScript(originalPath, capabilities, hookTimeoutMs);
@@ -54383,7 +54493,7 @@ var init_gemini_hook_event_map = __esm(() => {
54383
54493
  import { existsSync as existsSync26 } from "node:fs";
54384
54494
  import { mkdir as mkdir13, readFile as readFile21, rename as rename8, rm as rm6, writeFile as writeFile12 } from "node:fs/promises";
54385
54495
  import { homedir as homedir27 } from "node:os";
54386
- import { basename as basename14, dirname as dirname14, join as join44, resolve as resolve20 } from "node:path";
54496
+ import { basename as basename14, dirname as dirname15, join as join44, resolve as resolve20 } from "node:path";
54387
54497
  function validateHooksSectionShape(value) {
54388
54498
  if (!value || typeof value !== "object" || Array.isArray(value)) {
54389
54499
  return "hooks must be a non-null object";
@@ -54534,7 +54644,7 @@ async function mergeHooksIntoSettings(targetSettingsPath, newHooks) {
54534
54644
  const pruned = pruneStaleFileHooks(existingHooks);
54535
54645
  const merged = deduplicateMerge(pruned, newHooks);
54536
54646
  existingSettings.hooks = merged;
54537
- const dir = dirname14(targetSettingsPath);
54647
+ const dir = dirname15(targetSettingsPath);
54538
54648
  await mkdir13(dir, { recursive: true });
54539
54649
  const tempPath = `${targetSettingsPath}.tmp`;
54540
54650
  try {
@@ -56121,7 +56231,7 @@ __export(exports_skills_discovery, {
56121
56231
  });
56122
56232
  import { readFile as readFile24, readdir as readdir13, stat as stat9 } from "node:fs/promises";
56123
56233
  import { homedir as homedir28 } from "node:os";
56124
- import { dirname as dirname15, join as join45 } from "node:path";
56234
+ import { dirname as dirname16, join as join45 } from "node:path";
56125
56235
  function getSkillSourcePath(globalOnly = false) {
56126
56236
  const globalPath = join45(homedir28(), ".claude/skills");
56127
56237
  if (globalOnly) {
@@ -56148,7 +56258,7 @@ async function parseSkillMd(skillMdPath) {
56148
56258
  try {
56149
56259
  const content = await readFile24(skillMdPath, "utf-8");
56150
56260
  const { data } = import_gray_matter5.default(content, { engines: { javascript: { parse: () => ({}) } } });
56151
- const skillDir = dirname15(skillMdPath);
56261
+ const skillDir = dirname16(skillMdPath);
56152
56262
  const dirName = skillDir.split(/[/\\]/).pop() || "";
56153
56263
  if (!dirName) {
56154
56264
  logger.verbose(`Skipping ${skillMdPath}: cannot determine skill directory`);
@@ -57952,7 +58062,7 @@ var init_plan_metadata = __esm(() => {
57952
58062
 
57953
58063
  // src/domains/plan-parser/plan-table-parser.ts
57954
58064
  import { readFileSync as readFileSync7 } from "node:fs";
57955
- import { dirname as dirname16, resolve as resolve22 } from "node:path";
58065
+ import { dirname as dirname17, resolve as resolve22 } from "node:path";
57956
58066
  function normalizeStatus(raw) {
57957
58067
  const s = raw.toLowerCase().trim();
57958
58068
  if (s.includes("complete") || s.includes("done") || s.includes("✓") || s.includes("✅")) {
@@ -58212,7 +58322,7 @@ function parseFormat4(content, planFilePath, options2) {
58212
58322
  const hasCheck = /[✅✓]/.test(line);
58213
58323
  current = { name, status: hasCheck ? "completed" : "pending" };
58214
58324
  } else if (fileMatch && current) {
58215
- const planDir = dirname16(planFilePath);
58325
+ const planDir = dirname17(planFilePath);
58216
58326
  current.file = resolve22(planDir, fileMatch[1].trim());
58217
58327
  } else if (statusMatch && current) {
58218
58328
  current.status = normalizeStatus(statusMatch[2]);
@@ -58317,7 +58427,7 @@ function parsePhasesFromBody(body, dir, options2) {
58317
58427
  }
58318
58428
  function parsePlanFile(planFilePath, options2) {
58319
58429
  const content = readFileSync7(planFilePath, "utf8");
58320
- const dir = dirname16(planFilePath);
58430
+ const dir = dirname17(planFilePath);
58321
58431
  const { data: frontmatter, content: body } = import_gray_matter7.default(content, {
58322
58432
  engines: { javascript: { parse: () => ({}) } }
58323
58433
  });
@@ -58613,12 +58723,12 @@ var init_timeline_builder = __esm(() => {
58613
58723
 
58614
58724
  // src/domains/plan-parser/plan-validator.ts
58615
58725
  import { existsSync as existsSync32, readFileSync as readFileSync8 } from "node:fs";
58616
- import { basename as basename16, dirname as dirname17 } from "node:path";
58726
+ import { basename as basename16, dirname as dirname18 } from "node:path";
58617
58727
  function validatePlanFile(filePath, strict = false) {
58618
58728
  const rawContent = readFileSync8(filePath, "utf8");
58619
58729
  const content = rawContent.replace(/\r\n/g, `
58620
58730
  `);
58621
- const dir = dirname17(filePath);
58731
+ const dir = dirname18(filePath);
58622
58732
  const issues = [];
58623
58733
  const lines = content.split(`
58624
58734
  `);
@@ -58684,7 +58794,7 @@ var init_plan_validator = __esm(() => {
58684
58794
  import { execSync } from "node:child_process";
58685
58795
  import { mkdirSync as mkdirSync2, readFileSync as readFileSync9, writeFileSync as writeFileSync3 } from "node:fs";
58686
58796
  import { existsSync as existsSync33 } from "node:fs";
58687
- import { basename as basename17, dirname as dirname18, join as join51 } from "node:path";
58797
+ import { basename as basename17, dirname as dirname19, join as join51 } from "node:path";
58688
58798
  function phaseNameToFilename(id, name) {
58689
58799
  const numMatch = /^(\d+)([a-z]*)$/i.exec(id);
58690
58800
  const num = numMatch ? numMatch[1] : id;
@@ -58898,7 +59008,7 @@ function updatePhaseStatus(planFile, phaseId, newStatus) {
58898
59008
  const updatedFrontmatter = { ...frontmatter, status: planStatus };
58899
59009
  const updatedContent = import_gray_matter9.default.stringify(updatedBody, updatedFrontmatter);
58900
59010
  writeFileSync3(planFile, updatedContent, "utf8");
58901
- const planDir = dirname18(planFile);
59011
+ const planDir = dirname19(planFile);
58902
59012
  const phaseFilename = phaseNameFilenameFromTableRow(updatedBody, phaseId, planDir);
58903
59013
  if (phaseFilename && existsSync33(phaseFilename)) {
58904
59014
  updatePhaseFileFrontmatter(phaseFilename, newStatus);
@@ -58934,7 +59044,7 @@ function addPhase(planFile, name, afterId) {
58934
59044
  const { data: frontmatter, content: body } = import_gray_matter9.default(raw, {
58935
59045
  engines: { javascript: { parse: () => ({}) } }
58936
59046
  });
58937
- const planDir = dirname18(planFile);
59047
+ const planDir = dirname19(planFile);
58938
59048
  const existingIds = [];
58939
59049
  for (const match of body.matchAll(/^\|\s*(\d+[a-z]?)\s*\|/gim)) {
58940
59050
  existingIds.push(match[1].toLowerCase());
@@ -59007,7 +59117,7 @@ var init_plan_writer = __esm(() => {
59007
59117
  });
59008
59118
 
59009
59119
  // src/domains/plan-parser/index.ts
59010
- import { dirname as dirname19 } from "node:path";
59120
+ import { dirname as dirname20 } from "node:path";
59011
59121
  function buildPlanSummary(planFile) {
59012
59122
  const { frontmatter, phases } = parsePlanFile(planFile);
59013
59123
  const completed = phases.filter((p) => p.status === "completed").length;
@@ -59015,7 +59125,7 @@ function buildPlanSummary(planFile) {
59015
59125
  const pending = phases.filter((p) => p.status === "pending").length;
59016
59126
  const metadata = readPlanMetadata(planFile, { total: phases.length, completed, inProgress });
59017
59127
  return {
59018
- planDir: dirname19(planFile),
59128
+ planDir: dirname20(planFile),
59019
59129
  planFile,
59020
59130
  title: metadata.title ?? (typeof frontmatter.title === "string" ? frontmatter.title : undefined),
59021
59131
  description: metadata.description ?? (typeof frontmatter.description === "string" ? frontmatter.description : undefined),
@@ -59275,7 +59385,7 @@ import {
59275
59385
  unlinkSync,
59276
59386
  writeFileSync as writeFileSync4
59277
59387
  } from "node:fs";
59278
- import { dirname as dirname20, isAbsolute as isAbsolute7, join as join52, parse as parse2, relative as relative12, resolve as resolve24 } from "node:path";
59388
+ import { dirname as dirname21, isAbsolute as isAbsolute7, join as join52, parse as parse2, relative as relative12, resolve as resolve24 } from "node:path";
59279
59389
  function createEmptyRegistry() {
59280
59390
  return {
59281
59391
  version: 1,
@@ -59341,7 +59451,7 @@ function findProjectRoot(startDir) {
59341
59451
  if (existsSync34(join52(dir, ".claude")) || existsSync34(join52(dir, ".git"))) {
59342
59452
  return dir;
59343
59453
  }
59344
- dir = dirname20(dir);
59454
+ dir = dirname21(dir);
59345
59455
  }
59346
59456
  return startDir;
59347
59457
  }
@@ -59362,7 +59472,7 @@ function writeRegistry(registry, cwd2 = process.cwd()) {
59362
59472
  const globalPath = PathResolver.getPlansRegistryPath(cwd2);
59363
59473
  const toWrite = { ...registry, projectRoot: cwd2 };
59364
59474
  const validated = PlansRegistrySchema.parse(toWrite);
59365
- mkdirSync3(dirname20(globalPath), { recursive: true });
59475
+ mkdirSync3(dirname21(globalPath), { recursive: true });
59366
59476
  if (existsSync34(globalPath)) {
59367
59477
  try {
59368
59478
  writeFileSync4(`${globalPath}.bak`, readFileSync10(globalPath));
@@ -59472,7 +59582,7 @@ var init_plans_registry = __esm(() => {
59472
59582
  });
59473
59583
 
59474
59584
  // src/domains/plan-actions/action-executor.ts
59475
- import { dirname as dirname21, join as join53 } from "node:path";
59585
+ import { dirname as dirname22, join as join53 } from "node:path";
59476
59586
  function getPlanFile(planDir) {
59477
59587
  return join53(planDir, "plan.md");
59478
59588
  }
@@ -59486,7 +59596,7 @@ function assertPhaseId(phaseId) {
59486
59596
  function syncDashboardTracking(planFile) {
59487
59597
  const summary = buildPlanSummary(planFile);
59488
59598
  try {
59489
- const planDir = dirname21(planFile);
59599
+ const planDir = dirname22(planFile);
59490
59600
  const projectRoot = findProjectRoot(planDir);
59491
59601
  updateRegistryPhaseStatus({
59492
59602
  planDir,
@@ -59749,7 +59859,7 @@ var init_p_limit = __esm(() => {
59749
59859
  // src/domains/web-server/routes/plan-routes.ts
59750
59860
  import { existsSync as existsSync35, readFileSync as readFileSync11, realpathSync } from "node:fs";
59751
59861
  import { homedir as homedir31 } from "node:os";
59752
- import { basename as basename18, dirname as dirname22, join as join54, relative as relative13, resolve as resolve25, sep as sep8 } from "node:path";
59862
+ import { basename as basename18, dirname as dirname23, join as join54, relative as relative13, resolve as resolve25, sep as sep8 } from "node:path";
59753
59863
  function sanitizeError(err) {
59754
59864
  if (err instanceof Error) {
59755
59865
  if (/^(ENOENT|EACCES|EPERM|EISDIR)/.test(err.message))
@@ -59900,8 +60010,8 @@ function createDiscoveredProjectId(projectPath) {
59900
60010
  function toProjectPlanListItem(summary, plansDir) {
59901
60011
  return {
59902
60012
  file: relative13(plansDir, summary.planFile),
59903
- name: basename18(dirname22(summary.planFile)),
59904
- slug: basename18(dirname22(summary.planFile)),
60013
+ name: basename18(dirname23(summary.planFile)),
60014
+ slug: basename18(dirname23(summary.planFile)),
59905
60015
  summary: {
59906
60016
  ...summary,
59907
60017
  planDir: relative13(plansDir, summary.planDir),
@@ -59983,8 +60093,8 @@ function registerPlanRoutes(app) {
59983
60093
  const summaries = buildPlanSummaries(entries.slice(offset, offset + limit));
59984
60094
  const plans = summaries.map((summary) => ({
59985
60095
  file: relative13(process.cwd(), summary.planFile),
59986
- name: basename18(dirname22(summary.planFile)),
59987
- slug: basename18(dirname22(summary.planFile)),
60096
+ name: basename18(dirname23(summary.planFile)),
60097
+ slug: basename18(dirname23(summary.planFile)),
59988
60098
  summary: {
59989
60099
  ...summary,
59990
60100
  planDir: relative13(process.cwd(), summary.planDir),
@@ -61070,7 +61180,7 @@ var init_settings_routes = __esm(() => {
61070
61180
  // src/domains/skills/skill-catalog-generator.ts
61071
61181
  import { mkdir as mkdir14, readFile as readFile28, readdir as readdir15, rename as rename9, stat as stat11, writeFile as writeFile13 } from "node:fs/promises";
61072
61182
  import { homedir as homedir35 } from "node:os";
61073
- import { dirname as dirname23, join as join57, relative as relative14 } from "node:path";
61183
+ import { dirname as dirname24, join as join57, relative as relative14 } from "node:path";
61074
61184
  async function hasScripts(skillPath) {
61075
61185
  try {
61076
61186
  const entries = await readdir15(skillPath, { withFileTypes: true });
@@ -61136,7 +61246,7 @@ class SkillCatalogGenerator {
61136
61246
  };
61137
61247
  }
61138
61248
  async write(catalog) {
61139
- await mkdir14(dirname23(CATALOG_PATH), { recursive: true });
61249
+ await mkdir14(dirname24(CATALOG_PATH), { recursive: true });
61140
61250
  const tmpPath = `${CATALOG_PATH}.tmp`;
61141
61251
  const json = JSON.stringify(catalog, null, 2);
61142
61252
  await writeFile13(tmpPath, json, "utf-8");
@@ -61667,16 +61777,16 @@ var init_agents = __esm(() => {
61667
61777
  import { existsSync as existsSync39 } from "node:fs";
61668
61778
  import { mkdir as mkdir15, readFile as readFile30, writeFile as writeFile14 } from "node:fs/promises";
61669
61779
  import { homedir as homedir38 } from "node:os";
61670
- import { dirname as dirname24, join as join60, sep as sep10 } from "node:path";
61780
+ import { dirname as dirname25, join as join60, sep as sep10 } from "node:path";
61671
61781
  function getCliVersion3() {
61672
61782
  try {
61673
61783
  if (process.env.npm_package_version) {
61674
61784
  return process.env.npm_package_version;
61675
61785
  }
61676
61786
  const { readFileSync: readFileSync12 } = __require("node:fs");
61677
- const { dirname: dirname25, join: joinPath } = __require("node:path");
61787
+ const { dirname: dirname26, join: joinPath } = __require("node:path");
61678
61788
  const { fileURLToPath: fileURLToPath2 } = __require("node:url");
61679
- const __dirname3 = dirname25(fileURLToPath2(import.meta.url));
61789
+ const __dirname3 = dirname26(fileURLToPath2(import.meta.url));
61680
61790
  const pkgPath = joinPath(__dirname3, "../../../package.json");
61681
61791
  const pkg = JSON.parse(readFileSync12(pkgPath, "utf-8"));
61682
61792
  return pkg.version || "unknown";
@@ -61719,7 +61829,7 @@ async function readRegistry2() {
61719
61829
  }
61720
61830
  }
61721
61831
  async function writeRegistry2(registry) {
61722
- const dir = dirname24(REGISTRY_PATH2);
61832
+ const dir = dirname25(REGISTRY_PATH2);
61723
61833
  if (!existsSync39(dir)) {
61724
61834
  await mkdir15(dir, { recursive: true });
61725
61835
  }
@@ -61811,7 +61921,7 @@ var init_skills_registry = __esm(() => {
61811
61921
  import { existsSync as existsSync40 } from "node:fs";
61812
61922
  import { cp as cp3, mkdir as mkdir16, rm as rm8, stat as stat12 } from "node:fs/promises";
61813
61923
  import { homedir as homedir39 } from "node:os";
61814
- import { dirname as dirname25, join as join61, resolve as resolve28 } from "node:path";
61924
+ import { dirname as dirname26, join as join61, resolve as resolve28 } from "node:path";
61815
61925
  function isSamePath2(path1, path22) {
61816
61926
  try {
61817
61927
  return resolve28(path1) === resolve28(path22);
@@ -61880,7 +61990,7 @@ async function installSkillForAgent(skill, agent, options2) {
61880
61990
  try {
61881
61991
  await cleanupLegacySkillPath(skill.name, agent, options2.global);
61882
61992
  } catch {}
61883
- const parentDir = dirname25(targetPath);
61993
+ const parentDir = dirname26(targetPath);
61884
61994
  if (!existsSync40(parentDir)) {
61885
61995
  await mkdir16(parentDir, { recursive: true });
61886
61996
  }
@@ -62890,7 +63000,7 @@ var package_default;
62890
63000
  var init_package = __esm(() => {
62891
63001
  package_default = {
62892
63002
  name: "claudekit-cli",
62893
- version: "4.2.1",
63003
+ version: "4.2.3-dev.1",
62894
63004
  description: "CLI tool for bootstrapping and updating ClaudeKit projects",
62895
63005
  type: "module",
62896
63006
  repository: {
@@ -65970,7 +66080,7 @@ var init_routes = __esm(() => {
65970
66080
 
65971
66081
  // src/domains/web-server/static-server.ts
65972
66082
  import { existsSync as existsSync45 } from "node:fs";
65973
- import { basename as basename21, dirname as dirname26, join as join70, resolve as resolve30 } from "node:path";
66083
+ import { basename as basename21, dirname as dirname27, join as join70, resolve as resolve30 } from "node:path";
65974
66084
  import { fileURLToPath as fileURLToPath2 } from "node:url";
65975
66085
  function addRuntimeUiCandidate(candidates, runtimePath) {
65976
66086
  if (!runtimePath) {
@@ -65980,7 +66090,7 @@ function addRuntimeUiCandidate(candidates, runtimePath) {
65980
66090
  if (!looksLikePath) {
65981
66091
  return;
65982
66092
  }
65983
- const entryDir = dirname26(resolve30(runtimePath));
66093
+ const entryDir = dirname27(resolve30(runtimePath));
65984
66094
  if (basename21(entryDir) === "dist") {
65985
66095
  candidates.add(join70(entryDir, "ui"));
65986
66096
  }
@@ -66041,7 +66151,7 @@ var import_express, __dirname3;
66041
66151
  var init_static_server = __esm(() => {
66042
66152
  init_logger();
66043
66153
  import_express = __toESM(require_express2(), 1);
66044
- __dirname3 = dirname26(fileURLToPath2(import.meta.url));
66154
+ __dirname3 = dirname27(fileURLToPath2(import.meta.url));
66045
66155
  });
66046
66156
 
66047
66157
  // node_modules/ws/lib/constants.js
@@ -71527,7 +71637,7 @@ var init_skills_installer2 = __esm(() => {
71527
71637
  // src/services/package-installer/gemini-mcp/config-manager.ts
71528
71638
  import { existsSync as existsSync59 } from "node:fs";
71529
71639
  import { mkdir as mkdir23, readFile as readFile46, writeFile as writeFile22 } from "node:fs/promises";
71530
- import { dirname as dirname29, join as join92 } from "node:path";
71640
+ import { dirname as dirname30, join as join92 } from "node:path";
71531
71641
  async function readJsonFile(filePath) {
71532
71642
  try {
71533
71643
  const content = await readFile46(filePath, "utf-8");
@@ -71567,7 +71677,7 @@ ${geminiPattern}
71567
71677
  }
71568
71678
  }
71569
71679
  async function createNewSettingsWithMerge(geminiSettingsPath, mcpConfigPath) {
71570
- const linkDir = dirname29(geminiSettingsPath);
71680
+ const linkDir = dirname30(geminiSettingsPath);
71571
71681
  if (!existsSync59(linkDir)) {
71572
71682
  await mkdir23(linkDir, { recursive: true });
71573
71683
  logger.debug(`Created directory: ${linkDir}`);
@@ -71686,9 +71796,9 @@ var init_validation = __esm(() => {
71686
71796
  // src/services/package-installer/gemini-mcp/linker-core.ts
71687
71797
  import { existsSync as existsSync61 } from "node:fs";
71688
71798
  import { mkdir as mkdir24, symlink as symlink3 } from "node:fs/promises";
71689
- import { dirname as dirname30, join as join94 } from "node:path";
71799
+ import { dirname as dirname31, join as join94 } from "node:path";
71690
71800
  async function createSymlink(targetPath, linkPath, projectDir, isGlobal) {
71691
- const linkDir = dirname30(linkPath);
71801
+ const linkDir = dirname31(linkPath);
71692
71802
  if (!existsSync61(linkDir)) {
71693
71803
  await mkdir24(linkDir, { recursive: true });
71694
71804
  logger.debug(`Created directory: ${linkDir}`);
@@ -74006,76 +74116,6 @@ var init_ownership_display = __esm(() => {
74006
74116
  import_picocolors25 = __toESM(require_picocolors(), 1);
74007
74117
  });
74008
74118
 
74009
- // src/ui/node_modules/picocolors/picocolors.js
74010
- var require_picocolors2 = __commonJS((exports, module) => {
74011
- var p = process || {};
74012
- var argv = p.argv || [];
74013
- var env2 = p.env || {};
74014
- var isColorSupported = !(!!env2.NO_COLOR || argv.includes("--no-color")) && (!!env2.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env2.TERM !== "dumb" || !!env2.CI);
74015
- var formatter = (open6, close, replace3 = open6) => (input) => {
74016
- let string = "" + input, index = string.indexOf(close, open6.length);
74017
- return ~index ? open6 + replaceClose(string, close, replace3, index) + close : open6 + string + close;
74018
- };
74019
- var replaceClose = (string, close, replace3, index) => {
74020
- let result = "", cursor = 0;
74021
- do {
74022
- result += string.substring(cursor, index) + replace3;
74023
- cursor = index + close.length;
74024
- index = string.indexOf(close, cursor);
74025
- } while (~index);
74026
- return result + string.substring(cursor);
74027
- };
74028
- var createColors = (enabled = isColorSupported) => {
74029
- let f3 = enabled ? formatter : () => String;
74030
- return {
74031
- isColorSupported: enabled,
74032
- reset: f3("\x1B[0m", "\x1B[0m"),
74033
- bold: f3("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
74034
- dim: f3("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
74035
- italic: f3("\x1B[3m", "\x1B[23m"),
74036
- underline: f3("\x1B[4m", "\x1B[24m"),
74037
- inverse: f3("\x1B[7m", "\x1B[27m"),
74038
- hidden: f3("\x1B[8m", "\x1B[28m"),
74039
- strikethrough: f3("\x1B[9m", "\x1B[29m"),
74040
- black: f3("\x1B[30m", "\x1B[39m"),
74041
- red: f3("\x1B[31m", "\x1B[39m"),
74042
- green: f3("\x1B[32m", "\x1B[39m"),
74043
- yellow: f3("\x1B[33m", "\x1B[39m"),
74044
- blue: f3("\x1B[34m", "\x1B[39m"),
74045
- magenta: f3("\x1B[35m", "\x1B[39m"),
74046
- cyan: f3("\x1B[36m", "\x1B[39m"),
74047
- white: f3("\x1B[37m", "\x1B[39m"),
74048
- gray: f3("\x1B[90m", "\x1B[39m"),
74049
- bgBlack: f3("\x1B[40m", "\x1B[49m"),
74050
- bgRed: f3("\x1B[41m", "\x1B[49m"),
74051
- bgGreen: f3("\x1B[42m", "\x1B[49m"),
74052
- bgYellow: f3("\x1B[43m", "\x1B[49m"),
74053
- bgBlue: f3("\x1B[44m", "\x1B[49m"),
74054
- bgMagenta: f3("\x1B[45m", "\x1B[49m"),
74055
- bgCyan: f3("\x1B[46m", "\x1B[49m"),
74056
- bgWhite: f3("\x1B[47m", "\x1B[49m"),
74057
- blackBright: f3("\x1B[90m", "\x1B[39m"),
74058
- redBright: f3("\x1B[91m", "\x1B[39m"),
74059
- greenBright: f3("\x1B[92m", "\x1B[39m"),
74060
- yellowBright: f3("\x1B[93m", "\x1B[39m"),
74061
- blueBright: f3("\x1B[94m", "\x1B[39m"),
74062
- magentaBright: f3("\x1B[95m", "\x1B[39m"),
74063
- cyanBright: f3("\x1B[96m", "\x1B[39m"),
74064
- whiteBright: f3("\x1B[97m", "\x1B[39m"),
74065
- bgBlackBright: f3("\x1B[100m", "\x1B[49m"),
74066
- bgRedBright: f3("\x1B[101m", "\x1B[49m"),
74067
- bgGreenBright: f3("\x1B[102m", "\x1B[49m"),
74068
- bgYellowBright: f3("\x1B[103m", "\x1B[49m"),
74069
- bgBlueBright: f3("\x1B[104m", "\x1B[49m"),
74070
- bgMagentaBright: f3("\x1B[105m", "\x1B[49m"),
74071
- bgCyanBright: f3("\x1B[106m", "\x1B[49m"),
74072
- bgWhiteBright: f3("\x1B[107m", "\x1B[49m")
74073
- };
74074
- };
74075
- module.exports = createColors();
74076
- module.exports.createColors = createColors;
74077
- });
74078
-
74079
74119
  // src/commands/watch/phases/implementation-git-helpers.ts
74080
74120
  import { spawn as spawn5 } from "node:child_process";
74081
74121
  async function getCurrentBranch2(cwd2) {
@@ -75105,7 +75145,7 @@ var init_sqlite_client = () => {};
75105
75145
 
75106
75146
  // src/commands/content/phases/db-manager.ts
75107
75147
  import { existsSync as existsSync80, mkdirSync as mkdirSync8 } from "node:fs";
75108
- import { dirname as dirname47 } from "node:path";
75148
+ import { dirname as dirname48 } from "node:path";
75109
75149
  function initDatabase(dbPath) {
75110
75150
  ensureParentDir(dbPath);
75111
75151
  const db = openDatabase(dbPath);
@@ -75126,7 +75166,7 @@ function runRetentionCleanup(db, retentionDays = 90) {
75126
75166
  db.prepare("DELETE FROM git_events WHERE processed = 1 AND created_at < ?").run(cutoff);
75127
75167
  }
75128
75168
  function ensureParentDir(dbPath) {
75129
- const dir = dirname47(dbPath);
75169
+ const dir = dirname48(dbPath);
75130
75170
  if (dir && !existsSync80(dir)) {
75131
75171
  mkdirSync8(dir, { recursive: true });
75132
75172
  }
@@ -85190,12 +85230,13 @@ async function applyBudgetDefaults(settingsPath, projectClaudeDir, requiredFract
85190
85230
  var ENGINEER_SKILL_COUNT_THRESHOLD = 20;
85191
85231
  async function checkSkillBudget(setup, projectDir) {
85192
85232
  const projectClaudeDir = resolve31(projectDir, ".claude");
85193
- const globalClaudeDir = PathResolver.getGlobalKitDir();
85233
+ const globalClaudeDir = resolve31(PathResolver.getGlobalKitDir());
85234
+ const projectScopeAliasesGlobal = projectClaudeDir === globalClaudeDir;
85194
85235
  const [projectSkills, globalSkills] = await Promise.all([
85195
- scanSkills2(join75(projectClaudeDir, "skills")),
85236
+ projectScopeAliasesGlobal ? Promise.resolve([]) : scanSkills2(join75(projectClaudeDir, "skills")),
85196
85237
  scanSkills2(join75(globalClaudeDir, "skills"))
85197
85238
  ]);
85198
- if (!isEngineerLikeProject(setup, projectSkills))
85239
+ if (!isEngineerLikeProject(setup, [...projectSkills, ...globalSkills]))
85199
85240
  return [];
85200
85241
  const settingsPath = join75(projectClaudeDir, "settings.json");
85201
85242
  const settings = await readProjectSettings(settingsPath);
@@ -85216,7 +85257,10 @@ function isEngineerLikeProject(setup, projectSkills) {
85216
85257
  const metadataText = [
85217
85258
  setup.project.metadata?.name,
85218
85259
  setup.project.metadata?.description,
85219
- setup.project.metadata?.repository?.url
85260
+ setup.project.metadata?.repository?.url,
85261
+ setup.global.metadata?.name,
85262
+ setup.global.metadata?.description,
85263
+ setup.global.metadata?.repository?.url
85220
85264
  ].filter(Boolean).join(" ").toLowerCase();
85221
85265
  return metadataText.includes("engineer") || projectSkills.length >= ENGINEER_SKILL_COUNT_THRESHOLD;
85222
85266
  }
@@ -85593,7 +85637,7 @@ init_path_resolver();
85593
85637
  import { existsSync as existsSync54 } from "node:fs";
85594
85638
  import { readFile as readFile41 } from "node:fs/promises";
85595
85639
  import { homedir as homedir41 } from "node:os";
85596
- import { dirname as dirname27, join as join79, normalize as normalize6, resolve as resolve32 } from "node:path";
85640
+ import { dirname as dirname28, join as join79, normalize as normalize6, resolve as resolve32 } from "node:path";
85597
85641
  async function checkPathRefsValid(projectDir) {
85598
85642
  const globalClaudeMd = join79(PathResolver.getGlobalKitDir(), "CLAUDE.md");
85599
85643
  const projectClaudeMd = join79(projectDir, ".claude", "CLAUDE.md");
@@ -85624,7 +85668,7 @@ async function checkPathRefsValid(projectDir) {
85624
85668
  autoFixable: false
85625
85669
  };
85626
85670
  }
85627
- const baseDir = dirname27(claudeMdPath);
85671
+ const baseDir = dirname28(claudeMdPath);
85628
85672
  const home6 = homedir41();
85629
85673
  const broken = [];
85630
85674
  for (const ref of refs) {
@@ -86280,7 +86324,7 @@ function getClaudeSettingsFiles(projectDir) {
86280
86324
  return candidates.filter((candidate) => existsSync56(candidate.path));
86281
86325
  }
86282
86326
  function isAlreadyCanonical(cmd) {
86283
- return /^node\s+"\$HOME\/\.claude\/[^"]+"/.test(cmd) || /^node\s+"\$CLAUDE_PROJECT_DIR"\/\.claude\/\S+/.test(cmd);
86327
+ return /^node\s+"\$HOME\/\.claude\/[^"]+"/.test(cmd) || /^node\s+"\$CLAUDE_PROJECT_DIR"\/\.claude\/\S+/.test(cmd) || /^bash\s+"\$HOME\/\.claude\/hooks\/node-hook-runner\.sh"\s+"\$HOME\/\.claude\/[^"]+"/.test(cmd) || /^bash\s+"\$CLAUDE_PROJECT_DIR"\/\.claude\/hooks\/node-hook-runner\.sh\s+"\$CLAUDE_PROJECT_DIR"\/\.claude\/\S+/.test(cmd);
86284
86328
  }
86285
86329
  function collectHookCommandFindings(settings, settingsFile) {
86286
86330
  if (!settings.hooks) {
@@ -86292,7 +86336,7 @@ function collectHookCommandFindings(settings, settingsFile) {
86292
86336
  if ("command" in entry && typeof entry.command === "string") {
86293
86337
  if (isAlreadyCanonical(entry.command))
86294
86338
  continue;
86295
- const repair = repairClaudeNodeCommandPath(entry.command, settingsFile.root);
86339
+ const repair = repairClaudeHookCommandPath(entry.command, settingsFile.root);
86296
86340
  if (repair.changed && repair.issue) {
86297
86341
  findings.push({
86298
86342
  path: settingsFile.path,
@@ -86313,7 +86357,7 @@ function collectHookCommandFindings(settings, settingsFile) {
86313
86357
  }
86314
86358
  if (isAlreadyCanonical(hook.command))
86315
86359
  continue;
86316
- const repair = repairClaudeNodeCommandPath(hook.command, settingsFile.root);
86360
+ const repair = repairClaudeHookCommandPath(hook.command, settingsFile.root);
86317
86361
  if (!repair.changed || !repair.issue) {
86318
86362
  continue;
86319
86363
  }
@@ -88647,14 +88691,14 @@ class AutoHealer {
88647
88691
  import { execSync as execSync4, spawnSync as spawnSync6 } from "node:child_process";
88648
88692
  import { readFileSync as readFileSync16, unlinkSync as unlinkSync2, writeFileSync as writeFileSync6 } from "node:fs";
88649
88693
  import { tmpdir as tmpdir3 } from "node:os";
88650
- import { dirname as dirname28, join as join87 } from "node:path";
88694
+ import { dirname as dirname29, join as join87 } from "node:path";
88651
88695
  import { fileURLToPath as fileURLToPath4 } from "node:url";
88652
88696
  init_environment();
88653
88697
  init_logger();
88654
88698
  init_dist2();
88655
88699
  function getCliVersion4() {
88656
88700
  try {
88657
- const __dirname4 = dirname28(fileURLToPath4(import.meta.url));
88701
+ const __dirname4 = dirname29(fileURLToPath4(import.meta.url));
88658
88702
  const pkgPath = join87(__dirname4, "../../../package.json");
88659
88703
  const pkg = JSON.parse(readFileSync16(pkgPath, "utf-8"));
88660
88704
  return pkg.version || "unknown";
@@ -89119,7 +89163,7 @@ init_github_client();
89119
89163
  init_config_version_checker();
89120
89164
 
89121
89165
  // src/domains/sync/sync-engine.ts
89122
- import { lstat as lstat6, readFile as readFile45, readlink as readlink2, realpath as realpath6, stat as stat14 } from "node:fs/promises";
89166
+ import { lstat as lstat6, readFile as readFile45, readlink as readlink2, realpath as realpath7, stat as stat14 } from "node:fs/promises";
89123
89167
  import { isAbsolute as isAbsolute8, join as join88, normalize as normalize8, relative as relative17 } from "node:path";
89124
89168
 
89125
89169
  // src/services/file-operations/ownership-checker.ts
@@ -89747,14 +89791,14 @@ class JsonDiff extends Diff {
89747
89791
  }
89748
89792
  castInput(value, options2) {
89749
89793
  const { undefinedReplacement, stringifyReplacer = (k2, v2) => typeof v2 === "undefined" ? undefinedReplacement : v2 } = options2;
89750
- return typeof value === "string" ? value : JSON.stringify(canonicalize(value, null, null, stringifyReplacer), null, " ");
89794
+ return typeof value === "string" ? value : JSON.stringify(canonicalize2(value, null, null, stringifyReplacer), null, " ");
89751
89795
  }
89752
89796
  equals(left, right, options2) {
89753
89797
  return super.equals(left.replace(/,([\r\n])/g, "$1"), right.replace(/,([\r\n])/g, "$1"), options2);
89754
89798
  }
89755
89799
  }
89756
89800
  var jsonDiff = new JsonDiff;
89757
- function canonicalize(obj, stack, replacementStack, replacer, key) {
89801
+ function canonicalize2(obj, stack, replacementStack, replacer, key) {
89758
89802
  stack = stack || [];
89759
89803
  replacementStack = replacementStack || [];
89760
89804
  if (replacer) {
@@ -89772,7 +89816,7 @@ function canonicalize(obj, stack, replacementStack, replacer, key) {
89772
89816
  canonicalizedObj = new Array(obj.length);
89773
89817
  replacementStack.push(canonicalizedObj);
89774
89818
  for (i = 0;i < obj.length; i += 1) {
89775
- canonicalizedObj[i] = canonicalize(obj[i], stack, replacementStack, replacer, String(i));
89819
+ canonicalizedObj[i] = canonicalize2(obj[i], stack, replacementStack, replacer, String(i));
89776
89820
  }
89777
89821
  stack.pop();
89778
89822
  replacementStack.pop();
@@ -89795,7 +89839,7 @@ function canonicalize(obj, stack, replacementStack, replacer, key) {
89795
89839
  sortedKeys.sort();
89796
89840
  for (i = 0;i < sortedKeys.length; i += 1) {
89797
89841
  key2 = sortedKeys[i];
89798
- canonicalizedObj[key2] = canonicalize(obj[key2], stack, replacementStack, replacer, key2);
89842
+ canonicalizedObj[key2] = canonicalize2(obj[key2], stack, replacementStack, replacer, key2);
89799
89843
  }
89800
89844
  stack.pop();
89801
89845
  replacementStack.pop();
@@ -90378,8 +90422,8 @@ async function validateSyncPath(basePath, filePath) {
90378
90422
  }
90379
90423
  await validateSymlinkChain(fullPath, basePath);
90380
90424
  try {
90381
- const resolvedBase = await realpath6(basePath);
90382
- const resolvedFull = await realpath6(fullPath);
90425
+ const resolvedBase = await realpath7(basePath);
90426
+ const resolvedFull = await realpath7(fullPath);
90383
90427
  const resolvedRel = relative17(resolvedBase, resolvedFull);
90384
90428
  if (resolvedRel.startsWith("..") || isAbsolute8(resolvedRel)) {
90385
90429
  throw new Error(`Symlink escapes base directory: ${filePath}`);
@@ -90388,8 +90432,8 @@ async function validateSyncPath(basePath, filePath) {
90388
90432
  if (error.code === "ENOENT") {
90389
90433
  const parentPath = join88(fullPath, "..");
90390
90434
  try {
90391
- const resolvedBase = await realpath6(basePath);
90392
- const resolvedParent = await realpath6(parentPath);
90435
+ const resolvedBase = await realpath7(basePath);
90436
+ const resolvedParent = await realpath7(parentPath);
90393
90437
  const resolvedRel = relative17(resolvedBase, resolvedParent);
90394
90438
  if (resolvedRel.startsWith("..") || isAbsolute8(resolvedRel)) {
90395
90439
  throw new Error(`Parent symlink escapes base directory: ${filePath}`);
@@ -93222,7 +93266,7 @@ import path9 from "node:path";
93222
93266
 
93223
93267
  // node_modules/tar/dist/esm/list.js
93224
93268
  import fs10 from "node:fs";
93225
- import { dirname as dirname31, parse as parse4 } from "path";
93269
+ import { dirname as dirname32, parse as parse4 } from "path";
93226
93270
 
93227
93271
  // node_modules/tar/dist/esm/options.js
93228
93272
  var argmap = new Map([
@@ -96122,7 +96166,7 @@ var filesFilter = (opt, files) => {
96122
96166
  if (m2 !== undefined) {
96123
96167
  ret = m2;
96124
96168
  } else {
96125
- ret = mapHas(dirname31(file), root);
96169
+ ret = mapHas(dirname32(file), root);
96126
96170
  }
96127
96171
  }
96128
96172
  map.set(file, ret);
@@ -99865,7 +99909,7 @@ import { join as join120 } from "node:path";
99865
99909
 
99866
99910
  // src/domains/installation/deletion-handler.ts
99867
99911
  import { existsSync as existsSync62, lstatSync as lstatSync3, readdirSync as readdirSync7, rmSync as rmSync2, rmdirSync, unlinkSync as unlinkSync4 } from "node:fs";
99868
- import { dirname as dirname33, join as join106, relative as relative20, resolve as resolve38, sep as sep11 } from "node:path";
99912
+ import { dirname as dirname34, join as join106, relative as relative20, resolve as resolve38, sep as sep11 } from "node:path";
99869
99913
 
99870
99914
  // src/services/file-operations/manifest/manifest-reader.ts
99871
99915
  init_metadata_migration();
@@ -100091,7 +100135,7 @@ function expandGlobPatterns(patterns, claudeDir3) {
100091
100135
  var MAX_CLEANUP_ITERATIONS = 50;
100092
100136
  function cleanupEmptyDirectories(filePath, claudeDir3) {
100093
100137
  const normalizedClaudeDir = resolve38(claudeDir3);
100094
- let currentDir = resolve38(dirname33(filePath));
100138
+ let currentDir = resolve38(dirname34(filePath));
100095
100139
  let iterations = 0;
100096
100140
  while (currentDir !== normalizedClaudeDir && currentDir.startsWith(normalizedClaudeDir) && iterations < MAX_CLEANUP_ITERATIONS) {
100097
100141
  iterations++;
@@ -100100,7 +100144,7 @@ function cleanupEmptyDirectories(filePath, claudeDir3) {
100100
100144
  if (entries.length === 0) {
100101
100145
  rmdirSync(currentDir);
100102
100146
  logger.debug(`Removed empty directory: ${currentDir}`);
100103
- currentDir = resolve38(dirname33(currentDir));
100147
+ currentDir = resolve38(dirname34(currentDir));
100104
100148
  } else {
100105
100149
  break;
100106
100150
  }
@@ -100223,7 +100267,7 @@ init_logger();
100223
100267
  init_types3();
100224
100268
  var import_fs_extra15 = __toESM(require_lib(), 1);
100225
100269
  var import_ignore3 = __toESM(require_ignore(), 1);
100226
- import { dirname as dirname36, join as join110, relative as relative22 } from "node:path";
100270
+ import { dirname as dirname37, join as join110, relative as relative22 } from "node:path";
100227
100271
 
100228
100272
  // src/domains/installation/selective-merger.ts
100229
100273
  import { stat as stat18 } from "node:fs/promises";
@@ -101894,13 +101938,13 @@ class FileScanner {
101894
101938
  // src/domains/installation/merger/settings-processor.ts
101895
101939
  import { execSync as execSync5 } from "node:child_process";
101896
101940
  import { homedir as homedir45 } from "node:os";
101897
- import { dirname as dirname35, join as join109 } from "node:path";
101941
+ import { dirname as dirname36, join as join109 } from "node:path";
101898
101942
 
101899
101943
  // src/domains/config/installed-settings-tracker.ts
101900
101944
  init_shared();
101901
101945
  import { existsSync as existsSync63 } from "node:fs";
101902
101946
  import { mkdir as mkdir31, readFile as readFile49, writeFile as writeFile24 } from "node:fs/promises";
101903
- import { dirname as dirname34, join as join108 } from "node:path";
101947
+ import { dirname as dirname35, join as join108 } from "node:path";
101904
101948
  var CK_JSON_FILE = ".ck.json";
101905
101949
 
101906
101950
  class InstalledSettingsTracker {
@@ -101951,7 +101995,7 @@ class InstalledSettingsTracker {
101951
101995
  data.kits[this.kitName] = {};
101952
101996
  }
101953
101997
  data.kits[this.kitName].installedSettings = settings;
101954
- await mkdir31(dirname34(ckJsonPath), { recursive: true });
101998
+ await mkdir31(dirname35(ckJsonPath), { recursive: true });
101955
101999
  await writeFile24(ckJsonPath, JSON.stringify(data, null, 2), "utf-8");
101956
102000
  logger.debug(`Saved installed settings to ${ckJsonPath}`);
101957
102001
  } catch (error) {
@@ -102054,7 +102098,7 @@ class SettingsProcessor {
102054
102098
  } else {
102055
102099
  try {
102056
102100
  const parsedSettings = JSON.parse(transformedSource);
102057
- this.fixHookCommandPaths(parsedSettings);
102101
+ this.logHookCommandRepair(this.fixHookCommandPaths(parsedSettings), "fresh install");
102058
102102
  await SettingsMerger.writeSettingsFile(destFile, parsedSettings);
102059
102103
  try {
102060
102104
  if (this.forceOverwriteSettings && destExists) {
@@ -102132,10 +102176,7 @@ class SettingsProcessor {
102132
102176
  }
102133
102177
  await this.tracker.saveInstalledSettings(installedSettings);
102134
102178
  }
102135
- const pathsFixed = this.fixHookCommandPaths(mergeResult.merged);
102136
- if (pathsFixed) {
102137
- logger.info("Fixed hook command paths to canonical quoted format");
102138
- }
102179
+ this.logHookCommandRepair(this.fixHookCommandPaths(mergeResult.merged), "merged settings");
102139
102180
  const hooksPruned = this.pruneDeletedHooks(mergeResult.merged);
102140
102181
  if (hooksPruned > 0) {
102141
102182
  logger.info(`Pruned ${hooksPruned} stale hook(s) referencing deleted files`);
@@ -102279,7 +102320,7 @@ class SettingsProcessor {
102279
102320
  if (!content.trim())
102280
102321
  return null;
102281
102322
  const parsedSettings = JSON.parse(content);
102282
- this.fixHookCommandPaths(parsedSettings);
102323
+ this.logHookCommandRepair(this.fixHookCommandPaths(parsedSettings), "existing global settings");
102283
102324
  return parsedSettings;
102284
102325
  } catch {
102285
102326
  return null;
@@ -102302,8 +102343,14 @@ class SettingsProcessor {
102302
102343
  }
102303
102344
  return transformed;
102304
102345
  }
102346
+ logHookCommandRepair(count, context) {
102347
+ if (count <= 0)
102348
+ return;
102349
+ const suffix = context ? ` (${context})` : "";
102350
+ logger.info(`Repaired ${count} hook command path(s) to canonical quoted format${suffix} — protects against shells word-splitting on usernames with spaces`);
102351
+ }
102305
102352
  fixHookCommandPaths(settings) {
102306
- let fixed = false;
102353
+ let fixed = 0;
102307
102354
  if (settings.hooks) {
102308
102355
  for (const entries of Object.values(settings.hooks)) {
102309
102356
  for (const entry of entries) {
@@ -102311,7 +102358,7 @@ class SettingsProcessor {
102311
102358
  const result = this.fixSingleCommandPath(entry.command);
102312
102359
  if (result !== entry.command) {
102313
102360
  entry.command = result;
102314
- fixed = true;
102361
+ fixed++;
102315
102362
  }
102316
102363
  }
102317
102364
  if ("hooks" in entry && entry.hooks) {
@@ -102320,7 +102367,7 @@ class SettingsProcessor {
102320
102367
  const result = this.fixSingleCommandPath(hook.command);
102321
102368
  if (result !== hook.command) {
102322
102369
  hook.command = result;
102323
- fixed = true;
102370
+ fixed++;
102324
102371
  }
102325
102372
  }
102326
102373
  }
@@ -102333,13 +102380,13 @@ class SettingsProcessor {
102333
102380
  const result = this.fixSingleCommandPath(statusLine.command);
102334
102381
  if (result !== statusLine.command) {
102335
102382
  statusLine.command = result;
102336
- fixed = true;
102383
+ fixed++;
102337
102384
  }
102338
102385
  }
102339
102386
  return fixed;
102340
102387
  }
102341
102388
  fixSingleCommandPath(cmd) {
102342
- return repairClaudeNodeCommandPath(cmd, this.getClaudeCommandRoot()).command;
102389
+ return repairClaudeHookCommandPath(cmd, this.getClaudeCommandRoot()).command;
102343
102390
  }
102344
102391
  formatCommandPath(nodePrefix, capturedVar, relativePath, suffix = "") {
102345
102392
  const canonicalRoot = this.canonicalizePathRoot(capturedVar);
@@ -102391,20 +102438,19 @@ class SettingsProcessor {
102391
102438
  return false;
102392
102439
  }
102393
102440
  const pathsFixed = this.fixHookCommandPaths(settings);
102394
- if (!pathsFixed) {
102441
+ if (pathsFixed === 0) {
102395
102442
  return false;
102396
102443
  }
102444
+ this.logHookCommandRepair(pathsFixed, filePath);
102397
102445
  await SettingsMerger.writeSettingsFile(filePath, settings);
102398
102446
  return true;
102399
102447
  }
102400
102448
  async repairSiblingSettingsLocal(destFile) {
102401
- const settingsLocalPath = join109(dirname35(destFile), "settings.local.json");
102449
+ const settingsLocalPath = join109(dirname36(destFile), "settings.local.json");
102402
102450
  if (settingsLocalPath === destFile || !await import_fs_extra14.pathExists(settingsLocalPath)) {
102403
102451
  return;
102404
102452
  }
102405
- if (await this.repairSettingsFile(settingsLocalPath)) {
102406
- logger.info(`Repaired stale .claude command paths in ${settingsLocalPath}`);
102407
- }
102453
+ await this.repairSettingsFile(settingsLocalPath);
102408
102454
  }
102409
102455
  detectClaudeCodeVersion() {
102410
102456
  if (this.cachedVersion !== undefined)
@@ -102660,10 +102706,10 @@ class CopyExecutor {
102660
102706
  }
102661
102707
  trackInstalledFile(relativePath) {
102662
102708
  this.installedFiles.add(relativePath);
102663
- let dir = dirname36(relativePath);
102709
+ let dir = dirname37(relativePath);
102664
102710
  while (dir && dir !== "." && dir !== "/") {
102665
102711
  this.installedDirectories.add(`${dir}/`);
102666
- dir = dirname36(dir);
102712
+ dir = dirname37(dir);
102667
102713
  }
102668
102714
  }
102669
102715
  }
@@ -105813,7 +105859,7 @@ async function runPreflightChecks() {
105813
105859
  // src/domains/installation/fresh-installer.ts
105814
105860
  init_metadata_migration();
105815
105861
  import { existsSync as existsSync64, readdirSync as readdirSync8, rmSync as rmSync3, rmdirSync as rmdirSync2, unlinkSync as unlinkSync5 } from "node:fs";
105816
- import { basename as basename25, dirname as dirname37, join as join132, resolve as resolve40 } from "node:path";
105862
+ import { basename as basename25, dirname as dirname38, join as join132, resolve as resolve40 } from "node:path";
105817
105863
  init_logger();
105818
105864
  init_safe_spinner();
105819
105865
  var import_fs_extra34 = __toESM(require_lib(), 1);
@@ -105866,14 +105912,14 @@ async function analyzeFreshInstallation(claudeDir3) {
105866
105912
  }
105867
105913
  function cleanupEmptyDirectories2(filePath, claudeDir3) {
105868
105914
  const normalizedClaudeDir = resolve40(claudeDir3);
105869
- let currentDir = resolve40(dirname37(filePath));
105915
+ let currentDir = resolve40(dirname38(filePath));
105870
105916
  while (currentDir !== normalizedClaudeDir && currentDir.startsWith(normalizedClaudeDir)) {
105871
105917
  try {
105872
105918
  const entries = readdirSync8(currentDir);
105873
105919
  if (entries.length === 0) {
105874
105920
  rmdirSync2(currentDir);
105875
105921
  logger.debug(`Removed empty directory: ${currentDir}`);
105876
- currentDir = resolve40(dirname37(currentDir));
105922
+ currentDir = resolve40(dirname38(currentDir));
105877
105923
  } else {
105878
105924
  break;
105879
105925
  }
@@ -106440,7 +106486,7 @@ async function handleSelection(ctx) {
106440
106486
  }
106441
106487
  // src/commands/init/phases/sync-handler.ts
106442
106488
  import { copyFile as copyFile8, mkdir as mkdir36, open as open5, readFile as readFile58, rename as rename10, stat as stat22, unlink as unlink12, writeFile as writeFile32 } from "node:fs/promises";
106443
- import { dirname as dirname38, join as join134, resolve as resolve43 } from "node:path";
106489
+ import { dirname as dirname39, join as join134, resolve as resolve43 } from "node:path";
106444
106490
  init_logger();
106445
106491
  init_path_resolver();
106446
106492
  var import_fs_extra36 = __toESM(require_lib(), 1);
@@ -106559,7 +106605,7 @@ async function acquireSyncLock(global3) {
106559
106605
  const lockPath = join134(cacheDir, ".sync-lock");
106560
106606
  const startTime = Date.now();
106561
106607
  const lockTimeout = getLockTimeout();
106562
- await mkdir36(dirname38(lockPath), { recursive: true });
106608
+ await mkdir36(dirname39(lockPath), { recursive: true });
106563
106609
  while (Date.now() - startTime < lockTimeout) {
106564
106610
  try {
106565
106611
  const handle = await open5(lockPath, "wx");
@@ -107512,7 +107558,7 @@ import { basename as basename27, join as join142, resolve as resolve46 } from "n
107512
107558
  init_logger();
107513
107559
 
107514
107560
  // src/ui/ck-cli-design/tokens.ts
107515
- var import_picocolors27 = __toESM(require_picocolors2(), 1);
107561
+ var import_picocolors27 = __toESM(require_picocolors(), 1);
107516
107562
  import { homedir as homedir47, platform as platform16 } from "node:os";
107517
107563
  import { resolve as resolve45, win32 as win322 } from "node:path";
107518
107564
  var PANEL_MIN_WIDTH = 60;
@@ -107985,7 +108031,7 @@ init_dist2();
107985
108031
  init_model_taxonomy();
107986
108032
  import { mkdir as mkdir38, readFile as readFile63, writeFile as writeFile36 } from "node:fs/promises";
107987
108033
  import { homedir as homedir50 } from "node:os";
107988
- import { dirname as dirname39, join as join141 } from "node:path";
108034
+ import { dirname as dirname40, join as join141 } from "node:path";
107989
108035
 
107990
108036
  // src/commands/portable/models-dev-cache.ts
107991
108037
  init_logger();
@@ -108338,7 +108384,7 @@ async function ensureOpenCodeModel(options2) {
108338
108384
  }
108339
108385
  const chosenModel2 = response2.action === "custom" ? response2.value : suggestion2.model;
108340
108386
  const next2 = { ...existing, model: chosenModel2 };
108341
- await mkdir38(dirname39(configPath), { recursive: true });
108387
+ await mkdir38(dirname40(configPath), { recursive: true });
108342
108388
  await writeFile36(configPath, `${JSON.stringify(next2, null, 2)}
108343
108389
  `, "utf-8");
108344
108390
  return { path: configPath, action: "added", model: chosenModel2, reason: suggestion2.reason };
@@ -108349,7 +108395,7 @@ async function ensureOpenCodeModel(options2) {
108349
108395
  throw new OpenCodeAuthRequiredError(suggestion.failure);
108350
108396
  }
108351
108397
  const next2 = { ...existing ?? {}, model: suggestion.model };
108352
- await mkdir38(dirname39(configPath), { recursive: true });
108398
+ await mkdir38(dirname40(configPath), { recursive: true });
108353
108399
  await writeFile36(configPath, `${JSON.stringify(next2, null, 2)}
108354
108400
  `, "utf-8");
108355
108401
  return {
@@ -108371,7 +108417,7 @@ async function ensureOpenCodeModel(options2) {
108371
108417
  }
108372
108418
  const chosenModel = response.action === "custom" ? response.value : suggestion.ok ? suggestion.model : "";
108373
108419
  const next = { ...existing ?? {}, model: chosenModel };
108374
- await mkdir38(dirname39(configPath), { recursive: true });
108420
+ await mkdir38(dirname40(configPath), { recursive: true });
108375
108421
  await writeFile36(configPath, `${JSON.stringify(next, null, 2)}
108376
108422
  `, "utf-8");
108377
108423
  return {
@@ -108384,7 +108430,7 @@ async function ensureOpenCodeModel(options2) {
108384
108430
 
108385
108431
  // src/commands/portable/plan-display.ts
108386
108432
  var import_picocolors28 = __toESM(require_picocolors(), 1);
108387
- import { basename as basename26, dirname as dirname40, extname as extname7 } from "node:path";
108433
+ import { basename as basename26, dirname as dirname41, extname as extname7 } from "node:path";
108388
108434
  var DEFAULT_MAX_PLAN_GROUP_ITEMS = 20;
108389
108435
  var TYPE_ORDER = [
108390
108436
  "agent",
@@ -108610,21 +108656,21 @@ function collectPlannedWhereLines(plan) {
108610
108656
  return destinations.map((destination) => `${formatDisplayPath(destination)} -> ${formatCdHint(resolveCdTarget(destination))}`);
108611
108657
  }
108612
108658
  function resolveCdTarget(destination) {
108613
- return extname7(destination).length > 0 ? dirname40(destination) : destination;
108659
+ return extname7(destination).length > 0 ? dirname41(destination) : destination;
108614
108660
  }
108615
108661
  function normalizeWhereDestination(path16, portableType) {
108616
108662
  if (portableType === "agent" || portableType === "command" || portableType === "skill") {
108617
- return dirname40(path16);
108663
+ return dirname41(path16);
108618
108664
  }
108619
108665
  if (portableType === "hooks") {
108620
- return dirname40(path16);
108666
+ return dirname41(path16);
108621
108667
  }
108622
108668
  if (portableType === "rules") {
108623
108669
  const fileName = basename26(path16).toLowerCase();
108624
108670
  if (fileName === "agents.md" || fileName === "gemini.md" || fileName === ".goosehints" || fileName === "custom_modes.yaml" || fileName === "custom_modes.yml") {
108625
108671
  return path16;
108626
108672
  }
108627
- return dirname40(path16);
108673
+ return dirname41(path16);
108628
108674
  }
108629
108675
  return path16;
108630
108676
  }
@@ -110342,7 +110388,7 @@ Please use only one download method.`);
110342
110388
  // src/commands/plan/plan-command.ts
110343
110389
  init_output_manager();
110344
110390
  import { existsSync as existsSync68, statSync as statSync12 } from "node:fs";
110345
- import { dirname as dirname44, isAbsolute as isAbsolute11, join as join147, parse as parse7, resolve as resolve51 } from "node:path";
110391
+ import { dirname as dirname45, isAbsolute as isAbsolute11, join as join147, parse as parse7, resolve as resolve51 } from "node:path";
110346
110392
 
110347
110393
  // src/commands/plan/plan-read-handlers.ts
110348
110394
  init_config();
@@ -110352,18 +110398,18 @@ init_logger();
110352
110398
  init_output_manager();
110353
110399
  var import_picocolors32 = __toESM(require_picocolors(), 1);
110354
110400
  import { existsSync as existsSync67, statSync as statSync11 } from "node:fs";
110355
- import { basename as basename28, dirname as dirname42, join as join146, relative as relative30, resolve as resolve49 } from "node:path";
110401
+ import { basename as basename28, dirname as dirname43, join as join146, relative as relative30, resolve as resolve49 } from "node:path";
110356
110402
 
110357
110403
  // src/commands/plan/plan-dependencies.ts
110358
110404
  init_config();
110359
110405
  init_plan_parser();
110360
110406
  init_plans_registry();
110361
110407
  import { existsSync as existsSync66 } from "node:fs";
110362
- import { dirname as dirname41, join as join145 } from "node:path";
110408
+ import { dirname as dirname42, join as join145 } from "node:path";
110363
110409
  async function resolvePlanDependencies(references, currentPlanFile, options2 = {}) {
110364
110410
  if (references.length === 0)
110365
110411
  return [];
110366
- const currentPlanDir = dirname41(currentPlanFile);
110412
+ const currentPlanDir = dirname42(currentPlanFile);
110367
110413
  const projectRoot = findProjectRoot(currentPlanDir);
110368
110414
  const config = options2.preloadedConfig ?? (await CkConfigManager.loadFull(projectRoot)).config;
110369
110415
  const defaultScope = inferPlanScopeForDir(currentPlanDir, config);
@@ -110450,7 +110496,7 @@ async function handleParse(target, options2) {
110450
110496
  console.log(JSON.stringify({ file: relative30(process.cwd(), planFile), frontmatter, phases }, null, 2));
110451
110497
  return;
110452
110498
  }
110453
- const title = typeof frontmatter.title === "string" ? frontmatter.title : basename28(dirname42(planFile));
110499
+ const title = typeof frontmatter.title === "string" ? frontmatter.title : basename28(dirname43(planFile));
110454
110500
  console.log();
110455
110501
  console.log(import_picocolors32.default.bold(` Plan: ${title}`));
110456
110502
  console.log(` File: ${planFile}`);
@@ -110561,7 +110607,7 @@ async function handleStatus(target, options2) {
110561
110607
  const blockedBy2 = await resolvePlanDependencies(s.blockedBy, pf, { preloadedConfig });
110562
110608
  const blocks2 = await resolvePlanDependencies(s.blocks, pf, { preloadedConfig });
110563
110609
  const bar = progressBar(s.completed, s.totalPhases);
110564
- const title2 = s.title ?? basename28(dirname42(pf));
110610
+ const title2 = s.title ?? basename28(dirname43(pf));
110565
110611
  console.log(` ${import_picocolors32.default.bold(title2)}`);
110566
110612
  console.log(` ${bar}`);
110567
110613
  if (s.inProgress > 0)
@@ -110580,7 +110626,7 @@ async function handleStatus(target, options2) {
110580
110626
  }
110581
110627
  console.log();
110582
110628
  } catch {
110583
- console.log(` [X] Failed to read: ${basename28(dirname42(pf))}`);
110629
+ console.log(` [X] Failed to read: ${basename28(dirname43(pf))}`);
110584
110630
  console.log();
110585
110631
  }
110586
110632
  }
@@ -110607,7 +110653,7 @@ async function handleStatus(target, options2) {
110607
110653
  console.log(JSON.stringify({ ...summary, dependencyStatus: { blockedBy, blocks } }, null, 2));
110608
110654
  return;
110609
110655
  }
110610
- const title = summary.title ?? basename28(dirname42(planFile));
110656
+ const title = summary.title ?? basename28(dirname43(planFile));
110611
110657
  console.log();
110612
110658
  console.log(import_picocolors32.default.bold(` ${title}`));
110613
110659
  if (summary.status)
@@ -110670,7 +110716,7 @@ async function handleKanban(target, options2) {
110670
110716
  process.exitCode = 1;
110671
110717
  return;
110672
110718
  }
110673
- const route = `/plans?dir=${encodeURIComponent(dirname42(dirname42(planFile)))}&view=kanban`;
110719
+ const route = `/plans?dir=${encodeURIComponent(dirname43(dirname43(planFile)))}&view=kanban`;
110674
110720
  const url = `http://localhost:${server.port}${route}`;
110675
110721
  console.log();
110676
110722
  console.log(import_picocolors32.default.bold(" ClaudeKit Dashboard — Plans"));
@@ -110705,7 +110751,7 @@ init_plan_parser();
110705
110751
  init_plans_registry();
110706
110752
  init_output_manager();
110707
110753
  var import_picocolors33 = __toESM(require_picocolors(), 1);
110708
- import { basename as basename29, dirname as dirname43, relative as relative31, resolve as resolve50 } from "node:path";
110754
+ import { basename as basename29, dirname as dirname44, relative as relative31, resolve as resolve50 } from "node:path";
110709
110755
  async function handleCreate(target, options2) {
110710
110756
  if (!options2.title) {
110711
110757
  output.error("[X] --title is required for create");
@@ -110805,7 +110851,7 @@ async function handleCheck(target, options2) {
110805
110851
  process.exitCode = 1;
110806
110852
  return;
110807
110853
  }
110808
- const planDir = dirname43(planFile);
110854
+ const planDir = dirname44(planFile);
110809
110855
  let planStatus = "pending";
110810
110856
  try {
110811
110857
  const projectRoot = findProjectRoot(planDir);
@@ -110854,7 +110900,7 @@ async function handleUncheck(target, options2) {
110854
110900
  process.exitCode = 1;
110855
110901
  return;
110856
110902
  }
110857
- const planDir = dirname43(planFile);
110903
+ const planDir = dirname44(planFile);
110858
110904
  try {
110859
110905
  const projectRoot = findProjectRoot(planDir);
110860
110906
  const summary = buildPlanSummary(planFile);
@@ -110893,7 +110939,7 @@ async function handleAddPhase(target, options2) {
110893
110939
  try {
110894
110940
  const result = addPhase(planFile, target, options2.after);
110895
110941
  try {
110896
- const planDir = dirname43(planFile);
110942
+ const planDir = dirname44(planFile);
110897
110943
  const projectRoot = findProjectRoot(planDir);
110898
110944
  updateRegistryAddPhase({
110899
110945
  planDir,
@@ -110947,7 +110993,7 @@ function resolvePlanFile(target, baseDir) {
110947
110993
  const candidate = join147(dir, "plan.md");
110948
110994
  if (existsSync68(candidate))
110949
110995
  return candidate;
110950
- dir = dirname44(dir);
110996
+ dir = dirname45(dir);
110951
110997
  }
110952
110998
  }
110953
110999
  return null;
@@ -111466,7 +111512,7 @@ import { readFile as readFile65 } from "node:fs/promises";
111466
111512
  import { join as join149 } from "node:path";
111467
111513
 
111468
111514
  // src/commands/skills/installed-skills-inventory.ts
111469
- import { join as join148 } from "node:path";
111515
+ import { join as join148, resolve as resolve53 } from "node:path";
111470
111516
  init_path_resolver();
111471
111517
  var SCOPE_SORT_ORDER = {
111472
111518
  project: 0,
@@ -111474,9 +111520,11 @@ var SCOPE_SORT_ORDER = {
111474
111520
  };
111475
111521
  async function getActiveClaudeSkillInstallations(options2 = {}) {
111476
111522
  const projectDir = options2.projectDir ?? process.cwd();
111477
- const globalDir = options2.globalDir ?? PathResolver.getGlobalKitDir();
111523
+ const globalDir = resolve53(options2.globalDir ?? PathResolver.getGlobalKitDir());
111524
+ const projectClaudeDir = resolve53(projectDir, ".claude");
111525
+ const projectScopeAliasesGlobal = projectClaudeDir === globalDir;
111478
111526
  const [projectSkills, globalSkills] = await Promise.all([
111479
- scanSkills2(join148(projectDir, ".claude", "skills")),
111527
+ projectScopeAliasesGlobal ? Promise.resolve([]) : scanSkills2(join148(projectClaudeDir, "skills")),
111480
111528
  scanSkills2(join148(globalDir, "skills"))
111481
111529
  ]);
111482
111530
  const projectIds = new Set(projectSkills.map((skill) => skill.id));
@@ -112220,7 +112268,7 @@ async function detectInstallations() {
112220
112268
 
112221
112269
  // src/commands/uninstall/removal-handler.ts
112222
112270
  import { readdirSync as readdirSync10, rmSync as rmSync5 } from "node:fs";
112223
- import { basename as basename30, join as join151, resolve as resolve53, sep as sep13 } from "node:path";
112271
+ import { basename as basename30, join as join151, resolve as resolve54, sep as sep13 } from "node:path";
112224
112272
  init_logger();
112225
112273
  init_safe_prompts();
112226
112274
  init_safe_spinner();
@@ -112229,7 +112277,7 @@ var import_fs_extra41 = __toESM(require_lib(), 1);
112229
112277
  // src/commands/uninstall/analysis-handler.ts
112230
112278
  init_metadata_migration();
112231
112279
  import { readdirSync as readdirSync9, rmSync as rmSync4 } from "node:fs";
112232
- import { dirname as dirname45, join as join150 } from "node:path";
112280
+ import { dirname as dirname46, join as join150 } from "node:path";
112233
112281
  init_logger();
112234
112282
  init_safe_prompts();
112235
112283
  var import_fs_extra40 = __toESM(require_lib(), 1);
@@ -112251,7 +112299,7 @@ function classifyFileByOwnership(ownership, forceOverwrite, deleteReason) {
112251
112299
  }
112252
112300
  async function cleanupEmptyDirectories3(filePath, installationRoot) {
112253
112301
  let cleaned = 0;
112254
- let currentDir = dirname45(filePath);
112302
+ let currentDir = dirname46(filePath);
112255
112303
  while (currentDir !== installationRoot && currentDir.startsWith(installationRoot)) {
112256
112304
  try {
112257
112305
  const entries = readdirSync9(currentDir);
@@ -112259,7 +112307,7 @@ async function cleanupEmptyDirectories3(filePath, installationRoot) {
112259
112307
  rmSync4(currentDir, { recursive: true });
112260
112308
  cleaned++;
112261
112309
  logger.debug(`Removed empty directory: ${currentDir}`);
112262
- currentDir = dirname45(currentDir);
112310
+ currentDir = dirname46(currentDir);
112263
112311
  } else {
112264
112312
  break;
112265
112313
  }
@@ -112404,8 +112452,8 @@ async function restoreUninstallBackup(backup) {
112404
112452
  }
112405
112453
  async function isPathSafeToRemove(filePath, baseDir) {
112406
112454
  try {
112407
- const resolvedPath = resolve53(filePath);
112408
- const resolvedBase = resolve53(baseDir);
112455
+ const resolvedPath = resolve54(filePath);
112456
+ const resolvedBase = resolve54(baseDir);
112409
112457
  if (!resolvedPath.startsWith(resolvedBase + sep13) && resolvedPath !== resolvedBase) {
112410
112458
  logger.debug(`Path outside installation directory: ${filePath}`);
112411
112459
  return false;
@@ -112413,7 +112461,7 @@ async function isPathSafeToRemove(filePath, baseDir) {
112413
112461
  const stats = await import_fs_extra41.lstat(filePath);
112414
112462
  if (stats.isSymbolicLink()) {
112415
112463
  const realPath = await import_fs_extra41.realpath(filePath);
112416
- const resolvedReal = resolve53(realPath);
112464
+ const resolvedReal = resolve54(realPath);
112417
112465
  if (!resolvedReal.startsWith(resolvedBase + sep13) && resolvedReal !== resolvedBase) {
112418
112466
  logger.debug(`Symlink points outside installation directory: ${filePath} -> ${realPath}`);
112419
112467
  return false;
@@ -114181,7 +114229,7 @@ init_file_io();
114181
114229
  init_logger();
114182
114230
  import { existsSync as existsSync71 } from "node:fs";
114183
114231
  import { mkdir as mkdir40, readFile as readFile67 } from "node:fs/promises";
114184
- import { dirname as dirname46 } from "node:path";
114232
+ import { dirname as dirname47 } from "node:path";
114185
114233
  var PROCESSED_ISSUES_CAP = 500;
114186
114234
  async function readCkJson(projectDir) {
114187
114235
  const configPath = CkConfigManager.getProjectConfigPath(projectDir);
@@ -114211,7 +114259,7 @@ async function loadWatchState(projectDir) {
114211
114259
  }
114212
114260
  async function saveWatchState(projectDir, state) {
114213
114261
  const configPath = CkConfigManager.getProjectConfigPath(projectDir);
114214
- const configDir = dirname46(configPath);
114262
+ const configDir = dirname47(configPath);
114215
114263
  if (!existsSync71(configDir)) {
114216
114264
  await mkdir40(configDir, { recursive: true });
114217
114265
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudekit-cli",
3
- "version": "4.2.1",
3
+ "version": "4.2.3-dev.1",
4
4
  "description": "CLI tool for bootstrapping and updating ClaudeKit projects",
5
5
  "type": "module",
6
6
  "repository": {