claudekit-cli 3.5.2 → 3.6.0
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 +314 -134
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -12725,6 +12725,116 @@ var require_emoji_regex2 = __commonJS((exports, module) => {
|
|
|
12725
12725
|
};
|
|
12726
12726
|
});
|
|
12727
12727
|
|
|
12728
|
+
// src/utils/install-error-handler.ts
|
|
12729
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4, unlinkSync as unlinkSync2 } from "node:fs";
|
|
12730
|
+
import { join as join17 } from "node:path";
|
|
12731
|
+
function parseNameReason(str) {
|
|
12732
|
+
const colonIndex = str.indexOf(":");
|
|
12733
|
+
if (colonIndex === -1) {
|
|
12734
|
+
return [str.trim(), undefined];
|
|
12735
|
+
}
|
|
12736
|
+
return [str.slice(0, colonIndex).trim(), str.slice(colonIndex + 1).trim()];
|
|
12737
|
+
}
|
|
12738
|
+
function displayInstallErrors(skillsDir) {
|
|
12739
|
+
const summaryPath = join17(skillsDir, ".install-error-summary.json");
|
|
12740
|
+
if (!existsSync5(summaryPath)) {
|
|
12741
|
+
logger.error("Skills installation failed. Run with --verbose for details.");
|
|
12742
|
+
return;
|
|
12743
|
+
}
|
|
12744
|
+
let summary;
|
|
12745
|
+
try {
|
|
12746
|
+
summary = JSON.parse(readFileSync4(summaryPath, "utf-8"));
|
|
12747
|
+
} catch (parseError) {
|
|
12748
|
+
logger.error("Failed to parse error summary. File may be corrupted.");
|
|
12749
|
+
logger.debug(`Parse error: ${parseError instanceof Error ? parseError.message : String(parseError)}`);
|
|
12750
|
+
return;
|
|
12751
|
+
}
|
|
12752
|
+
try {
|
|
12753
|
+
if (summary.critical_failures.length > 0) {
|
|
12754
|
+
logger.error("");
|
|
12755
|
+
logger.error("━━━ Critical Failures ━━━");
|
|
12756
|
+
for (const failure of summary.critical_failures) {
|
|
12757
|
+
const [name2, reason] = parseNameReason(failure);
|
|
12758
|
+
logger.error(` ✗ ${name2}`);
|
|
12759
|
+
if (reason)
|
|
12760
|
+
logger.error(` Reason: ${reason}`);
|
|
12761
|
+
}
|
|
12762
|
+
logger.error("");
|
|
12763
|
+
logger.error("These must be fixed before skills can work.");
|
|
12764
|
+
}
|
|
12765
|
+
if (summary.optional_failures.length > 0) {
|
|
12766
|
+
logger.warning("");
|
|
12767
|
+
logger.warning("━━━ Optional Package Failures ━━━");
|
|
12768
|
+
for (const failure of summary.optional_failures) {
|
|
12769
|
+
const [name2, reason] = parseNameReason(failure);
|
|
12770
|
+
logger.warning(` ! ${name2}`);
|
|
12771
|
+
if (reason)
|
|
12772
|
+
logger.info(` Reason: ${reason}`);
|
|
12773
|
+
}
|
|
12774
|
+
}
|
|
12775
|
+
if (summary.skipped.length > 0) {
|
|
12776
|
+
logger.info("");
|
|
12777
|
+
logger.info("━━━ Skipped (No sudo) ━━━");
|
|
12778
|
+
for (const skipped of summary.skipped) {
|
|
12779
|
+
const [name2] = parseNameReason(skipped);
|
|
12780
|
+
logger.info(` ~ ${name2}`);
|
|
12781
|
+
}
|
|
12782
|
+
}
|
|
12783
|
+
logger.info("");
|
|
12784
|
+
logger.info("━━━ How to Fix ━━━");
|
|
12785
|
+
logger.info("");
|
|
12786
|
+
if (summary.optional_failures.some((f3) => f3.includes("no wheel") || f3.includes("build tools") || f3.includes("build failed")) && summary.remediation.build_tools) {
|
|
12787
|
+
logger.info("Install build tools (one-time):");
|
|
12788
|
+
logger.info(` ${summary.remediation.build_tools}`);
|
|
12789
|
+
logger.info("");
|
|
12790
|
+
}
|
|
12791
|
+
if (summary.skipped.length > 0 && summary.remediation.sudo_packages) {
|
|
12792
|
+
logger.info("Install system packages:");
|
|
12793
|
+
logger.info(` ${summary.remediation.sudo_packages}`);
|
|
12794
|
+
logger.info("");
|
|
12795
|
+
}
|
|
12796
|
+
if (summary.optional_failures.length > 0 && summary.remediation.pip_retry) {
|
|
12797
|
+
logger.info("Then retry failed packages manually:");
|
|
12798
|
+
logger.info(` ${summary.remediation.pip_retry}`);
|
|
12799
|
+
}
|
|
12800
|
+
try {
|
|
12801
|
+
unlinkSync2(summaryPath);
|
|
12802
|
+
} catch (cleanupError) {
|
|
12803
|
+
if (cleanupError.code !== "ENOENT") {
|
|
12804
|
+
logger.debug(`Failed to cleanup summary file: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}`);
|
|
12805
|
+
}
|
|
12806
|
+
}
|
|
12807
|
+
} catch (displayError) {
|
|
12808
|
+
logger.error("Failed to display error summary.");
|
|
12809
|
+
logger.debug(`Display error: ${displayError instanceof Error ? displayError.message : String(displayError)}`);
|
|
12810
|
+
}
|
|
12811
|
+
}
|
|
12812
|
+
async function checkNeedsSudoPackages() {
|
|
12813
|
+
if (process.platform !== "linux") {
|
|
12814
|
+
return false;
|
|
12815
|
+
}
|
|
12816
|
+
const { exec: exec5 } = await import("node:child_process");
|
|
12817
|
+
const { promisify: promisify5 } = await import("node:util");
|
|
12818
|
+
const execAsync5 = promisify5(exec5);
|
|
12819
|
+
try {
|
|
12820
|
+
await Promise.all([
|
|
12821
|
+
execAsync5("which ffmpeg", { timeout: WHICH_COMMAND_TIMEOUT_MS }),
|
|
12822
|
+
execAsync5("which convert", { timeout: WHICH_COMMAND_TIMEOUT_MS })
|
|
12823
|
+
]);
|
|
12824
|
+
return false;
|
|
12825
|
+
} catch {
|
|
12826
|
+
return true;
|
|
12827
|
+
}
|
|
12828
|
+
}
|
|
12829
|
+
function hasInstallState(skillsDir) {
|
|
12830
|
+
const stateFilePath = join17(skillsDir, ".install-state.json");
|
|
12831
|
+
return existsSync5(stateFilePath);
|
|
12832
|
+
}
|
|
12833
|
+
var WHICH_COMMAND_TIMEOUT_MS = 5000;
|
|
12834
|
+
var init_install_error_handler = __esm(() => {
|
|
12835
|
+
init_logger();
|
|
12836
|
+
});
|
|
12837
|
+
|
|
12728
12838
|
// src/utils/package-installer.ts
|
|
12729
12839
|
var exports_package_installer = {};
|
|
12730
12840
|
__export(exports_package_installer, {
|
|
@@ -12741,7 +12851,7 @@ __export(exports_package_installer, {
|
|
|
12741
12851
|
getPackageVersion: () => getPackageVersion
|
|
12742
12852
|
});
|
|
12743
12853
|
import { exec as exec5, execFile as execFile2, spawn } from "node:child_process";
|
|
12744
|
-
import { resolve as resolve2 } from "node:path";
|
|
12854
|
+
import { join as join18, resolve as resolve2 } from "node:path";
|
|
12745
12855
|
import { promisify as promisify5 } from "node:util";
|
|
12746
12856
|
function executeInteractiveScript(command, args, options) {
|
|
12747
12857
|
return new Promise((resolve3, reject) => {
|
|
@@ -12935,9 +13045,8 @@ async function installOpenCode() {
|
|
|
12935
13045
|
try {
|
|
12936
13046
|
logger.info(`Installing ${displayName}...`);
|
|
12937
13047
|
const { unlink: unlink2 } = await import("node:fs/promises");
|
|
12938
|
-
const { join: join17 } = await import("node:path");
|
|
12939
13048
|
const { tmpdir: tmpdir3 } = await import("node:os");
|
|
12940
|
-
const tempScriptPath =
|
|
13049
|
+
const tempScriptPath = join18(tmpdir3(), "opencode-install.sh");
|
|
12941
13050
|
try {
|
|
12942
13051
|
logger.info("Downloading OpenCode installation script...");
|
|
12943
13052
|
await execFileAsync("curl", ["-fsSL", "https://opencode.ai/install", "-o", tempScriptPath], {
|
|
@@ -13047,13 +13156,12 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
13047
13156
|
};
|
|
13048
13157
|
}
|
|
13049
13158
|
try {
|
|
13050
|
-
const { existsSync:
|
|
13159
|
+
const { existsSync: existsSync6 } = await import("node:fs");
|
|
13051
13160
|
const { readFile: readFile9 } = await import("node:fs/promises");
|
|
13052
|
-
const { join: join17 } = await import("node:path");
|
|
13053
13161
|
const clack = await Promise.resolve().then(() => (init_dist2(), exports_dist));
|
|
13054
13162
|
const platform8 = process.platform;
|
|
13055
13163
|
const scriptName = platform8 === "win32" ? "install.ps1" : "install.sh";
|
|
13056
|
-
const scriptPath =
|
|
13164
|
+
const scriptPath = join18(skillsDir, scriptName);
|
|
13057
13165
|
try {
|
|
13058
13166
|
validateScriptPath(skillsDir, scriptPath);
|
|
13059
13167
|
} catch (error) {
|
|
@@ -13065,11 +13173,11 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
13065
13173
|
error: `Path validation failed: ${errorMessage}`
|
|
13066
13174
|
};
|
|
13067
13175
|
}
|
|
13068
|
-
if (!
|
|
13176
|
+
if (!existsSync6(scriptPath)) {
|
|
13069
13177
|
logger.warning(`Skills installation script not found: ${scriptPath}`);
|
|
13070
13178
|
logger.info("");
|
|
13071
13179
|
logger.info("\uD83D\uDCD6 Manual Installation Instructions:");
|
|
13072
|
-
logger.info(` See: ${
|
|
13180
|
+
logger.info(` See: ${join18(skillsDir, "INSTALLATION.md")}`);
|
|
13073
13181
|
logger.info("");
|
|
13074
13182
|
logger.info("Quick start:");
|
|
13075
13183
|
logger.info(" cd .claude/skills/ai-multimodal/scripts");
|
|
@@ -13113,7 +13221,7 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
13113
13221
|
logger.info(` ${platform8 === "win32" ? `powershell -File "${scriptPath}"` : `bash ${scriptPath}`}`);
|
|
13114
13222
|
logger.info("");
|
|
13115
13223
|
logger.info("Or see complete guide:");
|
|
13116
|
-
logger.info(` ${
|
|
13224
|
+
logger.info(` ${join18(skillsDir, "INSTALLATION.md")}`);
|
|
13117
13225
|
return {
|
|
13118
13226
|
success: false,
|
|
13119
13227
|
package: displayName,
|
|
@@ -13122,6 +13230,47 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
13122
13230
|
}
|
|
13123
13231
|
logger.info(`Installing ${displayName}...`);
|
|
13124
13232
|
logger.info(`Running: ${scriptPath}`);
|
|
13233
|
+
const scriptArgs = ["--yes"];
|
|
13234
|
+
if (hasInstallState(skillsDir)) {
|
|
13235
|
+
if (isNonInteractive()) {
|
|
13236
|
+
logger.info("Resuming previous installation (non-interactive mode)...");
|
|
13237
|
+
scriptArgs.push("--resume");
|
|
13238
|
+
} else {
|
|
13239
|
+
const shouldResume = await clack.confirm({
|
|
13240
|
+
message: "Previous installation was interrupted. Resume?",
|
|
13241
|
+
initialValue: true
|
|
13242
|
+
});
|
|
13243
|
+
if (!clack.isCancel(shouldResume) && shouldResume) {
|
|
13244
|
+
scriptArgs.push("--resume");
|
|
13245
|
+
logger.info("Resuming previous installation...");
|
|
13246
|
+
}
|
|
13247
|
+
}
|
|
13248
|
+
}
|
|
13249
|
+
if (platform8 === "linux") {
|
|
13250
|
+
const needsSudo = await checkNeedsSudoPackages();
|
|
13251
|
+
if (needsSudo) {
|
|
13252
|
+
if (isNonInteractive()) {
|
|
13253
|
+
logger.info("Skipping system packages in non-interactive mode.");
|
|
13254
|
+
logger.info("Install manually: sudo apt-get install -y ffmpeg imagemagick");
|
|
13255
|
+
} else {
|
|
13256
|
+
logger.info("");
|
|
13257
|
+
logger.info("System packages (requires sudo):");
|
|
13258
|
+
logger.info(" • ffmpeg - Video/audio processing");
|
|
13259
|
+
logger.info(" • imagemagick - Image editing & conversion");
|
|
13260
|
+
logger.info("");
|
|
13261
|
+
const shouldInstallSudo = await clack.confirm({
|
|
13262
|
+
message: "Install these packages? (requires sudo password)",
|
|
13263
|
+
initialValue: true
|
|
13264
|
+
});
|
|
13265
|
+
if (!clack.isCancel(shouldInstallSudo) && shouldInstallSudo) {
|
|
13266
|
+
scriptArgs.push("--with-sudo");
|
|
13267
|
+
} else {
|
|
13268
|
+
logger.info("Skipping system packages. Install manually later:");
|
|
13269
|
+
logger.info(" sudo apt-get install -y ffmpeg imagemagick");
|
|
13270
|
+
}
|
|
13271
|
+
}
|
|
13272
|
+
}
|
|
13273
|
+
}
|
|
13125
13274
|
const scriptEnv = {
|
|
13126
13275
|
...process.env,
|
|
13127
13276
|
NON_INTERACTIVE: "1"
|
|
@@ -13137,7 +13286,7 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
13137
13286
|
env: scriptEnv
|
|
13138
13287
|
});
|
|
13139
13288
|
} else {
|
|
13140
|
-
await executeInteractiveScript("bash", [scriptPath,
|
|
13289
|
+
await executeInteractiveScript("bash", [scriptPath, ...scriptArgs], {
|
|
13141
13290
|
timeout: 600000,
|
|
13142
13291
|
cwd: skillsDir,
|
|
13143
13292
|
env: scriptEnv
|
|
@@ -13150,13 +13299,34 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
13150
13299
|
};
|
|
13151
13300
|
} catch (error) {
|
|
13152
13301
|
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
13153
|
-
|
|
13302
|
+
const exitCodeMatch = errorMessage.match(/exited with code (\d+)/);
|
|
13303
|
+
const exitCode = exitCodeMatch ? Number.parseInt(exitCodeMatch[1], 10) : 1;
|
|
13304
|
+
if (exitCode === EXIT_CODE_PARTIAL_SUCCESS) {
|
|
13305
|
+
displayInstallErrors(skillsDir);
|
|
13306
|
+
logger.info("");
|
|
13307
|
+
logger.success("Core functionality is available despite some package failures.");
|
|
13308
|
+
return {
|
|
13309
|
+
success: true,
|
|
13310
|
+
package: displayName,
|
|
13311
|
+
version: PARTIAL_INSTALL_VERSION
|
|
13312
|
+
};
|
|
13313
|
+
}
|
|
13314
|
+
if (exitCode === EXIT_CODE_CRITICAL_FAILURE) {
|
|
13315
|
+
displayInstallErrors(skillsDir);
|
|
13316
|
+
logger.error("");
|
|
13317
|
+
logger.error("Skills installation failed. See above for details.");
|
|
13318
|
+
return {
|
|
13319
|
+
success: false,
|
|
13320
|
+
package: displayName,
|
|
13321
|
+
error: "Critical dependencies missing"
|
|
13322
|
+
};
|
|
13323
|
+
}
|
|
13324
|
+
logger.error(`Unexpected error: ${errorMessage}`);
|
|
13154
13325
|
logger.info("");
|
|
13155
13326
|
logger.info("\uD83D\uDCD6 Manual Installation Instructions:");
|
|
13156
13327
|
logger.info("");
|
|
13157
13328
|
logger.info("See complete guide:");
|
|
13158
|
-
|
|
13159
|
-
logger.info(` cat ${join17(skillsDir, "INSTALLATION.md")}`);
|
|
13329
|
+
logger.info(` cat ${join18(skillsDir, "INSTALLATION.md")}`);
|
|
13160
13330
|
logger.info("");
|
|
13161
13331
|
logger.info("Quick start:");
|
|
13162
13332
|
logger.info(" cd .claude/skills/ai-multimodal/scripts");
|
|
@@ -13177,19 +13347,24 @@ async function handleSkillsInstallation(skillsDir) {
|
|
|
13177
13347
|
try {
|
|
13178
13348
|
const skillsResult = await installSkillsDependencies(skillsDir);
|
|
13179
13349
|
if (skillsResult.success) {
|
|
13180
|
-
|
|
13350
|
+
if (skillsResult.version === PARTIAL_INSTALL_VERSION) {
|
|
13351
|
+
logger.success("Skills core dependencies installed (some optional packages skipped)");
|
|
13352
|
+
} else {
|
|
13353
|
+
logger.success("Skills dependencies installed successfully");
|
|
13354
|
+
}
|
|
13181
13355
|
} else {
|
|
13182
|
-
logger.warning(`Skills installation
|
|
13183
|
-
logger.info(
|
|
13356
|
+
logger.warning(`Skills installation incomplete: ${skillsResult.error || "Unknown error"}`);
|
|
13357
|
+
logger.info("You can install skills dependencies manually. See INSTALLATION.md");
|
|
13184
13358
|
}
|
|
13185
|
-
} catch
|
|
13186
|
-
logger.warning(
|
|
13359
|
+
} catch {
|
|
13360
|
+
logger.warning("Skills installation failed");
|
|
13187
13361
|
logger.info("You can install skills dependencies manually later");
|
|
13188
13362
|
}
|
|
13189
13363
|
}
|
|
13190
|
-
var execAsync5, execFileAsync, NPM_PACKAGE_REGEX;
|
|
13364
|
+
var execAsync5, execFileAsync, PARTIAL_INSTALL_VERSION = "partial", EXIT_CODE_CRITICAL_FAILURE = 1, EXIT_CODE_PARTIAL_SUCCESS = 2, NPM_PACKAGE_REGEX;
|
|
13191
13365
|
var init_package_installer = __esm(() => {
|
|
13192
13366
|
init_environment();
|
|
13367
|
+
init_install_error_handler();
|
|
13193
13368
|
init_logger();
|
|
13194
13369
|
execAsync5 = promisify5(exec5);
|
|
13195
13370
|
execFileAsync = promisify5(execFile2);
|
|
@@ -14144,8 +14319,8 @@ var init_help_interceptor = __esm(() => {
|
|
|
14144
14319
|
});
|
|
14145
14320
|
|
|
14146
14321
|
// src/index.ts
|
|
14147
|
-
import { existsSync as
|
|
14148
|
-
import { join as
|
|
14322
|
+
import { existsSync as existsSync8, readFileSync as readFileSync5 } from "fs";
|
|
14323
|
+
import { join as join33 } from "path";
|
|
14149
14324
|
|
|
14150
14325
|
// node_modules/cac/dist/index.mjs
|
|
14151
14326
|
import { EventEmitter } from "events";
|
|
@@ -14750,7 +14925,7 @@ var cac = (name = "") => new CAC(name);
|
|
|
14750
14925
|
// package.json
|
|
14751
14926
|
var package_default = {
|
|
14752
14927
|
name: "claudekit-cli",
|
|
14753
|
-
version: "3.
|
|
14928
|
+
version: "3.6.0",
|
|
14754
14929
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
14755
14930
|
type: "module",
|
|
14756
14931
|
repository: {
|
|
@@ -17757,7 +17932,7 @@ async function doctorCommand(options = {}) {
|
|
|
17757
17932
|
|
|
17758
17933
|
// src/commands/init.ts
|
|
17759
17934
|
var import_fs_extra17 = __toESM(require_lib(), 1);
|
|
17760
|
-
import { join as
|
|
17935
|
+
import { join as join28, resolve as resolve4 } from "node:path";
|
|
17761
17936
|
|
|
17762
17937
|
// src/lib/commands-prefix.ts
|
|
17763
17938
|
init_logger();
|
|
@@ -29012,7 +29187,7 @@ class FileMerger {
|
|
|
29012
29187
|
const isWindows5 = process.platform === "win32";
|
|
29013
29188
|
let processedContent = content;
|
|
29014
29189
|
if (this.isGlobal) {
|
|
29015
|
-
const homeVar = isWindows5 ? "%USERPROFILE%" : "$HOME";
|
|
29190
|
+
const homeVar = isWindows5 ? '"%USERPROFILE%"' : '"$HOME"';
|
|
29016
29191
|
processedContent = this.transformClaudePaths(content, homeVar);
|
|
29017
29192
|
if (processedContent !== content) {
|
|
29018
29193
|
logger.debug(`Transformed .claude/ paths to ${homeVar}/.claude/ in settings.json for global installation`);
|
|
@@ -29031,12 +29206,17 @@ class FileMerger {
|
|
|
29031
29206
|
}
|
|
29032
29207
|
}
|
|
29033
29208
|
transformClaudePaths(content, prefix) {
|
|
29209
|
+
if (/\.claude\/[^\s"']*[;`$&|><]/.test(content)) {
|
|
29210
|
+
logger.warning("Potentially unsafe characters detected in .claude/ paths");
|
|
29211
|
+
throw new Error("Settings file contains potentially unsafe path characters");
|
|
29212
|
+
}
|
|
29034
29213
|
let transformed = content;
|
|
29035
29214
|
const jsonSafePrefix = prefix.includes('"') ? prefix.replace(/"/g, "\\\"") : prefix;
|
|
29215
|
+
const rawPrefix = prefix.replace(/"/g, "");
|
|
29036
29216
|
transformed = transformed.replace(/(node\s+)(?:\.\/)?\.claude\//g, `$1${jsonSafePrefix}/.claude/`);
|
|
29037
|
-
if (
|
|
29038
|
-
transformed = transformed.replace(/\$CLAUDE_PROJECT_DIR/g,
|
|
29039
|
-
transformed = transformed.replace(/%CLAUDE_PROJECT_DIR%/g,
|
|
29217
|
+
if (rawPrefix.includes("HOME") || rawPrefix.includes("USERPROFILE")) {
|
|
29218
|
+
transformed = transformed.replace(/\$CLAUDE_PROJECT_DIR/g, rawPrefix);
|
|
29219
|
+
transformed = transformed.replace(/%CLAUDE_PROJECT_DIR%/g, rawPrefix);
|
|
29040
29220
|
}
|
|
29041
29221
|
return transformed;
|
|
29042
29222
|
}
|
|
@@ -29905,11 +30085,11 @@ class PromptsManager {
|
|
|
29905
30085
|
init_dist2();
|
|
29906
30086
|
init_logger();
|
|
29907
30087
|
var import_fs_extra10 = __toESM(require_lib(), 1);
|
|
29908
|
-
import { join as
|
|
30088
|
+
import { join as join20 } from "node:path";
|
|
29909
30089
|
|
|
29910
30090
|
// src/lib/config-generator.ts
|
|
29911
30091
|
var import_fs_extra9 = __toESM(require_lib(), 1);
|
|
29912
|
-
import { join as
|
|
30092
|
+
import { join as join19 } from "node:path";
|
|
29913
30093
|
async function generateEnvFile(targetDir, values) {
|
|
29914
30094
|
const lines = [
|
|
29915
30095
|
"# Generated by ClaudeKit CLI setup wizard",
|
|
@@ -29921,7 +30101,7 @@ async function generateEnvFile(targetDir, values) {
|
|
|
29921
30101
|
lines.push(`${key}=${value}`);
|
|
29922
30102
|
}
|
|
29923
30103
|
}
|
|
29924
|
-
const envPath =
|
|
30104
|
+
const envPath = join19(targetDir, ".env");
|
|
29925
30105
|
await import_fs_extra9.writeFile(envPath, `${lines.join(`
|
|
29926
30106
|
`)}
|
|
29927
30107
|
`, { mode: 384 });
|
|
@@ -29992,7 +30172,7 @@ async function parseEnvFile(path9) {
|
|
|
29992
30172
|
}
|
|
29993
30173
|
}
|
|
29994
30174
|
async function checkGlobalConfig() {
|
|
29995
|
-
const globalEnvPath =
|
|
30175
|
+
const globalEnvPath = join20(PathResolver.getGlobalKitDir(), ".env");
|
|
29996
30176
|
if (!await import_fs_extra10.pathExists(globalEnvPath))
|
|
29997
30177
|
return false;
|
|
29998
30178
|
const env2 = await parseEnvFile(globalEnvPath);
|
|
@@ -30008,7 +30188,7 @@ async function runSetupWizard(options) {
|
|
|
30008
30188
|
let globalEnv = {};
|
|
30009
30189
|
const hasGlobalConfig = !isGlobal && await checkGlobalConfig();
|
|
30010
30190
|
if (!isGlobal) {
|
|
30011
|
-
const globalEnvPath =
|
|
30191
|
+
const globalEnvPath = join20(PathResolver.getGlobalKitDir(), ".env");
|
|
30012
30192
|
if (await import_fs_extra10.pathExists(globalEnvPath)) {
|
|
30013
30193
|
globalEnv = await parseEnvFile(globalEnvPath);
|
|
30014
30194
|
}
|
|
@@ -30061,7 +30241,7 @@ async function runSetupWizard(options) {
|
|
|
30061
30241
|
}
|
|
30062
30242
|
}
|
|
30063
30243
|
await generateEnvFile(targetDir, values);
|
|
30064
|
-
f2.success(`Configuration saved to ${
|
|
30244
|
+
f2.success(`Configuration saved to ${join20(targetDir, ".env")}`);
|
|
30065
30245
|
return true;
|
|
30066
30246
|
}
|
|
30067
30247
|
|
|
@@ -30069,7 +30249,7 @@ async function runSetupWizard(options) {
|
|
|
30069
30249
|
init_logger();
|
|
30070
30250
|
var import_fs_extra12 = __toESM(require_lib(), 1);
|
|
30071
30251
|
import { readdir as readdir8 } from "node:fs/promises";
|
|
30072
|
-
import { join as
|
|
30252
|
+
import { join as join22 } from "node:path";
|
|
30073
30253
|
|
|
30074
30254
|
// src/lib/skills-manifest.ts
|
|
30075
30255
|
init_types2();
|
|
@@ -30077,7 +30257,7 @@ init_logger();
|
|
|
30077
30257
|
var import_fs_extra11 = __toESM(require_lib(), 1);
|
|
30078
30258
|
import { createHash as createHash2 } from "node:crypto";
|
|
30079
30259
|
import { readFile as readFile10, readdir as readdir7, writeFile as writeFile9 } from "node:fs/promises";
|
|
30080
|
-
import { join as
|
|
30260
|
+
import { join as join21, relative as relative6 } from "node:path";
|
|
30081
30261
|
|
|
30082
30262
|
class SkillsManifestManager {
|
|
30083
30263
|
static MANIFEST_FILENAME = ".skills-manifest.json";
|
|
@@ -30099,12 +30279,12 @@ class SkillsManifestManager {
|
|
|
30099
30279
|
return manifest;
|
|
30100
30280
|
}
|
|
30101
30281
|
static async writeManifest(skillsDir, manifest) {
|
|
30102
|
-
const manifestPath =
|
|
30282
|
+
const manifestPath = join21(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
|
|
30103
30283
|
await writeFile9(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
30104
30284
|
logger.debug(`Wrote manifest to: ${manifestPath}`);
|
|
30105
30285
|
}
|
|
30106
30286
|
static async readManifest(skillsDir) {
|
|
30107
|
-
const manifestPath =
|
|
30287
|
+
const manifestPath = join21(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
|
|
30108
30288
|
if (!await import_fs_extra11.pathExists(manifestPath)) {
|
|
30109
30289
|
logger.debug(`No manifest found at: ${manifestPath}`);
|
|
30110
30290
|
return null;
|
|
@@ -30127,7 +30307,7 @@ class SkillsManifestManager {
|
|
|
30127
30307
|
return "flat";
|
|
30128
30308
|
}
|
|
30129
30309
|
for (const dir of dirs.slice(0, 3)) {
|
|
30130
|
-
const dirPath =
|
|
30310
|
+
const dirPath = join21(skillsDir, dir.name);
|
|
30131
30311
|
const subEntries = await readdir7(dirPath, { withFileTypes: true });
|
|
30132
30312
|
const hasSubdirs = subEntries.some((entry) => entry.isDirectory());
|
|
30133
30313
|
if (hasSubdirs) {
|
|
@@ -30146,7 +30326,7 @@ class SkillsManifestManager {
|
|
|
30146
30326
|
const entries = await readdir7(skillsDir, { withFileTypes: true });
|
|
30147
30327
|
for (const entry of entries) {
|
|
30148
30328
|
if (entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith(".")) {
|
|
30149
|
-
const skillPath =
|
|
30329
|
+
const skillPath = join21(skillsDir, entry.name);
|
|
30150
30330
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
30151
30331
|
skills.push({
|
|
30152
30332
|
name: entry.name,
|
|
@@ -30158,11 +30338,11 @@ class SkillsManifestManager {
|
|
|
30158
30338
|
const categories = await readdir7(skillsDir, { withFileTypes: true });
|
|
30159
30339
|
for (const category of categories) {
|
|
30160
30340
|
if (category.isDirectory() && category.name !== "node_modules" && !category.name.startsWith(".")) {
|
|
30161
|
-
const categoryPath =
|
|
30341
|
+
const categoryPath = join21(skillsDir, category.name);
|
|
30162
30342
|
const skillEntries = await readdir7(categoryPath, { withFileTypes: true });
|
|
30163
30343
|
for (const skillEntry of skillEntries) {
|
|
30164
30344
|
if (skillEntry.isDirectory() && !skillEntry.name.startsWith(".")) {
|
|
30165
|
-
const skillPath =
|
|
30345
|
+
const skillPath = join21(categoryPath, skillEntry.name);
|
|
30166
30346
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
30167
30347
|
skills.push({
|
|
30168
30348
|
name: skillEntry.name,
|
|
@@ -30192,7 +30372,7 @@ class SkillsManifestManager {
|
|
|
30192
30372
|
const files = [];
|
|
30193
30373
|
const entries = await readdir7(dirPath, { withFileTypes: true });
|
|
30194
30374
|
for (const entry of entries) {
|
|
30195
|
-
const fullPath =
|
|
30375
|
+
const fullPath = join21(dirPath, entry.name);
|
|
30196
30376
|
if (entry.name.startsWith(".") || entry.name === "node_modules") {
|
|
30197
30377
|
continue;
|
|
30198
30378
|
}
|
|
@@ -30435,12 +30615,12 @@ class SkillsMigrationDetector {
|
|
|
30435
30615
|
let totalSkillLikeCount = 0;
|
|
30436
30616
|
const allSkills = [];
|
|
30437
30617
|
for (const dir of dirs) {
|
|
30438
|
-
const dirPath =
|
|
30618
|
+
const dirPath = join22(skillsDir, dir.name);
|
|
30439
30619
|
const subEntries = await readdir8(dirPath, { withFileTypes: true });
|
|
30440
30620
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
30441
30621
|
if (subdirs.length > 0) {
|
|
30442
30622
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
30443
|
-
const subdirPath =
|
|
30623
|
+
const subdirPath = join22(dirPath, subdir.name);
|
|
30444
30624
|
const subdirFiles = await readdir8(subdirPath, { withFileTypes: true });
|
|
30445
30625
|
const hasSkillMarker = subdirFiles.some((file) => file.isFile() && (file.name === "skill.md" || file.name === "README.md" || file.name === "readme.md" || file.name === "config.json" || file.name === "package.json"));
|
|
30446
30626
|
if (hasSkillMarker) {
|
|
@@ -30479,14 +30659,14 @@ init_types2();
|
|
|
30479
30659
|
init_logger();
|
|
30480
30660
|
var import_fs_extra15 = __toESM(require_lib(), 1);
|
|
30481
30661
|
import { copyFile as copyFile2, mkdir as mkdir7, readdir as readdir11, rm as rm2 } from "node:fs/promises";
|
|
30482
|
-
import { join as
|
|
30662
|
+
import { join as join25 } from "node:path";
|
|
30483
30663
|
|
|
30484
30664
|
// src/lib/skills-backup-manager.ts
|
|
30485
30665
|
init_types2();
|
|
30486
30666
|
init_logger();
|
|
30487
30667
|
var import_fs_extra13 = __toESM(require_lib(), 1);
|
|
30488
30668
|
import { copyFile, mkdir as mkdir6, readdir as readdir9, rm, stat as stat4 } from "node:fs/promises";
|
|
30489
|
-
import { basename as basename2, join as
|
|
30669
|
+
import { basename as basename2, join as join23, normalize as normalize2 } from "node:path";
|
|
30490
30670
|
function validatePath2(path9, paramName) {
|
|
30491
30671
|
if (!path9 || typeof path9 !== "string") {
|
|
30492
30672
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
@@ -30512,7 +30692,7 @@ class SkillsBackupManager {
|
|
|
30512
30692
|
const timestamp = Date.now();
|
|
30513
30693
|
const randomSuffix = Math.random().toString(36).substring(2, 8);
|
|
30514
30694
|
const backupDirName = `${SkillsBackupManager.BACKUP_PREFIX}${timestamp}-${randomSuffix}`;
|
|
30515
|
-
const backupDir = parentDir ?
|
|
30695
|
+
const backupDir = parentDir ? join23(parentDir, backupDirName) : join23(skillsDir, "..", backupDirName);
|
|
30516
30696
|
logger.info(`Creating backup at: ${backupDir}`);
|
|
30517
30697
|
try {
|
|
30518
30698
|
await mkdir6(backupDir, { recursive: true });
|
|
@@ -30563,7 +30743,7 @@ class SkillsBackupManager {
|
|
|
30563
30743
|
}
|
|
30564
30744
|
try {
|
|
30565
30745
|
const entries = await readdir9(parentDir, { withFileTypes: true });
|
|
30566
|
-
const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) =>
|
|
30746
|
+
const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) => join23(parentDir, entry.name));
|
|
30567
30747
|
backups.sort().reverse();
|
|
30568
30748
|
return backups;
|
|
30569
30749
|
} catch (error) {
|
|
@@ -30591,8 +30771,8 @@ class SkillsBackupManager {
|
|
|
30591
30771
|
static async copyDirectory(sourceDir, destDir) {
|
|
30592
30772
|
const entries = await readdir9(sourceDir, { withFileTypes: true });
|
|
30593
30773
|
for (const entry of entries) {
|
|
30594
|
-
const sourcePath =
|
|
30595
|
-
const destPath =
|
|
30774
|
+
const sourcePath = join23(sourceDir, entry.name);
|
|
30775
|
+
const destPath = join23(destDir, entry.name);
|
|
30596
30776
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
30597
30777
|
continue;
|
|
30598
30778
|
}
|
|
@@ -30608,7 +30788,7 @@ class SkillsBackupManager {
|
|
|
30608
30788
|
let size = 0;
|
|
30609
30789
|
const entries = await readdir9(dirPath, { withFileTypes: true });
|
|
30610
30790
|
for (const entry of entries) {
|
|
30611
|
-
const fullPath =
|
|
30791
|
+
const fullPath = join23(dirPath, entry.name);
|
|
30612
30792
|
if (entry.isSymbolicLink()) {
|
|
30613
30793
|
continue;
|
|
30614
30794
|
}
|
|
@@ -30639,7 +30819,7 @@ var import_fs_extra14 = __toESM(require_lib(), 1);
|
|
|
30639
30819
|
import { createHash as createHash3 } from "node:crypto";
|
|
30640
30820
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
30641
30821
|
import { readFile as readFile11, readdir as readdir10 } from "node:fs/promises";
|
|
30642
|
-
import { join as
|
|
30822
|
+
import { join as join24, normalize as normalize3, relative as relative7 } from "node:path";
|
|
30643
30823
|
function validatePath3(path9, paramName) {
|
|
30644
30824
|
if (!path9 || typeof path9 !== "string") {
|
|
30645
30825
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
@@ -30786,13 +30966,13 @@ class SkillsCustomizationScanner {
|
|
|
30786
30966
|
if (dirs.length === 0) {
|
|
30787
30967
|
return ["flat", []];
|
|
30788
30968
|
}
|
|
30789
|
-
const firstDirPath =
|
|
30969
|
+
const firstDirPath = join24(skillsDir, dirs[0].name);
|
|
30790
30970
|
const subEntries = await readdir10(firstDirPath, { withFileTypes: true });
|
|
30791
30971
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
30792
30972
|
if (subdirs.length > 0) {
|
|
30793
30973
|
let skillLikeCount = 0;
|
|
30794
30974
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
30795
|
-
const subdirPath =
|
|
30975
|
+
const subdirPath = join24(firstDirPath, subdir.name);
|
|
30796
30976
|
const subdirFiles = await readdir10(subdirPath, { withFileTypes: true });
|
|
30797
30977
|
const hasSkillMarker = subdirFiles.some((file) => file.isFile() && (file.name === "skill.md" || file.name === "README.md" || file.name === "readme.md" || file.name === "config.json" || file.name === "package.json"));
|
|
30798
30978
|
if (hasSkillMarker) {
|
|
@@ -30802,7 +30982,7 @@ class SkillsCustomizationScanner {
|
|
|
30802
30982
|
if (skillLikeCount > 0) {
|
|
30803
30983
|
const skills = [];
|
|
30804
30984
|
for (const dir of dirs) {
|
|
30805
|
-
const categoryPath =
|
|
30985
|
+
const categoryPath = join24(skillsDir, dir.name);
|
|
30806
30986
|
const skillDirs = await readdir10(categoryPath, { withFileTypes: true });
|
|
30807
30987
|
skills.push(...skillDirs.filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name));
|
|
30808
30988
|
}
|
|
@@ -30812,7 +30992,7 @@ class SkillsCustomizationScanner {
|
|
|
30812
30992
|
return ["flat", dirs.map((dir) => dir.name)];
|
|
30813
30993
|
}
|
|
30814
30994
|
static async findSkillPath(skillsDir, skillName) {
|
|
30815
|
-
const flatPath =
|
|
30995
|
+
const flatPath = join24(skillsDir, skillName);
|
|
30816
30996
|
if (await import_fs_extra14.pathExists(flatPath)) {
|
|
30817
30997
|
return { path: flatPath, category: undefined };
|
|
30818
30998
|
}
|
|
@@ -30821,8 +31001,8 @@ class SkillsCustomizationScanner {
|
|
|
30821
31001
|
if (!entry.isDirectory() || entry.name.startsWith(".") || entry.name === "node_modules") {
|
|
30822
31002
|
continue;
|
|
30823
31003
|
}
|
|
30824
|
-
const categoryPath =
|
|
30825
|
-
const skillPath =
|
|
31004
|
+
const categoryPath = join24(skillsDir, entry.name);
|
|
31005
|
+
const skillPath = join24(categoryPath, skillName);
|
|
30826
31006
|
if (await import_fs_extra14.pathExists(skillPath)) {
|
|
30827
31007
|
return { path: skillPath, category: entry.name };
|
|
30828
31008
|
}
|
|
@@ -30833,7 +31013,7 @@ class SkillsCustomizationScanner {
|
|
|
30833
31013
|
const files = [];
|
|
30834
31014
|
const entries = await readdir10(dirPath, { withFileTypes: true });
|
|
30835
31015
|
for (const entry of entries) {
|
|
30836
|
-
const fullPath =
|
|
31016
|
+
const fullPath = join24(dirPath, entry.name);
|
|
30837
31017
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
30838
31018
|
continue;
|
|
30839
31019
|
}
|
|
@@ -31076,7 +31256,7 @@ class SkillsMigrator {
|
|
|
31076
31256
|
}
|
|
31077
31257
|
}
|
|
31078
31258
|
if (options.backup && !options.dryRun) {
|
|
31079
|
-
const claudeDir =
|
|
31259
|
+
const claudeDir = join25(currentSkillsDir, "..");
|
|
31080
31260
|
result.backupPath = await SkillsBackupManager.createBackup(currentSkillsDir, claudeDir);
|
|
31081
31261
|
logger.success(`Backup created at: ${result.backupPath}`);
|
|
31082
31262
|
}
|
|
@@ -31128,7 +31308,7 @@ class SkillsMigrator {
|
|
|
31128
31308
|
const migrated = [];
|
|
31129
31309
|
const preserved = [];
|
|
31130
31310
|
const errors2 = [];
|
|
31131
|
-
const tempDir =
|
|
31311
|
+
const tempDir = join25(currentSkillsDir, "..", ".skills-migration-temp");
|
|
31132
31312
|
await mkdir7(tempDir, { recursive: true });
|
|
31133
31313
|
try {
|
|
31134
31314
|
for (const mapping of mappings) {
|
|
@@ -31149,9 +31329,9 @@ class SkillsMigrator {
|
|
|
31149
31329
|
}
|
|
31150
31330
|
}
|
|
31151
31331
|
const category = mapping.category;
|
|
31152
|
-
const targetPath = category ?
|
|
31332
|
+
const targetPath = category ? join25(tempDir, category, skillName) : join25(tempDir, skillName);
|
|
31153
31333
|
if (category) {
|
|
31154
|
-
await mkdir7(
|
|
31334
|
+
await mkdir7(join25(tempDir, category), { recursive: true });
|
|
31155
31335
|
}
|
|
31156
31336
|
await SkillsMigrator.copySkillDirectory(currentSkillPath, targetPath);
|
|
31157
31337
|
migrated.push(skillName);
|
|
@@ -31185,8 +31365,8 @@ class SkillsMigrator {
|
|
|
31185
31365
|
await mkdir7(destDir, { recursive: true });
|
|
31186
31366
|
const entries = await readdir11(sourceDir, { withFileTypes: true });
|
|
31187
31367
|
for (const entry of entries) {
|
|
31188
|
-
const sourcePath =
|
|
31189
|
-
const destPath =
|
|
31368
|
+
const sourcePath = join25(sourceDir, entry.name);
|
|
31369
|
+
const destPath = join25(destDir, entry.name);
|
|
31190
31370
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
31191
31371
|
continue;
|
|
31192
31372
|
}
|
|
@@ -31205,18 +31385,18 @@ init_types2();
|
|
|
31205
31385
|
// src/utils/config.ts
|
|
31206
31386
|
init_types2();
|
|
31207
31387
|
init_logger();
|
|
31208
|
-
import { existsSync as
|
|
31388
|
+
import { existsSync as existsSync6 } from "node:fs";
|
|
31209
31389
|
import { mkdir as mkdir8, readFile as readFile12, rename as rename2, rm as rm3, writeFile as writeFile10 } from "node:fs/promises";
|
|
31210
31390
|
import { chmod as chmod2 } from "node:fs/promises";
|
|
31211
31391
|
import { platform as platform8 } from "node:os";
|
|
31212
|
-
import { join as
|
|
31392
|
+
import { join as join26 } from "node:path";
|
|
31213
31393
|
var PROJECT_CONFIG_FILE = ".ck.json";
|
|
31214
31394
|
|
|
31215
31395
|
class ConfigManager {
|
|
31216
31396
|
static config = null;
|
|
31217
31397
|
static globalFlag = false;
|
|
31218
31398
|
static getProjectConfigDir(projectDir, global3) {
|
|
31219
|
-
return global3 ? projectDir :
|
|
31399
|
+
return global3 ? projectDir : join26(projectDir, ".claude");
|
|
31220
31400
|
}
|
|
31221
31401
|
static setGlobalFlag(global3) {
|
|
31222
31402
|
ConfigManager.globalFlag = global3;
|
|
@@ -31231,7 +31411,7 @@ class ConfigManager {
|
|
|
31231
31411
|
}
|
|
31232
31412
|
const configFile = PathResolver.getConfigFile(ConfigManager.globalFlag);
|
|
31233
31413
|
try {
|
|
31234
|
-
if (
|
|
31414
|
+
if (existsSync6(configFile)) {
|
|
31235
31415
|
const content = await readFile12(configFile, "utf-8");
|
|
31236
31416
|
const data = JSON.parse(content);
|
|
31237
31417
|
ConfigManager.config = ConfigSchema.parse(data);
|
|
@@ -31249,7 +31429,7 @@ class ConfigManager {
|
|
|
31249
31429
|
const validConfig = ConfigSchema.parse(config);
|
|
31250
31430
|
const configDir = PathResolver.getConfigDir(ConfigManager.globalFlag);
|
|
31251
31431
|
const configFile = PathResolver.getConfigFile(ConfigManager.globalFlag);
|
|
31252
|
-
if (!
|
|
31432
|
+
if (!existsSync6(configDir)) {
|
|
31253
31433
|
await mkdir8(configDir, { recursive: true });
|
|
31254
31434
|
if (platform8() !== "win32") {
|
|
31255
31435
|
await chmod2(configDir, 448);
|
|
@@ -31283,9 +31463,9 @@ class ConfigManager {
|
|
|
31283
31463
|
}
|
|
31284
31464
|
static async loadProjectConfig(projectDir, global3 = false) {
|
|
31285
31465
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
31286
|
-
const configPath =
|
|
31466
|
+
const configPath = join26(configDir, PROJECT_CONFIG_FILE);
|
|
31287
31467
|
try {
|
|
31288
|
-
if (
|
|
31468
|
+
if (existsSync6(configPath)) {
|
|
31289
31469
|
const content = await readFile12(configPath, "utf-8");
|
|
31290
31470
|
const data = JSON.parse(content);
|
|
31291
31471
|
const folders = FoldersConfigSchema.parse(data.paths || data);
|
|
@@ -31299,9 +31479,9 @@ class ConfigManager {
|
|
|
31299
31479
|
}
|
|
31300
31480
|
static async saveProjectConfig(projectDir, folders, global3 = false) {
|
|
31301
31481
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
31302
|
-
const configPath =
|
|
31482
|
+
const configPath = join26(configDir, PROJECT_CONFIG_FILE);
|
|
31303
31483
|
try {
|
|
31304
|
-
if (!
|
|
31484
|
+
if (!existsSync6(configDir)) {
|
|
31305
31485
|
await mkdir8(configDir, { recursive: true });
|
|
31306
31486
|
}
|
|
31307
31487
|
const validFolders = FoldersConfigSchema.parse(folders);
|
|
@@ -31331,21 +31511,21 @@ class ConfigManager {
|
|
|
31331
31511
|
}
|
|
31332
31512
|
static projectConfigExists(projectDir, global3 = false) {
|
|
31333
31513
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
31334
|
-
return
|
|
31514
|
+
return existsSync6(join26(configDir, PROJECT_CONFIG_FILE));
|
|
31335
31515
|
}
|
|
31336
31516
|
static async migrateNestedConfig(globalDir) {
|
|
31337
|
-
const correctPath =
|
|
31338
|
-
const incorrectPath =
|
|
31339
|
-
if (
|
|
31517
|
+
const correctPath = join26(globalDir, PROJECT_CONFIG_FILE);
|
|
31518
|
+
const incorrectPath = join26(globalDir, ".claude", PROJECT_CONFIG_FILE);
|
|
31519
|
+
if (existsSync6(correctPath)) {
|
|
31340
31520
|
logger.debug("Config already exists at correct location, skipping migration");
|
|
31341
31521
|
return false;
|
|
31342
31522
|
}
|
|
31343
|
-
if (
|
|
31523
|
+
if (existsSync6(incorrectPath)) {
|
|
31344
31524
|
try {
|
|
31345
31525
|
logger.info("Migrating .ck.json from nested location to correct location...");
|
|
31346
31526
|
await rename2(incorrectPath, correctPath);
|
|
31347
31527
|
logger.success(`Migrated ${PROJECT_CONFIG_FILE} to ${correctPath}`);
|
|
31348
|
-
const nestedClaudeDir =
|
|
31528
|
+
const nestedClaudeDir = join26(globalDir, ".claude");
|
|
31349
31529
|
try {
|
|
31350
31530
|
await rm3(nestedClaudeDir, { recursive: false });
|
|
31351
31531
|
logger.debug("Removed empty nested .claude directory");
|
|
@@ -31368,7 +31548,7 @@ init_environment();
|
|
|
31368
31548
|
// src/utils/file-scanner.ts
|
|
31369
31549
|
init_logger();
|
|
31370
31550
|
var import_fs_extra16 = __toESM(require_lib(), 1);
|
|
31371
|
-
import { join as
|
|
31551
|
+
import { join as join27, relative as relative8, resolve as resolve3 } from "node:path";
|
|
31372
31552
|
var SKIP_DIRS = [
|
|
31373
31553
|
"node_modules",
|
|
31374
31554
|
".venv",
|
|
@@ -31395,7 +31575,7 @@ class FileScanner {
|
|
|
31395
31575
|
logger.debug(`Skipping directory: ${entry}`);
|
|
31396
31576
|
continue;
|
|
31397
31577
|
}
|
|
31398
|
-
const fullPath =
|
|
31578
|
+
const fullPath = join27(dirPath, entry);
|
|
31399
31579
|
if (!FileScanner.isSafePath(basePath, fullPath)) {
|
|
31400
31580
|
logger.warning(`Skipping potentially unsafe path: ${entry}`);
|
|
31401
31581
|
continue;
|
|
@@ -31430,8 +31610,8 @@ class FileScanner {
|
|
|
31430
31610
|
return files;
|
|
31431
31611
|
}
|
|
31432
31612
|
static async findCustomFiles(destDir, sourceDir, subPath) {
|
|
31433
|
-
const destSubDir =
|
|
31434
|
-
const sourceSubDir =
|
|
31613
|
+
const destSubDir = join27(destDir, subPath);
|
|
31614
|
+
const sourceSubDir = join27(sourceDir, subPath);
|
|
31435
31615
|
const destFiles = await FileScanner.getFiles(destSubDir, destDir);
|
|
31436
31616
|
const sourceFiles = await FileScanner.getFiles(sourceSubDir, sourceDir);
|
|
31437
31617
|
const sourceFileSet = new Set(sourceFiles);
|
|
@@ -31472,7 +31652,7 @@ async function initCommand(options) {
|
|
|
31472
31652
|
logger.info("Running in non-interactive mode (--yes flag)");
|
|
31473
31653
|
}
|
|
31474
31654
|
if (validOptions.global) {
|
|
31475
|
-
const localSettingsPath =
|
|
31655
|
+
const localSettingsPath = join28(process.cwd(), ".claude", "settings.json");
|
|
31476
31656
|
if (await import_fs_extra17.pathExists(localSettingsPath)) {
|
|
31477
31657
|
if (isNonInteractive2) {
|
|
31478
31658
|
logger.warning("Local .claude/settings.json detected. Local settings take precedence over global.");
|
|
@@ -31484,7 +31664,7 @@ async function initCommand(options) {
|
|
|
31484
31664
|
return;
|
|
31485
31665
|
}
|
|
31486
31666
|
if (choice === "remove") {
|
|
31487
|
-
const localClaudeDir =
|
|
31667
|
+
const localClaudeDir = join28(process.cwd(), ".claude");
|
|
31488
31668
|
try {
|
|
31489
31669
|
await import_fs_extra17.remove(localClaudeDir);
|
|
31490
31670
|
logger.success("Removed local .claude/ directory");
|
|
@@ -31543,7 +31723,7 @@ async function initCommand(options) {
|
|
|
31543
31723
|
}
|
|
31544
31724
|
if (validOptions.fresh) {
|
|
31545
31725
|
const prefix = PathResolver.getPathPrefix(validOptions.global);
|
|
31546
|
-
const claudeDir2 = prefix ?
|
|
31726
|
+
const claudeDir2 = prefix ? join28(resolvedDir, prefix) : resolvedDir;
|
|
31547
31727
|
const canProceed = await handleFreshInstallation(claudeDir2, prompts);
|
|
31548
31728
|
if (!canProceed) {
|
|
31549
31729
|
return;
|
|
@@ -31680,7 +31860,7 @@ async function initCommand(options) {
|
|
|
31680
31860
|
}
|
|
31681
31861
|
}
|
|
31682
31862
|
if (!validOptions.fresh) {
|
|
31683
|
-
const newSkillsDir =
|
|
31863
|
+
const newSkillsDir = join28(extractDir, ".claude", "skills");
|
|
31684
31864
|
const currentSkillsDir = PathResolver.buildSkillsPath(resolvedDir, validOptions.global);
|
|
31685
31865
|
if (await import_fs_extra17.pathExists(newSkillsDir) && await import_fs_extra17.pathExists(currentSkillsDir)) {
|
|
31686
31866
|
logger.info("Checking for skills directory migration...");
|
|
@@ -31705,7 +31885,7 @@ async function initCommand(options) {
|
|
|
31705
31885
|
let customClaudeFiles = [];
|
|
31706
31886
|
if (!validOptions.fresh) {
|
|
31707
31887
|
logger.info("Scanning for custom .claude files...");
|
|
31708
|
-
const scanSourceDir = validOptions.global ?
|
|
31888
|
+
const scanSourceDir = validOptions.global ? join28(extractDir, ".claude") : extractDir;
|
|
31709
31889
|
const scanTargetSubdir = validOptions.global ? "" : ".claude";
|
|
31710
31890
|
customClaudeFiles = await FileScanner.findCustomFiles(resolvedDir, scanSourceDir, scanTargetSubdir);
|
|
31711
31891
|
} else {
|
|
@@ -31734,7 +31914,7 @@ async function initCommand(options) {
|
|
|
31734
31914
|
merger.addIgnorePatterns(validOptions.exclude);
|
|
31735
31915
|
}
|
|
31736
31916
|
merger.setGlobalFlag(validOptions.global);
|
|
31737
|
-
const claudeDir = validOptions.global ? resolvedDir :
|
|
31917
|
+
const claudeDir = validOptions.global ? resolvedDir : join28(resolvedDir, ".claude");
|
|
31738
31918
|
const releaseManifest = await ReleaseManifestLoader.load(extractDir);
|
|
31739
31919
|
if (!validOptions.fresh && await import_fs_extra17.pathExists(claudeDir)) {
|
|
31740
31920
|
const legacyDetection = await LegacyMigration.detectLegacy(claudeDir);
|
|
@@ -31756,7 +31936,7 @@ async function initCommand(options) {
|
|
|
31756
31936
|
return;
|
|
31757
31937
|
}
|
|
31758
31938
|
}
|
|
31759
|
-
const sourceDir = validOptions.global ?
|
|
31939
|
+
const sourceDir = validOptions.global ? join28(extractDir, ".claude") : extractDir;
|
|
31760
31940
|
await merger.merge(sourceDir, resolvedDir, false);
|
|
31761
31941
|
const manifestWriter = new ManifestWriter;
|
|
31762
31942
|
const installedFiles = merger.getAllInstalledFiles();
|
|
@@ -31765,7 +31945,7 @@ async function initCommand(options) {
|
|
|
31765
31945
|
if (!validOptions.global && !installedPath.startsWith(".claude/"))
|
|
31766
31946
|
continue;
|
|
31767
31947
|
const relativePath = validOptions.global ? installedPath : installedPath.replace(/^\.claude\//, "");
|
|
31768
|
-
const filePath =
|
|
31948
|
+
const filePath = join28(claudeDir, relativePath);
|
|
31769
31949
|
const manifestEntry = releaseManifest ? ReleaseManifestLoader.findFile(releaseManifest, installedPath) : null;
|
|
31770
31950
|
const ownership = manifestEntry ? "ck" : "user";
|
|
31771
31951
|
filesToTrack.push({
|
|
@@ -31786,8 +31966,8 @@ async function initCommand(options) {
|
|
|
31786
31966
|
trackingSpinner.succeed(`Tracked ${trackResult.success} files`);
|
|
31787
31967
|
await manifestWriter.writeManifest(claudeDir, kitConfig.name, release.tag_name, validOptions.global ? "global" : "local");
|
|
31788
31968
|
if (validOptions.global) {
|
|
31789
|
-
const claudeMdSource =
|
|
31790
|
-
const claudeMdDest =
|
|
31969
|
+
const claudeMdSource = join28(extractDir, "CLAUDE.md");
|
|
31970
|
+
const claudeMdDest = join28(resolvedDir, "CLAUDE.md");
|
|
31791
31971
|
if (await import_fs_extra17.pathExists(claudeMdSource)) {
|
|
31792
31972
|
if (!await import_fs_extra17.pathExists(claudeMdDest)) {
|
|
31793
31973
|
await import_fs_extra17.copy(claudeMdSource, claudeMdDest);
|
|
@@ -31807,7 +31987,7 @@ async function initCommand(options) {
|
|
|
31807
31987
|
await handleSkillsInstallation2(skillsDir);
|
|
31808
31988
|
}
|
|
31809
31989
|
if (!validOptions.skipSetup && !isNonInteractive2) {
|
|
31810
|
-
const envPath =
|
|
31990
|
+
const envPath = join28(claudeDir, ".env");
|
|
31811
31991
|
if (!await import_fs_extra17.pathExists(envPath)) {
|
|
31812
31992
|
const shouldSetup = await prompts.confirm("Set up API keys now? (Gemini API key for ai-multimodal skill, optional webhooks)");
|
|
31813
31993
|
if (shouldSetup) {
|
|
@@ -31839,7 +32019,7 @@ Protected files (.env, etc.) were not modified.`;
|
|
|
31839
32019
|
|
|
31840
32020
|
// src/commands/new.ts
|
|
31841
32021
|
var import_fs_extra18 = __toESM(require_lib(), 1);
|
|
31842
|
-
import { join as
|
|
32022
|
+
import { join as join29, resolve as resolve5 } from "node:path";
|
|
31843
32023
|
init_types2();
|
|
31844
32024
|
init_environment();
|
|
31845
32025
|
init_logger();
|
|
@@ -32010,7 +32190,7 @@ async function newCommand(options) {
|
|
|
32010
32190
|
await CommandsPrefix.cleanupCommandsDirectory(resolvedDir, false);
|
|
32011
32191
|
}
|
|
32012
32192
|
await merger.merge(extractDir, resolvedDir, true);
|
|
32013
|
-
const claudeDir =
|
|
32193
|
+
const claudeDir = join29(resolvedDir, ".claude");
|
|
32014
32194
|
const manifestWriter = new ManifestWriter;
|
|
32015
32195
|
const releaseManifest = await ReleaseManifestLoader.load(extractDir);
|
|
32016
32196
|
const installedFiles = merger.getAllInstalledFiles();
|
|
@@ -32019,7 +32199,7 @@ async function newCommand(options) {
|
|
|
32019
32199
|
if (!installedPath.startsWith(".claude/"))
|
|
32020
32200
|
continue;
|
|
32021
32201
|
const relativePath = installedPath.replace(/^\.claude\//, "");
|
|
32022
|
-
const filePath =
|
|
32202
|
+
const filePath = join29(claudeDir, relativePath);
|
|
32023
32203
|
const manifestEntry = releaseManifest ? ReleaseManifestLoader.findFile(releaseManifest, installedPath) : null;
|
|
32024
32204
|
const ownership = manifestEntry ? "ck" : "user";
|
|
32025
32205
|
filesToTrack.push({
|
|
@@ -32075,7 +32255,7 @@ init_dist2();
|
|
|
32075
32255
|
var import_fs_extra19 = __toESM(require_lib(), 1);
|
|
32076
32256
|
var import_picocolors10 = __toESM(require_picocolors(), 1);
|
|
32077
32257
|
import { readdirSync, rmSync } from "node:fs";
|
|
32078
|
-
import { dirname as dirname4, join as
|
|
32258
|
+
import { dirname as dirname4, join as join30 } from "node:path";
|
|
32079
32259
|
init_types2();
|
|
32080
32260
|
init_logger();
|
|
32081
32261
|
async function detectInstallations() {
|
|
@@ -32166,7 +32346,7 @@ async function analyzeInstallation(installation, forceOverwrite) {
|
|
|
32166
32346
|
return result;
|
|
32167
32347
|
}
|
|
32168
32348
|
for (const trackedFile of metadata.files) {
|
|
32169
|
-
const filePath =
|
|
32349
|
+
const filePath = join30(installation.path, trackedFile.path);
|
|
32170
32350
|
const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
|
|
32171
32351
|
if (!ownershipResult.exists)
|
|
32172
32352
|
continue;
|
|
@@ -32224,7 +32404,7 @@ async function removeInstallations(installations, options) {
|
|
|
32224
32404
|
let removedCount = 0;
|
|
32225
32405
|
let cleanedDirs = 0;
|
|
32226
32406
|
for (const item of analysis.toDelete) {
|
|
32227
|
-
const filePath =
|
|
32407
|
+
const filePath = join30(installation.path, item.path);
|
|
32228
32408
|
if (await import_fs_extra19.pathExists(filePath)) {
|
|
32229
32409
|
await import_fs_extra19.remove(filePath);
|
|
32230
32410
|
removedCount++;
|
|
@@ -32326,7 +32506,7 @@ import { promisify as promisify6 } from "node:util";
|
|
|
32326
32506
|
// package.json
|
|
32327
32507
|
var package_default2 = {
|
|
32328
32508
|
name: "claudekit-cli",
|
|
32329
|
-
version: "3.
|
|
32509
|
+
version: "3.6.0",
|
|
32330
32510
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
32331
32511
|
type: "module",
|
|
32332
32512
|
repository: {
|
|
@@ -32771,20 +32951,20 @@ var import_picocolors12 = __toESM(require_picocolors(), 1);
|
|
|
32771
32951
|
|
|
32772
32952
|
// src/lib/version-cache.ts
|
|
32773
32953
|
init_logger();
|
|
32774
|
-
import { existsSync as
|
|
32954
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
32775
32955
|
import { mkdir as mkdir9, readFile as readFile13, writeFile as writeFile11 } from "node:fs/promises";
|
|
32776
|
-
import { join as
|
|
32956
|
+
import { join as join31 } from "node:path";
|
|
32777
32957
|
class VersionCacheManager {
|
|
32778
32958
|
static CACHE_FILENAME = "version-check.json";
|
|
32779
32959
|
static CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
32780
32960
|
static getCacheFile() {
|
|
32781
32961
|
const cacheDir = PathResolver.getCacheDir(false);
|
|
32782
|
-
return
|
|
32962
|
+
return join31(cacheDir, VersionCacheManager.CACHE_FILENAME);
|
|
32783
32963
|
}
|
|
32784
32964
|
static async load() {
|
|
32785
32965
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
32786
32966
|
try {
|
|
32787
|
-
if (!
|
|
32967
|
+
if (!existsSync7(cacheFile)) {
|
|
32788
32968
|
logger.debug("Version check cache not found");
|
|
32789
32969
|
return null;
|
|
32790
32970
|
}
|
|
@@ -32805,7 +32985,7 @@ class VersionCacheManager {
|
|
|
32805
32985
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
32806
32986
|
const cacheDir = PathResolver.getCacheDir(false);
|
|
32807
32987
|
try {
|
|
32808
|
-
if (!
|
|
32988
|
+
if (!existsSync7(cacheDir)) {
|
|
32809
32989
|
await mkdir9(cacheDir, { recursive: true, mode: 448 });
|
|
32810
32990
|
}
|
|
32811
32991
|
await writeFile11(cacheFile, JSON.stringify(cache2, null, 2), "utf-8");
|
|
@@ -32827,7 +33007,7 @@ class VersionCacheManager {
|
|
|
32827
33007
|
static async clear() {
|
|
32828
33008
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
32829
33009
|
try {
|
|
32830
|
-
if (
|
|
33010
|
+
if (existsSync7(cacheFile)) {
|
|
32831
33011
|
const fs12 = await import("node:fs/promises");
|
|
32832
33012
|
await fs12.unlink(cacheFile);
|
|
32833
33013
|
logger.debug("Version check cache cleared");
|
|
@@ -33255,7 +33435,7 @@ var logger2 = new Logger2;
|
|
|
33255
33435
|
|
|
33256
33436
|
// src/utils/path-resolver.ts
|
|
33257
33437
|
import { homedir as homedir2, platform as platform9 } from "node:os";
|
|
33258
|
-
import { join as
|
|
33438
|
+
import { join as join32, normalize as normalize4 } from "node:path";
|
|
33259
33439
|
|
|
33260
33440
|
class PathResolver2 {
|
|
33261
33441
|
static getTestHomeDir() {
|
|
@@ -33288,50 +33468,50 @@ class PathResolver2 {
|
|
|
33288
33468
|
static getConfigDir(global3 = false) {
|
|
33289
33469
|
const testHome = PathResolver2.getTestHomeDir();
|
|
33290
33470
|
if (testHome) {
|
|
33291
|
-
return global3 ?
|
|
33471
|
+
return global3 ? join32(testHome, ".config", "claude") : join32(testHome, ".claudekit");
|
|
33292
33472
|
}
|
|
33293
33473
|
if (!global3) {
|
|
33294
|
-
return
|
|
33474
|
+
return join32(homedir2(), ".claudekit");
|
|
33295
33475
|
}
|
|
33296
33476
|
const os2 = platform9();
|
|
33297
33477
|
if (os2 === "win32") {
|
|
33298
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
33299
|
-
return
|
|
33478
|
+
const localAppData = process.env.LOCALAPPDATA || join32(homedir2(), "AppData", "Local");
|
|
33479
|
+
return join32(localAppData, "claude");
|
|
33300
33480
|
}
|
|
33301
33481
|
const xdgConfigHome = process.env.XDG_CONFIG_HOME;
|
|
33302
33482
|
if (xdgConfigHome) {
|
|
33303
|
-
return
|
|
33483
|
+
return join32(xdgConfigHome, "claude");
|
|
33304
33484
|
}
|
|
33305
|
-
return
|
|
33485
|
+
return join32(homedir2(), ".config", "claude");
|
|
33306
33486
|
}
|
|
33307
33487
|
static getConfigFile(global3 = false) {
|
|
33308
|
-
return
|
|
33488
|
+
return join32(PathResolver2.getConfigDir(global3), "config.json");
|
|
33309
33489
|
}
|
|
33310
33490
|
static getCacheDir(global3 = false) {
|
|
33311
33491
|
const testHome = PathResolver2.getTestHomeDir();
|
|
33312
33492
|
if (testHome) {
|
|
33313
|
-
return global3 ?
|
|
33493
|
+
return global3 ? join32(testHome, ".cache", "claude") : join32(testHome, ".claudekit", "cache");
|
|
33314
33494
|
}
|
|
33315
33495
|
if (!global3) {
|
|
33316
|
-
return
|
|
33496
|
+
return join32(homedir2(), ".claudekit", "cache");
|
|
33317
33497
|
}
|
|
33318
33498
|
const os2 = platform9();
|
|
33319
33499
|
if (os2 === "win32") {
|
|
33320
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
33321
|
-
return
|
|
33500
|
+
const localAppData = process.env.LOCALAPPDATA || join32(homedir2(), "AppData", "Local");
|
|
33501
|
+
return join32(localAppData, "claude", "cache");
|
|
33322
33502
|
}
|
|
33323
33503
|
const xdgCacheHome = process.env.XDG_CACHE_HOME;
|
|
33324
33504
|
if (xdgCacheHome) {
|
|
33325
|
-
return
|
|
33505
|
+
return join32(xdgCacheHome, "claude");
|
|
33326
33506
|
}
|
|
33327
|
-
return
|
|
33507
|
+
return join32(homedir2(), ".cache", "claude");
|
|
33328
33508
|
}
|
|
33329
33509
|
static getGlobalKitDir() {
|
|
33330
33510
|
const testHome = PathResolver2.getTestHomeDir();
|
|
33331
33511
|
if (testHome) {
|
|
33332
|
-
return
|
|
33512
|
+
return join32(testHome, ".claude");
|
|
33333
33513
|
}
|
|
33334
|
-
return
|
|
33514
|
+
return join32(homedir2(), ".claude");
|
|
33335
33515
|
}
|
|
33336
33516
|
static getPathPrefix(global3) {
|
|
33337
33517
|
return global3 ? "" : ".claude";
|
|
@@ -33339,9 +33519,9 @@ class PathResolver2 {
|
|
|
33339
33519
|
static buildSkillsPath(baseDir, global3) {
|
|
33340
33520
|
const prefix = PathResolver2.getPathPrefix(global3);
|
|
33341
33521
|
if (prefix) {
|
|
33342
|
-
return
|
|
33522
|
+
return join32(baseDir, prefix, "skills");
|
|
33343
33523
|
}
|
|
33344
|
-
return
|
|
33524
|
+
return join32(baseDir, "skills");
|
|
33345
33525
|
}
|
|
33346
33526
|
static buildComponentPath(baseDir, component, global3) {
|
|
33347
33527
|
if (!PathResolver2.isPathSafe(component)) {
|
|
@@ -33349,9 +33529,9 @@ class PathResolver2 {
|
|
|
33349
33529
|
}
|
|
33350
33530
|
const prefix = PathResolver2.getPathPrefix(global3);
|
|
33351
33531
|
if (prefix) {
|
|
33352
|
-
return
|
|
33532
|
+
return join32(baseDir, prefix, component);
|
|
33353
33533
|
}
|
|
33354
|
-
return
|
|
33534
|
+
return join32(baseDir, component);
|
|
33355
33535
|
}
|
|
33356
33536
|
}
|
|
33357
33537
|
|
|
@@ -33369,13 +33549,13 @@ async function displayVersion() {
|
|
|
33369
33549
|
let localKitVersion = null;
|
|
33370
33550
|
let isGlobalOnlyKit = false;
|
|
33371
33551
|
const globalKitDir = PathResolver2.getGlobalKitDir();
|
|
33372
|
-
const globalMetadataPath =
|
|
33552
|
+
const globalMetadataPath = join33(globalKitDir, "metadata.json");
|
|
33373
33553
|
const prefix = PathResolver2.getPathPrefix(false);
|
|
33374
|
-
const localMetadataPath = prefix ?
|
|
33554
|
+
const localMetadataPath = prefix ? join33(process.cwd(), prefix, "metadata.json") : join33(process.cwd(), "metadata.json");
|
|
33375
33555
|
const isLocalSameAsGlobal = localMetadataPath === globalMetadataPath;
|
|
33376
|
-
if (!isLocalSameAsGlobal &&
|
|
33556
|
+
if (!isLocalSameAsGlobal && existsSync8(localMetadataPath)) {
|
|
33377
33557
|
try {
|
|
33378
|
-
const rawMetadata = JSON.parse(
|
|
33558
|
+
const rawMetadata = JSON.parse(readFileSync5(localMetadataPath, "utf-8"));
|
|
33379
33559
|
const metadata = MetadataSchema2.parse(rawMetadata);
|
|
33380
33560
|
if (metadata.version) {
|
|
33381
33561
|
const kitName = metadata.name || "ClaudeKit";
|
|
@@ -33387,9 +33567,9 @@ async function displayVersion() {
|
|
|
33387
33567
|
logger2.verbose("Failed to parse local metadata.json", { error });
|
|
33388
33568
|
}
|
|
33389
33569
|
}
|
|
33390
|
-
if (
|
|
33570
|
+
if (existsSync8(globalMetadataPath)) {
|
|
33391
33571
|
try {
|
|
33392
|
-
const rawMetadata = JSON.parse(
|
|
33572
|
+
const rawMetadata = JSON.parse(readFileSync5(globalMetadataPath, "utf-8"));
|
|
33393
33573
|
const metadata = MetadataSchema2.parse(rawMetadata);
|
|
33394
33574
|
if (metadata.version) {
|
|
33395
33575
|
const kitName = metadata.name || "ClaudeKit";
|