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 +2 -2
- package/dist/index.js +261 -213
- package/package.json +1 -1
package/cli-manifest.json
CHANGED
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
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 =
|
|
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
|
|
53984
|
+
import { dirname as dirname13, resolve as resolve18 } from "node:path";
|
|
53875
53985
|
async function ensureCodexHooksFeatureFlag(configTomlPath, isGlobal = false) {
|
|
53876
|
-
const boundary = isGlobal ? getCodexGlobalBoundary() :
|
|
53877
|
-
if (!await isCanonicalPathWithinBoundary2(
|
|
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
|
|
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(
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
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:
|
|
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
|
|
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 =
|
|
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(
|
|
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
|
|
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 =
|
|
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
|
|
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(
|
|
59904
|
-
slug: basename18(
|
|
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(
|
|
59987
|
-
slug: basename18(
|
|
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
|
|
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(
|
|
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
|
|
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:
|
|
61787
|
+
const { dirname: dirname26, join: joinPath } = __require("node:path");
|
|
61678
61788
|
const { fileURLToPath: fileURLToPath2 } = __require("node:url");
|
|
61679
|
-
const __dirname3 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
71799
|
+
import { dirname as dirname31, join as join94 } from "node:path";
|
|
71690
71800
|
async function createSymlink(targetPath, linkPath, projectDir, isGlobal) {
|
|
71691
|
-
const linkDir =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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(
|
|
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
|
|
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] =
|
|
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] =
|
|
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
|
|
90382
|
-
const resolvedFull = await
|
|
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
|
|
90392
|
-
const resolvedParent = await
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
102383
|
+
fixed++;
|
|
102337
102384
|
}
|
|
102338
102385
|
}
|
|
102339
102386
|
return fixed;
|
|
102340
102387
|
}
|
|
102341
102388
|
fixSingleCommandPath(cmd) {
|
|
102342
|
-
return
|
|
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 (
|
|
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(
|
|
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
|
-
|
|
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 =
|
|
102709
|
+
let dir = dirname37(relativePath);
|
|
102664
102710
|
while (dir && dir !== "." && dir !== "/") {
|
|
102665
102711
|
this.installedDirectories.add(`${dir}/`);
|
|
102666
|
-
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
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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 ?
|
|
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
|
|
108663
|
+
return dirname41(path16);
|
|
108618
108664
|
}
|
|
108619
108665
|
if (portableType === "hooks") {
|
|
108620
|
-
return
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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(
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
112408
|
-
const resolvedBase =
|
|
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 =
|
|
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
|
|
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 =
|
|
114262
|
+
const configDir = dirname47(configPath);
|
|
114215
114263
|
if (!existsSync71(configDir)) {
|
|
114216
114264
|
await mkdir40(configDir, { recursive: true });
|
|
114217
114265
|
}
|