claudekit-cli 3.9.2 → 3.10.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/dist/index.js +431 -143
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -12363,6 +12363,231 @@ var init_install_error_handler = __esm(() => {
|
|
|
12363
12363
|
init_logger();
|
|
12364
12364
|
});
|
|
12365
12365
|
|
|
12366
|
+
// src/services/package-installer/gemini-mcp-linker.ts
|
|
12367
|
+
var exports_gemini_mcp_linker = {};
|
|
12368
|
+
__export(exports_gemini_mcp_linker, {
|
|
12369
|
+
processGeminiMcpLinking: () => processGeminiMcpLinking,
|
|
12370
|
+
linkGeminiMcpConfig: () => linkGeminiMcpConfig,
|
|
12371
|
+
findMcpConfigPath: () => findMcpConfigPath,
|
|
12372
|
+
checkExistingGeminiConfig: () => checkExistingGeminiConfig,
|
|
12373
|
+
addGeminiToGitignore: () => addGeminiToGitignore
|
|
12374
|
+
});
|
|
12375
|
+
import { existsSync as existsSync7, lstatSync, readlinkSync } from "node:fs";
|
|
12376
|
+
import { mkdir as mkdir9, readFile as readFile14, symlink as symlink2, writeFile as writeFile12 } from "node:fs/promises";
|
|
12377
|
+
import { homedir as homedir4 } from "node:os";
|
|
12378
|
+
import { dirname as dirname6, join as join25, resolve as resolve3 } from "node:path";
|
|
12379
|
+
function getGlobalMcpConfigPath() {
|
|
12380
|
+
return join25(homedir4(), ".claude", ".mcp.json");
|
|
12381
|
+
}
|
|
12382
|
+
function getLocalMcpConfigPath(projectDir) {
|
|
12383
|
+
return join25(projectDir, ".mcp.json");
|
|
12384
|
+
}
|
|
12385
|
+
function findMcpConfigPath(projectDir) {
|
|
12386
|
+
const localPath = getLocalMcpConfigPath(projectDir);
|
|
12387
|
+
if (existsSync7(localPath)) {
|
|
12388
|
+
logger.debug(`Found local MCP config: ${localPath}`);
|
|
12389
|
+
return localPath;
|
|
12390
|
+
}
|
|
12391
|
+
const globalPath = getGlobalMcpConfigPath();
|
|
12392
|
+
if (existsSync7(globalPath)) {
|
|
12393
|
+
logger.debug(`Found global MCP config: ${globalPath}`);
|
|
12394
|
+
return globalPath;
|
|
12395
|
+
}
|
|
12396
|
+
logger.debug("No MCP config found (local or global)");
|
|
12397
|
+
return null;
|
|
12398
|
+
}
|
|
12399
|
+
function checkExistingGeminiConfig(projectDir) {
|
|
12400
|
+
const geminiSettingsPath = join25(projectDir, ".gemini", "settings.json");
|
|
12401
|
+
if (!existsSync7(geminiSettingsPath)) {
|
|
12402
|
+
return { exists: false, isSymlink: false };
|
|
12403
|
+
}
|
|
12404
|
+
try {
|
|
12405
|
+
const stats = lstatSync(geminiSettingsPath);
|
|
12406
|
+
if (stats.isSymbolicLink()) {
|
|
12407
|
+
const target = readlinkSync(geminiSettingsPath);
|
|
12408
|
+
return { exists: true, isSymlink: true, currentTarget: target };
|
|
12409
|
+
}
|
|
12410
|
+
return { exists: true, isSymlink: false };
|
|
12411
|
+
} catch {
|
|
12412
|
+
return { exists: true, isSymlink: false };
|
|
12413
|
+
}
|
|
12414
|
+
}
|
|
12415
|
+
async function readJsonFile(filePath) {
|
|
12416
|
+
try {
|
|
12417
|
+
const content = await readFile14(filePath, "utf-8");
|
|
12418
|
+
return JSON.parse(content);
|
|
12419
|
+
} catch (error) {
|
|
12420
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
12421
|
+
logger.debug(`Failed to read/parse JSON file ${filePath}: ${errorMessage}`);
|
|
12422
|
+
return null;
|
|
12423
|
+
}
|
|
12424
|
+
}
|
|
12425
|
+
async function createSymlink(targetPath, linkPath, projectDir) {
|
|
12426
|
+
const isWindows5 = process.platform === "win32";
|
|
12427
|
+
const linkDir = dirname6(linkPath);
|
|
12428
|
+
if (!existsSync7(linkDir)) {
|
|
12429
|
+
await mkdir9(linkDir, { recursive: true });
|
|
12430
|
+
logger.debug(`Created directory: ${linkDir}`);
|
|
12431
|
+
}
|
|
12432
|
+
const localMcpPath = join25(projectDir, ".mcp.json");
|
|
12433
|
+
const isLocalConfig = targetPath === localMcpPath;
|
|
12434
|
+
const symlinkTarget = isLocalConfig ? "../.mcp.json" : targetPath;
|
|
12435
|
+
try {
|
|
12436
|
+
await symlink2(symlinkTarget, linkPath, isWindows5 ? "file" : undefined);
|
|
12437
|
+
logger.debug(`Created symlink: ${linkPath} → ${symlinkTarget}`);
|
|
12438
|
+
return { success: true, method: "symlink", targetPath };
|
|
12439
|
+
} catch (error) {
|
|
12440
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
12441
|
+
return {
|
|
12442
|
+
success: false,
|
|
12443
|
+
method: "symlink",
|
|
12444
|
+
error: `Failed to create symlink: ${errorMessage}`
|
|
12445
|
+
};
|
|
12446
|
+
}
|
|
12447
|
+
}
|
|
12448
|
+
async function createNewSettingsWithMerge(geminiSettingsPath, mcpConfigPath) {
|
|
12449
|
+
const linkDir = dirname6(geminiSettingsPath);
|
|
12450
|
+
if (!existsSync7(linkDir)) {
|
|
12451
|
+
await mkdir9(linkDir, { recursive: true });
|
|
12452
|
+
logger.debug(`Created directory: ${linkDir}`);
|
|
12453
|
+
}
|
|
12454
|
+
const mcpConfig = await readJsonFile(mcpConfigPath);
|
|
12455
|
+
if (!mcpConfig) {
|
|
12456
|
+
return { success: false, method: "merge", error: "Failed to read MCP config" };
|
|
12457
|
+
}
|
|
12458
|
+
const mcpServers = mcpConfig.mcpServers;
|
|
12459
|
+
if (!mcpServers || typeof mcpServers !== "object" || Array.isArray(mcpServers)) {
|
|
12460
|
+
return { success: false, method: "merge", error: "MCP config has no valid mcpServers object" };
|
|
12461
|
+
}
|
|
12462
|
+
const newSettings = { mcpServers };
|
|
12463
|
+
try {
|
|
12464
|
+
await writeFile12(geminiSettingsPath, JSON.stringify(newSettings, null, 2), "utf-8");
|
|
12465
|
+
logger.debug(`Created new Gemini settings with mcpServers: ${geminiSettingsPath}`);
|
|
12466
|
+
return { success: true, method: "merge", targetPath: mcpConfigPath };
|
|
12467
|
+
} catch (error) {
|
|
12468
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
12469
|
+
return {
|
|
12470
|
+
success: false,
|
|
12471
|
+
method: "merge",
|
|
12472
|
+
error: `Failed to write settings: ${errorMessage}`
|
|
12473
|
+
};
|
|
12474
|
+
}
|
|
12475
|
+
}
|
|
12476
|
+
async function mergeGeminiSettings(geminiSettingsPath, mcpConfigPath) {
|
|
12477
|
+
const geminiSettings = await readJsonFile(geminiSettingsPath);
|
|
12478
|
+
if (!geminiSettings) {
|
|
12479
|
+
return { success: false, method: "merge", error: "Failed to read existing Gemini settings" };
|
|
12480
|
+
}
|
|
12481
|
+
const mcpConfig = await readJsonFile(mcpConfigPath);
|
|
12482
|
+
if (!mcpConfig) {
|
|
12483
|
+
return { success: false, method: "merge", error: "Failed to read MCP config" };
|
|
12484
|
+
}
|
|
12485
|
+
const mcpServers = mcpConfig.mcpServers;
|
|
12486
|
+
if (!mcpServers || typeof mcpServers !== "object" || Array.isArray(mcpServers)) {
|
|
12487
|
+
return { success: false, method: "merge", error: "MCP config has no valid mcpServers object" };
|
|
12488
|
+
}
|
|
12489
|
+
const mergedSettings = {
|
|
12490
|
+
...geminiSettings,
|
|
12491
|
+
mcpServers
|
|
12492
|
+
};
|
|
12493
|
+
try {
|
|
12494
|
+
await writeFile12(geminiSettingsPath, JSON.stringify(mergedSettings, null, 2), "utf-8");
|
|
12495
|
+
logger.debug(`Merged mcpServers into: ${geminiSettingsPath}`);
|
|
12496
|
+
return { success: true, method: "merge", targetPath: mcpConfigPath };
|
|
12497
|
+
} catch (error) {
|
|
12498
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
12499
|
+
return {
|
|
12500
|
+
success: false,
|
|
12501
|
+
method: "merge",
|
|
12502
|
+
error: `Failed to write merged settings: ${errorMessage}`
|
|
12503
|
+
};
|
|
12504
|
+
}
|
|
12505
|
+
}
|
|
12506
|
+
async function addGeminiToGitignore(projectDir) {
|
|
12507
|
+
const gitignorePath = join25(projectDir, ".gitignore");
|
|
12508
|
+
const geminiPattern = ".gemini/";
|
|
12509
|
+
try {
|
|
12510
|
+
let content = "";
|
|
12511
|
+
if (existsSync7(gitignorePath)) {
|
|
12512
|
+
content = await readFile14(gitignorePath, "utf-8");
|
|
12513
|
+
const lines = content.split(`
|
|
12514
|
+
`).map((line) => line.trim()).filter((line) => !line.startsWith("#"));
|
|
12515
|
+
const geminiPatterns = [".gemini/", ".gemini", "/.gemini/", "/.gemini"];
|
|
12516
|
+
if (lines.some((line) => geminiPatterns.includes(line))) {
|
|
12517
|
+
logger.debug(".gemini/ already in .gitignore");
|
|
12518
|
+
return;
|
|
12519
|
+
}
|
|
12520
|
+
}
|
|
12521
|
+
const newLine = content.endsWith(`
|
|
12522
|
+
`) || content === "" ? "" : `
|
|
12523
|
+
`;
|
|
12524
|
+
const comment = "# Gemini CLI settings (contains user-specific config)";
|
|
12525
|
+
await writeFile12(gitignorePath, `${content}${newLine}${comment}
|
|
12526
|
+
${geminiPattern}
|
|
12527
|
+
`, "utf-8");
|
|
12528
|
+
logger.debug(`Added ${geminiPattern} to .gitignore`);
|
|
12529
|
+
} catch (error) {
|
|
12530
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
12531
|
+
logger.warning(`Failed to update .gitignore: ${errorMessage}`);
|
|
12532
|
+
}
|
|
12533
|
+
}
|
|
12534
|
+
async function linkGeminiMcpConfig(projectDir, options = {}) {
|
|
12535
|
+
const { skipGitignore = false } = options;
|
|
12536
|
+
const resolvedProjectDir = resolve3(projectDir);
|
|
12537
|
+
const geminiSettingsPath = join25(resolvedProjectDir, ".gemini", "settings.json");
|
|
12538
|
+
const mcpConfigPath = findMcpConfigPath(resolvedProjectDir);
|
|
12539
|
+
if (!mcpConfigPath) {
|
|
12540
|
+
return {
|
|
12541
|
+
success: false,
|
|
12542
|
+
method: "symlink",
|
|
12543
|
+
error: "No MCP config found. Create .mcp.json or ~/.claude/.mcp.json first."
|
|
12544
|
+
};
|
|
12545
|
+
}
|
|
12546
|
+
const existing = checkExistingGeminiConfig(resolvedProjectDir);
|
|
12547
|
+
let result;
|
|
12548
|
+
if (!existing.exists) {
|
|
12549
|
+
result = await createSymlink(mcpConfigPath, geminiSettingsPath, resolvedProjectDir);
|
|
12550
|
+
if (!result.success && process.platform === "win32") {
|
|
12551
|
+
logger.debug("Symlink failed on Windows, falling back to creating new settings with mcpServers");
|
|
12552
|
+
result = await createNewSettingsWithMerge(geminiSettingsPath, mcpConfigPath);
|
|
12553
|
+
}
|
|
12554
|
+
} else if (existing.isSymlink) {
|
|
12555
|
+
logger.debug(`Gemini config already symlinked: ${existing.currentTarget}`);
|
|
12556
|
+
result = { success: true, method: "skipped", targetPath: existing.currentTarget };
|
|
12557
|
+
} else {
|
|
12558
|
+
result = await mergeGeminiSettings(geminiSettingsPath, mcpConfigPath);
|
|
12559
|
+
}
|
|
12560
|
+
if (result.success && !skipGitignore) {
|
|
12561
|
+
await addGeminiToGitignore(resolvedProjectDir);
|
|
12562
|
+
}
|
|
12563
|
+
return result;
|
|
12564
|
+
}
|
|
12565
|
+
async function processGeminiMcpLinking(projectDir) {
|
|
12566
|
+
logger.info("Setting up Gemini CLI MCP integration...");
|
|
12567
|
+
const result = await linkGeminiMcpConfig(projectDir);
|
|
12568
|
+
if (result.success) {
|
|
12569
|
+
switch (result.method) {
|
|
12570
|
+
case "symlink":
|
|
12571
|
+
logger.success(`Gemini MCP linked: .gemini/settings.json → ${result.targetPath}`);
|
|
12572
|
+
logger.info("MCP servers will auto-sync with your Claude config.");
|
|
12573
|
+
break;
|
|
12574
|
+
case "merge":
|
|
12575
|
+
logger.success("Gemini MCP config updated (merged mcpServers, preserved your settings)");
|
|
12576
|
+
logger.info("Note: Run 'ck init' again to sync MCP config changes.");
|
|
12577
|
+
break;
|
|
12578
|
+
case "skipped":
|
|
12579
|
+
logger.info("Gemini MCP config already configured.");
|
|
12580
|
+
break;
|
|
12581
|
+
}
|
|
12582
|
+
} else {
|
|
12583
|
+
logger.warning(`Gemini MCP setup incomplete: ${result.error}`);
|
|
12584
|
+
logger.info("Manual setup: mkdir -p .gemini && ln -sf .claude/.mcp.json .gemini/settings.json");
|
|
12585
|
+
}
|
|
12586
|
+
}
|
|
12587
|
+
var init_gemini_mcp_linker = __esm(() => {
|
|
12588
|
+
init_logger();
|
|
12589
|
+
});
|
|
12590
|
+
|
|
12366
12591
|
// src/services/package-installer/package-installer.ts
|
|
12367
12592
|
var exports_package_installer = {};
|
|
12368
12593
|
__export(exports_package_installer, {
|
|
@@ -12379,10 +12604,10 @@ __export(exports_package_installer, {
|
|
|
12379
12604
|
getPackageVersion: () => getPackageVersion
|
|
12380
12605
|
});
|
|
12381
12606
|
import { exec as exec5, execFile as execFile2, spawn } from "node:child_process";
|
|
12382
|
-
import { join as
|
|
12607
|
+
import { join as join26, resolve as resolve4 } from "node:path";
|
|
12383
12608
|
import { promisify as promisify5 } from "node:util";
|
|
12384
12609
|
function executeInteractiveScript(command, args, options) {
|
|
12385
|
-
return new Promise((
|
|
12610
|
+
return new Promise((resolve5, reject) => {
|
|
12386
12611
|
const child = spawn(command, args, {
|
|
12387
12612
|
stdio: ["ignore", "inherit", "inherit"],
|
|
12388
12613
|
cwd: options?.cwd,
|
|
@@ -12403,7 +12628,7 @@ function executeInteractiveScript(command, args, options) {
|
|
|
12403
12628
|
} else if (code2 !== 0) {
|
|
12404
12629
|
reject(new Error(`Command exited with code ${code2}`));
|
|
12405
12630
|
} else {
|
|
12406
|
-
|
|
12631
|
+
resolve5();
|
|
12407
12632
|
}
|
|
12408
12633
|
});
|
|
12409
12634
|
child.on("error", (error) => {
|
|
@@ -12574,7 +12799,7 @@ async function installOpenCode() {
|
|
|
12574
12799
|
logger.info(`Installing ${displayName}...`);
|
|
12575
12800
|
const { unlink: unlink5 } = await import("node:fs/promises");
|
|
12576
12801
|
const { tmpdir: tmpdir3 } = await import("node:os");
|
|
12577
|
-
const tempScriptPath =
|
|
12802
|
+
const tempScriptPath = join26(tmpdir3(), "opencode-install.sh");
|
|
12578
12803
|
try {
|
|
12579
12804
|
logger.info("Downloading OpenCode installation script...");
|
|
12580
12805
|
await execFileAsync("curl", ["-fsSL", "https://opencode.ai/install", "-o", tempScriptPath], {
|
|
@@ -12618,7 +12843,7 @@ async function installOpenCode() {
|
|
|
12618
12843
|
async function installGemini() {
|
|
12619
12844
|
return installPackageGlobally("@google/gemini-cli", "Google Gemini CLI");
|
|
12620
12845
|
}
|
|
12621
|
-
async function processPackageInstallations(shouldInstallOpenCode, shouldInstallGemini) {
|
|
12846
|
+
async function processPackageInstallations(shouldInstallOpenCode, shouldInstallGemini, projectDir) {
|
|
12622
12847
|
const results = {};
|
|
12623
12848
|
if (shouldInstallOpenCode) {
|
|
12624
12849
|
const alreadyInstalled = await isOpenCodeInstalled();
|
|
@@ -12643,12 +12868,17 @@ async function processPackageInstallations(shouldInstallOpenCode, shouldInstallG
|
|
|
12643
12868
|
} else {
|
|
12644
12869
|
results.gemini = await installGemini();
|
|
12645
12870
|
}
|
|
12871
|
+
const geminiAvailable = alreadyInstalled || results.gemini?.success;
|
|
12872
|
+
if (projectDir && geminiAvailable) {
|
|
12873
|
+
const { processGeminiMcpLinking: processGeminiMcpLinking2 } = await Promise.resolve().then(() => (init_gemini_mcp_linker(), exports_gemini_mcp_linker));
|
|
12874
|
+
await processGeminiMcpLinking2(projectDir);
|
|
12875
|
+
}
|
|
12646
12876
|
}
|
|
12647
12877
|
return results;
|
|
12648
12878
|
}
|
|
12649
12879
|
function validateScriptPath(skillsDir, scriptPath) {
|
|
12650
|
-
const skillsDirResolved =
|
|
12651
|
-
const scriptPathResolved =
|
|
12880
|
+
const skillsDirResolved = resolve4(skillsDir);
|
|
12881
|
+
const scriptPathResolved = resolve4(scriptPath);
|
|
12652
12882
|
const isWindows5 = process.platform === "win32";
|
|
12653
12883
|
const skillsDirNormalized = isWindows5 ? skillsDirResolved.toLowerCase() : skillsDirResolved;
|
|
12654
12884
|
const scriptPathNormalized = isWindows5 ? scriptPathResolved.toLowerCase() : scriptPathResolved;
|
|
@@ -12684,11 +12914,11 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
12684
12914
|
};
|
|
12685
12915
|
}
|
|
12686
12916
|
try {
|
|
12687
|
-
const { existsSync:
|
|
12917
|
+
const { existsSync: existsSync8 } = await import("node:fs");
|
|
12688
12918
|
const clack = await Promise.resolve().then(() => (init_dist2(), exports_dist));
|
|
12689
12919
|
const platform9 = process.platform;
|
|
12690
12920
|
const scriptName = platform9 === "win32" ? "install.ps1" : "install.sh";
|
|
12691
|
-
const scriptPath =
|
|
12921
|
+
const scriptPath = join26(skillsDir, scriptName);
|
|
12692
12922
|
try {
|
|
12693
12923
|
validateScriptPath(skillsDir, scriptPath);
|
|
12694
12924
|
} catch (error) {
|
|
@@ -12700,11 +12930,11 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
12700
12930
|
error: `Path validation failed: ${errorMessage}`
|
|
12701
12931
|
};
|
|
12702
12932
|
}
|
|
12703
|
-
if (!
|
|
12933
|
+
if (!existsSync8(scriptPath)) {
|
|
12704
12934
|
logger.warning(`Skills installation script not found: ${scriptPath}`);
|
|
12705
12935
|
logger.info("");
|
|
12706
12936
|
logger.info("\uD83D\uDCD6 Manual Installation Instructions:");
|
|
12707
|
-
logger.info(` See: ${
|
|
12937
|
+
logger.info(` See: ${join26(skillsDir, "INSTALLATION.md")}`);
|
|
12708
12938
|
logger.info("");
|
|
12709
12939
|
logger.info("Quick start:");
|
|
12710
12940
|
logger.info(" cd .claude/skills/ai-multimodal/scripts");
|
|
@@ -12720,8 +12950,8 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
12720
12950
|
logger.info(` Platform: ${platform9 === "win32" ? "Windows (PowerShell)" : "Unix (bash)"}`);
|
|
12721
12951
|
if (logger.isVerbose()) {
|
|
12722
12952
|
try {
|
|
12723
|
-
const { readFile:
|
|
12724
|
-
const scriptContent = await
|
|
12953
|
+
const { readFile: readFile15 } = await import("node:fs/promises");
|
|
12954
|
+
const scriptContent = await readFile15(scriptPath, "utf-8");
|
|
12725
12955
|
const previewLines = scriptContent.split(`
|
|
12726
12956
|
`).slice(0, 20);
|
|
12727
12957
|
logger.verbose("Script preview (first 20 lines):");
|
|
@@ -12747,7 +12977,7 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
12747
12977
|
logger.info(` ${platform9 === "win32" ? `powershell -File "${scriptPath}"` : `bash ${scriptPath}`}`);
|
|
12748
12978
|
logger.info("");
|
|
12749
12979
|
logger.info("Or see complete guide:");
|
|
12750
|
-
logger.info(` ${
|
|
12980
|
+
logger.info(` ${join26(skillsDir, "INSTALLATION.md")}`);
|
|
12751
12981
|
return {
|
|
12752
12982
|
success: false,
|
|
12753
12983
|
package: displayName,
|
|
@@ -12848,7 +13078,7 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
12848
13078
|
logger.info("\uD83D\uDCD6 Manual Installation Instructions:");
|
|
12849
13079
|
logger.info("");
|
|
12850
13080
|
logger.info("See complete guide:");
|
|
12851
|
-
logger.info(` cat ${
|
|
13081
|
+
logger.info(` cat ${join26(skillsDir, "INSTALLATION.md")}`);
|
|
12852
13082
|
logger.info("");
|
|
12853
13083
|
logger.info("Quick start:");
|
|
12854
13084
|
logger.info(" cd .claude/skills/ai-multimodal/scripts");
|
|
@@ -13524,7 +13754,7 @@ function getPagerArgs(pagerCmd) {
|
|
|
13524
13754
|
return [];
|
|
13525
13755
|
}
|
|
13526
13756
|
async function trySystemPager(content) {
|
|
13527
|
-
return new Promise((
|
|
13757
|
+
return new Promise((resolve8) => {
|
|
13528
13758
|
const pagerCmd = process.env.PAGER || "less";
|
|
13529
13759
|
const pagerArgs = getPagerArgs(pagerCmd);
|
|
13530
13760
|
try {
|
|
@@ -13534,20 +13764,20 @@ async function trySystemPager(content) {
|
|
|
13534
13764
|
});
|
|
13535
13765
|
const timeout = setTimeout(() => {
|
|
13536
13766
|
pager.kill();
|
|
13537
|
-
|
|
13767
|
+
resolve8(false);
|
|
13538
13768
|
}, 30000);
|
|
13539
13769
|
pager.stdin.write(content);
|
|
13540
13770
|
pager.stdin.end();
|
|
13541
13771
|
pager.on("close", (code2) => {
|
|
13542
13772
|
clearTimeout(timeout);
|
|
13543
|
-
|
|
13773
|
+
resolve8(code2 === 0);
|
|
13544
13774
|
});
|
|
13545
13775
|
pager.on("error", () => {
|
|
13546
13776
|
clearTimeout(timeout);
|
|
13547
|
-
|
|
13777
|
+
resolve8(false);
|
|
13548
13778
|
});
|
|
13549
13779
|
} catch {
|
|
13550
|
-
|
|
13780
|
+
resolve8(false);
|
|
13551
13781
|
}
|
|
13552
13782
|
});
|
|
13553
13783
|
}
|
|
@@ -13574,16 +13804,16 @@ async function basicPager(content) {
|
|
|
13574
13804
|
break;
|
|
13575
13805
|
}
|
|
13576
13806
|
const remaining = lines.length - currentLine;
|
|
13577
|
-
await new Promise((
|
|
13807
|
+
await new Promise((resolve8) => {
|
|
13578
13808
|
rl.question(`-- More (${remaining} lines) [Enter/q] --`, (answer) => {
|
|
13579
13809
|
if (answer.toLowerCase() === "q") {
|
|
13580
13810
|
rl.close();
|
|
13581
13811
|
process.exitCode = 0;
|
|
13582
|
-
|
|
13812
|
+
resolve8();
|
|
13583
13813
|
return;
|
|
13584
13814
|
}
|
|
13585
13815
|
process.stdout.write("\x1B[1A\x1B[2K");
|
|
13586
|
-
|
|
13816
|
+
resolve8();
|
|
13587
13817
|
});
|
|
13588
13818
|
});
|
|
13589
13819
|
}
|
|
@@ -13841,8 +14071,8 @@ var init_help_interceptor = __esm(() => {
|
|
|
13841
14071
|
});
|
|
13842
14072
|
|
|
13843
14073
|
// src/index.ts
|
|
13844
|
-
import { existsSync as
|
|
13845
|
-
import { join as
|
|
14074
|
+
import { existsSync as existsSync9, readFileSync as readFileSync5 } from "fs";
|
|
14075
|
+
import { join as join36 } from "path";
|
|
13846
14076
|
|
|
13847
14077
|
// node_modules/cac/dist/index.mjs
|
|
13848
14078
|
import { EventEmitter } from "events";
|
|
@@ -14447,7 +14677,7 @@ var cac = (name = "") => new CAC(name);
|
|
|
14447
14677
|
// package.json
|
|
14448
14678
|
var package_default = {
|
|
14449
14679
|
name: "claudekit-cli",
|
|
14450
|
-
version: "3.
|
|
14680
|
+
version: "3.10.1",
|
|
14451
14681
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
14452
14682
|
type: "module",
|
|
14453
14683
|
repository: {
|
|
@@ -18291,7 +18521,7 @@ async function doctorCommand(options = {}) {
|
|
|
18291
18521
|
}
|
|
18292
18522
|
|
|
18293
18523
|
// src/commands/init.ts
|
|
18294
|
-
import { join as
|
|
18524
|
+
import { join as join31, resolve as resolve6 } from "node:path";
|
|
18295
18525
|
|
|
18296
18526
|
// src/domains/config/config-manager.ts
|
|
18297
18527
|
init_logger();
|
|
@@ -27327,30 +27557,75 @@ class SettingsMerger {
|
|
|
27327
27557
|
return merged;
|
|
27328
27558
|
}
|
|
27329
27559
|
static mergeHookEntries(sourceEntries, destEntries, eventName, result) {
|
|
27330
|
-
const existingCommands = new Set;
|
|
27331
|
-
SettingsMerger.extractCommands(destEntries, existingCommands);
|
|
27332
27560
|
if (destEntries.length > 0) {
|
|
27333
27561
|
result.hooksPreserved += destEntries.length;
|
|
27334
27562
|
}
|
|
27335
|
-
const merged =
|
|
27563
|
+
const merged = destEntries.map((entry) => SettingsMerger.deepCopyEntry(entry));
|
|
27564
|
+
const matcherIndex = new Map;
|
|
27565
|
+
for (let i = 0;i < merged.length; i++) {
|
|
27566
|
+
const entry = merged[i];
|
|
27567
|
+
if ("matcher" in entry && entry.matcher) {
|
|
27568
|
+
matcherIndex.set(entry.matcher, i);
|
|
27569
|
+
}
|
|
27570
|
+
}
|
|
27571
|
+
const existingCommands = new Set;
|
|
27572
|
+
SettingsMerger.extractCommands(destEntries, existingCommands);
|
|
27336
27573
|
for (const entry of sourceEntries) {
|
|
27574
|
+
const sourceMatcher = "matcher" in entry ? entry.matcher : undefined;
|
|
27337
27575
|
const commands = SettingsMerger.getEntryCommands(entry);
|
|
27338
|
-
|
|
27339
|
-
|
|
27340
|
-
|
|
27341
|
-
|
|
27342
|
-
|
|
27343
|
-
|
|
27344
|
-
|
|
27345
|
-
|
|
27346
|
-
|
|
27347
|
-
|
|
27348
|
-
|
|
27576
|
+
if (sourceMatcher && matcherIndex.has(sourceMatcher)) {
|
|
27577
|
+
const existingIdx = matcherIndex.get(sourceMatcher);
|
|
27578
|
+
if (existingIdx === undefined)
|
|
27579
|
+
continue;
|
|
27580
|
+
const existingEntry = merged[existingIdx];
|
|
27581
|
+
const newCommands = commands.filter((cmd) => !existingCommands.has(cmd));
|
|
27582
|
+
const duplicateCommands = commands.filter((cmd) => existingCommands.has(cmd));
|
|
27583
|
+
if (duplicateCommands.length > 0) {
|
|
27584
|
+
const summary = duplicateCommands.length === 1 ? `"${SettingsMerger.truncateCommand(duplicateCommands[0])}"` : `${duplicateCommands.length} commands`;
|
|
27585
|
+
result.conflictsDetected.push(`${eventName}: duplicate ${summary}`);
|
|
27586
|
+
}
|
|
27587
|
+
if (newCommands.length > 0 && "hooks" in entry && entry.hooks) {
|
|
27588
|
+
if (!existingEntry.hooks) {
|
|
27589
|
+
existingEntry.hooks = [];
|
|
27590
|
+
}
|
|
27591
|
+
for (const hook of entry.hooks) {
|
|
27592
|
+
if (hook.command && !existingCommands.has(hook.command)) {
|
|
27593
|
+
existingEntry.hooks.push(hook);
|
|
27594
|
+
existingCommands.add(hook.command);
|
|
27595
|
+
}
|
|
27596
|
+
}
|
|
27597
|
+
result.hooksAdded++;
|
|
27598
|
+
}
|
|
27599
|
+
} else {
|
|
27600
|
+
const isFullyDuplicated = commands.length > 0 && commands.every((cmd) => existingCommands.has(cmd));
|
|
27601
|
+
const duplicateCommands = commands.filter((cmd) => existingCommands.has(cmd));
|
|
27602
|
+
if (duplicateCommands.length > 0) {
|
|
27603
|
+
const summary = duplicateCommands.length === 1 ? `"${SettingsMerger.truncateCommand(duplicateCommands[0])}"` : `${duplicateCommands.length} commands`;
|
|
27604
|
+
result.conflictsDetected.push(`${eventName}: duplicate ${summary}`);
|
|
27605
|
+
}
|
|
27606
|
+
if (!isFullyDuplicated) {
|
|
27607
|
+
merged.push(entry);
|
|
27608
|
+
result.hooksAdded++;
|
|
27609
|
+
if (sourceMatcher) {
|
|
27610
|
+
matcherIndex.set(sourceMatcher, merged.length - 1);
|
|
27611
|
+
}
|
|
27612
|
+
for (const cmd of commands) {
|
|
27613
|
+
existingCommands.add(cmd);
|
|
27614
|
+
}
|
|
27349
27615
|
}
|
|
27350
27616
|
}
|
|
27351
27617
|
}
|
|
27352
27618
|
return merged;
|
|
27353
27619
|
}
|
|
27620
|
+
static deepCopyEntry(entry) {
|
|
27621
|
+
if ("hooks" in entry) {
|
|
27622
|
+
return {
|
|
27623
|
+
...entry,
|
|
27624
|
+
hooks: entry.hooks ? [...entry.hooks.map((h2) => ({ ...h2 }))] : undefined
|
|
27625
|
+
};
|
|
27626
|
+
}
|
|
27627
|
+
return { ...entry };
|
|
27628
|
+
}
|
|
27354
27629
|
static extractCommands(entries, commands) {
|
|
27355
27630
|
for (const entry of entries) {
|
|
27356
27631
|
if ("command" in entry && entry.command) {
|
|
@@ -31577,7 +31852,7 @@ class PromptsManager {
|
|
|
31577
31852
|
|
|
31578
31853
|
// src/services/file-operations/file-scanner.ts
|
|
31579
31854
|
init_logger();
|
|
31580
|
-
import { join as
|
|
31855
|
+
import { join as join27, relative as relative7, resolve as resolve5 } from "node:path";
|
|
31581
31856
|
var import_fs_extra15 = __toESM(require_lib(), 1);
|
|
31582
31857
|
|
|
31583
31858
|
class FileScanner {
|
|
@@ -31594,7 +31869,7 @@ class FileScanner {
|
|
|
31594
31869
|
logger.debug(`Skipping directory: ${entry}`);
|
|
31595
31870
|
continue;
|
|
31596
31871
|
}
|
|
31597
|
-
const fullPath =
|
|
31872
|
+
const fullPath = join27(dirPath, entry);
|
|
31598
31873
|
if (!FileScanner.isSafePath(basePath, fullPath)) {
|
|
31599
31874
|
logger.warning(`Skipping potentially unsafe path: ${entry}`);
|
|
31600
31875
|
continue;
|
|
@@ -31629,8 +31904,8 @@ class FileScanner {
|
|
|
31629
31904
|
return files;
|
|
31630
31905
|
}
|
|
31631
31906
|
static async findCustomFiles(destDir, sourceDir, subPath) {
|
|
31632
|
-
const destSubDir =
|
|
31633
|
-
const sourceSubDir =
|
|
31907
|
+
const destSubDir = join27(destDir, subPath);
|
|
31908
|
+
const sourceSubDir = join27(sourceDir, subPath);
|
|
31634
31909
|
logger.debug(`findCustomFiles - destDir: ${destDir}`);
|
|
31635
31910
|
logger.debug(`findCustomFiles - sourceDir: ${sourceDir}`);
|
|
31636
31911
|
logger.debug(`findCustomFiles - subPath: "${subPath}"`);
|
|
@@ -31658,8 +31933,8 @@ class FileScanner {
|
|
|
31658
31933
|
return customFiles;
|
|
31659
31934
|
}
|
|
31660
31935
|
static isSafePath(basePath, targetPath) {
|
|
31661
|
-
const resolvedBase =
|
|
31662
|
-
const resolvedTarget =
|
|
31936
|
+
const resolvedBase = resolve5(basePath);
|
|
31937
|
+
const resolvedTarget = resolve5(targetPath);
|
|
31663
31938
|
return resolvedTarget.startsWith(resolvedBase);
|
|
31664
31939
|
}
|
|
31665
31940
|
static toPosixPath(path9) {
|
|
@@ -31668,8 +31943,8 @@ class FileScanner {
|
|
|
31668
31943
|
}
|
|
31669
31944
|
|
|
31670
31945
|
// src/services/transformers/commands-prefix.ts
|
|
31671
|
-
import { lstat as lstat3, mkdir as
|
|
31672
|
-
import { join as
|
|
31946
|
+
import { lstat as lstat3, mkdir as mkdir10, readdir as readdir11, stat as stat4 } from "node:fs/promises";
|
|
31947
|
+
import { join as join28 } from "node:path";
|
|
31673
31948
|
init_logger();
|
|
31674
31949
|
var import_fs_extra16 = __toESM(require_lib(), 1);
|
|
31675
31950
|
function stripWindowsDrivePrefix(path9) {
|
|
@@ -31710,14 +31985,14 @@ function validatePath4(path9, paramName) {
|
|
|
31710
31985
|
class CommandsPrefix {
|
|
31711
31986
|
static async applyPrefix(extractDir) {
|
|
31712
31987
|
validatePath4(extractDir, "extractDir");
|
|
31713
|
-
const commandsDir =
|
|
31988
|
+
const commandsDir = join28(extractDir, ".claude", "commands");
|
|
31714
31989
|
if (!await import_fs_extra16.pathExists(commandsDir)) {
|
|
31715
31990
|
logger.verbose("No commands directory found, skipping prefix application");
|
|
31716
31991
|
return;
|
|
31717
31992
|
}
|
|
31718
31993
|
logger.info("Applying /ck: prefix to slash commands...");
|
|
31719
|
-
const backupDir =
|
|
31720
|
-
const tempDir =
|
|
31994
|
+
const backupDir = join28(extractDir, ".commands-backup");
|
|
31995
|
+
const tempDir = join28(extractDir, ".commands-prefix-temp");
|
|
31721
31996
|
try {
|
|
31722
31997
|
const entries = await readdir11(commandsDir);
|
|
31723
31998
|
if (entries.length === 0) {
|
|
@@ -31725,7 +32000,7 @@ class CommandsPrefix {
|
|
|
31725
32000
|
return;
|
|
31726
32001
|
}
|
|
31727
32002
|
if (entries.length === 1 && entries[0] === "ck") {
|
|
31728
|
-
const ckDir2 =
|
|
32003
|
+
const ckDir2 = join28(commandsDir, "ck");
|
|
31729
32004
|
const ckStat = await stat4(ckDir2);
|
|
31730
32005
|
if (ckStat.isDirectory()) {
|
|
31731
32006
|
logger.verbose("Commands already have /ck: prefix, skipping");
|
|
@@ -31734,18 +32009,18 @@ class CommandsPrefix {
|
|
|
31734
32009
|
}
|
|
31735
32010
|
await import_fs_extra16.copy(commandsDir, backupDir);
|
|
31736
32011
|
logger.verbose("Created backup of commands directory");
|
|
31737
|
-
await
|
|
31738
|
-
const ckDir =
|
|
31739
|
-
await
|
|
32012
|
+
await mkdir10(tempDir, { recursive: true });
|
|
32013
|
+
const ckDir = join28(tempDir, "ck");
|
|
32014
|
+
await mkdir10(ckDir, { recursive: true });
|
|
31740
32015
|
let processedCount = 0;
|
|
31741
32016
|
for (const entry of entries) {
|
|
31742
|
-
const sourcePath =
|
|
32017
|
+
const sourcePath = join28(commandsDir, entry);
|
|
31743
32018
|
const stats = await lstat3(sourcePath);
|
|
31744
32019
|
if (stats.isSymbolicLink()) {
|
|
31745
32020
|
logger.warning(`Skipping symlink for security: ${entry}`);
|
|
31746
32021
|
continue;
|
|
31747
32022
|
}
|
|
31748
|
-
const destPath =
|
|
32023
|
+
const destPath = join28(ckDir, entry);
|
|
31749
32024
|
await import_fs_extra16.copy(sourcePath, destPath, {
|
|
31750
32025
|
overwrite: false,
|
|
31751
32026
|
errorOnExist: true
|
|
@@ -31793,8 +32068,8 @@ class CommandsPrefix {
|
|
|
31793
32068
|
static async cleanupCommandsDirectory(targetDir, isGlobal, options = {}) {
|
|
31794
32069
|
const { dryRun = false, forceOverwrite = false } = options;
|
|
31795
32070
|
validatePath4(targetDir, "targetDir");
|
|
31796
|
-
const claudeDir = isGlobal ? targetDir :
|
|
31797
|
-
const commandsDir =
|
|
32071
|
+
const claudeDir = isGlobal ? targetDir : join28(targetDir, ".claude");
|
|
32072
|
+
const commandsDir = join28(claudeDir, "commands");
|
|
31798
32073
|
const result = {
|
|
31799
32074
|
results: [],
|
|
31800
32075
|
deletedCount: 0,
|
|
@@ -31822,7 +32097,7 @@ class CommandsPrefix {
|
|
|
31822
32097
|
return result;
|
|
31823
32098
|
}
|
|
31824
32099
|
for (const entry of entries) {
|
|
31825
|
-
const entryPath =
|
|
32100
|
+
const entryPath = join28(commandsDir, entry);
|
|
31826
32101
|
const stats = await lstat3(entryPath);
|
|
31827
32102
|
if (stats.isSymbolicLink()) {
|
|
31828
32103
|
logger.warning(`Skipping symlink: ${entry}`);
|
|
@@ -31988,7 +32263,7 @@ class CommandsPrefix {
|
|
|
31988
32263
|
const files = [];
|
|
31989
32264
|
const entries = await readdir11(dir);
|
|
31990
32265
|
for (const entry of entries) {
|
|
31991
|
-
const fullPath =
|
|
32266
|
+
const fullPath = join28(dir, entry);
|
|
31992
32267
|
const stats = await lstat3(fullPath);
|
|
31993
32268
|
if (stats.isSymbolicLink()) {
|
|
31994
32269
|
continue;
|
|
@@ -32007,8 +32282,8 @@ class CommandsPrefix {
|
|
|
32007
32282
|
init_logger();
|
|
32008
32283
|
init_types2();
|
|
32009
32284
|
var import_fs_extra17 = __toESM(require_lib(), 1);
|
|
32010
|
-
import { readFile as
|
|
32011
|
-
import { join as
|
|
32285
|
+
import { readFile as readFile15, readdir as readdir12, rename as rename3, writeFile as writeFile13 } from "node:fs/promises";
|
|
32286
|
+
import { join as join29, relative as relative8 } from "node:path";
|
|
32012
32287
|
var TRANSFORMABLE_FILE_PATTERNS = [
|
|
32013
32288
|
".md",
|
|
32014
32289
|
".txt",
|
|
@@ -32054,34 +32329,34 @@ async function transformFolderPaths(extractDir, folders, options = {}) {
|
|
|
32054
32329
|
}
|
|
32055
32330
|
const dirsToRename = [];
|
|
32056
32331
|
if (folders.docs !== DEFAULT_FOLDERS.docs) {
|
|
32057
|
-
const docsPath =
|
|
32332
|
+
const docsPath = join29(extractDir, DEFAULT_FOLDERS.docs);
|
|
32058
32333
|
if (await import_fs_extra17.pathExists(docsPath)) {
|
|
32059
32334
|
dirsToRename.push({
|
|
32060
32335
|
from: docsPath,
|
|
32061
|
-
to:
|
|
32336
|
+
to: join29(extractDir, folders.docs)
|
|
32062
32337
|
});
|
|
32063
32338
|
}
|
|
32064
|
-
const claudeDocsPath =
|
|
32339
|
+
const claudeDocsPath = join29(extractDir, ".claude", DEFAULT_FOLDERS.docs);
|
|
32065
32340
|
if (await import_fs_extra17.pathExists(claudeDocsPath)) {
|
|
32066
32341
|
dirsToRename.push({
|
|
32067
32342
|
from: claudeDocsPath,
|
|
32068
|
-
to:
|
|
32343
|
+
to: join29(extractDir, ".claude", folders.docs)
|
|
32069
32344
|
});
|
|
32070
32345
|
}
|
|
32071
32346
|
}
|
|
32072
32347
|
if (folders.plans !== DEFAULT_FOLDERS.plans) {
|
|
32073
|
-
const plansPath =
|
|
32348
|
+
const plansPath = join29(extractDir, DEFAULT_FOLDERS.plans);
|
|
32074
32349
|
if (await import_fs_extra17.pathExists(plansPath)) {
|
|
32075
32350
|
dirsToRename.push({
|
|
32076
32351
|
from: plansPath,
|
|
32077
|
-
to:
|
|
32352
|
+
to: join29(extractDir, folders.plans)
|
|
32078
32353
|
});
|
|
32079
32354
|
}
|
|
32080
|
-
const claudePlansPath =
|
|
32355
|
+
const claudePlansPath = join29(extractDir, ".claude", DEFAULT_FOLDERS.plans);
|
|
32081
32356
|
if (await import_fs_extra17.pathExists(claudePlansPath)) {
|
|
32082
32357
|
dirsToRename.push({
|
|
32083
32358
|
from: claudePlansPath,
|
|
32084
|
-
to:
|
|
32359
|
+
to: join29(extractDir, ".claude", folders.plans)
|
|
32085
32360
|
});
|
|
32086
32361
|
}
|
|
32087
32362
|
}
|
|
@@ -32118,7 +32393,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
32118
32393
|
let replacementsCount = 0;
|
|
32119
32394
|
const entries = await readdir12(dir, { withFileTypes: true });
|
|
32120
32395
|
for (const entry of entries) {
|
|
32121
|
-
const fullPath =
|
|
32396
|
+
const fullPath = join29(dir, entry.name);
|
|
32122
32397
|
if (entry.isDirectory()) {
|
|
32123
32398
|
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
32124
32399
|
continue;
|
|
@@ -32131,7 +32406,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
32131
32406
|
if (!shouldTransform)
|
|
32132
32407
|
continue;
|
|
32133
32408
|
try {
|
|
32134
|
-
const content = await
|
|
32409
|
+
const content = await readFile15(fullPath, "utf-8");
|
|
32135
32410
|
let newContent = content;
|
|
32136
32411
|
let changeCount = 0;
|
|
32137
32412
|
for (const { regex: regex2, replacement } of compiledReplacements) {
|
|
@@ -32147,7 +32422,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
32147
32422
|
if (options.dryRun) {
|
|
32148
32423
|
logger.debug(`[dry-run] Would update ${relative8(dir, fullPath)}: ${changeCount} replacement(s)`);
|
|
32149
32424
|
} else {
|
|
32150
|
-
await
|
|
32425
|
+
await writeFile13(fullPath, newContent, "utf-8");
|
|
32151
32426
|
logger.debug(`Updated ${relative8(dir, fullPath)}: ${changeCount} replacement(s)`);
|
|
32152
32427
|
}
|
|
32153
32428
|
filesChanged++;
|
|
@@ -32227,9 +32502,9 @@ function validateFolderName(name2) {
|
|
|
32227
32502
|
|
|
32228
32503
|
// src/services/transformers/global-path-transformer.ts
|
|
32229
32504
|
init_logger();
|
|
32230
|
-
import { readFile as
|
|
32505
|
+
import { readFile as readFile16, readdir as readdir13, writeFile as writeFile14 } from "node:fs/promises";
|
|
32231
32506
|
import { platform as platform9 } from "node:os";
|
|
32232
|
-
import { extname, join as
|
|
32507
|
+
import { extname, join as join30 } from "node:path";
|
|
32233
32508
|
var IS_WINDOWS2 = platform9() === "win32";
|
|
32234
32509
|
var HOME_PREFIX = IS_WINDOWS2 ? "%USERPROFILE%" : "$HOME";
|
|
32235
32510
|
function getHomeDirPrefix() {
|
|
@@ -32321,7 +32596,7 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
|
32321
32596
|
async function processDirectory(dir) {
|
|
32322
32597
|
const entries = await readdir13(dir, { withFileTypes: true });
|
|
32323
32598
|
for (const entry of entries) {
|
|
32324
|
-
const fullPath =
|
|
32599
|
+
const fullPath = join30(dir, entry.name);
|
|
32325
32600
|
if (entry.isDirectory()) {
|
|
32326
32601
|
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
32327
32602
|
continue;
|
|
@@ -32329,10 +32604,10 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
|
32329
32604
|
await processDirectory(fullPath);
|
|
32330
32605
|
} else if (entry.isFile() && shouldTransformFile(entry.name)) {
|
|
32331
32606
|
try {
|
|
32332
|
-
const content = await
|
|
32607
|
+
const content = await readFile16(fullPath, "utf-8");
|
|
32333
32608
|
const { transformed, changes } = transformContent(content);
|
|
32334
32609
|
if (changes > 0) {
|
|
32335
|
-
await
|
|
32610
|
+
await writeFile14(fullPath, transformed, "utf-8");
|
|
32336
32611
|
filesTransformed++;
|
|
32337
32612
|
totalChanges += changes;
|
|
32338
32613
|
if (options.verbose) {
|
|
@@ -32380,9 +32655,9 @@ async function initCommand(options) {
|
|
|
32380
32655
|
}
|
|
32381
32656
|
if (validOptions.global) {
|
|
32382
32657
|
const globalKitDir = PathResolver.getGlobalKitDir();
|
|
32383
|
-
const cwdResolved =
|
|
32384
|
-
const isInGlobalDir = cwdResolved === globalKitDir || cwdResolved ===
|
|
32385
|
-
const localSettingsPath =
|
|
32658
|
+
const cwdResolved = resolve6(process.cwd());
|
|
32659
|
+
const isInGlobalDir = cwdResolved === globalKitDir || cwdResolved === resolve6(globalKitDir, "..");
|
|
32660
|
+
const localSettingsPath = join31(process.cwd(), ".claude", "settings.json");
|
|
32386
32661
|
if (!isInGlobalDir && await import_fs_extra18.pathExists(localSettingsPath)) {
|
|
32387
32662
|
if (isNonInteractive2) {
|
|
32388
32663
|
logger.warning("Local .claude/settings.json detected. Local settings take precedence over global.");
|
|
@@ -32394,7 +32669,7 @@ async function initCommand(options) {
|
|
|
32394
32669
|
return;
|
|
32395
32670
|
}
|
|
32396
32671
|
if (choice === "remove") {
|
|
32397
|
-
const localClaudeDir =
|
|
32672
|
+
const localClaudeDir = join31(process.cwd(), ".claude");
|
|
32398
32673
|
try {
|
|
32399
32674
|
await import_fs_extra18.remove(localClaudeDir);
|
|
32400
32675
|
logger.success("Removed local .claude/ directory");
|
|
@@ -32438,12 +32713,12 @@ async function initCommand(options) {
|
|
|
32438
32713
|
}
|
|
32439
32714
|
}
|
|
32440
32715
|
}
|
|
32441
|
-
const resolvedDir =
|
|
32716
|
+
const resolvedDir = resolve6(targetDir);
|
|
32442
32717
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
32443
32718
|
if (!await import_fs_extra18.pathExists(resolvedDir)) {
|
|
32444
32719
|
if (validOptions.global) {
|
|
32445
|
-
const { mkdir:
|
|
32446
|
-
await
|
|
32720
|
+
const { mkdir: mkdir11 } = await import("node:fs/promises");
|
|
32721
|
+
await mkdir11(resolvedDir, { recursive: true });
|
|
32447
32722
|
logger.info(`Created global directory: ${resolvedDir}`);
|
|
32448
32723
|
} else {
|
|
32449
32724
|
logger.error(`Directory does not exist: ${resolvedDir}`);
|
|
@@ -32453,7 +32728,7 @@ async function initCommand(options) {
|
|
|
32453
32728
|
}
|
|
32454
32729
|
if (validOptions.fresh) {
|
|
32455
32730
|
const prefix = PathResolver.getPathPrefix(validOptions.global);
|
|
32456
|
-
const claudeDir2 = prefix ?
|
|
32731
|
+
const claudeDir2 = prefix ? join31(resolvedDir, prefix) : resolvedDir;
|
|
32457
32732
|
const canProceed = await handleFreshInstallation(claudeDir2, prompts);
|
|
32458
32733
|
if (!canProceed) {
|
|
32459
32734
|
return;
|
|
@@ -32481,7 +32756,7 @@ async function initCommand(options) {
|
|
|
32481
32756
|
logger.info("Fetching available versions...");
|
|
32482
32757
|
let currentVersion = null;
|
|
32483
32758
|
try {
|
|
32484
|
-
const metadataPath = validOptions.global ?
|
|
32759
|
+
const metadataPath = validOptions.global ? join31(PathResolver.getGlobalKitDir(), "metadata.json") : join31(resolvedDir, ".claude", "metadata.json");
|
|
32485
32760
|
const metadata = await readClaudeKitMetadata(metadataPath);
|
|
32486
32761
|
currentVersion = metadata?.version || null;
|
|
32487
32762
|
if (currentVersion) {
|
|
@@ -32606,7 +32881,7 @@ async function initCommand(options) {
|
|
|
32606
32881
|
}
|
|
32607
32882
|
}
|
|
32608
32883
|
if (!validOptions.fresh) {
|
|
32609
|
-
const newSkillsDir =
|
|
32884
|
+
const newSkillsDir = join31(extractDir, ".claude", "skills");
|
|
32610
32885
|
const currentSkillsDir = PathResolver.buildSkillsPath(resolvedDir, validOptions.global);
|
|
32611
32886
|
if (await import_fs_extra18.pathExists(newSkillsDir) && await import_fs_extra18.pathExists(currentSkillsDir)) {
|
|
32612
32887
|
logger.info("Checking for skills directory migration...");
|
|
@@ -32631,7 +32906,7 @@ async function initCommand(options) {
|
|
|
32631
32906
|
let customClaudeFiles = [];
|
|
32632
32907
|
if (!validOptions.fresh) {
|
|
32633
32908
|
logger.info("Scanning for custom .claude files...");
|
|
32634
|
-
const scanSourceDir = validOptions.global ?
|
|
32909
|
+
const scanSourceDir = validOptions.global ? join31(extractDir, ".claude") : extractDir;
|
|
32635
32910
|
const scanTargetSubdir = validOptions.global ? "" : ".claude";
|
|
32636
32911
|
customClaudeFiles = await FileScanner.findCustomFiles(resolvedDir, scanSourceDir, scanTargetSubdir);
|
|
32637
32912
|
} else {
|
|
@@ -32666,7 +32941,7 @@ async function initCommand(options) {
|
|
|
32666
32941
|
}
|
|
32667
32942
|
merger.setGlobalFlag(validOptions.global);
|
|
32668
32943
|
merger.setForceOverwriteSettings(validOptions.forceOverwriteSettings);
|
|
32669
|
-
const claudeDir = validOptions.global ? resolvedDir :
|
|
32944
|
+
const claudeDir = validOptions.global ? resolvedDir : join31(resolvedDir, ".claude");
|
|
32670
32945
|
const releaseManifest = await ReleaseManifestLoader.load(extractDir);
|
|
32671
32946
|
if (!validOptions.fresh && await import_fs_extra18.pathExists(claudeDir)) {
|
|
32672
32947
|
const legacyDetection = await LegacyMigration.detectLegacy(claudeDir);
|
|
@@ -32688,7 +32963,7 @@ async function initCommand(options) {
|
|
|
32688
32963
|
return;
|
|
32689
32964
|
}
|
|
32690
32965
|
}
|
|
32691
|
-
const sourceDir = validOptions.global ?
|
|
32966
|
+
const sourceDir = validOptions.global ? join31(extractDir, ".claude") : extractDir;
|
|
32692
32967
|
await merger.merge(sourceDir, resolvedDir, false);
|
|
32693
32968
|
const manifestWriter = new ManifestWriter;
|
|
32694
32969
|
const installedFiles = merger.getAllInstalledFiles();
|
|
@@ -32697,7 +32972,7 @@ async function initCommand(options) {
|
|
|
32697
32972
|
if (!validOptions.global && !installedPath.startsWith(".claude/"))
|
|
32698
32973
|
continue;
|
|
32699
32974
|
const relativePath = validOptions.global ? installedPath : installedPath.replace(/^\.claude\//, "");
|
|
32700
|
-
const filePath =
|
|
32975
|
+
const filePath = join31(claudeDir, relativePath);
|
|
32701
32976
|
const manifestEntry = releaseManifest ? ReleaseManifestLoader.findFile(releaseManifest, installedPath) : null;
|
|
32702
32977
|
const ownership = manifestEntry ? "ck" : "user";
|
|
32703
32978
|
filesToTrack.push({
|
|
@@ -32718,8 +32993,8 @@ async function initCommand(options) {
|
|
|
32718
32993
|
trackingSpinner.succeed(`Tracked ${trackResult.success} files`);
|
|
32719
32994
|
await manifestWriter.writeManifest(claudeDir, kitConfig.name, release.tag_name, validOptions.global ? "global" : "local");
|
|
32720
32995
|
if (validOptions.global) {
|
|
32721
|
-
const claudeMdSource =
|
|
32722
|
-
const claudeMdDest =
|
|
32996
|
+
const claudeMdSource = join31(extractDir, "CLAUDE.md");
|
|
32997
|
+
const claudeMdDest = join31(resolvedDir, "CLAUDE.md");
|
|
32723
32998
|
if (await import_fs_extra18.pathExists(claudeMdSource)) {
|
|
32724
32999
|
if (!await import_fs_extra18.pathExists(claudeMdDest)) {
|
|
32725
33000
|
await import_fs_extra18.copy(claudeMdSource, claudeMdDest);
|
|
@@ -32738,8 +33013,21 @@ async function initCommand(options) {
|
|
|
32738
33013
|
const skillsDir = PathResolver.buildSkillsPath(resolvedDir, validOptions.global);
|
|
32739
33014
|
await handleSkillsInstallation2(skillsDir);
|
|
32740
33015
|
}
|
|
33016
|
+
if (!isNonInteractive2) {
|
|
33017
|
+
const { isGeminiInstalled: isGeminiInstalled2 } = await Promise.resolve().then(() => (init_package_installer(), exports_package_installer));
|
|
33018
|
+
const { checkExistingGeminiConfig: checkExistingGeminiConfig2, findMcpConfigPath: findMcpConfigPath2, processGeminiMcpLinking: processGeminiMcpLinking2 } = await Promise.resolve().then(() => (init_gemini_mcp_linker(), exports_gemini_mcp_linker));
|
|
33019
|
+
const geminiInstalled = await isGeminiInstalled2();
|
|
33020
|
+
const existingConfig = checkExistingGeminiConfig2(resolvedDir);
|
|
33021
|
+
const mcpConfigExists = findMcpConfigPath2(resolvedDir) !== null;
|
|
33022
|
+
if (geminiInstalled && !existingConfig.exists && mcpConfigExists) {
|
|
33023
|
+
const shouldSetupGemini = await prompts.confirm("Gemini CLI detected. Set up MCP integration? (creates .gemini/settings.json symlink)");
|
|
33024
|
+
if (shouldSetupGemini) {
|
|
33025
|
+
await processGeminiMcpLinking2(resolvedDir);
|
|
33026
|
+
}
|
|
33027
|
+
}
|
|
33028
|
+
}
|
|
32741
33029
|
if (!validOptions.skipSetup && !isNonInteractive2) {
|
|
32742
|
-
const envPath =
|
|
33030
|
+
const envPath = join31(claudeDir, ".env");
|
|
32743
33031
|
if (!await import_fs_extra18.pathExists(envPath)) {
|
|
32744
33032
|
const shouldSetup = await prompts.confirm("Set up API keys now? (Gemini API key for ai-multimodal skill, optional webhooks)");
|
|
32745
33033
|
if (shouldSetup) {
|
|
@@ -32770,7 +33058,7 @@ Protected files (.env, etc.) were not modified.`;
|
|
|
32770
33058
|
}
|
|
32771
33059
|
|
|
32772
33060
|
// src/commands/new.ts
|
|
32773
|
-
import { join as
|
|
33061
|
+
import { join as join32, resolve as resolve7 } from "node:path";
|
|
32774
33062
|
init_package_installer();
|
|
32775
33063
|
init_environment();
|
|
32776
33064
|
init_logger();
|
|
@@ -32801,7 +33089,7 @@ async function newCommand(options) {
|
|
|
32801
33089
|
targetDir = await prompts.getDirectory(targetDir);
|
|
32802
33090
|
}
|
|
32803
33091
|
}
|
|
32804
|
-
const resolvedDir =
|
|
33092
|
+
const resolvedDir = resolve7(targetDir);
|
|
32805
33093
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
32806
33094
|
if (await import_fs_extra19.pathExists(resolvedDir)) {
|
|
32807
33095
|
const files = await import_fs_extra19.readdir(resolvedDir);
|
|
@@ -32951,7 +33239,7 @@ async function newCommand(options) {
|
|
|
32951
33239
|
await CommandsPrefix.cleanupCommandsDirectory(resolvedDir, false);
|
|
32952
33240
|
}
|
|
32953
33241
|
await merger.merge(extractDir, resolvedDir, true);
|
|
32954
|
-
const claudeDir =
|
|
33242
|
+
const claudeDir = join32(resolvedDir, ".claude");
|
|
32955
33243
|
const manifestWriter = new ManifestWriter;
|
|
32956
33244
|
const releaseManifest = await ReleaseManifestLoader.load(extractDir);
|
|
32957
33245
|
const installedFiles = merger.getAllInstalledFiles();
|
|
@@ -32960,7 +33248,7 @@ async function newCommand(options) {
|
|
|
32960
33248
|
if (!installedPath.startsWith(".claude/"))
|
|
32961
33249
|
continue;
|
|
32962
33250
|
const relativePath = installedPath.replace(/^\.claude\//, "");
|
|
32963
|
-
const filePath =
|
|
33251
|
+
const filePath = join32(claudeDir, relativePath);
|
|
32964
33252
|
const manifestEntry = releaseManifest ? ReleaseManifestLoader.findFile(releaseManifest, installedPath) : null;
|
|
32965
33253
|
const ownership = manifestEntry ? "ck" : "user";
|
|
32966
33254
|
filesToTrack.push({
|
|
@@ -32992,7 +33280,7 @@ async function newCommand(options) {
|
|
|
32992
33280
|
if (installOpenCode2 || installGemini2) {
|
|
32993
33281
|
logger.info("Installing optional packages...");
|
|
32994
33282
|
try {
|
|
32995
|
-
const installationResults = await processPackageInstallations(installOpenCode2, installGemini2);
|
|
33283
|
+
const installationResults = await processPackageInstallations(installOpenCode2, installGemini2, resolvedDir);
|
|
32996
33284
|
prompts.showPackageInstallationResults(installationResults);
|
|
32997
33285
|
} catch (error) {
|
|
32998
33286
|
logger.warning(`Package installation failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -33013,7 +33301,7 @@ async function newCommand(options) {
|
|
|
33013
33301
|
|
|
33014
33302
|
// src/commands/uninstall.ts
|
|
33015
33303
|
import { readdirSync, rmSync } from "node:fs";
|
|
33016
|
-
import { dirname as
|
|
33304
|
+
import { dirname as dirname7, join as join33 } from "node:path";
|
|
33017
33305
|
init_logger();
|
|
33018
33306
|
init_types2();
|
|
33019
33307
|
var import_fs_extra20 = __toESM(require_lib(), 1);
|
|
@@ -33075,7 +33363,7 @@ async function confirmUninstall(scope) {
|
|
|
33075
33363
|
}
|
|
33076
33364
|
async function cleanupEmptyDirectories(filePath, installationRoot) {
|
|
33077
33365
|
let cleaned = 0;
|
|
33078
|
-
let currentDir =
|
|
33366
|
+
let currentDir = dirname7(filePath);
|
|
33079
33367
|
while (currentDir !== installationRoot && currentDir.startsWith(installationRoot)) {
|
|
33080
33368
|
try {
|
|
33081
33369
|
const entries = readdirSync(currentDir);
|
|
@@ -33083,7 +33371,7 @@ async function cleanupEmptyDirectories(filePath, installationRoot) {
|
|
|
33083
33371
|
rmSync(currentDir, { recursive: true });
|
|
33084
33372
|
cleaned++;
|
|
33085
33373
|
logger.debug(`Removed empty directory: ${currentDir}`);
|
|
33086
|
-
currentDir =
|
|
33374
|
+
currentDir = dirname7(currentDir);
|
|
33087
33375
|
} else {
|
|
33088
33376
|
break;
|
|
33089
33377
|
}
|
|
@@ -33106,7 +33394,7 @@ async function analyzeInstallation(installation, forceOverwrite) {
|
|
|
33106
33394
|
return result;
|
|
33107
33395
|
}
|
|
33108
33396
|
for (const trackedFile of metadata.files) {
|
|
33109
|
-
const filePath =
|
|
33397
|
+
const filePath = join33(installation.path, trackedFile.path);
|
|
33110
33398
|
const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
|
|
33111
33399
|
if (!ownershipResult.exists)
|
|
33112
33400
|
continue;
|
|
@@ -33164,7 +33452,7 @@ async function removeInstallations(installations, options) {
|
|
|
33164
33452
|
let removedCount = 0;
|
|
33165
33453
|
let cleanedDirs = 0;
|
|
33166
33454
|
for (const item of analysis.toDelete) {
|
|
33167
|
-
const filePath =
|
|
33455
|
+
const filePath = join33(installation.path, item.path);
|
|
33168
33456
|
if (await import_fs_extra20.pathExists(filePath)) {
|
|
33169
33457
|
await import_fs_extra20.remove(filePath);
|
|
33170
33458
|
removedCount++;
|
|
@@ -33405,7 +33693,7 @@ var import_compare_versions2 = __toESM(require_umd(), 1);
|
|
|
33405
33693
|
// package.json
|
|
33406
33694
|
var package_default2 = {
|
|
33407
33695
|
name: "claudekit-cli",
|
|
33408
|
-
version: "3.
|
|
33696
|
+
version: "3.10.1",
|
|
33409
33697
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
33410
33698
|
type: "module",
|
|
33411
33699
|
repository: {
|
|
@@ -33712,24 +34000,24 @@ var import_picocolors15 = __toESM(require_picocolors(), 1);
|
|
|
33712
34000
|
|
|
33713
34001
|
// src/domains/versioning/version-cache.ts
|
|
33714
34002
|
init_logger();
|
|
33715
|
-
import { existsSync as
|
|
33716
|
-
import { mkdir as
|
|
33717
|
-
import { join as
|
|
34003
|
+
import { existsSync as existsSync8 } from "node:fs";
|
|
34004
|
+
import { mkdir as mkdir11, readFile as readFile17, writeFile as writeFile15 } from "node:fs/promises";
|
|
34005
|
+
import { join as join34 } from "node:path";
|
|
33718
34006
|
class VersionCacheManager {
|
|
33719
34007
|
static CACHE_FILENAME = "version-check.json";
|
|
33720
34008
|
static CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
33721
34009
|
static getCacheFile() {
|
|
33722
34010
|
const cacheDir = PathResolver.getCacheDir(false);
|
|
33723
|
-
return
|
|
34011
|
+
return join34(cacheDir, VersionCacheManager.CACHE_FILENAME);
|
|
33724
34012
|
}
|
|
33725
34013
|
static async load() {
|
|
33726
34014
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
33727
34015
|
try {
|
|
33728
|
-
if (!
|
|
34016
|
+
if (!existsSync8(cacheFile)) {
|
|
33729
34017
|
logger.debug("Version check cache not found");
|
|
33730
34018
|
return null;
|
|
33731
34019
|
}
|
|
33732
|
-
const content = await
|
|
34020
|
+
const content = await readFile17(cacheFile, "utf-8");
|
|
33733
34021
|
const cache2 = JSON.parse(content);
|
|
33734
34022
|
if (!cache2.lastCheck || !cache2.currentVersion || !cache2.latestVersion) {
|
|
33735
34023
|
logger.debug("Invalid cache structure, ignoring");
|
|
@@ -33746,10 +34034,10 @@ class VersionCacheManager {
|
|
|
33746
34034
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
33747
34035
|
const cacheDir = PathResolver.getCacheDir(false);
|
|
33748
34036
|
try {
|
|
33749
|
-
if (!
|
|
33750
|
-
await
|
|
34037
|
+
if (!existsSync8(cacheDir)) {
|
|
34038
|
+
await mkdir11(cacheDir, { recursive: true, mode: 448 });
|
|
33751
34039
|
}
|
|
33752
|
-
await
|
|
34040
|
+
await writeFile15(cacheFile, JSON.stringify(cache2, null, 2), "utf-8");
|
|
33753
34041
|
logger.debug(`Version check cache saved to ${cacheFile}`);
|
|
33754
34042
|
} catch (error) {
|
|
33755
34043
|
logger.debug(`Failed to save version check cache: ${error}`);
|
|
@@ -33768,7 +34056,7 @@ class VersionCacheManager {
|
|
|
33768
34056
|
static async clear() {
|
|
33769
34057
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
33770
34058
|
try {
|
|
33771
|
-
if (
|
|
34059
|
+
if (existsSync8(cacheFile)) {
|
|
33772
34060
|
const fs12 = await import("node:fs/promises");
|
|
33773
34061
|
await fs12.unlink(cacheFile);
|
|
33774
34062
|
logger.debug("Version check cache cleared");
|
|
@@ -34231,8 +34519,8 @@ class OutputManager2 {
|
|
|
34231
34519
|
var output2 = new OutputManager2;
|
|
34232
34520
|
|
|
34233
34521
|
// src/shared/path-resolver.ts
|
|
34234
|
-
import { homedir as
|
|
34235
|
-
import { join as
|
|
34522
|
+
import { homedir as homedir5, platform as platform10 } from "node:os";
|
|
34523
|
+
import { join as join35, normalize as normalize6 } from "node:path";
|
|
34236
34524
|
|
|
34237
34525
|
class PathResolver2 {
|
|
34238
34526
|
static getTestHomeDir() {
|
|
@@ -34265,50 +34553,50 @@ class PathResolver2 {
|
|
|
34265
34553
|
static getConfigDir(global3 = false) {
|
|
34266
34554
|
const testHome = PathResolver2.getTestHomeDir();
|
|
34267
34555
|
if (testHome) {
|
|
34268
|
-
return global3 ?
|
|
34556
|
+
return global3 ? join35(testHome, ".config", "claude") : join35(testHome, ".claudekit");
|
|
34269
34557
|
}
|
|
34270
34558
|
if (!global3) {
|
|
34271
|
-
return
|
|
34559
|
+
return join35(homedir5(), ".claudekit");
|
|
34272
34560
|
}
|
|
34273
34561
|
const os2 = platform10();
|
|
34274
34562
|
if (os2 === "win32") {
|
|
34275
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
34276
|
-
return
|
|
34563
|
+
const localAppData = process.env.LOCALAPPDATA || join35(homedir5(), "AppData", "Local");
|
|
34564
|
+
return join35(localAppData, "claude");
|
|
34277
34565
|
}
|
|
34278
34566
|
const xdgConfigHome = process.env.XDG_CONFIG_HOME;
|
|
34279
34567
|
if (xdgConfigHome) {
|
|
34280
|
-
return
|
|
34568
|
+
return join35(xdgConfigHome, "claude");
|
|
34281
34569
|
}
|
|
34282
|
-
return
|
|
34570
|
+
return join35(homedir5(), ".config", "claude");
|
|
34283
34571
|
}
|
|
34284
34572
|
static getConfigFile(global3 = false) {
|
|
34285
|
-
return
|
|
34573
|
+
return join35(PathResolver2.getConfigDir(global3), "config.json");
|
|
34286
34574
|
}
|
|
34287
34575
|
static getCacheDir(global3 = false) {
|
|
34288
34576
|
const testHome = PathResolver2.getTestHomeDir();
|
|
34289
34577
|
if (testHome) {
|
|
34290
|
-
return global3 ?
|
|
34578
|
+
return global3 ? join35(testHome, ".cache", "claude") : join35(testHome, ".claudekit", "cache");
|
|
34291
34579
|
}
|
|
34292
34580
|
if (!global3) {
|
|
34293
|
-
return
|
|
34581
|
+
return join35(homedir5(), ".claudekit", "cache");
|
|
34294
34582
|
}
|
|
34295
34583
|
const os2 = platform10();
|
|
34296
34584
|
if (os2 === "win32") {
|
|
34297
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
34298
|
-
return
|
|
34585
|
+
const localAppData = process.env.LOCALAPPDATA || join35(homedir5(), "AppData", "Local");
|
|
34586
|
+
return join35(localAppData, "claude", "cache");
|
|
34299
34587
|
}
|
|
34300
34588
|
const xdgCacheHome = process.env.XDG_CACHE_HOME;
|
|
34301
34589
|
if (xdgCacheHome) {
|
|
34302
|
-
return
|
|
34590
|
+
return join35(xdgCacheHome, "claude");
|
|
34303
34591
|
}
|
|
34304
|
-
return
|
|
34592
|
+
return join35(homedir5(), ".cache", "claude");
|
|
34305
34593
|
}
|
|
34306
34594
|
static getGlobalKitDir() {
|
|
34307
34595
|
const testHome = PathResolver2.getTestHomeDir();
|
|
34308
34596
|
if (testHome) {
|
|
34309
|
-
return
|
|
34597
|
+
return join35(testHome, ".claude");
|
|
34310
34598
|
}
|
|
34311
|
-
return
|
|
34599
|
+
return join35(homedir5(), ".claude");
|
|
34312
34600
|
}
|
|
34313
34601
|
static getPathPrefix(global3) {
|
|
34314
34602
|
return global3 ? "" : ".claude";
|
|
@@ -34316,9 +34604,9 @@ class PathResolver2 {
|
|
|
34316
34604
|
static buildSkillsPath(baseDir, global3) {
|
|
34317
34605
|
const prefix = PathResolver2.getPathPrefix(global3);
|
|
34318
34606
|
if (prefix) {
|
|
34319
|
-
return
|
|
34607
|
+
return join35(baseDir, prefix, "skills");
|
|
34320
34608
|
}
|
|
34321
|
-
return
|
|
34609
|
+
return join35(baseDir, "skills");
|
|
34322
34610
|
}
|
|
34323
34611
|
static buildComponentPath(baseDir, component, global3) {
|
|
34324
34612
|
if (!PathResolver2.isPathSafe(component)) {
|
|
@@ -34326,9 +34614,9 @@ class PathResolver2 {
|
|
|
34326
34614
|
}
|
|
34327
34615
|
const prefix = PathResolver2.getPathPrefix(global3);
|
|
34328
34616
|
if (prefix) {
|
|
34329
|
-
return
|
|
34617
|
+
return join35(baseDir, prefix, component);
|
|
34330
34618
|
}
|
|
34331
|
-
return
|
|
34619
|
+
return join35(baseDir, component);
|
|
34332
34620
|
}
|
|
34333
34621
|
}
|
|
34334
34622
|
|
|
@@ -34360,11 +34648,11 @@ async function displayVersion() {
|
|
|
34360
34648
|
let localKitVersion = null;
|
|
34361
34649
|
let isGlobalOnlyKit = false;
|
|
34362
34650
|
const globalKitDir = PathResolver2.getGlobalKitDir();
|
|
34363
|
-
const globalMetadataPath =
|
|
34651
|
+
const globalMetadataPath = join36(globalKitDir, "metadata.json");
|
|
34364
34652
|
const prefix = PathResolver2.getPathPrefix(false);
|
|
34365
|
-
const localMetadataPath = prefix ?
|
|
34653
|
+
const localMetadataPath = prefix ? join36(process.cwd(), prefix, "metadata.json") : join36(process.cwd(), "metadata.json");
|
|
34366
34654
|
const isLocalSameAsGlobal = localMetadataPath === globalMetadataPath;
|
|
34367
|
-
if (!isLocalSameAsGlobal &&
|
|
34655
|
+
if (!isLocalSameAsGlobal && existsSync9(localMetadataPath)) {
|
|
34368
34656
|
try {
|
|
34369
34657
|
const rawMetadata = JSON.parse(readFileSync5(localMetadataPath, "utf-8"));
|
|
34370
34658
|
const metadata = MetadataSchema.parse(rawMetadata);
|
|
@@ -34378,7 +34666,7 @@ async function displayVersion() {
|
|
|
34378
34666
|
logger2.verbose("Failed to parse local metadata.json", { error });
|
|
34379
34667
|
}
|
|
34380
34668
|
}
|
|
34381
|
-
if (
|
|
34669
|
+
if (existsSync9(globalMetadataPath)) {
|
|
34382
34670
|
try {
|
|
34383
34671
|
const rawMetadata = JSON.parse(readFileSync5(globalMetadataPath, "utf-8"));
|
|
34384
34672
|
const metadata = MetadataSchema.parse(rawMetadata);
|