claudekit-cli 4.2.1 → 4.2.3
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 +94 -16
- 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 "";
|
|
@@ -62890,7 +62962,7 @@ var package_default;
|
|
|
62890
62962
|
var init_package = __esm(() => {
|
|
62891
62963
|
package_default = {
|
|
62892
62964
|
name: "claudekit-cli",
|
|
62893
|
-
version: "4.2.
|
|
62965
|
+
version: "4.2.3",
|
|
62894
62966
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
62895
62967
|
type: "module",
|
|
62896
62968
|
repository: {
|
|
@@ -85190,12 +85262,13 @@ async function applyBudgetDefaults(settingsPath, projectClaudeDir, requiredFract
|
|
|
85190
85262
|
var ENGINEER_SKILL_COUNT_THRESHOLD = 20;
|
|
85191
85263
|
async function checkSkillBudget(setup, projectDir) {
|
|
85192
85264
|
const projectClaudeDir = resolve31(projectDir, ".claude");
|
|
85193
|
-
const globalClaudeDir = PathResolver.getGlobalKitDir();
|
|
85265
|
+
const globalClaudeDir = resolve31(PathResolver.getGlobalKitDir());
|
|
85266
|
+
const projectScopeAliasesGlobal = projectClaudeDir === globalClaudeDir;
|
|
85194
85267
|
const [projectSkills, globalSkills] = await Promise.all([
|
|
85195
|
-
scanSkills2(join75(projectClaudeDir, "skills")),
|
|
85268
|
+
projectScopeAliasesGlobal ? Promise.resolve([]) : scanSkills2(join75(projectClaudeDir, "skills")),
|
|
85196
85269
|
scanSkills2(join75(globalClaudeDir, "skills"))
|
|
85197
85270
|
]);
|
|
85198
|
-
if (!isEngineerLikeProject(setup, projectSkills))
|
|
85271
|
+
if (!isEngineerLikeProject(setup, [...projectSkills, ...globalSkills]))
|
|
85199
85272
|
return [];
|
|
85200
85273
|
const settingsPath = join75(projectClaudeDir, "settings.json");
|
|
85201
85274
|
const settings = await readProjectSettings(settingsPath);
|
|
@@ -85216,7 +85289,10 @@ function isEngineerLikeProject(setup, projectSkills) {
|
|
|
85216
85289
|
const metadataText = [
|
|
85217
85290
|
setup.project.metadata?.name,
|
|
85218
85291
|
setup.project.metadata?.description,
|
|
85219
|
-
setup.project.metadata?.repository?.url
|
|
85292
|
+
setup.project.metadata?.repository?.url,
|
|
85293
|
+
setup.global.metadata?.name,
|
|
85294
|
+
setup.global.metadata?.description,
|
|
85295
|
+
setup.global.metadata?.repository?.url
|
|
85220
85296
|
].filter(Boolean).join(" ").toLowerCase();
|
|
85221
85297
|
return metadataText.includes("engineer") || projectSkills.length >= ENGINEER_SKILL_COUNT_THRESHOLD;
|
|
85222
85298
|
}
|
|
@@ -86280,7 +86356,7 @@ function getClaudeSettingsFiles(projectDir) {
|
|
|
86280
86356
|
return candidates.filter((candidate) => existsSync56(candidate.path));
|
|
86281
86357
|
}
|
|
86282
86358
|
function isAlreadyCanonical(cmd) {
|
|
86283
|
-
return /^node\s+"\$HOME\/\.claude\/[^"]+"/.test(cmd) || /^node\s+"\$CLAUDE_PROJECT_DIR"\/\.claude\/\S+/.test(cmd);
|
|
86359
|
+
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
86360
|
}
|
|
86285
86361
|
function collectHookCommandFindings(settings, settingsFile) {
|
|
86286
86362
|
if (!settings.hooks) {
|
|
@@ -86292,7 +86368,7 @@ function collectHookCommandFindings(settings, settingsFile) {
|
|
|
86292
86368
|
if ("command" in entry && typeof entry.command === "string") {
|
|
86293
86369
|
if (isAlreadyCanonical(entry.command))
|
|
86294
86370
|
continue;
|
|
86295
|
-
const repair =
|
|
86371
|
+
const repair = repairClaudeHookCommandPath(entry.command, settingsFile.root);
|
|
86296
86372
|
if (repair.changed && repair.issue) {
|
|
86297
86373
|
findings.push({
|
|
86298
86374
|
path: settingsFile.path,
|
|
@@ -86313,7 +86389,7 @@ function collectHookCommandFindings(settings, settingsFile) {
|
|
|
86313
86389
|
}
|
|
86314
86390
|
if (isAlreadyCanonical(hook.command))
|
|
86315
86391
|
continue;
|
|
86316
|
-
const repair =
|
|
86392
|
+
const repair = repairClaudeHookCommandPath(hook.command, settingsFile.root);
|
|
86317
86393
|
if (!repair.changed || !repair.issue) {
|
|
86318
86394
|
continue;
|
|
86319
86395
|
}
|
|
@@ -102339,7 +102415,7 @@ class SettingsProcessor {
|
|
|
102339
102415
|
return fixed;
|
|
102340
102416
|
}
|
|
102341
102417
|
fixSingleCommandPath(cmd) {
|
|
102342
|
-
return
|
|
102418
|
+
return repairClaudeHookCommandPath(cmd, this.getClaudeCommandRoot()).command;
|
|
102343
102419
|
}
|
|
102344
102420
|
formatCommandPath(nodePrefix, capturedVar, relativePath, suffix = "") {
|
|
102345
102421
|
const canonicalRoot = this.canonicalizePathRoot(capturedVar);
|
|
@@ -111466,7 +111542,7 @@ import { readFile as readFile65 } from "node:fs/promises";
|
|
|
111466
111542
|
import { join as join149 } from "node:path";
|
|
111467
111543
|
|
|
111468
111544
|
// src/commands/skills/installed-skills-inventory.ts
|
|
111469
|
-
import { join as join148 } from "node:path";
|
|
111545
|
+
import { join as join148, resolve as resolve53 } from "node:path";
|
|
111470
111546
|
init_path_resolver();
|
|
111471
111547
|
var SCOPE_SORT_ORDER = {
|
|
111472
111548
|
project: 0,
|
|
@@ -111474,9 +111550,11 @@ var SCOPE_SORT_ORDER = {
|
|
|
111474
111550
|
};
|
|
111475
111551
|
async function getActiveClaudeSkillInstallations(options2 = {}) {
|
|
111476
111552
|
const projectDir = options2.projectDir ?? process.cwd();
|
|
111477
|
-
const globalDir = options2.globalDir ?? PathResolver.getGlobalKitDir();
|
|
111553
|
+
const globalDir = resolve53(options2.globalDir ?? PathResolver.getGlobalKitDir());
|
|
111554
|
+
const projectClaudeDir = resolve53(projectDir, ".claude");
|
|
111555
|
+
const projectScopeAliasesGlobal = projectClaudeDir === globalDir;
|
|
111478
111556
|
const [projectSkills, globalSkills] = await Promise.all([
|
|
111479
|
-
scanSkills2(join148(
|
|
111557
|
+
projectScopeAliasesGlobal ? Promise.resolve([]) : scanSkills2(join148(projectClaudeDir, "skills")),
|
|
111480
111558
|
scanSkills2(join148(globalDir, "skills"))
|
|
111481
111559
|
]);
|
|
111482
111560
|
const projectIds = new Set(projectSkills.map((skill) => skill.id));
|
|
@@ -112220,7 +112298,7 @@ async function detectInstallations() {
|
|
|
112220
112298
|
|
|
112221
112299
|
// src/commands/uninstall/removal-handler.ts
|
|
112222
112300
|
import { readdirSync as readdirSync10, rmSync as rmSync5 } from "node:fs";
|
|
112223
|
-
import { basename as basename30, join as join151, resolve as
|
|
112301
|
+
import { basename as basename30, join as join151, resolve as resolve54, sep as sep13 } from "node:path";
|
|
112224
112302
|
init_logger();
|
|
112225
112303
|
init_safe_prompts();
|
|
112226
112304
|
init_safe_spinner();
|
|
@@ -112404,8 +112482,8 @@ async function restoreUninstallBackup(backup) {
|
|
|
112404
112482
|
}
|
|
112405
112483
|
async function isPathSafeToRemove(filePath, baseDir) {
|
|
112406
112484
|
try {
|
|
112407
|
-
const resolvedPath =
|
|
112408
|
-
const resolvedBase =
|
|
112485
|
+
const resolvedPath = resolve54(filePath);
|
|
112486
|
+
const resolvedBase = resolve54(baseDir);
|
|
112409
112487
|
if (!resolvedPath.startsWith(resolvedBase + sep13) && resolvedPath !== resolvedBase) {
|
|
112410
112488
|
logger.debug(`Path outside installation directory: ${filePath}`);
|
|
112411
112489
|
return false;
|
|
@@ -112413,7 +112491,7 @@ async function isPathSafeToRemove(filePath, baseDir) {
|
|
|
112413
112491
|
const stats = await import_fs_extra41.lstat(filePath);
|
|
112414
112492
|
if (stats.isSymbolicLink()) {
|
|
112415
112493
|
const realPath = await import_fs_extra41.realpath(filePath);
|
|
112416
|
-
const resolvedReal =
|
|
112494
|
+
const resolvedReal = resolve54(realPath);
|
|
112417
112495
|
if (!resolvedReal.startsWith(resolvedBase + sep13) && resolvedReal !== resolvedBase) {
|
|
112418
112496
|
logger.debug(`Symlink points outside installation directory: ${filePath} -> ${realPath}`);
|
|
112419
112497
|
return false;
|