claudekit-cli 3.6.1 → 3.7.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 +1176 -385
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9329,7 +9329,7 @@ var require_get_stream = __commonJS((exports, module) => {
|
|
|
9329
9329
|
};
|
|
9330
9330
|
const { maxBuffer } = options;
|
|
9331
9331
|
let stream;
|
|
9332
|
-
await new Promise((
|
|
9332
|
+
await new Promise((resolve2, reject) => {
|
|
9333
9333
|
const rejectPromise = (error) => {
|
|
9334
9334
|
if (error && stream.getBufferedLength() <= BufferConstants.MAX_LENGTH) {
|
|
9335
9335
|
error.bufferedData = stream.getBufferedValue();
|
|
@@ -9341,7 +9341,7 @@ var require_get_stream = __commonJS((exports, module) => {
|
|
|
9341
9341
|
rejectPromise(error);
|
|
9342
9342
|
return;
|
|
9343
9343
|
}
|
|
9344
|
-
|
|
9344
|
+
resolve2();
|
|
9345
9345
|
});
|
|
9346
9346
|
stream.on("data", () => {
|
|
9347
9347
|
if (stream.getBufferedLength() > maxBuffer) {
|
|
@@ -10702,7 +10702,7 @@ var require_extract_zip = __commonJS((exports, module) => {
|
|
|
10702
10702
|
debug("opening", this.zipPath, "with opts", this.opts);
|
|
10703
10703
|
this.zipfile = await openZip(this.zipPath, { lazyEntries: true });
|
|
10704
10704
|
this.canceled = false;
|
|
10705
|
-
return new Promise((
|
|
10705
|
+
return new Promise((resolve2, reject) => {
|
|
10706
10706
|
this.zipfile.on("error", (err) => {
|
|
10707
10707
|
this.canceled = true;
|
|
10708
10708
|
reject(err);
|
|
@@ -10711,7 +10711,7 @@ var require_extract_zip = __commonJS((exports, module) => {
|
|
|
10711
10711
|
this.zipfile.on("close", () => {
|
|
10712
10712
|
if (!this.canceled) {
|
|
10713
10713
|
debug("zip extraction complete");
|
|
10714
|
-
|
|
10714
|
+
resolve2();
|
|
10715
10715
|
}
|
|
10716
10716
|
});
|
|
10717
10717
|
this.zipfile.on("entry", async (entry) => {
|
|
@@ -10756,7 +10756,7 @@ var require_extract_zip = __commonJS((exports, module) => {
|
|
|
10756
10756
|
const IFMT = 61440;
|
|
10757
10757
|
const IFDIR = 16384;
|
|
10758
10758
|
const IFLNK = 40960;
|
|
10759
|
-
const
|
|
10759
|
+
const symlink2 = (mode & IFMT) === IFLNK;
|
|
10760
10760
|
let isDir = (mode & IFMT) === IFDIR;
|
|
10761
10761
|
if (!isDir && entry.fileName.endsWith("/")) {
|
|
10762
10762
|
isDir = true;
|
|
@@ -10764,7 +10764,7 @@ var require_extract_zip = __commonJS((exports, module) => {
|
|
|
10764
10764
|
const madeBy = entry.versionMadeBy >> 8;
|
|
10765
10765
|
if (!isDir)
|
|
10766
10766
|
isDir = madeBy === 0 && entry.externalFileAttributes === 16;
|
|
10767
|
-
debug("extracting entry", { filename: entry.fileName, isDir, isSymlink:
|
|
10767
|
+
debug("extracting entry", { filename: entry.fileName, isDir, isSymlink: symlink2 });
|
|
10768
10768
|
const procMode = this.getExtractedMode(mode, isDir) & 511;
|
|
10769
10769
|
const destDir = isDir ? dest : path.dirname(dest);
|
|
10770
10770
|
const mkdirOptions = { recursive: true };
|
|
@@ -10777,7 +10777,7 @@ var require_extract_zip = __commonJS((exports, module) => {
|
|
|
10777
10777
|
return;
|
|
10778
10778
|
debug("opening read stream", dest);
|
|
10779
10779
|
const readStream = await promisify5(this.zipfile.openReadStream.bind(this.zipfile))(entry);
|
|
10780
|
-
if (
|
|
10780
|
+
if (symlink2) {
|
|
10781
10781
|
const link = await getStream(readStream);
|
|
10782
10782
|
debug("creating symlink", link, dest);
|
|
10783
10783
|
await fs2.symlink(link, dest);
|
|
@@ -12727,7 +12727,7 @@ var require_emoji_regex2 = __commonJS((exports, module) => {
|
|
|
12727
12727
|
|
|
12728
12728
|
// src/utils/install-error-handler.ts
|
|
12729
12729
|
import { existsSync as existsSync5, readFileSync as readFileSync4, unlinkSync as unlinkSync2 } from "node:fs";
|
|
12730
|
-
import { join as
|
|
12730
|
+
import { join as join18 } from "node:path";
|
|
12731
12731
|
function parseNameReason(str) {
|
|
12732
12732
|
const colonIndex = str.indexOf(":");
|
|
12733
12733
|
if (colonIndex === -1) {
|
|
@@ -12736,7 +12736,7 @@ function parseNameReason(str) {
|
|
|
12736
12736
|
return [str.slice(0, colonIndex).trim(), str.slice(colonIndex + 1).trim()];
|
|
12737
12737
|
}
|
|
12738
12738
|
function displayInstallErrors(skillsDir) {
|
|
12739
|
-
const summaryPath =
|
|
12739
|
+
const summaryPath = join18(skillsDir, ".install-error-summary.json");
|
|
12740
12740
|
if (!existsSync5(summaryPath)) {
|
|
12741
12741
|
logger.error("Skills installation failed. Run with --verbose for details.");
|
|
12742
12742
|
return;
|
|
@@ -12827,7 +12827,7 @@ async function checkNeedsSudoPackages() {
|
|
|
12827
12827
|
}
|
|
12828
12828
|
}
|
|
12829
12829
|
function hasInstallState(skillsDir) {
|
|
12830
|
-
const stateFilePath =
|
|
12830
|
+
const stateFilePath = join18(skillsDir, ".install-state.json");
|
|
12831
12831
|
return existsSync5(stateFilePath);
|
|
12832
12832
|
}
|
|
12833
12833
|
var WHICH_COMMAND_TIMEOUT_MS = 5000;
|
|
@@ -12851,10 +12851,10 @@ __export(exports_package_installer, {
|
|
|
12851
12851
|
getPackageVersion: () => getPackageVersion
|
|
12852
12852
|
});
|
|
12853
12853
|
import { exec as exec5, execFile as execFile2, spawn } from "node:child_process";
|
|
12854
|
-
import { join as
|
|
12854
|
+
import { join as join19, resolve as resolve3 } from "node:path";
|
|
12855
12855
|
import { promisify as promisify5 } from "node:util";
|
|
12856
12856
|
function executeInteractiveScript(command, args, options) {
|
|
12857
|
-
return new Promise((
|
|
12857
|
+
return new Promise((resolve4, reject) => {
|
|
12858
12858
|
const child = spawn(command, args, {
|
|
12859
12859
|
stdio: ["ignore", "inherit", "inherit"],
|
|
12860
12860
|
cwd: options?.cwd,
|
|
@@ -12875,7 +12875,7 @@ function executeInteractiveScript(command, args, options) {
|
|
|
12875
12875
|
} else if (code2 !== 0) {
|
|
12876
12876
|
reject(new Error(`Command exited with code ${code2}`));
|
|
12877
12877
|
} else {
|
|
12878
|
-
|
|
12878
|
+
resolve4();
|
|
12879
12879
|
}
|
|
12880
12880
|
});
|
|
12881
12881
|
child.on("error", (error) => {
|
|
@@ -12886,8 +12886,8 @@ function executeInteractiveScript(command, args, options) {
|
|
|
12886
12886
|
});
|
|
12887
12887
|
}
|
|
12888
12888
|
function getNpmCommand() {
|
|
12889
|
-
const
|
|
12890
|
-
return
|
|
12889
|
+
const platform9 = process.platform;
|
|
12890
|
+
return platform9 === "win32" ? "npm.cmd" : "npm";
|
|
12891
12891
|
}
|
|
12892
12892
|
function validatePackageName(packageName) {
|
|
12893
12893
|
if (!packageName || typeof packageName !== "string") {
|
|
@@ -13044,9 +13044,9 @@ async function installOpenCode() {
|
|
|
13044
13044
|
}
|
|
13045
13045
|
try {
|
|
13046
13046
|
logger.info(`Installing ${displayName}...`);
|
|
13047
|
-
const { unlink:
|
|
13047
|
+
const { unlink: unlink4 } = await import("node:fs/promises");
|
|
13048
13048
|
const { tmpdir: tmpdir3 } = await import("node:os");
|
|
13049
|
-
const tempScriptPath =
|
|
13049
|
+
const tempScriptPath = join19(tmpdir3(), "opencode-install.sh");
|
|
13050
13050
|
try {
|
|
13051
13051
|
logger.info("Downloading OpenCode installation script...");
|
|
13052
13052
|
await execFileAsync("curl", ["-fsSL", "https://opencode.ai/install", "-o", tempScriptPath], {
|
|
@@ -13061,7 +13061,7 @@ async function installOpenCode() {
|
|
|
13061
13061
|
});
|
|
13062
13062
|
} finally {
|
|
13063
13063
|
try {
|
|
13064
|
-
await
|
|
13064
|
+
await unlink4(tempScriptPath);
|
|
13065
13065
|
} catch {}
|
|
13066
13066
|
}
|
|
13067
13067
|
const installed = await isOpenCodeInstalled();
|
|
@@ -13119,8 +13119,8 @@ async function processPackageInstallations(shouldInstallOpenCode, shouldInstallG
|
|
|
13119
13119
|
return results;
|
|
13120
13120
|
}
|
|
13121
13121
|
function validateScriptPath(skillsDir, scriptPath) {
|
|
13122
|
-
const skillsDirResolved =
|
|
13123
|
-
const scriptPathResolved =
|
|
13122
|
+
const skillsDirResolved = resolve3(skillsDir);
|
|
13123
|
+
const scriptPathResolved = resolve3(scriptPath);
|
|
13124
13124
|
const isWindows5 = process.platform === "win32";
|
|
13125
13125
|
const skillsDirNormalized = isWindows5 ? skillsDirResolved.toLowerCase() : skillsDirResolved;
|
|
13126
13126
|
const scriptPathNormalized = isWindows5 ? scriptPathResolved.toLowerCase() : scriptPathResolved;
|
|
@@ -13157,11 +13157,11 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
13157
13157
|
}
|
|
13158
13158
|
try {
|
|
13159
13159
|
const { existsSync: existsSync6 } = await import("node:fs");
|
|
13160
|
-
const { readFile:
|
|
13160
|
+
const { readFile: readFile11 } = await import("node:fs/promises");
|
|
13161
13161
|
const clack = await Promise.resolve().then(() => (init_dist2(), exports_dist));
|
|
13162
|
-
const
|
|
13163
|
-
const scriptName =
|
|
13164
|
-
const scriptPath =
|
|
13162
|
+
const platform9 = process.platform;
|
|
13163
|
+
const scriptName = platform9 === "win32" ? "install.ps1" : "install.sh";
|
|
13164
|
+
const scriptPath = join19(skillsDir, scriptName);
|
|
13165
13165
|
try {
|
|
13166
13166
|
validateScriptPath(skillsDir, scriptPath);
|
|
13167
13167
|
} catch (error) {
|
|
@@ -13177,7 +13177,7 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
13177
13177
|
logger.warning(`Skills installation script not found: ${scriptPath}`);
|
|
13178
13178
|
logger.info("");
|
|
13179
13179
|
logger.info("\uD83D\uDCD6 Manual Installation Instructions:");
|
|
13180
|
-
logger.info(` See: ${
|
|
13180
|
+
logger.info(` See: ${join19(skillsDir, "INSTALLATION.md")}`);
|
|
13181
13181
|
logger.info("");
|
|
13182
13182
|
logger.info("Quick start:");
|
|
13183
13183
|
logger.info(" cd .claude/skills/ai-multimodal/scripts");
|
|
@@ -13190,10 +13190,10 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
13190
13190
|
}
|
|
13191
13191
|
logger.warning("⚠️ Installation script will execute with user privileges:");
|
|
13192
13192
|
logger.info(` Script: ${scriptPath}`);
|
|
13193
|
-
logger.info(` Platform: ${
|
|
13193
|
+
logger.info(` Platform: ${platform9 === "win32" ? "Windows (PowerShell)" : "Unix (bash)"}`);
|
|
13194
13194
|
logger.info("");
|
|
13195
13195
|
try {
|
|
13196
|
-
const scriptContent = await
|
|
13196
|
+
const scriptContent = await readFile11(scriptPath, "utf-8");
|
|
13197
13197
|
const previewLines = scriptContent.split(`
|
|
13198
13198
|
`).slice(0, 20);
|
|
13199
13199
|
logger.info("Script preview (first 20 lines):");
|
|
@@ -13218,10 +13218,10 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
13218
13218
|
logger.info("Installation cancelled by user");
|
|
13219
13219
|
logger.info("");
|
|
13220
13220
|
logger.info("\uD83D\uDCD6 Manual Installation Instructions:");
|
|
13221
|
-
logger.info(` ${
|
|
13221
|
+
logger.info(` ${platform9 === "win32" ? `powershell -File "${scriptPath}"` : `bash ${scriptPath}`}`);
|
|
13222
13222
|
logger.info("");
|
|
13223
13223
|
logger.info("Or see complete guide:");
|
|
13224
|
-
logger.info(` ${
|
|
13224
|
+
logger.info(` ${join19(skillsDir, "INSTALLATION.md")}`);
|
|
13225
13225
|
return {
|
|
13226
13226
|
success: false,
|
|
13227
13227
|
package: displayName,
|
|
@@ -13246,7 +13246,7 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
13246
13246
|
}
|
|
13247
13247
|
}
|
|
13248
13248
|
}
|
|
13249
|
-
if (
|
|
13249
|
+
if (platform9 === "linux") {
|
|
13250
13250
|
const needsSudo = await checkNeedsSudoPackages();
|
|
13251
13251
|
if (needsSudo) {
|
|
13252
13252
|
if (isNonInteractive()) {
|
|
@@ -13275,7 +13275,7 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
13275
13275
|
...process.env,
|
|
13276
13276
|
NON_INTERACTIVE: "1"
|
|
13277
13277
|
};
|
|
13278
|
-
if (
|
|
13278
|
+
if (platform9 === "win32") {
|
|
13279
13279
|
logger.warning("⚠️ Windows: Respecting system PowerShell execution policy");
|
|
13280
13280
|
logger.info(" If the script fails, you may need to set execution policy:");
|
|
13281
13281
|
logger.info(" Set-ExecutionPolicy RemoteSigned -Scope CurrentUser");
|
|
@@ -13326,7 +13326,7 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
13326
13326
|
logger.info("\uD83D\uDCD6 Manual Installation Instructions:");
|
|
13327
13327
|
logger.info("");
|
|
13328
13328
|
logger.info("See complete guide:");
|
|
13329
|
-
logger.info(` cat ${
|
|
13329
|
+
logger.info(` cat ${join19(skillsDir, "INSTALLATION.md")}`);
|
|
13330
13330
|
logger.info("");
|
|
13331
13331
|
logger.info("Quick start:");
|
|
13332
13332
|
logger.info(" cd .claude/skills/ai-multimodal/scripts");
|
|
@@ -14002,7 +14002,7 @@ function getPagerArgs(pagerCmd) {
|
|
|
14002
14002
|
return [];
|
|
14003
14003
|
}
|
|
14004
14004
|
async function trySystemPager(content) {
|
|
14005
|
-
return new Promise((
|
|
14005
|
+
return new Promise((resolve7) => {
|
|
14006
14006
|
const pagerCmd = process.env.PAGER || "less";
|
|
14007
14007
|
const pagerArgs = getPagerArgs(pagerCmd);
|
|
14008
14008
|
try {
|
|
@@ -14012,20 +14012,20 @@ async function trySystemPager(content) {
|
|
|
14012
14012
|
});
|
|
14013
14013
|
const timeout = setTimeout(() => {
|
|
14014
14014
|
pager.kill();
|
|
14015
|
-
|
|
14015
|
+
resolve7(false);
|
|
14016
14016
|
}, 30000);
|
|
14017
14017
|
pager.stdin.write(content);
|
|
14018
14018
|
pager.stdin.end();
|
|
14019
14019
|
pager.on("close", (code2) => {
|
|
14020
14020
|
clearTimeout(timeout);
|
|
14021
|
-
|
|
14021
|
+
resolve7(code2 === 0);
|
|
14022
14022
|
});
|
|
14023
14023
|
pager.on("error", () => {
|
|
14024
14024
|
clearTimeout(timeout);
|
|
14025
|
-
|
|
14025
|
+
resolve7(false);
|
|
14026
14026
|
});
|
|
14027
14027
|
} catch {
|
|
14028
|
-
|
|
14028
|
+
resolve7(false);
|
|
14029
14029
|
}
|
|
14030
14030
|
});
|
|
14031
14031
|
}
|
|
@@ -14052,16 +14052,16 @@ async function basicPager(content) {
|
|
|
14052
14052
|
break;
|
|
14053
14053
|
}
|
|
14054
14054
|
const remaining = lines.length - currentLine;
|
|
14055
|
-
await new Promise((
|
|
14055
|
+
await new Promise((resolve7) => {
|
|
14056
14056
|
rl.question(`-- More (${remaining} lines) [Enter/q] --`, (answer) => {
|
|
14057
14057
|
if (answer.toLowerCase() === "q") {
|
|
14058
14058
|
rl.close();
|
|
14059
14059
|
process.exitCode = 0;
|
|
14060
|
-
|
|
14060
|
+
resolve7();
|
|
14061
14061
|
return;
|
|
14062
14062
|
}
|
|
14063
14063
|
process.stdout.write("\x1B[1A\x1B[2K");
|
|
14064
|
-
|
|
14064
|
+
resolve7();
|
|
14065
14065
|
});
|
|
14066
14066
|
});
|
|
14067
14067
|
}
|
|
@@ -14320,7 +14320,7 @@ var init_help_interceptor = __esm(() => {
|
|
|
14320
14320
|
|
|
14321
14321
|
// src/index.ts
|
|
14322
14322
|
import { existsSync as existsSync8, readFileSync as readFileSync5 } from "fs";
|
|
14323
|
-
import { join as
|
|
14323
|
+
import { join as join34 } from "path";
|
|
14324
14324
|
|
|
14325
14325
|
// node_modules/cac/dist/index.mjs
|
|
14326
14326
|
import { EventEmitter } from "events";
|
|
@@ -14925,7 +14925,7 @@ var cac = (name = "") => new CAC(name);
|
|
|
14925
14925
|
// package.json
|
|
14926
14926
|
var package_default = {
|
|
14927
14927
|
name: "claudekit-cli",
|
|
14928
|
-
version: "3.
|
|
14928
|
+
version: "3.7.0",
|
|
14929
14929
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
14930
14930
|
type: "module",
|
|
14931
14931
|
repository: {
|
|
@@ -15016,7 +15016,8 @@ init_dist2();
|
|
|
15016
15016
|
// src/lib/health-checks/types.ts
|
|
15017
15017
|
init_zod();
|
|
15018
15018
|
var CheckStatusSchema = exports_external.enum(["pass", "warn", "fail", "info"]);
|
|
15019
|
-
var
|
|
15019
|
+
var CheckPrioritySchema = exports_external.enum(["critical", "standard", "extended"]);
|
|
15020
|
+
var CheckGroupSchema = exports_external.enum(["system", "claudekit", "auth", "platform", "network"]);
|
|
15020
15021
|
var FixResultSchema = exports_external.object({
|
|
15021
15022
|
success: exports_external.boolean(),
|
|
15022
15023
|
message: exports_external.string(),
|
|
@@ -15026,6 +15027,7 @@ var CheckResultSchema = exports_external.object({
|
|
|
15026
15027
|
id: exports_external.string().min(1),
|
|
15027
15028
|
name: exports_external.string().min(1),
|
|
15028
15029
|
group: CheckGroupSchema,
|
|
15030
|
+
priority: CheckPrioritySchema.optional().default("standard"),
|
|
15029
15031
|
status: CheckStatusSchema,
|
|
15030
15032
|
message: exports_external.string(),
|
|
15031
15033
|
details: exports_external.string().optional(),
|
|
@@ -15039,7 +15041,8 @@ var CheckRunnerOptionsSchema = exports_external.object({
|
|
|
15039
15041
|
checkOnly: exports_external.boolean().optional(),
|
|
15040
15042
|
json: exports_external.boolean().optional(),
|
|
15041
15043
|
groups: exports_external.array(CheckGroupSchema).optional(),
|
|
15042
|
-
verbose: exports_external.boolean().optional()
|
|
15044
|
+
verbose: exports_external.boolean().optional(),
|
|
15045
|
+
full: exports_external.boolean().optional()
|
|
15043
15046
|
});
|
|
15044
15047
|
var CheckSummarySchema = exports_external.object({
|
|
15045
15048
|
timestamp: exports_external.string().datetime(),
|
|
@@ -15091,8 +15094,9 @@ class CheckRunner {
|
|
|
15091
15094
|
groups: filteredCheckers.map((c2) => c2.group)
|
|
15092
15095
|
});
|
|
15093
15096
|
const allResults = await this.executeCheckersInParallel(filteredCheckers);
|
|
15097
|
+
const filteredResults = this.filterChecksByPriority(allResults);
|
|
15094
15098
|
logger.verbose("All checks completed, building summary");
|
|
15095
|
-
return this.buildSummary(
|
|
15099
|
+
return this.buildSummary(filteredResults);
|
|
15096
15100
|
}
|
|
15097
15101
|
filterCheckersByGroup() {
|
|
15098
15102
|
if (!this.options.groups || this.options.groups.length === 0) {
|
|
@@ -15101,6 +15105,16 @@ class CheckRunner {
|
|
|
15101
15105
|
const allowedGroups = new Set(this.options.groups);
|
|
15102
15106
|
return this.checkers.filter((checker) => allowedGroups.has(checker.group));
|
|
15103
15107
|
}
|
|
15108
|
+
filterChecksByPriority(checks) {
|
|
15109
|
+
const includedPriorities = new Set(["critical", "standard"]);
|
|
15110
|
+
if (this.options.full) {
|
|
15111
|
+
includedPriorities.add("extended");
|
|
15112
|
+
}
|
|
15113
|
+
return checks.filter((check) => {
|
|
15114
|
+
const priority = check.priority ?? "standard";
|
|
15115
|
+
return includedPriorities.has(priority);
|
|
15116
|
+
});
|
|
15117
|
+
}
|
|
15104
15118
|
async executeCheckersInParallel(checkers) {
|
|
15105
15119
|
const resultsArrays = await Promise.all(checkers.map(async (checker) => {
|
|
15106
15120
|
logger.verbose(`Starting checker: ${checker.group}`);
|
|
@@ -15794,7 +15808,9 @@ class SystemChecker {
|
|
|
15794
15808
|
}
|
|
15795
15809
|
// src/lib/health-checks/claudekit-checker.ts
|
|
15796
15810
|
import { existsSync as existsSync3, readFileSync as readFileSync2, statSync } from "node:fs";
|
|
15797
|
-
import {
|
|
15811
|
+
import { constants, access, readFile as readFile3, readdir as readdir2, unlink, writeFile as writeFile2 } from "node:fs/promises";
|
|
15812
|
+
import { homedir as homedir2 } from "node:os";
|
|
15813
|
+
import { dirname, join as join4, normalize as normalize2, resolve } from "node:path";
|
|
15798
15814
|
|
|
15799
15815
|
// src/utils/claudekit-scanner.ts
|
|
15800
15816
|
var import_fs_extra = __toESM(require_lib(), 1);
|
|
@@ -15903,6 +15919,16 @@ class PathResolver {
|
|
|
15903
15919
|
}
|
|
15904
15920
|
|
|
15905
15921
|
// src/utils/claudekit-scanner.ts
|
|
15922
|
+
var SKIP_DIRS = [
|
|
15923
|
+
"debug",
|
|
15924
|
+
"projects",
|
|
15925
|
+
"shell-snapshots",
|
|
15926
|
+
"file-history",
|
|
15927
|
+
"todos",
|
|
15928
|
+
"session-env",
|
|
15929
|
+
"statsig",
|
|
15930
|
+
".anthropic"
|
|
15931
|
+
];
|
|
15906
15932
|
async function scanClaudeKitDirectory(directoryPath) {
|
|
15907
15933
|
const counts = {
|
|
15908
15934
|
agents: 0,
|
|
@@ -15935,6 +15961,9 @@ async function scanClaudeKitDirectory(directoryPath) {
|
|
|
15935
15961
|
const skillItems = await import_fs_extra.readdir(skillsPath);
|
|
15936
15962
|
let skillCount = 0;
|
|
15937
15963
|
for (const item of skillItems) {
|
|
15964
|
+
if (SKIP_DIRS.includes(item)) {
|
|
15965
|
+
continue;
|
|
15966
|
+
}
|
|
15938
15967
|
const itemPath = join2(skillsPath, item);
|
|
15939
15968
|
const stat = await import_fs_extra.readdir(itemPath).catch(() => null);
|
|
15940
15969
|
if (stat?.includes("SKILL.md")) {
|
|
@@ -16271,6 +16300,8 @@ class PackageManagerDetector {
|
|
|
16271
16300
|
}
|
|
16272
16301
|
|
|
16273
16302
|
// src/lib/health-checks/claudekit-checker.ts
|
|
16303
|
+
var HOOK_EXTENSIONS = [".js", ".cjs", ".mjs", ".ts", ".sh", ".ps1"];
|
|
16304
|
+
|
|
16274
16305
|
class ClaudekitChecker {
|
|
16275
16306
|
group = "claudekit";
|
|
16276
16307
|
projectDir;
|
|
@@ -16298,6 +16329,18 @@ class ClaudekitChecker {
|
|
|
16298
16329
|
results.push(...this.checkSkillsScripts(setup));
|
|
16299
16330
|
logger.verbose("ClaudekitChecker: Checking component counts");
|
|
16300
16331
|
results.push(this.checkComponentCounts(setup));
|
|
16332
|
+
logger.verbose("ClaudekitChecker: Checking global dir readability");
|
|
16333
|
+
results.push(await this.checkGlobalDirReadable());
|
|
16334
|
+
logger.verbose("ClaudekitChecker: Checking global dir writability");
|
|
16335
|
+
results.push(await this.checkGlobalDirWritable());
|
|
16336
|
+
logger.verbose("ClaudekitChecker: Checking hooks directory");
|
|
16337
|
+
results.push(await this.checkHooksExist());
|
|
16338
|
+
logger.verbose("ClaudekitChecker: Checking settings.json validity");
|
|
16339
|
+
results.push(await this.checkSettingsValid());
|
|
16340
|
+
logger.verbose("ClaudekitChecker: Checking path references");
|
|
16341
|
+
results.push(await this.checkPathRefsValid());
|
|
16342
|
+
logger.verbose("ClaudekitChecker: Checking project config completeness");
|
|
16343
|
+
results.push(await this.checkProjectConfigCompleteness(setup));
|
|
16301
16344
|
logger.verbose("ClaudekitChecker: All checks complete");
|
|
16302
16345
|
return results;
|
|
16303
16346
|
}
|
|
@@ -16310,6 +16353,7 @@ class ClaudekitChecker {
|
|
|
16310
16353
|
id: "ck-cli-install-method",
|
|
16311
16354
|
name: "CLI Installed Via",
|
|
16312
16355
|
group: "claudekit",
|
|
16356
|
+
priority: "standard",
|
|
16313
16357
|
status: pm !== "unknown" ? "pass" : "warn",
|
|
16314
16358
|
message: pmVersion ? `${displayName} (v${pmVersion})` : displayName,
|
|
16315
16359
|
suggestion: pm === "unknown" ? "Run: npm install -g claudekit-cli" : undefined,
|
|
@@ -16325,6 +16369,7 @@ class ClaudekitChecker {
|
|
|
16325
16369
|
id: "ck-global-install",
|
|
16326
16370
|
name: "Global CK",
|
|
16327
16371
|
group: "claudekit",
|
|
16372
|
+
priority: "critical",
|
|
16328
16373
|
status: hasGlobal ? "pass" : "warn",
|
|
16329
16374
|
message: hasGlobal ? `${kitName} ${version}` : "Not installed",
|
|
16330
16375
|
details: hasGlobal ? setup.global.path : undefined,
|
|
@@ -16341,6 +16386,7 @@ class ClaudekitChecker {
|
|
|
16341
16386
|
id: "ck-project-install",
|
|
16342
16387
|
name: "Project CK",
|
|
16343
16388
|
group: "claudekit",
|
|
16389
|
+
priority: "standard",
|
|
16344
16390
|
status: hasProject ? "pass" : "info",
|
|
16345
16391
|
message: hasProject ? `${kitName} ${version}` : "Not a ClaudeKit project",
|
|
16346
16392
|
details: hasProject ? setup.project.path : undefined,
|
|
@@ -16369,6 +16415,7 @@ class ClaudekitChecker {
|
|
|
16369
16415
|
id,
|
|
16370
16416
|
name,
|
|
16371
16417
|
group: "claudekit",
|
|
16418
|
+
priority: "standard",
|
|
16372
16419
|
status: "warn",
|
|
16373
16420
|
message: "Missing",
|
|
16374
16421
|
suggestion: "Create CLAUDE.md with project instructions",
|
|
@@ -16383,6 +16430,7 @@ class ClaudekitChecker {
|
|
|
16383
16430
|
id,
|
|
16384
16431
|
name,
|
|
16385
16432
|
group: "claudekit",
|
|
16433
|
+
priority: "standard",
|
|
16386
16434
|
status: "warn",
|
|
16387
16435
|
message: "Empty (0 bytes)",
|
|
16388
16436
|
details: path,
|
|
@@ -16394,6 +16442,7 @@ class ClaudekitChecker {
|
|
|
16394
16442
|
id,
|
|
16395
16443
|
name,
|
|
16396
16444
|
group: "claudekit",
|
|
16445
|
+
priority: "standard",
|
|
16397
16446
|
status: "pass",
|
|
16398
16447
|
message: `Found (${sizeKB}KB)`,
|
|
16399
16448
|
details: path,
|
|
@@ -16404,6 +16453,7 @@ class ClaudekitChecker {
|
|
|
16404
16453
|
id,
|
|
16405
16454
|
name,
|
|
16406
16455
|
group: "claudekit",
|
|
16456
|
+
priority: "standard",
|
|
16407
16457
|
status: "warn",
|
|
16408
16458
|
message: "Unreadable",
|
|
16409
16459
|
details: path,
|
|
@@ -16419,6 +16469,7 @@ class ClaudekitChecker {
|
|
|
16419
16469
|
id: "ck-active-plan",
|
|
16420
16470
|
name: "Active Plan",
|
|
16421
16471
|
group: "claudekit",
|
|
16472
|
+
priority: "standard",
|
|
16422
16473
|
status: "info",
|
|
16423
16474
|
message: "None",
|
|
16424
16475
|
autoFixable: false
|
|
@@ -16432,6 +16483,7 @@ class ClaudekitChecker {
|
|
|
16432
16483
|
id: "ck-active-plan",
|
|
16433
16484
|
name: "Active Plan",
|
|
16434
16485
|
group: "claudekit",
|
|
16486
|
+
priority: "standard",
|
|
16435
16487
|
status: "warn",
|
|
16436
16488
|
message: "Orphaned (target missing)",
|
|
16437
16489
|
details: targetPath,
|
|
@@ -16443,6 +16495,7 @@ class ClaudekitChecker {
|
|
|
16443
16495
|
id: "ck-active-plan",
|
|
16444
16496
|
name: "Active Plan",
|
|
16445
16497
|
group: "claudekit",
|
|
16498
|
+
priority: "standard",
|
|
16446
16499
|
status: "pass",
|
|
16447
16500
|
message: targetPath,
|
|
16448
16501
|
autoFixable: false
|
|
@@ -16452,6 +16505,7 @@ class ClaudekitChecker {
|
|
|
16452
16505
|
id: "ck-active-plan",
|
|
16453
16506
|
name: "Active Plan",
|
|
16454
16507
|
group: "claudekit",
|
|
16508
|
+
priority: "standard",
|
|
16455
16509
|
status: "warn",
|
|
16456
16510
|
message: "Unreadable",
|
|
16457
16511
|
details: activePlanPath,
|
|
@@ -16470,6 +16524,7 @@ class ClaudekitChecker {
|
|
|
16470
16524
|
id: "ck-global-skills-script",
|
|
16471
16525
|
name: "Global Skills Script",
|
|
16472
16526
|
group: "claudekit",
|
|
16527
|
+
priority: "standard",
|
|
16473
16528
|
status: hasGlobalScript ? "pass" : "info",
|
|
16474
16529
|
message: hasGlobalScript ? "Available" : "Not found",
|
|
16475
16530
|
details: hasGlobalScript ? globalScriptPath : undefined,
|
|
@@ -16484,6 +16539,7 @@ class ClaudekitChecker {
|
|
|
16484
16539
|
id: "ck-project-skills-script",
|
|
16485
16540
|
name: "Project Skills Script",
|
|
16486
16541
|
group: "claudekit",
|
|
16542
|
+
priority: "standard",
|
|
16487
16543
|
status: hasProjectScript ? "pass" : "info",
|
|
16488
16544
|
message: hasProjectScript ? "Available" : "Not found",
|
|
16489
16545
|
details: hasProjectScript ? projectScriptPath : undefined,
|
|
@@ -16505,12 +16561,349 @@ class ClaudekitChecker {
|
|
|
16505
16561
|
id: "ck-component-counts",
|
|
16506
16562
|
name: "ClaudeKit Components",
|
|
16507
16563
|
group: "claudekit",
|
|
16564
|
+
priority: "standard",
|
|
16508
16565
|
status: totalComponents > 0 ? "info" : "warn",
|
|
16509
16566
|
message: totalComponents > 0 ? `${totalAgents} agents, ${totalCommands} commands, ${totalWorkflows} workflows, ${totalSkills} skills` : "No components found",
|
|
16510
16567
|
suggestion: totalComponents === 0 ? "Install ClaudeKit: ck new --kit engineer" : undefined,
|
|
16511
16568
|
autoFixable: false
|
|
16512
16569
|
};
|
|
16513
16570
|
}
|
|
16571
|
+
async checkGlobalDirReadable() {
|
|
16572
|
+
const globalDir = PathResolver.getGlobalKitDir();
|
|
16573
|
+
try {
|
|
16574
|
+
await access(globalDir, constants.R_OK);
|
|
16575
|
+
return {
|
|
16576
|
+
id: "ck-global-dir-readable",
|
|
16577
|
+
name: "Global Dir Readable",
|
|
16578
|
+
group: "claudekit",
|
|
16579
|
+
priority: "standard",
|
|
16580
|
+
status: "pass",
|
|
16581
|
+
message: "Read access OK",
|
|
16582
|
+
details: globalDir,
|
|
16583
|
+
autoFixable: false
|
|
16584
|
+
};
|
|
16585
|
+
} catch (error) {
|
|
16586
|
+
return {
|
|
16587
|
+
id: "ck-global-dir-readable",
|
|
16588
|
+
name: "Global Dir Readable",
|
|
16589
|
+
group: "claudekit",
|
|
16590
|
+
priority: "standard",
|
|
16591
|
+
status: "fail",
|
|
16592
|
+
message: "Read access denied",
|
|
16593
|
+
details: globalDir,
|
|
16594
|
+
suggestion: "Check file permissions on ~/.claude/",
|
|
16595
|
+
autoFixable: false
|
|
16596
|
+
};
|
|
16597
|
+
}
|
|
16598
|
+
}
|
|
16599
|
+
async checkGlobalDirWritable() {
|
|
16600
|
+
const globalDir = PathResolver.getGlobalKitDir();
|
|
16601
|
+
const timestamp = Date.now();
|
|
16602
|
+
const random = Math.random().toString(36).substring(2);
|
|
16603
|
+
const testFile = join4(globalDir, `.ck-write-test-${timestamp}-${random}`);
|
|
16604
|
+
try {
|
|
16605
|
+
await writeFile2(testFile, "test", { encoding: "utf-8", flag: "wx" });
|
|
16606
|
+
} catch (error) {
|
|
16607
|
+
return {
|
|
16608
|
+
id: "ck-global-dir-writable",
|
|
16609
|
+
name: "Global Dir Writable",
|
|
16610
|
+
group: "claudekit",
|
|
16611
|
+
priority: "standard",
|
|
16612
|
+
status: "fail",
|
|
16613
|
+
message: "Write access denied",
|
|
16614
|
+
details: globalDir,
|
|
16615
|
+
suggestion: "Check file permissions on ~/.claude/",
|
|
16616
|
+
autoFixable: false
|
|
16617
|
+
};
|
|
16618
|
+
}
|
|
16619
|
+
try {
|
|
16620
|
+
await unlink(testFile);
|
|
16621
|
+
} catch (_error) {
|
|
16622
|
+
logger.verbose("Failed to cleanup write test file", { testFile });
|
|
16623
|
+
}
|
|
16624
|
+
return {
|
|
16625
|
+
id: "ck-global-dir-writable",
|
|
16626
|
+
name: "Global Dir Writable",
|
|
16627
|
+
group: "claudekit",
|
|
16628
|
+
priority: "standard",
|
|
16629
|
+
status: "pass",
|
|
16630
|
+
message: "Write access OK",
|
|
16631
|
+
details: globalDir,
|
|
16632
|
+
autoFixable: false
|
|
16633
|
+
};
|
|
16634
|
+
}
|
|
16635
|
+
normalizePath(filePath) {
|
|
16636
|
+
const normalized = normalize2(filePath);
|
|
16637
|
+
const isCaseInsensitive = process.platform === "win32" || process.platform === "darwin";
|
|
16638
|
+
return isCaseInsensitive ? normalized.toLowerCase() : normalized;
|
|
16639
|
+
}
|
|
16640
|
+
async checkHooksExist() {
|
|
16641
|
+
const globalHooksDir = join4(PathResolver.getGlobalKitDir(), "hooks");
|
|
16642
|
+
const projectHooksDir = join4(this.projectDir, ".claude", "hooks");
|
|
16643
|
+
const globalExists = existsSync3(globalHooksDir);
|
|
16644
|
+
const projectExists = existsSync3(projectHooksDir);
|
|
16645
|
+
let hookCount = 0;
|
|
16646
|
+
const checkedFiles = new Set;
|
|
16647
|
+
if (globalExists) {
|
|
16648
|
+
const files = await readdir2(globalHooksDir, { withFileTypes: false });
|
|
16649
|
+
const hooks = files.filter((f3) => HOOK_EXTENSIONS.some((ext) => f3.endsWith(ext)));
|
|
16650
|
+
hooks.forEach((hook) => {
|
|
16651
|
+
const fullPath = join4(globalHooksDir, hook);
|
|
16652
|
+
checkedFiles.add(this.normalizePath(fullPath));
|
|
16653
|
+
});
|
|
16654
|
+
}
|
|
16655
|
+
const normalizedGlobal = this.normalizePath(globalHooksDir);
|
|
16656
|
+
const normalizedProject = this.normalizePath(projectHooksDir);
|
|
16657
|
+
if (projectExists && normalizedProject !== normalizedGlobal) {
|
|
16658
|
+
const files = await readdir2(projectHooksDir, { withFileTypes: false });
|
|
16659
|
+
const hooks = files.filter((f3) => HOOK_EXTENSIONS.some((ext) => f3.endsWith(ext)));
|
|
16660
|
+
hooks.forEach((hook) => {
|
|
16661
|
+
const fullPath = join4(projectHooksDir, hook);
|
|
16662
|
+
checkedFiles.add(this.normalizePath(fullPath));
|
|
16663
|
+
});
|
|
16664
|
+
}
|
|
16665
|
+
hookCount = checkedFiles.size;
|
|
16666
|
+
if (!globalExists && !projectExists) {
|
|
16667
|
+
return {
|
|
16668
|
+
id: "ck-hooks-exist",
|
|
16669
|
+
name: "Hooks Directory",
|
|
16670
|
+
group: "claudekit",
|
|
16671
|
+
priority: "standard",
|
|
16672
|
+
status: "info",
|
|
16673
|
+
message: "No hooks directory",
|
|
16674
|
+
autoFixable: false
|
|
16675
|
+
};
|
|
16676
|
+
}
|
|
16677
|
+
return {
|
|
16678
|
+
id: "ck-hooks-exist",
|
|
16679
|
+
name: "Hooks Directory",
|
|
16680
|
+
group: "claudekit",
|
|
16681
|
+
priority: "standard",
|
|
16682
|
+
status: "pass",
|
|
16683
|
+
message: `${hookCount} hook(s) found`,
|
|
16684
|
+
details: globalExists ? globalHooksDir : projectHooksDir,
|
|
16685
|
+
autoFixable: false
|
|
16686
|
+
};
|
|
16687
|
+
}
|
|
16688
|
+
async checkSettingsValid() {
|
|
16689
|
+
const globalSettings = join4(PathResolver.getGlobalKitDir(), "settings.json");
|
|
16690
|
+
const projectSettings = join4(this.projectDir, ".claude", "settings.json");
|
|
16691
|
+
const settingsPath = existsSync3(globalSettings) ? globalSettings : existsSync3(projectSettings) ? projectSettings : null;
|
|
16692
|
+
if (!settingsPath) {
|
|
16693
|
+
return {
|
|
16694
|
+
id: "ck-settings-valid",
|
|
16695
|
+
name: "Settings.json",
|
|
16696
|
+
group: "claudekit",
|
|
16697
|
+
priority: "extended",
|
|
16698
|
+
status: "info",
|
|
16699
|
+
message: "No settings.json found",
|
|
16700
|
+
autoFixable: false
|
|
16701
|
+
};
|
|
16702
|
+
}
|
|
16703
|
+
try {
|
|
16704
|
+
const content = await readFile3(settingsPath, "utf-8");
|
|
16705
|
+
JSON.parse(content);
|
|
16706
|
+
return {
|
|
16707
|
+
id: "ck-settings-valid",
|
|
16708
|
+
name: "Settings.json",
|
|
16709
|
+
group: "claudekit",
|
|
16710
|
+
priority: "extended",
|
|
16711
|
+
status: "pass",
|
|
16712
|
+
message: "Valid JSON",
|
|
16713
|
+
details: settingsPath,
|
|
16714
|
+
autoFixable: false
|
|
16715
|
+
};
|
|
16716
|
+
} catch (error) {
|
|
16717
|
+
let message = "Invalid JSON";
|
|
16718
|
+
let suggestion = "Fix JSON syntax in settings.json";
|
|
16719
|
+
let details = settingsPath;
|
|
16720
|
+
if (error instanceof SyntaxError) {
|
|
16721
|
+
message = "JSON syntax error";
|
|
16722
|
+
details = `${settingsPath}: ${error.message}`;
|
|
16723
|
+
logger.verbose("Settings.json syntax error", {
|
|
16724
|
+
path: settingsPath,
|
|
16725
|
+
error: error.message
|
|
16726
|
+
});
|
|
16727
|
+
} else if (error instanceof Error) {
|
|
16728
|
+
if (error.message.includes("EACCES") || error.message.includes("EPERM")) {
|
|
16729
|
+
message = "Permission denied";
|
|
16730
|
+
suggestion = "Check file permissions on settings.json";
|
|
16731
|
+
} else if (error.message.includes("ENOENT")) {
|
|
16732
|
+
message = "File not found";
|
|
16733
|
+
suggestion = "Ensure settings.json exists at the expected location";
|
|
16734
|
+
} else {
|
|
16735
|
+
message = `Read error: ${error.message}`;
|
|
16736
|
+
suggestion = "Check file system and permissions";
|
|
16737
|
+
}
|
|
16738
|
+
logger.verbose("Settings.json read error", {
|
|
16739
|
+
path: settingsPath,
|
|
16740
|
+
error: error.message,
|
|
16741
|
+
code: error.code
|
|
16742
|
+
});
|
|
16743
|
+
}
|
|
16744
|
+
return {
|
|
16745
|
+
id: "ck-settings-valid",
|
|
16746
|
+
name: "Settings.json",
|
|
16747
|
+
group: "claudekit",
|
|
16748
|
+
priority: "extended",
|
|
16749
|
+
status: "fail",
|
|
16750
|
+
message,
|
|
16751
|
+
details,
|
|
16752
|
+
suggestion,
|
|
16753
|
+
autoFixable: false
|
|
16754
|
+
};
|
|
16755
|
+
}
|
|
16756
|
+
}
|
|
16757
|
+
async checkPathRefsValid() {
|
|
16758
|
+
const globalClaudeMd = join4(PathResolver.getGlobalKitDir(), "CLAUDE.md");
|
|
16759
|
+
const projectClaudeMd = join4(this.projectDir, ".claude", "CLAUDE.md");
|
|
16760
|
+
const claudeMdPath = existsSync3(globalClaudeMd) ? globalClaudeMd : existsSync3(projectClaudeMd) ? projectClaudeMd : null;
|
|
16761
|
+
if (!claudeMdPath) {
|
|
16762
|
+
return {
|
|
16763
|
+
id: "ck-path-refs-valid",
|
|
16764
|
+
name: "Path References",
|
|
16765
|
+
group: "claudekit",
|
|
16766
|
+
priority: "extended",
|
|
16767
|
+
status: "info",
|
|
16768
|
+
message: "No CLAUDE.md found",
|
|
16769
|
+
autoFixable: false
|
|
16770
|
+
};
|
|
16771
|
+
}
|
|
16772
|
+
try {
|
|
16773
|
+
const content = await readFile3(claudeMdPath, "utf-8");
|
|
16774
|
+
const refPattern = /@([^\s\)]+)/g;
|
|
16775
|
+
const refs = [...content.matchAll(refPattern)].map((m2) => m2[1]);
|
|
16776
|
+
if (refs.length === 0) {
|
|
16777
|
+
return {
|
|
16778
|
+
id: "ck-path-refs-valid",
|
|
16779
|
+
name: "Path References",
|
|
16780
|
+
group: "claudekit",
|
|
16781
|
+
priority: "extended",
|
|
16782
|
+
status: "info",
|
|
16783
|
+
message: "No @path references found",
|
|
16784
|
+
autoFixable: false
|
|
16785
|
+
};
|
|
16786
|
+
}
|
|
16787
|
+
const baseDir = dirname(claudeMdPath);
|
|
16788
|
+
const home = homedir2();
|
|
16789
|
+
const broken = [];
|
|
16790
|
+
for (const ref of refs) {
|
|
16791
|
+
let refPath;
|
|
16792
|
+
if (ref.startsWith("$HOME") || ref.startsWith("%USERPROFILE%")) {
|
|
16793
|
+
refPath = normalize2(ref.replace("$HOME", home).replace("%USERPROFILE%", home));
|
|
16794
|
+
} else if (ref.startsWith("/")) {
|
|
16795
|
+
refPath = normalize2(ref);
|
|
16796
|
+
} else if (ref.includes(":") && ref.startsWith("\\")) {
|
|
16797
|
+
refPath = normalize2(ref);
|
|
16798
|
+
} else {
|
|
16799
|
+
refPath = resolve(baseDir, ref);
|
|
16800
|
+
}
|
|
16801
|
+
const normalizedPath = normalize2(refPath);
|
|
16802
|
+
const isWithinHome = normalizedPath.startsWith(home);
|
|
16803
|
+
const isWithinBase = normalizedPath.startsWith(normalize2(baseDir));
|
|
16804
|
+
const isAbsoluteAllowed = ref.startsWith("/") || ref.includes(":") && ref.startsWith("\\");
|
|
16805
|
+
if (!isWithinHome && !isWithinBase && !isAbsoluteAllowed) {
|
|
16806
|
+
logger.verbose("Skipping potentially unsafe path reference", { ref, refPath });
|
|
16807
|
+
continue;
|
|
16808
|
+
}
|
|
16809
|
+
if (!existsSync3(normalizedPath)) {
|
|
16810
|
+
broken.push(ref);
|
|
16811
|
+
}
|
|
16812
|
+
}
|
|
16813
|
+
if (broken.length > 0) {
|
|
16814
|
+
return {
|
|
16815
|
+
id: "ck-path-refs-valid",
|
|
16816
|
+
name: "Path References",
|
|
16817
|
+
group: "claudekit",
|
|
16818
|
+
priority: "extended",
|
|
16819
|
+
status: "warn",
|
|
16820
|
+
message: `${broken.length}/${refs.length} broken`,
|
|
16821
|
+
details: broken.slice(0, 3).join(", "),
|
|
16822
|
+
suggestion: "Some @path references point to missing files",
|
|
16823
|
+
autoFixable: false
|
|
16824
|
+
};
|
|
16825
|
+
}
|
|
16826
|
+
return {
|
|
16827
|
+
id: "ck-path-refs-valid",
|
|
16828
|
+
name: "Path References",
|
|
16829
|
+
group: "claudekit",
|
|
16830
|
+
priority: "extended",
|
|
16831
|
+
status: "pass",
|
|
16832
|
+
message: `${refs.length} valid`,
|
|
16833
|
+
autoFixable: false
|
|
16834
|
+
};
|
|
16835
|
+
} catch (error) {
|
|
16836
|
+
return {
|
|
16837
|
+
id: "ck-path-refs-valid",
|
|
16838
|
+
name: "Path References",
|
|
16839
|
+
group: "claudekit",
|
|
16840
|
+
priority: "extended",
|
|
16841
|
+
status: "info",
|
|
16842
|
+
message: "Could not parse CLAUDE.md",
|
|
16843
|
+
autoFixable: false
|
|
16844
|
+
};
|
|
16845
|
+
}
|
|
16846
|
+
}
|
|
16847
|
+
async checkProjectConfigCompleteness(setup) {
|
|
16848
|
+
if (setup.project.path === setup.global.path) {
|
|
16849
|
+
return {
|
|
16850
|
+
id: "ck-project-config-complete",
|
|
16851
|
+
name: "Project Config Completeness",
|
|
16852
|
+
group: "claudekit",
|
|
16853
|
+
priority: "standard",
|
|
16854
|
+
status: "info",
|
|
16855
|
+
message: "Not in a project directory",
|
|
16856
|
+
autoFixable: false
|
|
16857
|
+
};
|
|
16858
|
+
}
|
|
16859
|
+
const projectDir = join4(this.projectDir, ".claude");
|
|
16860
|
+
const requiredDirs = ["agents", "commands", "workflows", "skills"];
|
|
16861
|
+
const missingDirs = [];
|
|
16862
|
+
for (const dir of requiredDirs) {
|
|
16863
|
+
const dirPath = join4(projectDir, dir);
|
|
16864
|
+
if (!existsSync3(dirPath)) {
|
|
16865
|
+
missingDirs.push(dir);
|
|
16866
|
+
}
|
|
16867
|
+
}
|
|
16868
|
+
const files = await readdir2(projectDir).catch(() => []);
|
|
16869
|
+
const hasOnlyClaudeMd = files.length === 1 && files.includes("CLAUDE.md");
|
|
16870
|
+
if (hasOnlyClaudeMd || missingDirs.length === requiredDirs.length) {
|
|
16871
|
+
return {
|
|
16872
|
+
id: "ck-project-config-complete",
|
|
16873
|
+
name: "Project Config Completeness",
|
|
16874
|
+
group: "claudekit",
|
|
16875
|
+
priority: "standard",
|
|
16876
|
+
status: "fail",
|
|
16877
|
+
message: "Incomplete configuration",
|
|
16878
|
+
details: "Only CLAUDE.md found - missing agents, commands, workflows, skills",
|
|
16879
|
+
suggestion: "Run 'ck init' to install complete ClaudeKit in project",
|
|
16880
|
+
autoFixable: false
|
|
16881
|
+
};
|
|
16882
|
+
}
|
|
16883
|
+
if (missingDirs.length > 0) {
|
|
16884
|
+
return {
|
|
16885
|
+
id: "ck-project-config-complete",
|
|
16886
|
+
name: "Project Config Completeness",
|
|
16887
|
+
group: "claudekit",
|
|
16888
|
+
priority: "standard",
|
|
16889
|
+
status: "warn",
|
|
16890
|
+
message: `Missing ${missingDirs.length} directories`,
|
|
16891
|
+
details: `Missing: ${missingDirs.join(", ")}`,
|
|
16892
|
+
suggestion: "Run 'ck init' to update project configuration",
|
|
16893
|
+
autoFixable: false
|
|
16894
|
+
};
|
|
16895
|
+
}
|
|
16896
|
+
return {
|
|
16897
|
+
id: "ck-project-config-complete",
|
|
16898
|
+
name: "Project Config Completeness",
|
|
16899
|
+
group: "claudekit",
|
|
16900
|
+
priority: "standard",
|
|
16901
|
+
status: "pass",
|
|
16902
|
+
message: "Complete configuration",
|
|
16903
|
+
details: projectDir,
|
|
16904
|
+
autoFixable: false
|
|
16905
|
+
};
|
|
16906
|
+
}
|
|
16514
16907
|
}
|
|
16515
16908
|
// src/lib/health-checks/auth-checker.ts
|
|
16516
16909
|
init_types2();
|
|
@@ -16672,7 +17065,7 @@ import { Octokit } from "@octokit/rest";
|
|
|
16672
17065
|
init_zod();
|
|
16673
17066
|
init_logger();
|
|
16674
17067
|
import { existsSync as existsSync4 } from "node:fs";
|
|
16675
|
-
import { mkdir as mkdir2, readFile as
|
|
17068
|
+
import { mkdir as mkdir2, readFile as readFile4, unlink as unlink2, writeFile as writeFile3 } from "node:fs/promises";
|
|
16676
17069
|
import { join as join5 } from "node:path";
|
|
16677
17070
|
var ReleaseCacheEntrySchema = exports_external.object({
|
|
16678
17071
|
timestamp: exports_external.number(),
|
|
@@ -16693,7 +17086,7 @@ class ReleaseCache {
|
|
|
16693
17086
|
logger.debug(`Release cache not found for key: ${key}`);
|
|
16694
17087
|
return null;
|
|
16695
17088
|
}
|
|
16696
|
-
const content = await
|
|
17089
|
+
const content = await readFile4(cacheFile, "utf-8");
|
|
16697
17090
|
const parsed = JSON.parse(content);
|
|
16698
17091
|
const cacheEntry = ReleaseCacheEntrySchema.parse(parsed);
|
|
16699
17092
|
if (this.isExpired(cacheEntry.timestamp)) {
|
|
@@ -16719,7 +17112,7 @@ class ReleaseCache {
|
|
|
16719
17112
|
timestamp: Date.now(),
|
|
16720
17113
|
releases
|
|
16721
17114
|
};
|
|
16722
|
-
await
|
|
17115
|
+
await writeFile3(cacheFile, JSON.stringify(cacheEntry, null, 2), "utf-8");
|
|
16723
17116
|
logger.debug(`Release cache set for key: ${key}, cached ${releases.length} releases`);
|
|
16724
17117
|
} catch (error) {
|
|
16725
17118
|
logger.debug(`Failed to set release cache for key ${key}: ${error}`);
|
|
@@ -16730,7 +17123,7 @@ class ReleaseCache {
|
|
|
16730
17123
|
const cacheFile = this.getCachePath(key);
|
|
16731
17124
|
try {
|
|
16732
17125
|
if (existsSync4(cacheFile)) {
|
|
16733
|
-
await
|
|
17126
|
+
await unlink2(cacheFile);
|
|
16734
17127
|
logger.debug(`Release cache cleared for key: ${key}`);
|
|
16735
17128
|
}
|
|
16736
17129
|
} catch (error) {
|
|
@@ -16738,11 +17131,11 @@ class ReleaseCache {
|
|
|
16738
17131
|
}
|
|
16739
17132
|
} else {
|
|
16740
17133
|
try {
|
|
16741
|
-
const { readdir:
|
|
16742
|
-
const files = await
|
|
17134
|
+
const { readdir: readdir3 } = await import("node:fs/promises");
|
|
17135
|
+
const files = await readdir3(this.cacheDir);
|
|
16743
17136
|
for (const file of files) {
|
|
16744
17137
|
if (file.endsWith(".json")) {
|
|
16745
|
-
await
|
|
17138
|
+
await unlink2(join5(this.cacheDir, file));
|
|
16746
17139
|
}
|
|
16747
17140
|
}
|
|
16748
17141
|
logger.debug("All release cache cleared");
|
|
@@ -17343,6 +17736,7 @@ class AuthChecker {
|
|
|
17343
17736
|
}
|
|
17344
17737
|
}
|
|
17345
17738
|
async checkGhToken() {
|
|
17739
|
+
if (false) {}
|
|
17346
17740
|
try {
|
|
17347
17741
|
logger.verbose("AuthChecker: Getting GitHub token via AuthManager");
|
|
17348
17742
|
const { token } = await AuthManager.getToken();
|
|
@@ -17435,6 +17829,392 @@ class AuthChecker {
|
|
|
17435
17829
|
};
|
|
17436
17830
|
}
|
|
17437
17831
|
}
|
|
17832
|
+
// src/lib/health-checks/platform-checker.ts
|
|
17833
|
+
import { constants as constants2, access as access2, mkdir as mkdir3, readFile as readFile5, symlink, unlink as unlink3, writeFile as writeFile4 } from "node:fs/promises";
|
|
17834
|
+
import { arch, homedir as homedir3, platform as platform3 } from "node:os";
|
|
17835
|
+
import { join as join6, normalize as normalize3 } from "node:path";
|
|
17836
|
+
var IS_WINDOWS = platform3() === "win32";
|
|
17837
|
+
|
|
17838
|
+
class PlatformChecker {
|
|
17839
|
+
group = "platform";
|
|
17840
|
+
async run() {
|
|
17841
|
+
const results = [];
|
|
17842
|
+
results.push(await this.checkPlatformDetect());
|
|
17843
|
+
results.push(await this.checkHomeDirResolution());
|
|
17844
|
+
if (IS_WINDOWS) {
|
|
17845
|
+
results.push(await this.checkEnvVarExpansion());
|
|
17846
|
+
}
|
|
17847
|
+
results.push(await this.checkGlobalDirAccess());
|
|
17848
|
+
results.push(await this.checkShellDetection());
|
|
17849
|
+
if (this.isWSL()) {
|
|
17850
|
+
results.push(await this.checkWSLBoundary());
|
|
17851
|
+
}
|
|
17852
|
+
if (IS_WINDOWS) {
|
|
17853
|
+
results.push(await this.checkLongPathSupport());
|
|
17854
|
+
results.push(await this.checkSymlinkSupport());
|
|
17855
|
+
}
|
|
17856
|
+
return results;
|
|
17857
|
+
}
|
|
17858
|
+
isWSL() {
|
|
17859
|
+
return !!process.env.WSL_DISTRO_NAME || process.env.WSLENV !== undefined;
|
|
17860
|
+
}
|
|
17861
|
+
async checkPlatformDetect() {
|
|
17862
|
+
const os = platform3();
|
|
17863
|
+
const architecture = arch();
|
|
17864
|
+
const wslDistro = process.env.WSL_DISTRO_NAME;
|
|
17865
|
+
let message = `${os} (${architecture})`;
|
|
17866
|
+
if (wslDistro)
|
|
17867
|
+
message += ` - WSL: ${wslDistro}`;
|
|
17868
|
+
return {
|
|
17869
|
+
id: "platform-detect",
|
|
17870
|
+
name: "Platform",
|
|
17871
|
+
group: "platform",
|
|
17872
|
+
priority: "standard",
|
|
17873
|
+
status: "info",
|
|
17874
|
+
message,
|
|
17875
|
+
autoFixable: false
|
|
17876
|
+
};
|
|
17877
|
+
}
|
|
17878
|
+
async checkHomeDirResolution() {
|
|
17879
|
+
const nodeHome = normalize3(homedir3());
|
|
17880
|
+
const envHome = normalize3(IS_WINDOWS ? process.env.USERPROFILE || "" : process.env.HOME || "");
|
|
17881
|
+
const match = nodeHome === envHome && envHome !== "";
|
|
17882
|
+
return {
|
|
17883
|
+
id: "home-dir-resolution",
|
|
17884
|
+
name: "Home Directory",
|
|
17885
|
+
group: "platform",
|
|
17886
|
+
priority: "standard",
|
|
17887
|
+
status: match ? "pass" : "warn",
|
|
17888
|
+
message: match ? nodeHome : `Mismatch: Node=${nodeHome}, Env=${envHome || "not set"}`,
|
|
17889
|
+
suggestion: !match ? "homedir() differs from environment. May cause path issues." : undefined,
|
|
17890
|
+
autoFixable: false
|
|
17891
|
+
};
|
|
17892
|
+
}
|
|
17893
|
+
async checkEnvVarExpansion() {
|
|
17894
|
+
const userProfile = process.env.USERPROFILE;
|
|
17895
|
+
if (!userProfile) {
|
|
17896
|
+
return {
|
|
17897
|
+
id: "env-var-expansion",
|
|
17898
|
+
name: "Env Var Expansion",
|
|
17899
|
+
group: "platform",
|
|
17900
|
+
priority: "standard",
|
|
17901
|
+
status: "fail",
|
|
17902
|
+
message: "USERPROFILE not set",
|
|
17903
|
+
suggestion: "Environment variable USERPROFILE is not set",
|
|
17904
|
+
autoFixable: false
|
|
17905
|
+
};
|
|
17906
|
+
}
|
|
17907
|
+
try {
|
|
17908
|
+
await access2(userProfile, constants2.F_OK);
|
|
17909
|
+
return {
|
|
17910
|
+
id: "env-var-expansion",
|
|
17911
|
+
name: "Env Var Expansion",
|
|
17912
|
+
group: "platform",
|
|
17913
|
+
priority: "standard",
|
|
17914
|
+
status: "pass",
|
|
17915
|
+
message: "USERPROFILE expands correctly",
|
|
17916
|
+
details: userProfile,
|
|
17917
|
+
autoFixable: false
|
|
17918
|
+
};
|
|
17919
|
+
} catch {
|
|
17920
|
+
return {
|
|
17921
|
+
id: "env-var-expansion",
|
|
17922
|
+
name: "Env Var Expansion",
|
|
17923
|
+
group: "platform",
|
|
17924
|
+
priority: "standard",
|
|
17925
|
+
status: "fail",
|
|
17926
|
+
message: "USERPROFILE path not accessible",
|
|
17927
|
+
details: userProfile,
|
|
17928
|
+
suggestion: "Check if USERPROFILE directory exists and is accessible",
|
|
17929
|
+
autoFixable: false
|
|
17930
|
+
};
|
|
17931
|
+
}
|
|
17932
|
+
}
|
|
17933
|
+
async checkGlobalDirAccess() {
|
|
17934
|
+
const globalDir = PathResolver.getGlobalKitDir();
|
|
17935
|
+
const testFile = join6(globalDir, ".ck-doctor-access-test");
|
|
17936
|
+
try {
|
|
17937
|
+
await mkdir3(globalDir, { recursive: true });
|
|
17938
|
+
await writeFile4(testFile, "test", "utf-8");
|
|
17939
|
+
const content = await readFile5(testFile, "utf-8");
|
|
17940
|
+
await unlink3(testFile);
|
|
17941
|
+
if (content !== "test")
|
|
17942
|
+
throw new Error("Read mismatch");
|
|
17943
|
+
return {
|
|
17944
|
+
id: "global-dir-access",
|
|
17945
|
+
name: "Global Dir Access",
|
|
17946
|
+
group: "platform",
|
|
17947
|
+
priority: "critical",
|
|
17948
|
+
status: "pass",
|
|
17949
|
+
message: "Read/write OK",
|
|
17950
|
+
details: globalDir,
|
|
17951
|
+
autoFixable: false
|
|
17952
|
+
};
|
|
17953
|
+
} catch (error) {
|
|
17954
|
+
return {
|
|
17955
|
+
id: "global-dir-access",
|
|
17956
|
+
name: "Global Dir Access",
|
|
17957
|
+
group: "platform",
|
|
17958
|
+
priority: "critical",
|
|
17959
|
+
status: "fail",
|
|
17960
|
+
message: `Access denied: ${error instanceof Error ? error.message : "unknown"}`,
|
|
17961
|
+
details: globalDir,
|
|
17962
|
+
suggestion: "Check file permissions on ~/.claude/ directory",
|
|
17963
|
+
autoFixable: false
|
|
17964
|
+
};
|
|
17965
|
+
}
|
|
17966
|
+
}
|
|
17967
|
+
async checkShellDetection() {
|
|
17968
|
+
const shell = process.env.SHELL || process.env.ComSpec || "unknown";
|
|
17969
|
+
let shellName = "Unknown";
|
|
17970
|
+
if (shell.includes("pwsh") || shell.includes("powershell")) {
|
|
17971
|
+
shellName = shell.includes("pwsh") ? "PowerShell Core" : "Windows PowerShell";
|
|
17972
|
+
} else if (shell.includes("cmd")) {
|
|
17973
|
+
shellName = "Command Prompt";
|
|
17974
|
+
} else if (shell.includes("bash")) {
|
|
17975
|
+
shellName = "Bash";
|
|
17976
|
+
} else if (shell.includes("zsh")) {
|
|
17977
|
+
shellName = "Zsh";
|
|
17978
|
+
} else if (shell.includes("fish")) {
|
|
17979
|
+
shellName = "Fish";
|
|
17980
|
+
}
|
|
17981
|
+
return {
|
|
17982
|
+
id: "shell-detection",
|
|
17983
|
+
name: "Shell",
|
|
17984
|
+
group: "platform",
|
|
17985
|
+
priority: "standard",
|
|
17986
|
+
status: "info",
|
|
17987
|
+
message: shellName,
|
|
17988
|
+
details: shell,
|
|
17989
|
+
autoFixable: false
|
|
17990
|
+
};
|
|
17991
|
+
}
|
|
17992
|
+
async checkWSLBoundary() {
|
|
17993
|
+
const cwd = process.cwd();
|
|
17994
|
+
const accessingWindows = cwd.startsWith("/mnt/");
|
|
17995
|
+
return {
|
|
17996
|
+
id: "wsl-boundary",
|
|
17997
|
+
name: "WSL Boundary",
|
|
17998
|
+
group: "platform",
|
|
17999
|
+
priority: "standard",
|
|
18000
|
+
status: accessingWindows ? "warn" : "pass",
|
|
18001
|
+
message: accessingWindows ? "Working in Windows filesystem from WSL" : "Working in native Linux filesystem",
|
|
18002
|
+
details: cwd,
|
|
18003
|
+
suggestion: accessingWindows ? "Performance may be slower. Consider using native Linux paths." : undefined,
|
|
18004
|
+
autoFixable: false
|
|
18005
|
+
};
|
|
18006
|
+
}
|
|
18007
|
+
async checkLongPathSupport() {
|
|
18008
|
+
try {
|
|
18009
|
+
const { execSync: execSync3 } = await import("node:child_process");
|
|
18010
|
+
const result = execSync3('reg query "HKLM\\SYSTEM\\CurrentControlSet\\Control\\FileSystem" /v LongPathsEnabled', { encoding: "utf-8", timeout: 2000 });
|
|
18011
|
+
const enabled = result.includes("0x1");
|
|
18012
|
+
return {
|
|
18013
|
+
id: "long-path-support",
|
|
18014
|
+
name: "Long Path Support",
|
|
18015
|
+
group: "platform",
|
|
18016
|
+
priority: "extended",
|
|
18017
|
+
status: enabled ? "pass" : "warn",
|
|
18018
|
+
message: enabled ? "Enabled" : "Disabled (260 char limit)",
|
|
18019
|
+
suggestion: !enabled ? 'Enable long paths: run as admin: reg add "HKLM\\SYSTEM\\CurrentControlSet\\Control\\FileSystem" /v LongPathsEnabled /t REG_DWORD /d 1 /f' : undefined,
|
|
18020
|
+
autoFixable: false
|
|
18021
|
+
};
|
|
18022
|
+
} catch {
|
|
18023
|
+
return {
|
|
18024
|
+
id: "long-path-support",
|
|
18025
|
+
name: "Long Path Support",
|
|
18026
|
+
group: "platform",
|
|
18027
|
+
priority: "extended",
|
|
18028
|
+
status: "info",
|
|
18029
|
+
message: "Could not determine (requires admin)",
|
|
18030
|
+
autoFixable: false
|
|
18031
|
+
};
|
|
18032
|
+
}
|
|
18033
|
+
}
|
|
18034
|
+
async checkSymlinkSupport() {
|
|
18035
|
+
const testDir = PathResolver.getGlobalKitDir();
|
|
18036
|
+
const target = join6(testDir, ".ck-symlink-test-target");
|
|
18037
|
+
const link = join6(testDir, ".ck-symlink-test-link");
|
|
18038
|
+
try {
|
|
18039
|
+
await mkdir3(testDir, { recursive: true });
|
|
18040
|
+
await writeFile4(target, "test", "utf-8");
|
|
18041
|
+
await symlink(target, link);
|
|
18042
|
+
await unlink3(link);
|
|
18043
|
+
await unlink3(target);
|
|
18044
|
+
return {
|
|
18045
|
+
id: "symlink-support",
|
|
18046
|
+
name: "Symlink Support",
|
|
18047
|
+
group: "platform",
|
|
18048
|
+
priority: "extended",
|
|
18049
|
+
status: "pass",
|
|
18050
|
+
message: "Symlinks work",
|
|
18051
|
+
autoFixable: false
|
|
18052
|
+
};
|
|
18053
|
+
} catch (error) {
|
|
18054
|
+
try {
|
|
18055
|
+
await unlink3(link).catch(() => {});
|
|
18056
|
+
await unlink3(target).catch(() => {});
|
|
18057
|
+
} catch {}
|
|
18058
|
+
return {
|
|
18059
|
+
id: "symlink-support",
|
|
18060
|
+
name: "Symlink Support",
|
|
18061
|
+
group: "platform",
|
|
18062
|
+
priority: "extended",
|
|
18063
|
+
status: "warn",
|
|
18064
|
+
message: "Symlinks not available",
|
|
18065
|
+
suggestion: "Enable Developer Mode or run as admin for symlink support",
|
|
18066
|
+
details: error instanceof Error ? error.message : "unknown error",
|
|
18067
|
+
autoFixable: false
|
|
18068
|
+
};
|
|
18069
|
+
}
|
|
18070
|
+
}
|
|
18071
|
+
}
|
|
18072
|
+
// src/lib/health-checks/network-checker.ts
|
|
18073
|
+
init_logger();
|
|
18074
|
+
var NETWORK_TIMEOUT = Number.parseInt(process.env.CLAUDEKIT_NETWORK_TIMEOUT || "3000", 10);
|
|
18075
|
+
|
|
18076
|
+
class NetworkChecker {
|
|
18077
|
+
group = "network";
|
|
18078
|
+
async run() {
|
|
18079
|
+
if (this.isCI()) {
|
|
18080
|
+
logger.verbose("NetworkChecker: Skipping in CI environment");
|
|
18081
|
+
return [];
|
|
18082
|
+
}
|
|
18083
|
+
const results = [];
|
|
18084
|
+
results.push(this.checkProxyDetected());
|
|
18085
|
+
results.push(await this.checkGitHubReachable());
|
|
18086
|
+
results.push(await this.checkApiGitHub());
|
|
18087
|
+
return results;
|
|
18088
|
+
}
|
|
18089
|
+
isCI() {
|
|
18090
|
+
return process.env.CI === "true" || process.env.CI_SAFE_MODE === "true" || false || process.env.VITEST === "true" || process.env.JEST_WORKER_ID !== undefined || process.env.TEST === "true";
|
|
18091
|
+
}
|
|
18092
|
+
checkProxyDetected() {
|
|
18093
|
+
const httpProxy = process.env.HTTP_PROXY || process.env.http_proxy;
|
|
18094
|
+
const httpsProxy = process.env.HTTPS_PROXY || process.env.https_proxy;
|
|
18095
|
+
const noProxy = process.env.NO_PROXY || process.env.no_proxy;
|
|
18096
|
+
const hasProxy = !!(httpProxy || httpsProxy);
|
|
18097
|
+
if (!hasProxy) {
|
|
18098
|
+
return {
|
|
18099
|
+
id: "net-proxy-detected",
|
|
18100
|
+
name: "Proxy",
|
|
18101
|
+
group: "network",
|
|
18102
|
+
priority: "standard",
|
|
18103
|
+
status: "info",
|
|
18104
|
+
message: "No proxy configured",
|
|
18105
|
+
autoFixable: false
|
|
18106
|
+
};
|
|
18107
|
+
}
|
|
18108
|
+
const details = [];
|
|
18109
|
+
if (httpProxy)
|
|
18110
|
+
details.push(`HTTP_PROXY=${httpProxy}`);
|
|
18111
|
+
if (httpsProxy)
|
|
18112
|
+
details.push(`HTTPS_PROXY=${httpsProxy}`);
|
|
18113
|
+
if (noProxy)
|
|
18114
|
+
details.push(`NO_PROXY=${noProxy}`);
|
|
18115
|
+
return {
|
|
18116
|
+
id: "net-proxy-detected",
|
|
18117
|
+
name: "Proxy",
|
|
18118
|
+
group: "network",
|
|
18119
|
+
priority: "standard",
|
|
18120
|
+
status: "warn",
|
|
18121
|
+
message: "Proxy detected",
|
|
18122
|
+
details: details.join(", "),
|
|
18123
|
+
suggestion: "Ensure proxy settings allow access to github.com",
|
|
18124
|
+
autoFixable: false
|
|
18125
|
+
};
|
|
18126
|
+
}
|
|
18127
|
+
async checkGitHubReachable() {
|
|
18128
|
+
const startTime = Date.now();
|
|
18129
|
+
try {
|
|
18130
|
+
const response = await fetch("https://github.com", {
|
|
18131
|
+
method: "HEAD",
|
|
18132
|
+
signal: AbortSignal.timeout(NETWORK_TIMEOUT)
|
|
18133
|
+
});
|
|
18134
|
+
const latency = Date.now() - startTime;
|
|
18135
|
+
if (response.ok || response.status === 301 || response.status === 302) {
|
|
18136
|
+
return {
|
|
18137
|
+
id: "net-github-reachable",
|
|
18138
|
+
name: "GitHub",
|
|
18139
|
+
group: "network",
|
|
18140
|
+
priority: "standard",
|
|
18141
|
+
status: "pass",
|
|
18142
|
+
message: `Connected (${latency}ms)`,
|
|
18143
|
+
autoFixable: false
|
|
18144
|
+
};
|
|
18145
|
+
}
|
|
18146
|
+
return {
|
|
18147
|
+
id: "net-github-reachable",
|
|
18148
|
+
name: "GitHub",
|
|
18149
|
+
group: "network",
|
|
18150
|
+
priority: "standard",
|
|
18151
|
+
status: "warn",
|
|
18152
|
+
message: `HTTP ${response.status}`,
|
|
18153
|
+
suggestion: "GitHub returned unexpected status",
|
|
18154
|
+
autoFixable: false
|
|
18155
|
+
};
|
|
18156
|
+
} catch (error) {
|
|
18157
|
+
const isTimeout = error instanceof Error && error.name === "AbortError";
|
|
18158
|
+
return {
|
|
18159
|
+
id: "net-github-reachable",
|
|
18160
|
+
name: "GitHub",
|
|
18161
|
+
group: "network",
|
|
18162
|
+
priority: "standard",
|
|
18163
|
+
status: "fail",
|
|
18164
|
+
message: isTimeout ? `Timeout (>${NETWORK_TIMEOUT}ms)` : "Connection failed",
|
|
18165
|
+
suggestion: "Check internet connection or proxy settings",
|
|
18166
|
+
autoFixable: false
|
|
18167
|
+
};
|
|
18168
|
+
}
|
|
18169
|
+
}
|
|
18170
|
+
async checkApiGitHub() {
|
|
18171
|
+
const startTime = Date.now();
|
|
18172
|
+
try {
|
|
18173
|
+
const response = await fetch("https://api.github.com/rate_limit", {
|
|
18174
|
+
method: "GET",
|
|
18175
|
+
headers: {
|
|
18176
|
+
Accept: "application/vnd.github.v3+json",
|
|
18177
|
+
"User-Agent": "claudekit-cli"
|
|
18178
|
+
},
|
|
18179
|
+
signal: AbortSignal.timeout(NETWORK_TIMEOUT)
|
|
18180
|
+
});
|
|
18181
|
+
const latency = Date.now() - startTime;
|
|
18182
|
+
if (response.ok) {
|
|
18183
|
+
return {
|
|
18184
|
+
id: "net-api-github",
|
|
18185
|
+
name: "GitHub API",
|
|
18186
|
+
group: "network",
|
|
18187
|
+
priority: "standard",
|
|
18188
|
+
status: "pass",
|
|
18189
|
+
message: `Connected (${latency}ms)`,
|
|
18190
|
+
autoFixable: false
|
|
18191
|
+
};
|
|
18192
|
+
}
|
|
18193
|
+
return {
|
|
18194
|
+
id: "net-api-github",
|
|
18195
|
+
name: "GitHub API",
|
|
18196
|
+
group: "network",
|
|
18197
|
+
priority: "standard",
|
|
18198
|
+
status: "warn",
|
|
18199
|
+
message: `HTTP ${response.status}`,
|
|
18200
|
+
suggestion: response.status === 403 ? "Rate limited - wait or authenticate" : "API returned unexpected status",
|
|
18201
|
+
autoFixable: false
|
|
18202
|
+
};
|
|
18203
|
+
} catch (error) {
|
|
18204
|
+
const isTimeout = error instanceof Error && error.name === "AbortError";
|
|
18205
|
+
return {
|
|
18206
|
+
id: "net-api-github",
|
|
18207
|
+
name: "GitHub API",
|
|
18208
|
+
group: "network",
|
|
18209
|
+
priority: "standard",
|
|
18210
|
+
status: "fail",
|
|
18211
|
+
message: isTimeout ? `Timeout (>${NETWORK_TIMEOUT}ms)` : "Connection failed",
|
|
18212
|
+
suggestion: "Check internet connection or proxy settings for api.github.com",
|
|
18213
|
+
autoFixable: false
|
|
18214
|
+
};
|
|
18215
|
+
}
|
|
18216
|
+
}
|
|
18217
|
+
}
|
|
17438
18218
|
// src/lib/health-checks/auto-healer.ts
|
|
17439
18219
|
class AutoHealer {
|
|
17440
18220
|
timeout;
|
|
@@ -17514,14 +18294,14 @@ init_dist2();
|
|
|
17514
18294
|
import { execSync as execSync3, spawnSync } from "node:child_process";
|
|
17515
18295
|
import { readFileSync as readFileSync3, unlinkSync, writeFileSync } from "node:fs";
|
|
17516
18296
|
import { tmpdir } from "node:os";
|
|
17517
|
-
import { dirname, join as
|
|
18297
|
+
import { dirname as dirname2, join as join7 } from "node:path";
|
|
17518
18298
|
import { fileURLToPath } from "node:url";
|
|
17519
18299
|
init_environment();
|
|
17520
18300
|
init_logger();
|
|
17521
18301
|
function getCliVersion() {
|
|
17522
18302
|
try {
|
|
17523
|
-
const __dirname2 =
|
|
17524
|
-
const pkgPath =
|
|
18303
|
+
const __dirname2 = dirname2(fileURLToPath(import.meta.url));
|
|
18304
|
+
const pkgPath = join7(__dirname2, "../../../package.json");
|
|
17525
18305
|
const pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
|
|
17526
18306
|
return pkg.version || "unknown";
|
|
17527
18307
|
} catch (err) {
|
|
@@ -17660,7 +18440,7 @@ class ReportGenerator {
|
|
|
17660
18440
|
return null;
|
|
17661
18441
|
}
|
|
17662
18442
|
}
|
|
17663
|
-
const tmpFile =
|
|
18443
|
+
const tmpFile = join7(tmpdir(), `ck-report-${Date.now()}.txt`);
|
|
17664
18444
|
writeFileSync(tmpFile, report);
|
|
17665
18445
|
try {
|
|
17666
18446
|
const result = spawnSync("gh", ["gist", "create", tmpFile, "--desc", "ClaudeKit Diagnostic Report"], {
|
|
@@ -17865,12 +18645,13 @@ class DoctorUIRenderer {
|
|
|
17865
18645
|
init_environment();
|
|
17866
18646
|
init_logger();
|
|
17867
18647
|
async function doctorCommand(options = {}) {
|
|
17868
|
-
const { report, fix, checkOnly, json } = options;
|
|
18648
|
+
const { report, fix, checkOnly, json, full } = options;
|
|
17869
18649
|
const runnerOptions = {
|
|
17870
18650
|
fix: fix ?? false,
|
|
17871
18651
|
checkOnly: checkOnly ?? false,
|
|
17872
18652
|
json: json ?? false,
|
|
17873
|
-
verbose: logger.isVerbose()
|
|
18653
|
+
verbose: logger.isVerbose(),
|
|
18654
|
+
full: full ?? false
|
|
17874
18655
|
};
|
|
17875
18656
|
if (!json && !report) {
|
|
17876
18657
|
oe("ClaudeKit Health Check");
|
|
@@ -17879,6 +18660,8 @@ async function doctorCommand(options = {}) {
|
|
|
17879
18660
|
runner.registerChecker(new SystemChecker);
|
|
17880
18661
|
runner.registerChecker(new ClaudekitChecker);
|
|
17881
18662
|
runner.registerChecker(new AuthChecker);
|
|
18663
|
+
runner.registerChecker(new PlatformChecker);
|
|
18664
|
+
runner.registerChecker(new NetworkChecker);
|
|
17882
18665
|
const summary = await runner.run();
|
|
17883
18666
|
if (json) {
|
|
17884
18667
|
const generator = new ReportGenerator;
|
|
@@ -17933,17 +18716,17 @@ async function doctorCommand(options = {}) {
|
|
|
17933
18716
|
|
|
17934
18717
|
// src/commands/init.ts
|
|
17935
18718
|
var import_fs_extra17 = __toESM(require_lib(), 1);
|
|
17936
|
-
import { join as
|
|
18719
|
+
import { join as join29, resolve as resolve5 } from "node:path";
|
|
17937
18720
|
|
|
17938
18721
|
// src/lib/commands-prefix.ts
|
|
17939
18722
|
init_logger();
|
|
17940
18723
|
var import_fs_extra3 = __toESM(require_lib(), 1);
|
|
17941
|
-
import { lstat, mkdir as
|
|
17942
|
-
import { join as
|
|
18724
|
+
import { lstat, mkdir as mkdir4, readdir as readdir3, stat as stat2 } from "node:fs/promises";
|
|
18725
|
+
import { join as join9 } from "node:path";
|
|
17943
18726
|
|
|
17944
18727
|
// src/utils/manifest-writer.ts
|
|
17945
18728
|
var import_fs_extra2 = __toESM(require_lib(), 1);
|
|
17946
|
-
import { join as
|
|
18729
|
+
import { join as join8 } from "node:path";
|
|
17947
18730
|
|
|
17948
18731
|
// node_modules/yocto-queue/index.js
|
|
17949
18732
|
class Node {
|
|
@@ -18027,24 +18810,24 @@ function pLimit(concurrency) {
|
|
|
18027
18810
|
activeCount--;
|
|
18028
18811
|
resumeNext();
|
|
18029
18812
|
};
|
|
18030
|
-
const run = async (function_,
|
|
18813
|
+
const run = async (function_, resolve2, arguments_) => {
|
|
18031
18814
|
const result = (async () => function_(...arguments_))();
|
|
18032
|
-
|
|
18815
|
+
resolve2(result);
|
|
18033
18816
|
try {
|
|
18034
18817
|
await result;
|
|
18035
18818
|
} catch {}
|
|
18036
18819
|
next();
|
|
18037
18820
|
};
|
|
18038
|
-
const enqueue = (function_,
|
|
18821
|
+
const enqueue = (function_, resolve2, arguments_) => {
|
|
18039
18822
|
new Promise((internalResolve) => {
|
|
18040
18823
|
queue.enqueue(internalResolve);
|
|
18041
|
-
}).then(run.bind(undefined, function_,
|
|
18824
|
+
}).then(run.bind(undefined, function_, resolve2, arguments_));
|
|
18042
18825
|
if (activeCount < concurrency) {
|
|
18043
18826
|
resumeNext();
|
|
18044
18827
|
}
|
|
18045
18828
|
};
|
|
18046
|
-
const generator = (function_, ...arguments_) => new Promise((
|
|
18047
|
-
enqueue(function_,
|
|
18829
|
+
const generator = (function_, ...arguments_) => new Promise((resolve2) => {
|
|
18830
|
+
enqueue(function_, resolve2, arguments_);
|
|
18048
18831
|
});
|
|
18049
18832
|
Object.defineProperties(generator, {
|
|
18050
18833
|
activeCount: {
|
|
@@ -18093,12 +18876,12 @@ import { relative } from "node:path";
|
|
|
18093
18876
|
|
|
18094
18877
|
class OwnershipChecker {
|
|
18095
18878
|
static async calculateChecksum(filePath) {
|
|
18096
|
-
return new Promise((
|
|
18879
|
+
return new Promise((resolve2, reject) => {
|
|
18097
18880
|
const hash = createHash("sha256");
|
|
18098
18881
|
const stream = createReadStream(filePath);
|
|
18099
18882
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
18100
18883
|
stream.on("end", () => {
|
|
18101
|
-
|
|
18884
|
+
resolve2(hash.digest("hex"));
|
|
18102
18885
|
});
|
|
18103
18886
|
stream.on("error", (err) => {
|
|
18104
18887
|
stream.destroy();
|
|
@@ -18224,7 +19007,7 @@ class ManifestWriter {
|
|
|
18224
19007
|
return Array.from(this.trackedFiles.values()).sort((a3, b3) => a3.path.localeCompare(b3.path));
|
|
18225
19008
|
}
|
|
18226
19009
|
async writeManifest(claudeDir, kitName, version, scope) {
|
|
18227
|
-
const metadataPath =
|
|
19010
|
+
const metadataPath = join8(claudeDir, "metadata.json");
|
|
18228
19011
|
let existingMetadata = {};
|
|
18229
19012
|
if (await import_fs_extra2.pathExists(metadataPath)) {
|
|
18230
19013
|
try {
|
|
@@ -18250,7 +19033,7 @@ class ManifestWriter {
|
|
|
18250
19033
|
logger.debug(`Wrote manifest with ${this.installedFiles.size} installed files, ${trackedFiles.length} tracked`);
|
|
18251
19034
|
}
|
|
18252
19035
|
static async readManifest(claudeDir) {
|
|
18253
|
-
const metadataPath =
|
|
19036
|
+
const metadataPath = join8(claudeDir, "metadata.json");
|
|
18254
19037
|
if (!await import_fs_extra2.pathExists(metadataPath)) {
|
|
18255
19038
|
return null;
|
|
18256
19039
|
}
|
|
@@ -18321,22 +19104,22 @@ function validatePath(path, paramName) {
|
|
|
18321
19104
|
class CommandsPrefix {
|
|
18322
19105
|
static async applyPrefix(extractDir) {
|
|
18323
19106
|
validatePath(extractDir, "extractDir");
|
|
18324
|
-
const commandsDir =
|
|
19107
|
+
const commandsDir = join9(extractDir, ".claude", "commands");
|
|
18325
19108
|
if (!await import_fs_extra3.pathExists(commandsDir)) {
|
|
18326
19109
|
logger.verbose("No commands directory found, skipping prefix application");
|
|
18327
19110
|
return;
|
|
18328
19111
|
}
|
|
18329
19112
|
logger.info("Applying /ck: prefix to slash commands...");
|
|
18330
|
-
const backupDir =
|
|
18331
|
-
const tempDir =
|
|
19113
|
+
const backupDir = join9(extractDir, ".commands-backup");
|
|
19114
|
+
const tempDir = join9(extractDir, ".commands-prefix-temp");
|
|
18332
19115
|
try {
|
|
18333
|
-
const entries = await
|
|
19116
|
+
const entries = await readdir3(commandsDir);
|
|
18334
19117
|
if (entries.length === 0) {
|
|
18335
19118
|
logger.verbose("Commands directory is empty, skipping prefix application");
|
|
18336
19119
|
return;
|
|
18337
19120
|
}
|
|
18338
19121
|
if (entries.length === 1 && entries[0] === "ck") {
|
|
18339
|
-
const ckDir2 =
|
|
19122
|
+
const ckDir2 = join9(commandsDir, "ck");
|
|
18340
19123
|
const ckStat = await stat2(ckDir2);
|
|
18341
19124
|
if (ckStat.isDirectory()) {
|
|
18342
19125
|
logger.verbose("Commands already have /ck: prefix, skipping");
|
|
@@ -18345,18 +19128,18 @@ class CommandsPrefix {
|
|
|
18345
19128
|
}
|
|
18346
19129
|
await import_fs_extra3.copy(commandsDir, backupDir);
|
|
18347
19130
|
logger.verbose("Created backup of commands directory");
|
|
18348
|
-
await
|
|
18349
|
-
const ckDir =
|
|
18350
|
-
await
|
|
19131
|
+
await mkdir4(tempDir, { recursive: true });
|
|
19132
|
+
const ckDir = join9(tempDir, "ck");
|
|
19133
|
+
await mkdir4(ckDir, { recursive: true });
|
|
18351
19134
|
let processedCount = 0;
|
|
18352
19135
|
for (const entry of entries) {
|
|
18353
|
-
const sourcePath =
|
|
19136
|
+
const sourcePath = join9(commandsDir, entry);
|
|
18354
19137
|
const stats = await lstat(sourcePath);
|
|
18355
19138
|
if (stats.isSymbolicLink()) {
|
|
18356
19139
|
logger.warning(`Skipping symlink for security: ${entry}`);
|
|
18357
19140
|
continue;
|
|
18358
19141
|
}
|
|
18359
|
-
const destPath =
|
|
19142
|
+
const destPath = join9(ckDir, entry);
|
|
18360
19143
|
await import_fs_extra3.copy(sourcePath, destPath, {
|
|
18361
19144
|
overwrite: false,
|
|
18362
19145
|
errorOnExist: true
|
|
@@ -18404,8 +19187,8 @@ class CommandsPrefix {
|
|
|
18404
19187
|
static async cleanupCommandsDirectory(targetDir, isGlobal, options = {}) {
|
|
18405
19188
|
const { dryRun = false, forceOverwrite = false } = options;
|
|
18406
19189
|
validatePath(targetDir, "targetDir");
|
|
18407
|
-
const claudeDir = isGlobal ? targetDir :
|
|
18408
|
-
const commandsDir =
|
|
19190
|
+
const claudeDir = isGlobal ? targetDir : join9(targetDir, ".claude");
|
|
19191
|
+
const commandsDir = join9(claudeDir, "commands");
|
|
18409
19192
|
const result = {
|
|
18410
19193
|
results: [],
|
|
18411
19194
|
deletedCount: 0,
|
|
@@ -18427,13 +19210,13 @@ class CommandsPrefix {
|
|
|
18427
19210
|
logger.verbose("All existing files will be preserved as user-owned");
|
|
18428
19211
|
return result;
|
|
18429
19212
|
}
|
|
18430
|
-
const entries = await
|
|
19213
|
+
const entries = await readdir3(commandsDir);
|
|
18431
19214
|
if (entries.length === 0) {
|
|
18432
19215
|
logger.verbose("Commands directory is empty");
|
|
18433
19216
|
return result;
|
|
18434
19217
|
}
|
|
18435
19218
|
for (const entry of entries) {
|
|
18436
|
-
const entryPath =
|
|
19219
|
+
const entryPath = join9(commandsDir, entry);
|
|
18437
19220
|
const stats = await lstat(entryPath);
|
|
18438
19221
|
if (stats.isSymbolicLink()) {
|
|
18439
19222
|
logger.warning(`Skipping symlink: ${entry}`);
|
|
@@ -18597,9 +19380,9 @@ class CommandsPrefix {
|
|
|
18597
19380
|
}
|
|
18598
19381
|
static async scanDirectoryFiles(dir) {
|
|
18599
19382
|
const files = [];
|
|
18600
|
-
const entries = await
|
|
19383
|
+
const entries = await readdir3(dir);
|
|
18601
19384
|
for (const entry of entries) {
|
|
18602
|
-
const fullPath =
|
|
19385
|
+
const fullPath = join9(dir, entry);
|
|
18603
19386
|
const stats = await lstat(fullPath);
|
|
18604
19387
|
if (stats.isSymbolicLink()) {
|
|
18605
19388
|
continue;
|
|
@@ -18621,9 +19404,9 @@ var import_ignore = __toESM(require_ignore(), 1);
|
|
|
18621
19404
|
import { Buffer as Buffer3 } from "node:buffer";
|
|
18622
19405
|
import { execFile } from "node:child_process";
|
|
18623
19406
|
import { createWriteStream as createWriteStream2 } from "node:fs";
|
|
18624
|
-
import { mkdir as
|
|
19407
|
+
import { mkdir as mkdir6 } from "node:fs/promises";
|
|
18625
19408
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
18626
|
-
import { join as
|
|
19409
|
+
import { join as join11, relative as relative2, resolve as resolve2 } from "node:path";
|
|
18627
19410
|
import { TextDecoder } from "node:util";
|
|
18628
19411
|
|
|
18629
19412
|
// node_modules/@isaacs/fs-minipass/dist/esm/index.js
|
|
@@ -19172,10 +19955,10 @@ class Minipass extends EventEmitter2 {
|
|
|
19172
19955
|
return this[ENCODING] ? buf.join("") : Buffer.concat(buf, buf.dataLength);
|
|
19173
19956
|
}
|
|
19174
19957
|
async promise() {
|
|
19175
|
-
return new Promise((
|
|
19958
|
+
return new Promise((resolve2, reject) => {
|
|
19176
19959
|
this.on(DESTROYED, () => reject(new Error("stream destroyed")));
|
|
19177
19960
|
this.on("error", (er) => reject(er));
|
|
19178
|
-
this.on("end", () =>
|
|
19961
|
+
this.on("end", () => resolve2());
|
|
19179
19962
|
});
|
|
19180
19963
|
}
|
|
19181
19964
|
[Symbol.asyncIterator]() {
|
|
@@ -19194,7 +19977,7 @@ class Minipass extends EventEmitter2 {
|
|
|
19194
19977
|
return Promise.resolve({ done: false, value: res });
|
|
19195
19978
|
if (this[EOF])
|
|
19196
19979
|
return stop();
|
|
19197
|
-
let
|
|
19980
|
+
let resolve2;
|
|
19198
19981
|
let reject;
|
|
19199
19982
|
const onerr = (er) => {
|
|
19200
19983
|
this.off("data", ondata);
|
|
@@ -19208,19 +19991,19 @@ class Minipass extends EventEmitter2 {
|
|
|
19208
19991
|
this.off("end", onend);
|
|
19209
19992
|
this.off(DESTROYED, ondestroy);
|
|
19210
19993
|
this.pause();
|
|
19211
|
-
|
|
19994
|
+
resolve2({ value, done: !!this[EOF] });
|
|
19212
19995
|
};
|
|
19213
19996
|
const onend = () => {
|
|
19214
19997
|
this.off("error", onerr);
|
|
19215
19998
|
this.off("data", ondata);
|
|
19216
19999
|
this.off(DESTROYED, ondestroy);
|
|
19217
20000
|
stop();
|
|
19218
|
-
|
|
20001
|
+
resolve2({ done: true, value: undefined });
|
|
19219
20002
|
};
|
|
19220
20003
|
const ondestroy = () => onerr(new Error("stream destroyed"));
|
|
19221
20004
|
return new Promise((res2, rej) => {
|
|
19222
20005
|
reject = rej;
|
|
19223
|
-
|
|
20006
|
+
resolve2 = res2;
|
|
19224
20007
|
this.once(DESTROYED, ondestroy);
|
|
19225
20008
|
this.once("error", onerr);
|
|
19226
20009
|
this.once("end", onend);
|
|
@@ -19677,7 +20460,7 @@ import path3 from "node:path";
|
|
|
19677
20460
|
|
|
19678
20461
|
// node_modules/tar/dist/esm/list.js
|
|
19679
20462
|
import fs3 from "node:fs";
|
|
19680
|
-
import { dirname as
|
|
20463
|
+
import { dirname as dirname3, parse as parse2 } from "path";
|
|
19681
20464
|
|
|
19682
20465
|
// node_modules/tar/dist/esm/options.js
|
|
19683
20466
|
var argmap = new Map([
|
|
@@ -20326,10 +21109,10 @@ class Minipass2 extends EventEmitter3 {
|
|
|
20326
21109
|
return this[ENCODING2] ? buf.join("") : Buffer.concat(buf, buf.dataLength);
|
|
20327
21110
|
}
|
|
20328
21111
|
async promise() {
|
|
20329
|
-
return new Promise((
|
|
21112
|
+
return new Promise((resolve2, reject) => {
|
|
20330
21113
|
this.on(DESTROYED2, () => reject(new Error("stream destroyed")));
|
|
20331
21114
|
this.on("error", (er) => reject(er));
|
|
20332
|
-
this.on("end", () =>
|
|
21115
|
+
this.on("end", () => resolve2());
|
|
20333
21116
|
});
|
|
20334
21117
|
}
|
|
20335
21118
|
[Symbol.asyncIterator]() {
|
|
@@ -20348,7 +21131,7 @@ class Minipass2 extends EventEmitter3 {
|
|
|
20348
21131
|
return Promise.resolve({ done: false, value: res });
|
|
20349
21132
|
if (this[EOF2])
|
|
20350
21133
|
return stop();
|
|
20351
|
-
let
|
|
21134
|
+
let resolve2;
|
|
20352
21135
|
let reject;
|
|
20353
21136
|
const onerr = (er) => {
|
|
20354
21137
|
this.off("data", ondata);
|
|
@@ -20362,19 +21145,19 @@ class Minipass2 extends EventEmitter3 {
|
|
|
20362
21145
|
this.off("end", onend);
|
|
20363
21146
|
this.off(DESTROYED2, ondestroy);
|
|
20364
21147
|
this.pause();
|
|
20365
|
-
|
|
21148
|
+
resolve2({ value, done: !!this[EOF2] });
|
|
20366
21149
|
};
|
|
20367
21150
|
const onend = () => {
|
|
20368
21151
|
this.off("error", onerr);
|
|
20369
21152
|
this.off("data", ondata);
|
|
20370
21153
|
this.off(DESTROYED2, ondestroy);
|
|
20371
21154
|
stop();
|
|
20372
|
-
|
|
21155
|
+
resolve2({ done: true, value: undefined });
|
|
20373
21156
|
};
|
|
20374
21157
|
const ondestroy = () => onerr(new Error("stream destroyed"));
|
|
20375
21158
|
return new Promise((res2, rej) => {
|
|
20376
21159
|
reject = rej;
|
|
20377
|
-
|
|
21160
|
+
resolve2 = res2;
|
|
20378
21161
|
this.once(DESTROYED2, ondestroy);
|
|
20379
21162
|
this.once("error", onerr);
|
|
20380
21163
|
this.once("end", onend);
|
|
@@ -20451,7 +21234,7 @@ import * as realZlib2 from "zlib";
|
|
|
20451
21234
|
// node_modules/minizlib/dist/esm/constants.js
|
|
20452
21235
|
import realZlib from "zlib";
|
|
20453
21236
|
var realZlibConstants = realZlib.constants || { ZLIB_VERNUM: 4736 };
|
|
20454
|
-
var
|
|
21237
|
+
var constants3 = Object.freeze(Object.assign(Object.create(null), {
|
|
20455
21238
|
Z_NO_FLUSH: 0,
|
|
20456
21239
|
Z_PARTIAL_FLUSH: 1,
|
|
20457
21240
|
Z_SYNC_FLUSH: 2,
|
|
@@ -20730,9 +21513,9 @@ class Zlib extends ZlibBase {
|
|
|
20730
21513
|
#strategy;
|
|
20731
21514
|
constructor(opts, mode) {
|
|
20732
21515
|
opts = opts || {};
|
|
20733
|
-
opts.flush = opts.flush ||
|
|
20734
|
-
opts.finishFlush = opts.finishFlush ||
|
|
20735
|
-
opts.fullFlushFlag =
|
|
21516
|
+
opts.flush = opts.flush || constants3.Z_NO_FLUSH;
|
|
21517
|
+
opts.finishFlush = opts.finishFlush || constants3.Z_FINISH;
|
|
21518
|
+
opts.fullFlushFlag = constants3.Z_FULL_FLUSH;
|
|
20736
21519
|
super(opts, mode);
|
|
20737
21520
|
this.#level = opts.level;
|
|
20738
21521
|
this.#strategy = opts.strategy;
|
|
@@ -20745,7 +21528,7 @@ class Zlib extends ZlibBase {
|
|
|
20745
21528
|
if (!this.handle.params)
|
|
20746
21529
|
throw new Error("not supported in this implementation");
|
|
20747
21530
|
if (this.#level !== level || this.#strategy !== strategy) {
|
|
20748
|
-
this.flush(
|
|
21531
|
+
this.flush(constants3.Z_SYNC_FLUSH);
|
|
20749
21532
|
assert(this.handle, "zlib binding closed");
|
|
20750
21533
|
const origFlush = this.handle.flush;
|
|
20751
21534
|
this.handle.flush = (flushFlag, cb) => {
|
|
@@ -20791,9 +21574,9 @@ class Unzip extends Zlib {
|
|
|
20791
21574
|
class Brotli extends ZlibBase {
|
|
20792
21575
|
constructor(opts, mode) {
|
|
20793
21576
|
opts = opts || {};
|
|
20794
|
-
opts.flush = opts.flush ||
|
|
20795
|
-
opts.finishFlush = opts.finishFlush ||
|
|
20796
|
-
opts.fullFlushFlag =
|
|
21577
|
+
opts.flush = opts.flush || constants3.BROTLI_OPERATION_PROCESS;
|
|
21578
|
+
opts.finishFlush = opts.finishFlush || constants3.BROTLI_OPERATION_FINISH;
|
|
21579
|
+
opts.fullFlushFlag = constants3.BROTLI_OPERATION_FLUSH;
|
|
20797
21580
|
super(opts, mode);
|
|
20798
21581
|
}
|
|
20799
21582
|
}
|
|
@@ -20813,9 +21596,9 @@ class BrotliDecompress extends Brotli {
|
|
|
20813
21596
|
class Zstd extends ZlibBase {
|
|
20814
21597
|
constructor(opts, mode) {
|
|
20815
21598
|
opts = opts || {};
|
|
20816
|
-
opts.flush = opts.flush ||
|
|
20817
|
-
opts.finishFlush = opts.finishFlush ||
|
|
20818
|
-
opts.fullFlushFlag =
|
|
21599
|
+
opts.flush = opts.flush || constants3.ZSTD_e_continue;
|
|
21600
|
+
opts.finishFlush = opts.finishFlush || constants3.ZSTD_e_end;
|
|
21601
|
+
opts.fullFlushFlag = constants3.ZSTD_e_flush;
|
|
20819
21602
|
super(opts, mode);
|
|
20820
21603
|
}
|
|
20821
21604
|
}
|
|
@@ -21802,10 +22585,10 @@ class Minipass3 extends EventEmitter4 {
|
|
|
21802
22585
|
return this[ENCODING3] ? buf.join("") : Buffer.concat(buf, buf.dataLength);
|
|
21803
22586
|
}
|
|
21804
22587
|
async promise() {
|
|
21805
|
-
return new Promise((
|
|
22588
|
+
return new Promise((resolve2, reject) => {
|
|
21806
22589
|
this.on(DESTROYED3, () => reject(new Error("stream destroyed")));
|
|
21807
22590
|
this.on("error", (er) => reject(er));
|
|
21808
|
-
this.on("end", () =>
|
|
22591
|
+
this.on("end", () => resolve2());
|
|
21809
22592
|
});
|
|
21810
22593
|
}
|
|
21811
22594
|
[Symbol.asyncIterator]() {
|
|
@@ -21824,7 +22607,7 @@ class Minipass3 extends EventEmitter4 {
|
|
|
21824
22607
|
return Promise.resolve({ done: false, value: res });
|
|
21825
22608
|
if (this[EOF3])
|
|
21826
22609
|
return stop();
|
|
21827
|
-
let
|
|
22610
|
+
let resolve2;
|
|
21828
22611
|
let reject;
|
|
21829
22612
|
const onerr = (er) => {
|
|
21830
22613
|
this.off("data", ondata);
|
|
@@ -21838,19 +22621,19 @@ class Minipass3 extends EventEmitter4 {
|
|
|
21838
22621
|
this.off("end", onend);
|
|
21839
22622
|
this.off(DESTROYED3, ondestroy);
|
|
21840
22623
|
this.pause();
|
|
21841
|
-
|
|
22624
|
+
resolve2({ value, done: !!this[EOF3] });
|
|
21842
22625
|
};
|
|
21843
22626
|
const onend = () => {
|
|
21844
22627
|
this.off("error", onerr);
|
|
21845
22628
|
this.off("data", ondata);
|
|
21846
22629
|
this.off(DESTROYED3, ondestroy);
|
|
21847
22630
|
stop();
|
|
21848
|
-
|
|
22631
|
+
resolve2({ done: true, value: undefined });
|
|
21849
22632
|
};
|
|
21850
22633
|
const ondestroy = () => onerr(new Error("stream destroyed"));
|
|
21851
22634
|
return new Promise((res2, rej) => {
|
|
21852
22635
|
reject = rej;
|
|
21853
|
-
|
|
22636
|
+
resolve2 = res2;
|
|
21854
22637
|
this.once(DESTROYED3, ondestroy);
|
|
21855
22638
|
this.once("error", onerr);
|
|
21856
22639
|
this.once("end", onend);
|
|
@@ -21922,8 +22705,8 @@ class Minipass3 extends EventEmitter4 {
|
|
|
21922
22705
|
}
|
|
21923
22706
|
|
|
21924
22707
|
// node_modules/tar/dist/esm/normalize-windows-path.js
|
|
21925
|
-
var
|
|
21926
|
-
var normalizeWindowsPath =
|
|
22708
|
+
var platform4 = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform;
|
|
22709
|
+
var normalizeWindowsPath = platform4 !== "win32" ? (p) => p : (p) => p && p.replace(/\\/g, "/");
|
|
21927
22710
|
|
|
21928
22711
|
// node_modules/tar/dist/esm/read-entry.js
|
|
21929
22712
|
class ReadEntry extends Minipass3 {
|
|
@@ -22577,7 +23360,7 @@ var filesFilter = (opt, files) => {
|
|
|
22577
23360
|
if (m2 !== undefined) {
|
|
22578
23361
|
ret = m2;
|
|
22579
23362
|
} else {
|
|
22580
|
-
ret = mapHas(
|
|
23363
|
+
ret = mapHas(dirname3(file), root);
|
|
22581
23364
|
}
|
|
22582
23365
|
}
|
|
22583
23366
|
map.set(file, ret);
|
|
@@ -22621,9 +23404,9 @@ var listFile = (opt, _files) => {
|
|
|
22621
23404
|
const parse3 = new Parser(opt);
|
|
22622
23405
|
const readSize = opt.maxReadSize || 16 * 1024 * 1024;
|
|
22623
23406
|
const file = opt.file;
|
|
22624
|
-
const p = new Promise((
|
|
23407
|
+
const p = new Promise((resolve2, reject) => {
|
|
22625
23408
|
parse3.on("error", reject);
|
|
22626
|
-
parse3.on("end",
|
|
23409
|
+
parse3.on("end", resolve2);
|
|
22627
23410
|
fs3.stat(file, (er, stat3) => {
|
|
22628
23411
|
if (er) {
|
|
22629
23412
|
reject(er);
|
|
@@ -24121,8 +24904,8 @@ import path6 from "node:path";
|
|
|
24121
24904
|
|
|
24122
24905
|
// node_modules/tar/dist/esm/get-write-flag.js
|
|
24123
24906
|
import fs6 from "fs";
|
|
24124
|
-
var
|
|
24125
|
-
var isWindows2 =
|
|
24907
|
+
var platform5 = process.env.__FAKE_PLATFORM__ || process.platform;
|
|
24908
|
+
var isWindows2 = platform5 === "win32";
|
|
24126
24909
|
var { O_CREAT, O_TRUNC, O_WRONLY } = fs6.constants;
|
|
24127
24910
|
var UV_FS_O_FILEMAP = Number(process.env.__FAKE_FS_O_FILENAME__) || fs6.constants.UV_FS_O_FILEMAP || 0;
|
|
24128
24911
|
var fMapEnabled = isWindows2 && !!UV_FS_O_FILEMAP;
|
|
@@ -24234,9 +25017,9 @@ class SymlinkError extends Error {
|
|
|
24234
25017
|
symlink;
|
|
24235
25018
|
syscall = "symlink";
|
|
24236
25019
|
code = "TAR_SYMLINK_ERROR";
|
|
24237
|
-
constructor(
|
|
25020
|
+
constructor(symlink2, path5) {
|
|
24238
25021
|
super("TAR_SYMLINK_ERROR: Cannot extract through symbolic link");
|
|
24239
|
-
this.symlink =
|
|
25022
|
+
this.symlink = symlink2;
|
|
24240
25023
|
this.path = path5;
|
|
24241
25024
|
}
|
|
24242
25025
|
get name() {
|
|
@@ -24253,7 +25036,7 @@ var checkCwd = (dir, cb) => {
|
|
|
24253
25036
|
cb(er);
|
|
24254
25037
|
});
|
|
24255
25038
|
};
|
|
24256
|
-
var
|
|
25039
|
+
var mkdir5 = (dir, opt, cb) => {
|
|
24257
25040
|
dir = normalizeWindowsPath(dir);
|
|
24258
25041
|
const umask = opt.umask ?? 18;
|
|
24259
25042
|
const mode = opt.mode | 448;
|
|
@@ -24262,7 +25045,7 @@ var mkdir4 = (dir, opt, cb) => {
|
|
|
24262
25045
|
const gid = opt.gid;
|
|
24263
25046
|
const doChown = typeof uid === "number" && typeof gid === "number" && (uid !== opt.processUid || gid !== opt.processGid);
|
|
24264
25047
|
const preserve = opt.preserve;
|
|
24265
|
-
const
|
|
25048
|
+
const unlink4 = opt.unlink;
|
|
24266
25049
|
const cwd = normalizeWindowsPath(opt.cwd);
|
|
24267
25050
|
const done = (er, created) => {
|
|
24268
25051
|
if (er) {
|
|
@@ -24285,30 +25068,30 @@ var mkdir4 = (dir, opt, cb) => {
|
|
|
24285
25068
|
}
|
|
24286
25069
|
const sub = normalizeWindowsPath(path5.relative(cwd, dir));
|
|
24287
25070
|
const parts = sub.split("/");
|
|
24288
|
-
mkdir_(cwd, parts, mode,
|
|
25071
|
+
mkdir_(cwd, parts, mode, unlink4, cwd, undefined, done);
|
|
24289
25072
|
};
|
|
24290
|
-
var mkdir_ = (base, parts, mode,
|
|
25073
|
+
var mkdir_ = (base, parts, mode, unlink4, cwd, created, cb) => {
|
|
24291
25074
|
if (!parts.length) {
|
|
24292
25075
|
return cb(null, created);
|
|
24293
25076
|
}
|
|
24294
25077
|
const p = parts.shift();
|
|
24295
25078
|
const part = normalizeWindowsPath(path5.resolve(base + "/" + p));
|
|
24296
|
-
fs8.mkdir(part, mode, onmkdir(part, parts, mode,
|
|
25079
|
+
fs8.mkdir(part, mode, onmkdir(part, parts, mode, unlink4, cwd, created, cb));
|
|
24297
25080
|
};
|
|
24298
|
-
var onmkdir = (part, parts, mode,
|
|
25081
|
+
var onmkdir = (part, parts, mode, unlink4, cwd, created, cb) => (er) => {
|
|
24299
25082
|
if (er) {
|
|
24300
25083
|
fs8.lstat(part, (statEr, st) => {
|
|
24301
25084
|
if (statEr) {
|
|
24302
25085
|
statEr.path = statEr.path && normalizeWindowsPath(statEr.path);
|
|
24303
25086
|
cb(statEr);
|
|
24304
25087
|
} else if (st.isDirectory()) {
|
|
24305
|
-
mkdir_(part, parts, mode,
|
|
24306
|
-
} else if (
|
|
25088
|
+
mkdir_(part, parts, mode, unlink4, cwd, created, cb);
|
|
25089
|
+
} else if (unlink4) {
|
|
24307
25090
|
fs8.unlink(part, (er2) => {
|
|
24308
25091
|
if (er2) {
|
|
24309
25092
|
return cb(er2);
|
|
24310
25093
|
}
|
|
24311
|
-
fs8.mkdir(part, mode, onmkdir(part, parts, mode,
|
|
25094
|
+
fs8.mkdir(part, mode, onmkdir(part, parts, mode, unlink4, cwd, created, cb));
|
|
24312
25095
|
});
|
|
24313
25096
|
} else if (st.isSymbolicLink()) {
|
|
24314
25097
|
return cb(new SymlinkError(part, part + "/" + parts.join("/")));
|
|
@@ -24318,7 +25101,7 @@ var onmkdir = (part, parts, mode, unlink2, cwd, created, cb) => (er) => {
|
|
|
24318
25101
|
});
|
|
24319
25102
|
} else {
|
|
24320
25103
|
created = created || part;
|
|
24321
|
-
mkdir_(part, parts, mode,
|
|
25104
|
+
mkdir_(part, parts, mode, unlink4, cwd, created, cb);
|
|
24322
25105
|
}
|
|
24323
25106
|
};
|
|
24324
25107
|
var checkCwdSync = (dir) => {
|
|
@@ -24343,7 +25126,7 @@ var mkdirSync = (dir, opt) => {
|
|
|
24343
25126
|
const gid = opt.gid;
|
|
24344
25127
|
const doChown = typeof uid === "number" && typeof gid === "number" && (uid !== opt.processUid || gid !== opt.processGid);
|
|
24345
25128
|
const preserve = opt.preserve;
|
|
24346
|
-
const
|
|
25129
|
+
const unlink4 = opt.unlink;
|
|
24347
25130
|
const cwd = normalizeWindowsPath(opt.cwd);
|
|
24348
25131
|
const done = (created2) => {
|
|
24349
25132
|
if (created2 && doChown) {
|
|
@@ -24372,7 +25155,7 @@ var mkdirSync = (dir, opt) => {
|
|
|
24372
25155
|
const st = fs8.lstatSync(part);
|
|
24373
25156
|
if (st.isDirectory()) {
|
|
24374
25157
|
continue;
|
|
24375
|
-
} else if (
|
|
25158
|
+
} else if (unlink4) {
|
|
24376
25159
|
fs8.unlinkSync(part);
|
|
24377
25160
|
fs8.mkdirSync(part, mode);
|
|
24378
25161
|
created = created || part;
|
|
@@ -24386,7 +25169,7 @@ var mkdirSync = (dir, opt) => {
|
|
|
24386
25169
|
};
|
|
24387
25170
|
|
|
24388
25171
|
// node_modules/tar/dist/esm/path-reservations.js
|
|
24389
|
-
import { join as
|
|
25172
|
+
import { join as join10 } from "node:path";
|
|
24390
25173
|
|
|
24391
25174
|
// node_modules/tar/dist/esm/normalize-unicode.js
|
|
24392
25175
|
var normalizeCache = Object.create(null);
|
|
@@ -24413,13 +25196,13 @@ var normalizeUnicode = (s) => {
|
|
|
24413
25196
|
};
|
|
24414
25197
|
|
|
24415
25198
|
// node_modules/tar/dist/esm/path-reservations.js
|
|
24416
|
-
var
|
|
24417
|
-
var isWindows3 =
|
|
25199
|
+
var platform6 = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform;
|
|
25200
|
+
var isWindows3 = platform6 === "win32";
|
|
24418
25201
|
var getDirs = (path6) => {
|
|
24419
25202
|
const dirs = path6.split("/").slice(0, -1).reduce((set, path7) => {
|
|
24420
25203
|
const s = set[set.length - 1];
|
|
24421
25204
|
if (s !== undefined) {
|
|
24422
|
-
path7 =
|
|
25205
|
+
path7 = join10(s, path7);
|
|
24423
25206
|
}
|
|
24424
25207
|
set.push(path7 || "/");
|
|
24425
25208
|
return set;
|
|
@@ -24433,7 +25216,7 @@ class PathReservations {
|
|
|
24433
25216
|
#running = new Set;
|
|
24434
25217
|
reserve(paths, fn) {
|
|
24435
25218
|
paths = isWindows3 ? ["win32 parallelization disabled"] : paths.map((p) => {
|
|
24436
|
-
return stripTrailingSlashes(
|
|
25219
|
+
return stripTrailingSlashes(join10(normalizeUnicode(p))).toLowerCase();
|
|
24437
25220
|
});
|
|
24438
25221
|
const dirs = new Set(paths.map((path6) => getDirs(path6)).reduce((a3, b3) => a3.concat(b3)));
|
|
24439
25222
|
this.#reservations.set(fn, { dirs, paths });
|
|
@@ -24560,8 +25343,8 @@ var DOCHOWN = Symbol("doChown");
|
|
|
24560
25343
|
var UID = Symbol("uid");
|
|
24561
25344
|
var GID = Symbol("gid");
|
|
24562
25345
|
var CHECKED_CWD = Symbol("checkedCwd");
|
|
24563
|
-
var
|
|
24564
|
-
var isWindows4 =
|
|
25346
|
+
var platform7 = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform;
|
|
25347
|
+
var isWindows4 = platform7 === "win32";
|
|
24565
25348
|
var DEFAULT_MAX_DEPTH = 1024;
|
|
24566
25349
|
var unlinkFile = (path7, cb) => {
|
|
24567
25350
|
if (!isWindows4) {
|
|
@@ -24776,7 +25559,7 @@ class Unpack extends Parser {
|
|
|
24776
25559
|
}
|
|
24777
25560
|
}
|
|
24778
25561
|
[MKDIR](dir, mode, cb) {
|
|
24779
|
-
|
|
25562
|
+
mkdir5(normalizeWindowsPath(dir), {
|
|
24780
25563
|
uid: this.uid,
|
|
24781
25564
|
gid: this.gid,
|
|
24782
25565
|
processUid: this.processUid,
|
|
@@ -25203,9 +25986,9 @@ var extractFile = (opt, _3) => {
|
|
|
25203
25986
|
const u = new Unpack(opt);
|
|
25204
25987
|
const readSize = opt.maxReadSize || 16 * 1024 * 1024;
|
|
25205
25988
|
const file = opt.file;
|
|
25206
|
-
const p = new Promise((
|
|
25989
|
+
const p = new Promise((resolve2, reject) => {
|
|
25207
25990
|
u.on("error", reject);
|
|
25208
|
-
u.on("close",
|
|
25991
|
+
u.on("close", resolve2);
|
|
25209
25992
|
fs10.stat(file, (er, stat3) => {
|
|
25210
25993
|
if (er) {
|
|
25211
25994
|
reject(er);
|
|
@@ -25338,7 +26121,7 @@ var replaceAsync = (opt, files) => {
|
|
|
25338
26121
|
};
|
|
25339
26122
|
fs11.read(fd, headBuf, 0, 512, position, onread);
|
|
25340
26123
|
};
|
|
25341
|
-
const promise = new Promise((
|
|
26124
|
+
const promise = new Promise((resolve2, reject) => {
|
|
25342
26125
|
p.on("error", reject);
|
|
25343
26126
|
let flag = "r+";
|
|
25344
26127
|
const onopen = (er, fd) => {
|
|
@@ -25363,7 +26146,7 @@ var replaceAsync = (opt, files) => {
|
|
|
25363
26146
|
});
|
|
25364
26147
|
p.pipe(stream);
|
|
25365
26148
|
stream.on("error", reject);
|
|
25366
|
-
stream.on("close",
|
|
26149
|
+
stream.on("close", resolve2);
|
|
25367
26150
|
addFilesAsync2(p, files);
|
|
25368
26151
|
});
|
|
25369
26152
|
});
|
|
@@ -26830,8 +27613,8 @@ class DownloadManager {
|
|
|
26830
27613
|
}
|
|
26831
27614
|
}
|
|
26832
27615
|
isPathSafe(basePath, targetPath) {
|
|
26833
|
-
const resolvedBase =
|
|
26834
|
-
const resolvedTarget =
|
|
27616
|
+
const resolvedBase = resolve2(basePath);
|
|
27617
|
+
const resolvedTarget = resolve2(targetPath);
|
|
26835
27618
|
const relativePath = relative2(resolvedBase, resolvedTarget);
|
|
26836
27619
|
return !relativePath.startsWith("..") && !relativePath.startsWith("/") && resolvedTarget.startsWith(resolvedBase);
|
|
26837
27620
|
}
|
|
@@ -26846,8 +27629,8 @@ class DownloadManager {
|
|
|
26846
27629
|
}
|
|
26847
27630
|
async downloadAsset(asset, destDir) {
|
|
26848
27631
|
try {
|
|
26849
|
-
const destPath =
|
|
26850
|
-
await
|
|
27632
|
+
const destPath = join11(destDir, asset.name);
|
|
27633
|
+
await mkdir6(destDir, { recursive: true });
|
|
26851
27634
|
logger.info(`Downloading ${asset.name} (${this.formatBytes(asset.size)})...`);
|
|
26852
27635
|
const progressBar = new import_cli_progress.default.SingleBar({
|
|
26853
27636
|
format: "Progress |{bar}| {percentage}% | {value}/{total} MB",
|
|
@@ -26896,8 +27679,8 @@ class DownloadManager {
|
|
|
26896
27679
|
}
|
|
26897
27680
|
async downloadFile(params) {
|
|
26898
27681
|
const { url, name: name2, size, destDir, token } = params;
|
|
26899
|
-
const destPath =
|
|
26900
|
-
await
|
|
27682
|
+
const destPath = join11(destDir, name2);
|
|
27683
|
+
await mkdir6(destDir, { recursive: true });
|
|
26901
27684
|
logger.info(`Downloading ${name2}${size ? ` (${this.formatBytes(size)})` : ""}...`);
|
|
26902
27685
|
const headers = {};
|
|
26903
27686
|
if (token && url.includes("api.github.com")) {
|
|
@@ -26961,7 +27744,7 @@ class DownloadManager {
|
|
|
26961
27744
|
try {
|
|
26962
27745
|
this.resetExtractionSize();
|
|
26963
27746
|
const detectedType = archiveType || this.detectArchiveType(archivePath);
|
|
26964
|
-
await
|
|
27747
|
+
await mkdir6(destDir, { recursive: true });
|
|
26965
27748
|
if (detectedType === "tar.gz") {
|
|
26966
27749
|
await this.extractTarGz(archivePath, destDir);
|
|
26967
27750
|
} else if (detectedType === "zip") {
|
|
@@ -26981,7 +27764,7 @@ class DownloadManager {
|
|
|
26981
27764
|
}
|
|
26982
27765
|
}
|
|
26983
27766
|
async extractTarGz(archivePath, destDir) {
|
|
26984
|
-
const { readdir:
|
|
27767
|
+
const { readdir: readdir4, stat: stat3, mkdir: mkdirPromise, copyFile, rm } = await import("node:fs/promises");
|
|
26985
27768
|
const { join: pathJoin } = await import("node:path");
|
|
26986
27769
|
const tempExtractDir = `${destDir}-temp`;
|
|
26987
27770
|
await mkdirPromise(tempExtractDir, { recursive: true });
|
|
@@ -27000,14 +27783,14 @@ class DownloadManager {
|
|
|
27000
27783
|
}
|
|
27001
27784
|
});
|
|
27002
27785
|
logger.debug(`Extracted TAR.GZ to temp: ${tempExtractDir}`);
|
|
27003
|
-
const entries = await
|
|
27786
|
+
const entries = await readdir4(tempExtractDir, { encoding: "utf8" });
|
|
27004
27787
|
logger.debug(`Root entries: ${entries.join(", ")}`);
|
|
27005
27788
|
if (entries.length === 1) {
|
|
27006
27789
|
const rootEntry = entries[0];
|
|
27007
27790
|
const rootPath = pathJoin(tempExtractDir, rootEntry);
|
|
27008
27791
|
const rootStat = await stat3(rootPath);
|
|
27009
27792
|
if (rootStat.isDirectory()) {
|
|
27010
|
-
const rootContents = await
|
|
27793
|
+
const rootContents = await readdir4(rootPath, { encoding: "utf8" });
|
|
27011
27794
|
logger.debug(`Root directory '${rootEntry}' contains: ${rootContents.join(", ")}`);
|
|
27012
27795
|
const isWrapper = this.isWrapperDirectory(rootEntry);
|
|
27013
27796
|
logger.debug(`Is wrapper directory: ${isWrapper}`);
|
|
@@ -27044,26 +27827,26 @@ class DownloadManager {
|
|
|
27044
27827
|
if (!isMacOS()) {
|
|
27045
27828
|
return false;
|
|
27046
27829
|
}
|
|
27047
|
-
return new Promise((
|
|
27830
|
+
return new Promise((resolve3) => {
|
|
27048
27831
|
const { mkdir: mkdirPromise } = __require("node:fs/promises");
|
|
27049
27832
|
mkdirPromise(destDir, { recursive: true }).then(() => {
|
|
27050
27833
|
execFile("unzip", ["-o", "-q", archivePath, "-d", destDir], (error, _stdout, stderr) => {
|
|
27051
27834
|
if (error) {
|
|
27052
27835
|
logger.debug(`Native unzip failed: ${stderr || error.message}`);
|
|
27053
|
-
|
|
27836
|
+
resolve3(false);
|
|
27054
27837
|
return;
|
|
27055
27838
|
}
|
|
27056
27839
|
logger.debug("Native unzip succeeded");
|
|
27057
|
-
|
|
27840
|
+
resolve3(true);
|
|
27058
27841
|
});
|
|
27059
27842
|
}).catch((err) => {
|
|
27060
27843
|
logger.debug(`Failed to create directory for native unzip: ${err.message}`);
|
|
27061
|
-
|
|
27844
|
+
resolve3(false);
|
|
27062
27845
|
});
|
|
27063
27846
|
});
|
|
27064
27847
|
}
|
|
27065
27848
|
async extractZip(archivePath, destDir) {
|
|
27066
|
-
const { readdir:
|
|
27849
|
+
const { readdir: readdir4, stat: stat3, mkdir: mkdirPromise, copyFile, rm } = await import("node:fs/promises");
|
|
27067
27850
|
const { join: pathJoin } = await import("node:path");
|
|
27068
27851
|
const tempExtractDir = `${destDir}-temp`;
|
|
27069
27852
|
await mkdirPromise(tempExtractDir, { recursive: true });
|
|
@@ -27082,14 +27865,14 @@ class DownloadManager {
|
|
|
27082
27865
|
await import_extract_zip.default(archivePath, zipOptions);
|
|
27083
27866
|
}
|
|
27084
27867
|
logger.debug(`Extracted ZIP to temp: ${tempExtractDir}`);
|
|
27085
|
-
const entries = await
|
|
27868
|
+
const entries = await readdir4(tempExtractDir, { encoding: "utf8" });
|
|
27086
27869
|
logger.debug(`Root entries: ${entries.join(", ")}`);
|
|
27087
27870
|
if (entries.length === 1) {
|
|
27088
27871
|
const rootEntry = entries[0];
|
|
27089
27872
|
const rootPath = pathJoin(tempExtractDir, rootEntry);
|
|
27090
27873
|
const rootStat = await stat3(rootPath);
|
|
27091
27874
|
if (rootStat.isDirectory()) {
|
|
27092
|
-
const rootContents = await
|
|
27875
|
+
const rootContents = await readdir4(rootPath, { encoding: "utf8" });
|
|
27093
27876
|
logger.debug(`Root directory '${rootEntry}' contains: ${rootContents.join(", ")}`);
|
|
27094
27877
|
const isWrapper = this.isWrapperDirectory(rootEntry);
|
|
27095
27878
|
logger.debug(`Is wrapper directory: ${isWrapper}`);
|
|
@@ -27118,10 +27901,10 @@ class DownloadManager {
|
|
|
27118
27901
|
}
|
|
27119
27902
|
}
|
|
27120
27903
|
async moveDirectoryContents(sourceDir, destDir) {
|
|
27121
|
-
const { readdir:
|
|
27904
|
+
const { readdir: readdir4, stat: stat3, mkdir: mkdirPromise, copyFile } = await import("node:fs/promises");
|
|
27122
27905
|
const { join: pathJoin, relative: relative3 } = await import("node:path");
|
|
27123
27906
|
await mkdirPromise(destDir, { recursive: true });
|
|
27124
|
-
const entries = await
|
|
27907
|
+
const entries = await readdir4(sourceDir, { encoding: "utf8" });
|
|
27125
27908
|
for (const entry of entries) {
|
|
27126
27909
|
const sourcePath = pathJoin(sourceDir, entry);
|
|
27127
27910
|
const destPath = pathJoin(destDir, entry);
|
|
@@ -27144,10 +27927,10 @@ class DownloadManager {
|
|
|
27144
27927
|
}
|
|
27145
27928
|
}
|
|
27146
27929
|
async copyDirectory(sourceDir, destDir) {
|
|
27147
|
-
const { readdir:
|
|
27930
|
+
const { readdir: readdir4, stat: stat3, mkdir: mkdirPromise, copyFile } = await import("node:fs/promises");
|
|
27148
27931
|
const { join: pathJoin, relative: relative3 } = await import("node:path");
|
|
27149
27932
|
await mkdirPromise(destDir, { recursive: true });
|
|
27150
|
-
const entries = await
|
|
27933
|
+
const entries = await readdir4(sourceDir, { encoding: "utf8" });
|
|
27151
27934
|
for (const entry of entries) {
|
|
27152
27935
|
const sourcePath = pathJoin(sourceDir, entry);
|
|
27153
27936
|
const destPath = pathJoin(destDir, entry);
|
|
@@ -27179,11 +27962,11 @@ class DownloadManager {
|
|
|
27179
27962
|
throw new ExtractionError(`Cannot detect archive type from filename: ${filename}`);
|
|
27180
27963
|
}
|
|
27181
27964
|
async validateExtraction(extractDir) {
|
|
27182
|
-
const { readdir:
|
|
27965
|
+
const { readdir: readdir4, access: access3 } = await import("node:fs/promises");
|
|
27183
27966
|
const { join: pathJoin } = await import("node:path");
|
|
27184
|
-
const { constants:
|
|
27967
|
+
const { constants: constants4 } = await import("node:fs");
|
|
27185
27968
|
try {
|
|
27186
|
-
const entries = await
|
|
27969
|
+
const entries = await readdir4(extractDir, { encoding: "utf8" });
|
|
27187
27970
|
logger.debug(`Extracted files: ${entries.join(", ")}`);
|
|
27188
27971
|
if (entries.length === 0) {
|
|
27189
27972
|
throw new ExtractionError("Extraction resulted in no files");
|
|
@@ -27192,7 +27975,7 @@ class DownloadManager {
|
|
|
27192
27975
|
const missingPaths = [];
|
|
27193
27976
|
for (const path8 of criticalPaths) {
|
|
27194
27977
|
try {
|
|
27195
|
-
await
|
|
27978
|
+
await access3(pathJoin(extractDir, path8), constants4.F_OK);
|
|
27196
27979
|
logger.debug(`✓ Found: ${path8}`);
|
|
27197
27980
|
} catch {
|
|
27198
27981
|
logger.warning(`Expected path not found: ${path8}`);
|
|
@@ -27213,9 +27996,9 @@ class DownloadManager {
|
|
|
27213
27996
|
async createTempDir() {
|
|
27214
27997
|
const timestamp = Date.now();
|
|
27215
27998
|
const counter = DownloadManager.tempDirCounter++;
|
|
27216
|
-
const primaryTempDir =
|
|
27999
|
+
const primaryTempDir = join11(tmpdir2(), `claudekit-${timestamp}-${counter}`);
|
|
27217
28000
|
try {
|
|
27218
|
-
await
|
|
28001
|
+
await mkdir6(primaryTempDir, { recursive: true });
|
|
27219
28002
|
logger.debug(`Created temp directory: ${primaryTempDir}`);
|
|
27220
28003
|
return primaryTempDir;
|
|
27221
28004
|
} catch (primaryError) {
|
|
@@ -27229,9 +28012,9 @@ Solutions:
|
|
|
27229
28012
|
2. Set HOME environment variable
|
|
27230
28013
|
3. Try running from a different directory`);
|
|
27231
28014
|
}
|
|
27232
|
-
const fallbackTempDir =
|
|
28015
|
+
const fallbackTempDir = join11(homeDir, ".claudekit", "tmp", `claudekit-${timestamp}-${counter}`);
|
|
27233
28016
|
try {
|
|
27234
|
-
await
|
|
28017
|
+
await mkdir6(fallbackTempDir, { recursive: true });
|
|
27235
28018
|
logger.debug(`Created temp directory (fallback): ${fallbackTempDir}`);
|
|
27236
28019
|
logger.warning(`Using fallback temp directory: ${fallbackTempDir}
|
|
27237
28020
|
(OS temp directory was not accessible)`);
|
|
@@ -27266,8 +28049,8 @@ Solutions:
|
|
|
27266
28049
|
init_types2();
|
|
27267
28050
|
init_logger();
|
|
27268
28051
|
var import_fs_extra4 = __toESM(require_lib(), 1);
|
|
27269
|
-
import { readFile as
|
|
27270
|
-
import { join as
|
|
28052
|
+
import { readFile as readFile7, readdir as readdir4, rename, writeFile as writeFile6 } from "node:fs/promises";
|
|
28053
|
+
import { join as join12, relative as relative3 } from "node:path";
|
|
27271
28054
|
var TRANSFORMABLE_FILE_PATTERNS = [
|
|
27272
28055
|
".md",
|
|
27273
28056
|
".txt",
|
|
@@ -27313,34 +28096,34 @@ async function transformFolderPaths(extractDir, folders, options = {}) {
|
|
|
27313
28096
|
}
|
|
27314
28097
|
const dirsToRename = [];
|
|
27315
28098
|
if (folders.docs !== DEFAULT_FOLDERS.docs) {
|
|
27316
|
-
const docsPath =
|
|
28099
|
+
const docsPath = join12(extractDir, DEFAULT_FOLDERS.docs);
|
|
27317
28100
|
if (await import_fs_extra4.pathExists(docsPath)) {
|
|
27318
28101
|
dirsToRename.push({
|
|
27319
28102
|
from: docsPath,
|
|
27320
|
-
to:
|
|
28103
|
+
to: join12(extractDir, folders.docs)
|
|
27321
28104
|
});
|
|
27322
28105
|
}
|
|
27323
|
-
const claudeDocsPath =
|
|
28106
|
+
const claudeDocsPath = join12(extractDir, ".claude", DEFAULT_FOLDERS.docs);
|
|
27324
28107
|
if (await import_fs_extra4.pathExists(claudeDocsPath)) {
|
|
27325
28108
|
dirsToRename.push({
|
|
27326
28109
|
from: claudeDocsPath,
|
|
27327
|
-
to:
|
|
28110
|
+
to: join12(extractDir, ".claude", folders.docs)
|
|
27328
28111
|
});
|
|
27329
28112
|
}
|
|
27330
28113
|
}
|
|
27331
28114
|
if (folders.plans !== DEFAULT_FOLDERS.plans) {
|
|
27332
|
-
const plansPath =
|
|
28115
|
+
const plansPath = join12(extractDir, DEFAULT_FOLDERS.plans);
|
|
27333
28116
|
if (await import_fs_extra4.pathExists(plansPath)) {
|
|
27334
28117
|
dirsToRename.push({
|
|
27335
28118
|
from: plansPath,
|
|
27336
|
-
to:
|
|
28119
|
+
to: join12(extractDir, folders.plans)
|
|
27337
28120
|
});
|
|
27338
28121
|
}
|
|
27339
|
-
const claudePlansPath =
|
|
28122
|
+
const claudePlansPath = join12(extractDir, ".claude", DEFAULT_FOLDERS.plans);
|
|
27340
28123
|
if (await import_fs_extra4.pathExists(claudePlansPath)) {
|
|
27341
28124
|
dirsToRename.push({
|
|
27342
28125
|
from: claudePlansPath,
|
|
27343
|
-
to:
|
|
28126
|
+
to: join12(extractDir, ".claude", folders.plans)
|
|
27344
28127
|
});
|
|
27345
28128
|
}
|
|
27346
28129
|
}
|
|
@@ -27375,9 +28158,9 @@ async function transformFolderPaths(extractDir, folders, options = {}) {
|
|
|
27375
28158
|
async function transformFileContents(dir, compiledReplacements, options) {
|
|
27376
28159
|
let filesChanged = 0;
|
|
27377
28160
|
let replacementsCount = 0;
|
|
27378
|
-
const entries = await
|
|
28161
|
+
const entries = await readdir4(dir, { withFileTypes: true });
|
|
27379
28162
|
for (const entry of entries) {
|
|
27380
|
-
const fullPath =
|
|
28163
|
+
const fullPath = join12(dir, entry.name);
|
|
27381
28164
|
if (entry.isDirectory()) {
|
|
27382
28165
|
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
27383
28166
|
continue;
|
|
@@ -27390,7 +28173,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
27390
28173
|
if (!shouldTransform)
|
|
27391
28174
|
continue;
|
|
27392
28175
|
try {
|
|
27393
|
-
const content = await
|
|
28176
|
+
const content = await readFile7(fullPath, "utf-8");
|
|
27394
28177
|
let newContent = content;
|
|
27395
28178
|
let changeCount = 0;
|
|
27396
28179
|
for (const { regex: regex2, replacement } of compiledReplacements) {
|
|
@@ -27406,7 +28189,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
27406
28189
|
if (options.dryRun) {
|
|
27407
28190
|
logger.debug(`[dry-run] Would update ${relative3(dir, fullPath)}: ${changeCount} replacement(s)`);
|
|
27408
28191
|
} else {
|
|
27409
|
-
await
|
|
28192
|
+
await writeFile6(fullPath, newContent, "utf-8");
|
|
27410
28193
|
logger.debug(`Updated ${relative3(dir, fullPath)}: ${changeCount} replacement(s)`);
|
|
27411
28194
|
}
|
|
27412
28195
|
filesChanged++;
|
|
@@ -27487,7 +28270,7 @@ function validateFolderName(name2) {
|
|
|
27487
28270
|
// src/lib/fresh-installer.ts
|
|
27488
28271
|
init_logger();
|
|
27489
28272
|
var import_fs_extra5 = __toESM(require_lib(), 1);
|
|
27490
|
-
import { join as
|
|
28273
|
+
import { join as join13 } from "node:path";
|
|
27491
28274
|
var CLAUDEKIT_SUBDIRECTORIES = ["commands", "agents", "skills", "workflows", "hooks"];
|
|
27492
28275
|
async function handleFreshInstallation(claudeDir, prompts) {
|
|
27493
28276
|
if (!await import_fs_extra5.pathExists(claudeDir)) {
|
|
@@ -27505,7 +28288,7 @@ async function handleFreshInstallation(claudeDir, prompts) {
|
|
|
27505
28288
|
const { rmSync } = await import("node:fs");
|
|
27506
28289
|
let removedCount = 0;
|
|
27507
28290
|
for (const subdir of CLAUDEKIT_SUBDIRECTORIES) {
|
|
27508
|
-
const subdirPath =
|
|
28291
|
+
const subdirPath = join13(claudeDir, subdir);
|
|
27509
28292
|
if (await import_fs_extra5.pathExists(subdirPath)) {
|
|
27510
28293
|
rmSync(subdirPath, { recursive: true, force: true });
|
|
27511
28294
|
removedCount++;
|
|
@@ -27522,11 +28305,11 @@ async function handleFreshInstallation(claudeDir, prompts) {
|
|
|
27522
28305
|
|
|
27523
28306
|
// src/lib/global-path-transformer.ts
|
|
27524
28307
|
init_logger();
|
|
27525
|
-
import { readFile as
|
|
27526
|
-
import { platform as
|
|
27527
|
-
import { extname, join as
|
|
27528
|
-
var
|
|
27529
|
-
var HOME_PREFIX =
|
|
28308
|
+
import { readFile as readFile8, readdir as readdir5, writeFile as writeFile7 } from "node:fs/promises";
|
|
28309
|
+
import { platform as platform8 } from "node:os";
|
|
28310
|
+
import { extname, join as join14 } from "node:path";
|
|
28311
|
+
var IS_WINDOWS2 = platform8() === "win32";
|
|
28312
|
+
var HOME_PREFIX = IS_WINDOWS2 ? "%USERPROFILE%" : "$HOME";
|
|
27530
28313
|
function getHomeDirPrefix() {
|
|
27531
28314
|
return HOME_PREFIX;
|
|
27532
28315
|
}
|
|
@@ -27547,7 +28330,7 @@ function transformContent(content) {
|
|
|
27547
28330
|
let transformed = content;
|
|
27548
28331
|
const homePrefix = getHomeDirPrefix();
|
|
27549
28332
|
const claudePath = `${homePrefix}/.claude/`;
|
|
27550
|
-
if (
|
|
28333
|
+
if (IS_WINDOWS2) {
|
|
27551
28334
|
transformed = transformed.replace(/\$HOME\/\.claude\//g, () => {
|
|
27552
28335
|
changes++;
|
|
27553
28336
|
return claudePath;
|
|
@@ -27614,9 +28397,9 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
|
27614
28397
|
let filesSkipped = 0;
|
|
27615
28398
|
const skippedFiles = [];
|
|
27616
28399
|
async function processDirectory(dir) {
|
|
27617
|
-
const entries = await
|
|
28400
|
+
const entries = await readdir5(dir, { withFileTypes: true });
|
|
27618
28401
|
for (const entry of entries) {
|
|
27619
|
-
const fullPath =
|
|
28402
|
+
const fullPath = join14(dir, entry.name);
|
|
27620
28403
|
if (entry.isDirectory()) {
|
|
27621
28404
|
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
27622
28405
|
continue;
|
|
@@ -27624,10 +28407,10 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
|
27624
28407
|
await processDirectory(fullPath);
|
|
27625
28408
|
} else if (entry.isFile() && shouldTransformFile(entry.name)) {
|
|
27626
28409
|
try {
|
|
27627
|
-
const content = await
|
|
28410
|
+
const content = await readFile8(fullPath, "utf-8");
|
|
27628
28411
|
const { transformed, changes } = transformContent(content);
|
|
27629
28412
|
if (changes > 0) {
|
|
27630
|
-
await
|
|
28413
|
+
await writeFile7(fullPath, transformed, "utf-8");
|
|
27631
28414
|
filesTransformed++;
|
|
27632
28415
|
totalChanges += changes;
|
|
27633
28416
|
if (options.verbose) {
|
|
@@ -27657,7 +28440,7 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
|
27657
28440
|
init_dist2();
|
|
27658
28441
|
var import_fs_extra6 = __toESM(require_lib(), 1);
|
|
27659
28442
|
var import_ignore2 = __toESM(require_ignore(), 1);
|
|
27660
|
-
import { dirname as
|
|
28443
|
+
import { dirname as dirname4, join as join15, relative as relative4 } from "node:path";
|
|
27661
28444
|
|
|
27662
28445
|
// node_modules/@isaacs/balanced-match/dist/esm/index.js
|
|
27663
28446
|
var balanced = (a3, b3, str) => {
|
|
@@ -29133,7 +29916,7 @@ class FileMerger {
|
|
|
29133
29916
|
for (const file of files) {
|
|
29134
29917
|
const relativePath = relative4(sourceDir, file);
|
|
29135
29918
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
29136
|
-
const destPath =
|
|
29919
|
+
const destPath = join15(destDir, relativePath);
|
|
29137
29920
|
if (await import_fs_extra6.pathExists(destPath)) {
|
|
29138
29921
|
if (this.neverCopyChecker.ignores(normalizedRelativePath)) {
|
|
29139
29922
|
logger.debug(`Security-sensitive file exists but won't be overwritten: ${normalizedRelativePath}`);
|
|
@@ -29155,7 +29938,7 @@ class FileMerger {
|
|
|
29155
29938
|
for (const file of files) {
|
|
29156
29939
|
const relativePath = relative4(sourceDir, file);
|
|
29157
29940
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
29158
|
-
const destPath =
|
|
29941
|
+
const destPath = join15(destDir, relativePath);
|
|
29159
29942
|
if (this.neverCopyChecker.ignores(normalizedRelativePath)) {
|
|
29160
29943
|
logger.debug(`Skipping security-sensitive file: ${normalizedRelativePath}`);
|
|
29161
29944
|
skippedCount++;
|
|
@@ -29225,7 +30008,7 @@ class FileMerger {
|
|
|
29225
30008
|
const files = [];
|
|
29226
30009
|
const entries = await import_fs_extra6.readdir(dir, { encoding: "utf8" });
|
|
29227
30010
|
for (const entry of entries) {
|
|
29228
|
-
const fullPath =
|
|
30011
|
+
const fullPath = join15(dir, entry);
|
|
29229
30012
|
const relativePath = relative4(baseDir, fullPath);
|
|
29230
30013
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
29231
30014
|
const stats = await import_fs_extra6.lstat(fullPath);
|
|
@@ -29276,10 +30059,10 @@ class FileMerger {
|
|
|
29276
30059
|
}
|
|
29277
30060
|
trackInstalledFile(relativePath) {
|
|
29278
30061
|
this.installedFiles.add(relativePath);
|
|
29279
|
-
let dir =
|
|
30062
|
+
let dir = dirname4(relativePath);
|
|
29280
30063
|
while (dir && dir !== "." && dir !== "/") {
|
|
29281
30064
|
this.installedDirectories.add(`${dir}/`);
|
|
29282
|
-
dir =
|
|
30065
|
+
dir = dirname4(dir);
|
|
29283
30066
|
}
|
|
29284
30067
|
}
|
|
29285
30068
|
}
|
|
@@ -29287,14 +30070,14 @@ class FileMerger {
|
|
|
29287
30070
|
// src/lib/migration/legacy-migration.ts
|
|
29288
30071
|
init_logger();
|
|
29289
30072
|
var import_fs_extra8 = __toESM(require_lib(), 1);
|
|
29290
|
-
import { readdir as
|
|
29291
|
-
import { join as
|
|
30073
|
+
import { readdir as readdir7, stat as stat3 } from "node:fs/promises";
|
|
30074
|
+
import { join as join17, relative as relative5 } from "node:path";
|
|
29292
30075
|
|
|
29293
30076
|
// src/lib/migration/release-manifest.ts
|
|
29294
30077
|
init_zod();
|
|
29295
30078
|
init_logger();
|
|
29296
30079
|
var import_fs_extra7 = __toESM(require_lib(), 1);
|
|
29297
|
-
import { join as
|
|
30080
|
+
import { join as join16 } from "node:path";
|
|
29298
30081
|
var ReleaseManifestFileSchema = exports_external.object({
|
|
29299
30082
|
path: exports_external.string(),
|
|
29300
30083
|
checksum: exports_external.string().regex(/^[a-f0-9]{64}$/),
|
|
@@ -29308,7 +30091,7 @@ var ReleaseManifestSchema = exports_external.object({
|
|
|
29308
30091
|
|
|
29309
30092
|
class ReleaseManifestLoader {
|
|
29310
30093
|
static async load(extractDir) {
|
|
29311
|
-
const manifestPath =
|
|
30094
|
+
const manifestPath = join16(extractDir, "release-manifest.json");
|
|
29312
30095
|
try {
|
|
29313
30096
|
const content = await import_fs_extra7.readFile(manifestPath, "utf-8");
|
|
29314
30097
|
const parsed = JSON.parse(content);
|
|
@@ -29339,7 +30122,7 @@ class LegacyMigration {
|
|
|
29339
30122
|
const files = [];
|
|
29340
30123
|
let entries;
|
|
29341
30124
|
try {
|
|
29342
|
-
entries = await
|
|
30125
|
+
entries = await readdir7(dir);
|
|
29343
30126
|
} catch (err) {
|
|
29344
30127
|
const error = err;
|
|
29345
30128
|
if (error.code === "ENOENT") {
|
|
@@ -29354,7 +30137,7 @@ class LegacyMigration {
|
|
|
29354
30137
|
for (const entry of entries) {
|
|
29355
30138
|
if (entry === "metadata.json")
|
|
29356
30139
|
continue;
|
|
29357
|
-
const fullPath =
|
|
30140
|
+
const fullPath = join17(dir, entry);
|
|
29358
30141
|
let stats;
|
|
29359
30142
|
try {
|
|
29360
30143
|
stats = await stat3(fullPath);
|
|
@@ -29456,7 +30239,7 @@ User-created files (sample):`);
|
|
|
29456
30239
|
];
|
|
29457
30240
|
if (filesToChecksum.length > 0) {
|
|
29458
30241
|
const checksumResults = await Promise.all(filesToChecksum.map(async ({ relativePath, ownership }) => {
|
|
29459
|
-
const fullPath =
|
|
30242
|
+
const fullPath = join17(claudeDir, relativePath);
|
|
29460
30243
|
const checksum = await OwnershipChecker.calculateChecksum(fullPath);
|
|
29461
30244
|
return { relativePath, checksum, ownership };
|
|
29462
30245
|
}));
|
|
@@ -29477,7 +30260,7 @@ User-created files (sample):`);
|
|
|
29477
30260
|
installedAt: new Date().toISOString(),
|
|
29478
30261
|
files: trackedFiles
|
|
29479
30262
|
};
|
|
29480
|
-
const metadataPath =
|
|
30263
|
+
const metadataPath = join17(claudeDir, "metadata.json");
|
|
29481
30264
|
await import_fs_extra8.writeFile(metadataPath, JSON.stringify(updatedMetadata, null, 2));
|
|
29482
30265
|
logger.success(`Migration complete: tracked ${trackedFiles.length} files`);
|
|
29483
30266
|
return true;
|
|
@@ -30086,11 +30869,11 @@ class PromptsManager {
|
|
|
30086
30869
|
init_dist2();
|
|
30087
30870
|
init_logger();
|
|
30088
30871
|
var import_fs_extra10 = __toESM(require_lib(), 1);
|
|
30089
|
-
import { join as
|
|
30872
|
+
import { join as join21 } from "node:path";
|
|
30090
30873
|
|
|
30091
30874
|
// src/lib/config-generator.ts
|
|
30092
30875
|
var import_fs_extra9 = __toESM(require_lib(), 1);
|
|
30093
|
-
import { join as
|
|
30876
|
+
import { join as join20 } from "node:path";
|
|
30094
30877
|
async function generateEnvFile(targetDir, values) {
|
|
30095
30878
|
const lines = [
|
|
30096
30879
|
"# Generated by ClaudeKit CLI setup wizard",
|
|
@@ -30102,7 +30885,7 @@ async function generateEnvFile(targetDir, values) {
|
|
|
30102
30885
|
lines.push(`${key}=${value}`);
|
|
30103
30886
|
}
|
|
30104
30887
|
}
|
|
30105
|
-
const envPath =
|
|
30888
|
+
const envPath = join20(targetDir, ".env");
|
|
30106
30889
|
await import_fs_extra9.writeFile(envPath, `${lines.join(`
|
|
30107
30890
|
`)}
|
|
30108
30891
|
`, { mode: 384 });
|
|
@@ -30173,7 +30956,7 @@ async function parseEnvFile(path9) {
|
|
|
30173
30956
|
}
|
|
30174
30957
|
}
|
|
30175
30958
|
async function checkGlobalConfig() {
|
|
30176
|
-
const globalEnvPath =
|
|
30959
|
+
const globalEnvPath = join21(PathResolver.getGlobalKitDir(), ".env");
|
|
30177
30960
|
if (!await import_fs_extra10.pathExists(globalEnvPath))
|
|
30178
30961
|
return false;
|
|
30179
30962
|
const env2 = await parseEnvFile(globalEnvPath);
|
|
@@ -30189,7 +30972,7 @@ async function runSetupWizard(options) {
|
|
|
30189
30972
|
let globalEnv = {};
|
|
30190
30973
|
const hasGlobalConfig = !isGlobal && await checkGlobalConfig();
|
|
30191
30974
|
if (!isGlobal) {
|
|
30192
|
-
const globalEnvPath =
|
|
30975
|
+
const globalEnvPath = join21(PathResolver.getGlobalKitDir(), ".env");
|
|
30193
30976
|
if (await import_fs_extra10.pathExists(globalEnvPath)) {
|
|
30194
30977
|
globalEnv = await parseEnvFile(globalEnvPath);
|
|
30195
30978
|
}
|
|
@@ -30242,23 +31025,23 @@ async function runSetupWizard(options) {
|
|
|
30242
31025
|
}
|
|
30243
31026
|
}
|
|
30244
31027
|
await generateEnvFile(targetDir, values);
|
|
30245
|
-
f2.success(`Configuration saved to ${
|
|
31028
|
+
f2.success(`Configuration saved to ${join21(targetDir, ".env")}`);
|
|
30246
31029
|
return true;
|
|
30247
31030
|
}
|
|
30248
31031
|
|
|
30249
31032
|
// src/lib/skills-detector.ts
|
|
30250
31033
|
init_logger();
|
|
30251
31034
|
var import_fs_extra12 = __toESM(require_lib(), 1);
|
|
30252
|
-
import { readdir as
|
|
30253
|
-
import { join as
|
|
31035
|
+
import { readdir as readdir9 } from "node:fs/promises";
|
|
31036
|
+
import { join as join23 } from "node:path";
|
|
30254
31037
|
|
|
30255
31038
|
// src/lib/skills-manifest.ts
|
|
30256
31039
|
init_types2();
|
|
30257
31040
|
init_logger();
|
|
30258
31041
|
var import_fs_extra11 = __toESM(require_lib(), 1);
|
|
30259
31042
|
import { createHash as createHash2 } from "node:crypto";
|
|
30260
|
-
import { readFile as
|
|
30261
|
-
import { join as
|
|
31043
|
+
import { readFile as readFile12, readdir as readdir8, writeFile as writeFile11 } from "node:fs/promises";
|
|
31044
|
+
import { join as join22, relative as relative6 } from "node:path";
|
|
30262
31045
|
|
|
30263
31046
|
class SkillsManifestManager {
|
|
30264
31047
|
static MANIFEST_FILENAME = ".skills-manifest.json";
|
|
@@ -30280,18 +31063,18 @@ class SkillsManifestManager {
|
|
|
30280
31063
|
return manifest;
|
|
30281
31064
|
}
|
|
30282
31065
|
static async writeManifest(skillsDir, manifest) {
|
|
30283
|
-
const manifestPath =
|
|
30284
|
-
await
|
|
31066
|
+
const manifestPath = join22(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
|
|
31067
|
+
await writeFile11(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
30285
31068
|
logger.debug(`Wrote manifest to: ${manifestPath}`);
|
|
30286
31069
|
}
|
|
30287
31070
|
static async readManifest(skillsDir) {
|
|
30288
|
-
const manifestPath =
|
|
31071
|
+
const manifestPath = join22(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
|
|
30289
31072
|
if (!await import_fs_extra11.pathExists(manifestPath)) {
|
|
30290
31073
|
logger.debug(`No manifest found at: ${manifestPath}`);
|
|
30291
31074
|
return null;
|
|
30292
31075
|
}
|
|
30293
31076
|
try {
|
|
30294
|
-
const content = await
|
|
31077
|
+
const content = await readFile12(manifestPath, "utf-8");
|
|
30295
31078
|
const data = JSON.parse(content);
|
|
30296
31079
|
const manifest = SkillsManifestSchema.parse(data);
|
|
30297
31080
|
logger.debug(`Read manifest from: ${manifestPath}`);
|
|
@@ -30302,14 +31085,14 @@ class SkillsManifestManager {
|
|
|
30302
31085
|
}
|
|
30303
31086
|
}
|
|
30304
31087
|
static async detectStructure(skillsDir) {
|
|
30305
|
-
const entries = await
|
|
31088
|
+
const entries = await readdir8(skillsDir, { withFileTypes: true });
|
|
30306
31089
|
const dirs = entries.filter((entry) => entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith("."));
|
|
30307
31090
|
if (dirs.length === 0) {
|
|
30308
31091
|
return "flat";
|
|
30309
31092
|
}
|
|
30310
31093
|
for (const dir of dirs.slice(0, 3)) {
|
|
30311
|
-
const dirPath =
|
|
30312
|
-
const subEntries = await
|
|
31094
|
+
const dirPath = join22(skillsDir, dir.name);
|
|
31095
|
+
const subEntries = await readdir8(dirPath, { withFileTypes: true });
|
|
30313
31096
|
const hasSubdirs = subEntries.some((entry) => entry.isDirectory());
|
|
30314
31097
|
if (hasSubdirs) {
|
|
30315
31098
|
return "categorized";
|
|
@@ -30324,10 +31107,10 @@ class SkillsManifestManager {
|
|
|
30324
31107
|
static async scanSkills(skillsDir, structure) {
|
|
30325
31108
|
const skills = [];
|
|
30326
31109
|
if (structure === "flat") {
|
|
30327
|
-
const entries = await
|
|
31110
|
+
const entries = await readdir8(skillsDir, { withFileTypes: true });
|
|
30328
31111
|
for (const entry of entries) {
|
|
30329
31112
|
if (entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith(".")) {
|
|
30330
|
-
const skillPath =
|
|
31113
|
+
const skillPath = join22(skillsDir, entry.name);
|
|
30331
31114
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
30332
31115
|
skills.push({
|
|
30333
31116
|
name: entry.name,
|
|
@@ -30336,14 +31119,14 @@ class SkillsManifestManager {
|
|
|
30336
31119
|
}
|
|
30337
31120
|
}
|
|
30338
31121
|
} else {
|
|
30339
|
-
const categories = await
|
|
31122
|
+
const categories = await readdir8(skillsDir, { withFileTypes: true });
|
|
30340
31123
|
for (const category of categories) {
|
|
30341
31124
|
if (category.isDirectory() && category.name !== "node_modules" && !category.name.startsWith(".")) {
|
|
30342
|
-
const categoryPath =
|
|
30343
|
-
const skillEntries = await
|
|
31125
|
+
const categoryPath = join22(skillsDir, category.name);
|
|
31126
|
+
const skillEntries = await readdir8(categoryPath, { withFileTypes: true });
|
|
30344
31127
|
for (const skillEntry of skillEntries) {
|
|
30345
31128
|
if (skillEntry.isDirectory() && !skillEntry.name.startsWith(".")) {
|
|
30346
|
-
const skillPath =
|
|
31129
|
+
const skillPath = join22(categoryPath, skillEntry.name);
|
|
30347
31130
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
30348
31131
|
skills.push({
|
|
30349
31132
|
name: skillEntry.name,
|
|
@@ -30363,7 +31146,7 @@ class SkillsManifestManager {
|
|
|
30363
31146
|
files.sort();
|
|
30364
31147
|
for (const file of files) {
|
|
30365
31148
|
const relativePath = relative6(dirPath, file);
|
|
30366
|
-
const content = await
|
|
31149
|
+
const content = await readFile12(file);
|
|
30367
31150
|
hash.update(relativePath);
|
|
30368
31151
|
hash.update(content);
|
|
30369
31152
|
}
|
|
@@ -30371,9 +31154,9 @@ class SkillsManifestManager {
|
|
|
30371
31154
|
}
|
|
30372
31155
|
static async getAllFiles(dirPath) {
|
|
30373
31156
|
const files = [];
|
|
30374
|
-
const entries = await
|
|
31157
|
+
const entries = await readdir8(dirPath, { withFileTypes: true });
|
|
30375
31158
|
for (const entry of entries) {
|
|
30376
|
-
const fullPath =
|
|
31159
|
+
const fullPath = join22(dirPath, entry.name);
|
|
30377
31160
|
if (entry.name.startsWith(".") || entry.name === "node_modules") {
|
|
30378
31161
|
continue;
|
|
30379
31162
|
}
|
|
@@ -30608,7 +31391,7 @@ class SkillsMigrationDetector {
|
|
|
30608
31391
|
if (!await import_fs_extra12.pathExists(skillsDir)) {
|
|
30609
31392
|
return ["flat", []];
|
|
30610
31393
|
}
|
|
30611
|
-
const entries = await
|
|
31394
|
+
const entries = await readdir9(skillsDir, { withFileTypes: true });
|
|
30612
31395
|
const dirs = entries.filter((entry) => entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith("."));
|
|
30613
31396
|
if (dirs.length === 0) {
|
|
30614
31397
|
return ["flat", []];
|
|
@@ -30616,13 +31399,13 @@ class SkillsMigrationDetector {
|
|
|
30616
31399
|
let totalSkillLikeCount = 0;
|
|
30617
31400
|
const allSkills = [];
|
|
30618
31401
|
for (const dir of dirs) {
|
|
30619
|
-
const dirPath =
|
|
30620
|
-
const subEntries = await
|
|
31402
|
+
const dirPath = join23(skillsDir, dir.name);
|
|
31403
|
+
const subEntries = await readdir9(dirPath, { withFileTypes: true });
|
|
30621
31404
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
30622
31405
|
if (subdirs.length > 0) {
|
|
30623
31406
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
30624
|
-
const subdirPath =
|
|
30625
|
-
const subdirFiles = await
|
|
31407
|
+
const subdirPath = join23(dirPath, subdir.name);
|
|
31408
|
+
const subdirFiles = await readdir9(subdirPath, { withFileTypes: true });
|
|
30626
31409
|
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"));
|
|
30627
31410
|
if (hasSkillMarker) {
|
|
30628
31411
|
totalSkillLikeCount++;
|
|
@@ -30659,21 +31442,21 @@ class SkillsMigrationDetector {
|
|
|
30659
31442
|
init_types2();
|
|
30660
31443
|
init_logger();
|
|
30661
31444
|
var import_fs_extra15 = __toESM(require_lib(), 1);
|
|
30662
|
-
import { copyFile as copyFile2, mkdir as
|
|
30663
|
-
import { join as
|
|
31445
|
+
import { copyFile as copyFile2, mkdir as mkdir8, readdir as readdir12, rm as rm2 } from "node:fs/promises";
|
|
31446
|
+
import { join as join26 } from "node:path";
|
|
30664
31447
|
|
|
30665
31448
|
// src/lib/skills-backup-manager.ts
|
|
30666
31449
|
init_types2();
|
|
30667
31450
|
init_logger();
|
|
30668
31451
|
var import_fs_extra13 = __toESM(require_lib(), 1);
|
|
30669
|
-
import { copyFile, mkdir as
|
|
30670
|
-
import { basename as basename2, join as
|
|
31452
|
+
import { copyFile, mkdir as mkdir7, readdir as readdir10, rm, stat as stat4 } from "node:fs/promises";
|
|
31453
|
+
import { basename as basename2, join as join24, normalize as normalize4 } from "node:path";
|
|
30671
31454
|
function validatePath2(path9, paramName) {
|
|
30672
31455
|
if (!path9 || typeof path9 !== "string") {
|
|
30673
31456
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
30674
31457
|
}
|
|
30675
31458
|
if (path9.includes("..")) {
|
|
30676
|
-
const normalized =
|
|
31459
|
+
const normalized = normalize4(path9);
|
|
30677
31460
|
if (normalized.startsWith("..")) {
|
|
30678
31461
|
throw new SkillsMigrationError(`${paramName} contains invalid path traversal: ${path9}`);
|
|
30679
31462
|
}
|
|
@@ -30693,10 +31476,10 @@ class SkillsBackupManager {
|
|
|
30693
31476
|
const timestamp = Date.now();
|
|
30694
31477
|
const randomSuffix = Math.random().toString(36).substring(2, 8);
|
|
30695
31478
|
const backupDirName = `${SkillsBackupManager.BACKUP_PREFIX}${timestamp}-${randomSuffix}`;
|
|
30696
|
-
const backupDir = parentDir ?
|
|
31479
|
+
const backupDir = parentDir ? join24(parentDir, backupDirName) : join24(skillsDir, "..", backupDirName);
|
|
30697
31480
|
logger.info(`Creating backup at: ${backupDir}`);
|
|
30698
31481
|
try {
|
|
30699
|
-
await
|
|
31482
|
+
await mkdir7(backupDir, { recursive: true });
|
|
30700
31483
|
await SkillsBackupManager.copyDirectory(skillsDir, backupDir);
|
|
30701
31484
|
logger.success("Backup created successfully");
|
|
30702
31485
|
return backupDir;
|
|
@@ -30718,7 +31501,7 @@ class SkillsBackupManager {
|
|
|
30718
31501
|
if (await import_fs_extra13.pathExists(targetDir)) {
|
|
30719
31502
|
await rm(targetDir, { recursive: true, force: true });
|
|
30720
31503
|
}
|
|
30721
|
-
await
|
|
31504
|
+
await mkdir7(targetDir, { recursive: true });
|
|
30722
31505
|
await SkillsBackupManager.copyDirectory(backupDir, targetDir);
|
|
30723
31506
|
logger.success("Backup restored successfully");
|
|
30724
31507
|
} catch (error) {
|
|
@@ -30743,8 +31526,8 @@ class SkillsBackupManager {
|
|
|
30743
31526
|
return [];
|
|
30744
31527
|
}
|
|
30745
31528
|
try {
|
|
30746
|
-
const entries = await
|
|
30747
|
-
const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) =>
|
|
31529
|
+
const entries = await readdir10(parentDir, { withFileTypes: true });
|
|
31530
|
+
const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) => join24(parentDir, entry.name));
|
|
30748
31531
|
backups.sort().reverse();
|
|
30749
31532
|
return backups;
|
|
30750
31533
|
} catch (error) {
|
|
@@ -30770,15 +31553,15 @@ class SkillsBackupManager {
|
|
|
30770
31553
|
return await SkillsBackupManager.getDirectorySize(backupDir);
|
|
30771
31554
|
}
|
|
30772
31555
|
static async copyDirectory(sourceDir, destDir) {
|
|
30773
|
-
const entries = await
|
|
31556
|
+
const entries = await readdir10(sourceDir, { withFileTypes: true });
|
|
30774
31557
|
for (const entry of entries) {
|
|
30775
|
-
const sourcePath =
|
|
30776
|
-
const destPath =
|
|
31558
|
+
const sourcePath = join24(sourceDir, entry.name);
|
|
31559
|
+
const destPath = join24(destDir, entry.name);
|
|
30777
31560
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
30778
31561
|
continue;
|
|
30779
31562
|
}
|
|
30780
31563
|
if (entry.isDirectory()) {
|
|
30781
|
-
await
|
|
31564
|
+
await mkdir7(destPath, { recursive: true });
|
|
30782
31565
|
await SkillsBackupManager.copyDirectory(sourcePath, destPath);
|
|
30783
31566
|
} else if (entry.isFile()) {
|
|
30784
31567
|
await copyFile(sourcePath, destPath);
|
|
@@ -30787,9 +31570,9 @@ class SkillsBackupManager {
|
|
|
30787
31570
|
}
|
|
30788
31571
|
static async getDirectorySize(dirPath) {
|
|
30789
31572
|
let size = 0;
|
|
30790
|
-
const entries = await
|
|
31573
|
+
const entries = await readdir10(dirPath, { withFileTypes: true });
|
|
30791
31574
|
for (const entry of entries) {
|
|
30792
|
-
const fullPath =
|
|
31575
|
+
const fullPath = join24(dirPath, entry.name);
|
|
30793
31576
|
if (entry.isSymbolicLink()) {
|
|
30794
31577
|
continue;
|
|
30795
31578
|
}
|
|
@@ -30819,14 +31602,14 @@ init_logger();
|
|
|
30819
31602
|
var import_fs_extra14 = __toESM(require_lib(), 1);
|
|
30820
31603
|
import { createHash as createHash3 } from "node:crypto";
|
|
30821
31604
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
30822
|
-
import { readFile as
|
|
30823
|
-
import { join as
|
|
31605
|
+
import { readFile as readFile13, readdir as readdir11 } from "node:fs/promises";
|
|
31606
|
+
import { join as join25, normalize as normalize5, relative as relative7 } from "node:path";
|
|
30824
31607
|
function validatePath3(path9, paramName) {
|
|
30825
31608
|
if (!path9 || typeof path9 !== "string") {
|
|
30826
31609
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
30827
31610
|
}
|
|
30828
31611
|
if (path9.includes("..")) {
|
|
30829
|
-
const normalized =
|
|
31612
|
+
const normalized = normalize5(path9);
|
|
30830
31613
|
if (normalized.startsWith("..")) {
|
|
30831
31614
|
throw new SkillsMigrationError(`${paramName} contains invalid path traversal: ${path9}`);
|
|
30832
31615
|
}
|
|
@@ -30962,19 +31745,19 @@ class SkillsCustomizationScanner {
|
|
|
30962
31745
|
if (!await import_fs_extra14.pathExists(skillsDir)) {
|
|
30963
31746
|
return ["flat", []];
|
|
30964
31747
|
}
|
|
30965
|
-
const entries = await
|
|
31748
|
+
const entries = await readdir11(skillsDir, { withFileTypes: true });
|
|
30966
31749
|
const dirs = entries.filter((entry) => entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith("."));
|
|
30967
31750
|
if (dirs.length === 0) {
|
|
30968
31751
|
return ["flat", []];
|
|
30969
31752
|
}
|
|
30970
|
-
const firstDirPath =
|
|
30971
|
-
const subEntries = await
|
|
31753
|
+
const firstDirPath = join25(skillsDir, dirs[0].name);
|
|
31754
|
+
const subEntries = await readdir11(firstDirPath, { withFileTypes: true });
|
|
30972
31755
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
30973
31756
|
if (subdirs.length > 0) {
|
|
30974
31757
|
let skillLikeCount = 0;
|
|
30975
31758
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
30976
|
-
const subdirPath =
|
|
30977
|
-
const subdirFiles = await
|
|
31759
|
+
const subdirPath = join25(firstDirPath, subdir.name);
|
|
31760
|
+
const subdirFiles = await readdir11(subdirPath, { withFileTypes: true });
|
|
30978
31761
|
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"));
|
|
30979
31762
|
if (hasSkillMarker) {
|
|
30980
31763
|
skillLikeCount++;
|
|
@@ -30983,8 +31766,8 @@ class SkillsCustomizationScanner {
|
|
|
30983
31766
|
if (skillLikeCount > 0) {
|
|
30984
31767
|
const skills = [];
|
|
30985
31768
|
for (const dir of dirs) {
|
|
30986
|
-
const categoryPath =
|
|
30987
|
-
const skillDirs = await
|
|
31769
|
+
const categoryPath = join25(skillsDir, dir.name);
|
|
31770
|
+
const skillDirs = await readdir11(categoryPath, { withFileTypes: true });
|
|
30988
31771
|
skills.push(...skillDirs.filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name));
|
|
30989
31772
|
}
|
|
30990
31773
|
return ["categorized", skills];
|
|
@@ -30993,17 +31776,17 @@ class SkillsCustomizationScanner {
|
|
|
30993
31776
|
return ["flat", dirs.map((dir) => dir.name)];
|
|
30994
31777
|
}
|
|
30995
31778
|
static async findSkillPath(skillsDir, skillName) {
|
|
30996
|
-
const flatPath =
|
|
31779
|
+
const flatPath = join25(skillsDir, skillName);
|
|
30997
31780
|
if (await import_fs_extra14.pathExists(flatPath)) {
|
|
30998
31781
|
return { path: flatPath, category: undefined };
|
|
30999
31782
|
}
|
|
31000
|
-
const entries = await
|
|
31783
|
+
const entries = await readdir11(skillsDir, { withFileTypes: true });
|
|
31001
31784
|
for (const entry of entries) {
|
|
31002
31785
|
if (!entry.isDirectory() || entry.name.startsWith(".") || entry.name === "node_modules") {
|
|
31003
31786
|
continue;
|
|
31004
31787
|
}
|
|
31005
|
-
const categoryPath =
|
|
31006
|
-
const skillPath =
|
|
31788
|
+
const categoryPath = join25(skillsDir, entry.name);
|
|
31789
|
+
const skillPath = join25(categoryPath, skillName);
|
|
31007
31790
|
if (await import_fs_extra14.pathExists(skillPath)) {
|
|
31008
31791
|
return { path: skillPath, category: entry.name };
|
|
31009
31792
|
}
|
|
@@ -31012,9 +31795,9 @@ class SkillsCustomizationScanner {
|
|
|
31012
31795
|
}
|
|
31013
31796
|
static async getAllFiles(dirPath) {
|
|
31014
31797
|
const files = [];
|
|
31015
|
-
const entries = await
|
|
31798
|
+
const entries = await readdir11(dirPath, { withFileTypes: true });
|
|
31016
31799
|
for (const entry of entries) {
|
|
31017
|
-
const fullPath =
|
|
31800
|
+
const fullPath = join25(dirPath, entry.name);
|
|
31018
31801
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
31019
31802
|
continue;
|
|
31020
31803
|
}
|
|
@@ -31028,12 +31811,12 @@ class SkillsCustomizationScanner {
|
|
|
31028
31811
|
return files;
|
|
31029
31812
|
}
|
|
31030
31813
|
static async hashFile(filePath) {
|
|
31031
|
-
return new Promise((
|
|
31814
|
+
return new Promise((resolve4, reject) => {
|
|
31032
31815
|
const hash = createHash3("sha256");
|
|
31033
31816
|
const stream = createReadStream2(filePath);
|
|
31034
31817
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
31035
31818
|
stream.on("end", () => {
|
|
31036
|
-
|
|
31819
|
+
resolve4(hash.digest("hex"));
|
|
31037
31820
|
});
|
|
31038
31821
|
stream.on("error", (error) => {
|
|
31039
31822
|
stream.destroy();
|
|
@@ -31047,7 +31830,7 @@ class SkillsCustomizationScanner {
|
|
|
31047
31830
|
files.sort();
|
|
31048
31831
|
for (const file of files) {
|
|
31049
31832
|
const relativePath = relative7(dirPath, file);
|
|
31050
|
-
const content = await
|
|
31833
|
+
const content = await readFile13(file);
|
|
31051
31834
|
hash.update(relativePath);
|
|
31052
31835
|
hash.update(content);
|
|
31053
31836
|
}
|
|
@@ -31257,7 +32040,7 @@ class SkillsMigrator {
|
|
|
31257
32040
|
}
|
|
31258
32041
|
}
|
|
31259
32042
|
if (options.backup && !options.dryRun) {
|
|
31260
|
-
const claudeDir =
|
|
32043
|
+
const claudeDir = join26(currentSkillsDir, "..");
|
|
31261
32044
|
result.backupPath = await SkillsBackupManager.createBackup(currentSkillsDir, claudeDir);
|
|
31262
32045
|
logger.success(`Backup created at: ${result.backupPath}`);
|
|
31263
32046
|
}
|
|
@@ -31309,8 +32092,8 @@ class SkillsMigrator {
|
|
|
31309
32092
|
const migrated = [];
|
|
31310
32093
|
const preserved = [];
|
|
31311
32094
|
const errors2 = [];
|
|
31312
|
-
const tempDir =
|
|
31313
|
-
await
|
|
32095
|
+
const tempDir = join26(currentSkillsDir, "..", ".skills-migration-temp");
|
|
32096
|
+
await mkdir8(tempDir, { recursive: true });
|
|
31314
32097
|
try {
|
|
31315
32098
|
for (const mapping of mappings) {
|
|
31316
32099
|
try {
|
|
@@ -31330,9 +32113,9 @@ class SkillsMigrator {
|
|
|
31330
32113
|
}
|
|
31331
32114
|
}
|
|
31332
32115
|
const category = mapping.category;
|
|
31333
|
-
const targetPath = category ?
|
|
32116
|
+
const targetPath = category ? join26(tempDir, category, skillName) : join26(tempDir, skillName);
|
|
31334
32117
|
if (category) {
|
|
31335
|
-
await
|
|
32118
|
+
await mkdir8(join26(tempDir, category), { recursive: true });
|
|
31336
32119
|
}
|
|
31337
32120
|
await SkillsMigrator.copySkillDirectory(currentSkillPath, targetPath);
|
|
31338
32121
|
migrated.push(skillName);
|
|
@@ -31351,7 +32134,7 @@ class SkillsMigrator {
|
|
|
31351
32134
|
}
|
|
31352
32135
|
}
|
|
31353
32136
|
await rm2(currentSkillsDir, { recursive: true, force: true });
|
|
31354
|
-
await
|
|
32137
|
+
await mkdir8(currentSkillsDir, { recursive: true });
|
|
31355
32138
|
await SkillsMigrator.copySkillDirectory(tempDir, currentSkillsDir);
|
|
31356
32139
|
await rm2(tempDir, { recursive: true, force: true });
|
|
31357
32140
|
return { migrated, preserved, errors: errors2 };
|
|
@@ -31363,11 +32146,11 @@ class SkillsMigrator {
|
|
|
31363
32146
|
}
|
|
31364
32147
|
}
|
|
31365
32148
|
static async copySkillDirectory(sourceDir, destDir) {
|
|
31366
|
-
await
|
|
31367
|
-
const entries = await
|
|
32149
|
+
await mkdir8(destDir, { recursive: true });
|
|
32150
|
+
const entries = await readdir12(sourceDir, { withFileTypes: true });
|
|
31368
32151
|
for (const entry of entries) {
|
|
31369
|
-
const sourcePath =
|
|
31370
|
-
const destPath =
|
|
32152
|
+
const sourcePath = join26(sourceDir, entry.name);
|
|
32153
|
+
const destPath = join26(destDir, entry.name);
|
|
31371
32154
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
31372
32155
|
continue;
|
|
31373
32156
|
}
|
|
@@ -31387,17 +32170,17 @@ init_types2();
|
|
|
31387
32170
|
init_types2();
|
|
31388
32171
|
init_logger();
|
|
31389
32172
|
import { existsSync as existsSync6 } from "node:fs";
|
|
31390
|
-
import { mkdir as
|
|
32173
|
+
import { mkdir as mkdir9, readFile as readFile14, rename as rename2, rm as rm3, writeFile as writeFile12 } from "node:fs/promises";
|
|
31391
32174
|
import { chmod as chmod2 } from "node:fs/promises";
|
|
31392
|
-
import { platform as
|
|
31393
|
-
import { join as
|
|
32175
|
+
import { platform as platform9 } from "node:os";
|
|
32176
|
+
import { join as join27 } from "node:path";
|
|
31394
32177
|
var PROJECT_CONFIG_FILE = ".ck.json";
|
|
31395
32178
|
|
|
31396
32179
|
class ConfigManager {
|
|
31397
32180
|
static config = null;
|
|
31398
32181
|
static globalFlag = false;
|
|
31399
32182
|
static getProjectConfigDir(projectDir, global3) {
|
|
31400
|
-
return global3 ? projectDir :
|
|
32183
|
+
return global3 ? projectDir : join27(projectDir, ".claude");
|
|
31401
32184
|
}
|
|
31402
32185
|
static setGlobalFlag(global3) {
|
|
31403
32186
|
ConfigManager.globalFlag = global3;
|
|
@@ -31413,7 +32196,7 @@ class ConfigManager {
|
|
|
31413
32196
|
const configFile = PathResolver.getConfigFile(ConfigManager.globalFlag);
|
|
31414
32197
|
try {
|
|
31415
32198
|
if (existsSync6(configFile)) {
|
|
31416
|
-
const content = await
|
|
32199
|
+
const content = await readFile14(configFile, "utf-8");
|
|
31417
32200
|
const data = JSON.parse(content);
|
|
31418
32201
|
ConfigManager.config = ConfigSchema.parse(data);
|
|
31419
32202
|
logger.debug(`Config loaded from ${configFile}`);
|
|
@@ -31431,13 +32214,13 @@ class ConfigManager {
|
|
|
31431
32214
|
const configDir = PathResolver.getConfigDir(ConfigManager.globalFlag);
|
|
31432
32215
|
const configFile = PathResolver.getConfigFile(ConfigManager.globalFlag);
|
|
31433
32216
|
if (!existsSync6(configDir)) {
|
|
31434
|
-
await
|
|
31435
|
-
if (
|
|
32217
|
+
await mkdir9(configDir, { recursive: true });
|
|
32218
|
+
if (platform9() !== "win32") {
|
|
31436
32219
|
await chmod2(configDir, 448);
|
|
31437
32220
|
}
|
|
31438
32221
|
}
|
|
31439
|
-
await
|
|
31440
|
-
if (
|
|
32222
|
+
await writeFile12(configFile, JSON.stringify(validConfig, null, 2), "utf-8");
|
|
32223
|
+
if (platform9() !== "win32") {
|
|
31441
32224
|
await chmod2(configFile, 384);
|
|
31442
32225
|
}
|
|
31443
32226
|
ConfigManager.config = validConfig;
|
|
@@ -31464,10 +32247,10 @@ class ConfigManager {
|
|
|
31464
32247
|
}
|
|
31465
32248
|
static async loadProjectConfig(projectDir, global3 = false) {
|
|
31466
32249
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
31467
|
-
const configPath =
|
|
32250
|
+
const configPath = join27(configDir, PROJECT_CONFIG_FILE);
|
|
31468
32251
|
try {
|
|
31469
32252
|
if (existsSync6(configPath)) {
|
|
31470
|
-
const content = await
|
|
32253
|
+
const content = await readFile14(configPath, "utf-8");
|
|
31471
32254
|
const data = JSON.parse(content);
|
|
31472
32255
|
const folders = FoldersConfigSchema.parse(data.paths || data);
|
|
31473
32256
|
logger.debug(`Project config loaded from ${configPath}`);
|
|
@@ -31480,13 +32263,13 @@ class ConfigManager {
|
|
|
31480
32263
|
}
|
|
31481
32264
|
static async saveProjectConfig(projectDir, folders, global3 = false) {
|
|
31482
32265
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
31483
|
-
const configPath =
|
|
32266
|
+
const configPath = join27(configDir, PROJECT_CONFIG_FILE);
|
|
31484
32267
|
try {
|
|
31485
32268
|
if (!existsSync6(configDir)) {
|
|
31486
|
-
await
|
|
32269
|
+
await mkdir9(configDir, { recursive: true });
|
|
31487
32270
|
}
|
|
31488
32271
|
const validFolders = FoldersConfigSchema.parse(folders);
|
|
31489
|
-
await
|
|
32272
|
+
await writeFile12(configPath, JSON.stringify({ paths: validFolders }, null, 2), "utf-8");
|
|
31490
32273
|
logger.debug(`Project config saved to ${configPath}`);
|
|
31491
32274
|
} catch (error) {
|
|
31492
32275
|
throw new Error(`Failed to save project config: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
@@ -31512,11 +32295,11 @@ class ConfigManager {
|
|
|
31512
32295
|
}
|
|
31513
32296
|
static projectConfigExists(projectDir, global3 = false) {
|
|
31514
32297
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
31515
|
-
return existsSync6(
|
|
32298
|
+
return existsSync6(join27(configDir, PROJECT_CONFIG_FILE));
|
|
31516
32299
|
}
|
|
31517
32300
|
static async migrateNestedConfig(globalDir) {
|
|
31518
|
-
const correctPath =
|
|
31519
|
-
const incorrectPath =
|
|
32301
|
+
const correctPath = join27(globalDir, PROJECT_CONFIG_FILE);
|
|
32302
|
+
const incorrectPath = join27(globalDir, ".claude", PROJECT_CONFIG_FILE);
|
|
31520
32303
|
if (existsSync6(correctPath)) {
|
|
31521
32304
|
logger.debug("Config already exists at correct location, skipping migration");
|
|
31522
32305
|
return false;
|
|
@@ -31526,7 +32309,7 @@ class ConfigManager {
|
|
|
31526
32309
|
logger.info("Migrating .ck.json from nested location to correct location...");
|
|
31527
32310
|
await rename2(incorrectPath, correctPath);
|
|
31528
32311
|
logger.success(`Migrated ${PROJECT_CONFIG_FILE} to ${correctPath}`);
|
|
31529
|
-
const nestedClaudeDir =
|
|
32312
|
+
const nestedClaudeDir = join27(globalDir, ".claude");
|
|
31530
32313
|
try {
|
|
31531
32314
|
await rm3(nestedClaudeDir, { recursive: false });
|
|
31532
32315
|
logger.debug("Removed empty nested .claude directory");
|
|
@@ -31549,8 +32332,8 @@ init_environment();
|
|
|
31549
32332
|
// src/utils/file-scanner.ts
|
|
31550
32333
|
init_logger();
|
|
31551
32334
|
var import_fs_extra16 = __toESM(require_lib(), 1);
|
|
31552
|
-
import { join as
|
|
31553
|
-
var
|
|
32335
|
+
import { join as join28, relative as relative8, resolve as resolve4 } from "node:path";
|
|
32336
|
+
var SKIP_DIRS2 = [
|
|
31554
32337
|
"node_modules",
|
|
31555
32338
|
".venv",
|
|
31556
32339
|
"venv",
|
|
@@ -31559,7 +32342,15 @@ var SKIP_DIRS = [
|
|
|
31559
32342
|
".git",
|
|
31560
32343
|
".svn",
|
|
31561
32344
|
"dist",
|
|
31562
|
-
"build"
|
|
32345
|
+
"build",
|
|
32346
|
+
"debug",
|
|
32347
|
+
"projects",
|
|
32348
|
+
"shell-snapshots",
|
|
32349
|
+
"file-history",
|
|
32350
|
+
"todos",
|
|
32351
|
+
"session-env",
|
|
32352
|
+
"statsig",
|
|
32353
|
+
".anthropic"
|
|
31563
32354
|
];
|
|
31564
32355
|
|
|
31565
32356
|
class FileScanner {
|
|
@@ -31572,11 +32363,11 @@ class FileScanner {
|
|
|
31572
32363
|
try {
|
|
31573
32364
|
const entries = await import_fs_extra16.readdir(dirPath, { encoding: "utf8" });
|
|
31574
32365
|
for (const entry of entries) {
|
|
31575
|
-
if (
|
|
32366
|
+
if (SKIP_DIRS2.includes(entry)) {
|
|
31576
32367
|
logger.debug(`Skipping directory: ${entry}`);
|
|
31577
32368
|
continue;
|
|
31578
32369
|
}
|
|
31579
|
-
const fullPath =
|
|
32370
|
+
const fullPath = join28(dirPath, entry);
|
|
31580
32371
|
if (!FileScanner.isSafePath(basePath, fullPath)) {
|
|
31581
32372
|
logger.warning(`Skipping potentially unsafe path: ${entry}`);
|
|
31582
32373
|
continue;
|
|
@@ -31611,8 +32402,8 @@ class FileScanner {
|
|
|
31611
32402
|
return files;
|
|
31612
32403
|
}
|
|
31613
32404
|
static async findCustomFiles(destDir, sourceDir, subPath) {
|
|
31614
|
-
const destSubDir =
|
|
31615
|
-
const sourceSubDir =
|
|
32405
|
+
const destSubDir = join28(destDir, subPath);
|
|
32406
|
+
const sourceSubDir = join28(sourceDir, subPath);
|
|
31616
32407
|
logger.debug(`findCustomFiles - destDir: ${destDir}`);
|
|
31617
32408
|
logger.debug(`findCustomFiles - sourceDir: ${sourceDir}`);
|
|
31618
32409
|
logger.debug(`findCustomFiles - subPath: "${subPath}"`);
|
|
@@ -31640,8 +32431,8 @@ class FileScanner {
|
|
|
31640
32431
|
return customFiles;
|
|
31641
32432
|
}
|
|
31642
32433
|
static isSafePath(basePath, targetPath) {
|
|
31643
|
-
const resolvedBase =
|
|
31644
|
-
const resolvedTarget =
|
|
32434
|
+
const resolvedBase = resolve4(basePath);
|
|
32435
|
+
const resolvedTarget = resolve4(targetPath);
|
|
31645
32436
|
return resolvedTarget.startsWith(resolvedBase);
|
|
31646
32437
|
}
|
|
31647
32438
|
static toPosixPath(path9) {
|
|
@@ -31667,9 +32458,9 @@ async function initCommand(options) {
|
|
|
31667
32458
|
}
|
|
31668
32459
|
if (validOptions.global) {
|
|
31669
32460
|
const globalKitDir = PathResolver.getGlobalKitDir();
|
|
31670
|
-
const cwdResolved =
|
|
31671
|
-
const isInGlobalDir = cwdResolved === globalKitDir || cwdResolved ===
|
|
31672
|
-
const localSettingsPath =
|
|
32461
|
+
const cwdResolved = resolve5(process.cwd());
|
|
32462
|
+
const isInGlobalDir = cwdResolved === globalKitDir || cwdResolved === resolve5(globalKitDir, "..");
|
|
32463
|
+
const localSettingsPath = join29(process.cwd(), ".claude", "settings.json");
|
|
31673
32464
|
if (!isInGlobalDir && await import_fs_extra17.pathExists(localSettingsPath)) {
|
|
31674
32465
|
if (isNonInteractive2) {
|
|
31675
32466
|
logger.warning("Local .claude/settings.json detected. Local settings take precedence over global.");
|
|
@@ -31681,7 +32472,7 @@ async function initCommand(options) {
|
|
|
31681
32472
|
return;
|
|
31682
32473
|
}
|
|
31683
32474
|
if (choice === "remove") {
|
|
31684
|
-
const localClaudeDir =
|
|
32475
|
+
const localClaudeDir = join29(process.cwd(), ".claude");
|
|
31685
32476
|
try {
|
|
31686
32477
|
await import_fs_extra17.remove(localClaudeDir);
|
|
31687
32478
|
logger.success("Removed local .claude/ directory");
|
|
@@ -31725,12 +32516,12 @@ async function initCommand(options) {
|
|
|
31725
32516
|
}
|
|
31726
32517
|
}
|
|
31727
32518
|
}
|
|
31728
|
-
const resolvedDir =
|
|
32519
|
+
const resolvedDir = resolve5(targetDir);
|
|
31729
32520
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
31730
32521
|
if (!await import_fs_extra17.pathExists(resolvedDir)) {
|
|
31731
32522
|
if (validOptions.global) {
|
|
31732
|
-
const { mkdir:
|
|
31733
|
-
await
|
|
32523
|
+
const { mkdir: mkdir10 } = await import("node:fs/promises");
|
|
32524
|
+
await mkdir10(resolvedDir, { recursive: true });
|
|
31734
32525
|
logger.info(`Created global directory: ${resolvedDir}`);
|
|
31735
32526
|
} else {
|
|
31736
32527
|
logger.error(`Directory does not exist: ${resolvedDir}`);
|
|
@@ -31740,7 +32531,7 @@ async function initCommand(options) {
|
|
|
31740
32531
|
}
|
|
31741
32532
|
if (validOptions.fresh) {
|
|
31742
32533
|
const prefix = PathResolver.getPathPrefix(validOptions.global);
|
|
31743
|
-
const claudeDir2 = prefix ?
|
|
32534
|
+
const claudeDir2 = prefix ? join29(resolvedDir, prefix) : resolvedDir;
|
|
31744
32535
|
const canProceed = await handleFreshInstallation(claudeDir2, prompts);
|
|
31745
32536
|
if (!canProceed) {
|
|
31746
32537
|
return;
|
|
@@ -31877,7 +32668,7 @@ async function initCommand(options) {
|
|
|
31877
32668
|
}
|
|
31878
32669
|
}
|
|
31879
32670
|
if (!validOptions.fresh) {
|
|
31880
|
-
const newSkillsDir =
|
|
32671
|
+
const newSkillsDir = join29(extractDir, ".claude", "skills");
|
|
31881
32672
|
const currentSkillsDir = PathResolver.buildSkillsPath(resolvedDir, validOptions.global);
|
|
31882
32673
|
if (await import_fs_extra17.pathExists(newSkillsDir) && await import_fs_extra17.pathExists(currentSkillsDir)) {
|
|
31883
32674
|
logger.info("Checking for skills directory migration...");
|
|
@@ -31902,7 +32693,7 @@ async function initCommand(options) {
|
|
|
31902
32693
|
let customClaudeFiles = [];
|
|
31903
32694
|
if (!validOptions.fresh) {
|
|
31904
32695
|
logger.info("Scanning for custom .claude files...");
|
|
31905
|
-
const scanSourceDir = validOptions.global ?
|
|
32696
|
+
const scanSourceDir = validOptions.global ? join29(extractDir, ".claude") : extractDir;
|
|
31906
32697
|
const scanTargetSubdir = validOptions.global ? "" : ".claude";
|
|
31907
32698
|
customClaudeFiles = await FileScanner.findCustomFiles(resolvedDir, scanSourceDir, scanTargetSubdir);
|
|
31908
32699
|
} else {
|
|
@@ -31931,7 +32722,7 @@ async function initCommand(options) {
|
|
|
31931
32722
|
merger.addIgnorePatterns(validOptions.exclude);
|
|
31932
32723
|
}
|
|
31933
32724
|
merger.setGlobalFlag(validOptions.global);
|
|
31934
|
-
const claudeDir = validOptions.global ? resolvedDir :
|
|
32725
|
+
const claudeDir = validOptions.global ? resolvedDir : join29(resolvedDir, ".claude");
|
|
31935
32726
|
const releaseManifest = await ReleaseManifestLoader.load(extractDir);
|
|
31936
32727
|
if (!validOptions.fresh && await import_fs_extra17.pathExists(claudeDir)) {
|
|
31937
32728
|
const legacyDetection = await LegacyMigration.detectLegacy(claudeDir);
|
|
@@ -31953,7 +32744,7 @@ async function initCommand(options) {
|
|
|
31953
32744
|
return;
|
|
31954
32745
|
}
|
|
31955
32746
|
}
|
|
31956
|
-
const sourceDir = validOptions.global ?
|
|
32747
|
+
const sourceDir = validOptions.global ? join29(extractDir, ".claude") : extractDir;
|
|
31957
32748
|
await merger.merge(sourceDir, resolvedDir, false);
|
|
31958
32749
|
const manifestWriter = new ManifestWriter;
|
|
31959
32750
|
const installedFiles = merger.getAllInstalledFiles();
|
|
@@ -31962,7 +32753,7 @@ async function initCommand(options) {
|
|
|
31962
32753
|
if (!validOptions.global && !installedPath.startsWith(".claude/"))
|
|
31963
32754
|
continue;
|
|
31964
32755
|
const relativePath = validOptions.global ? installedPath : installedPath.replace(/^\.claude\//, "");
|
|
31965
|
-
const filePath =
|
|
32756
|
+
const filePath = join29(claudeDir, relativePath);
|
|
31966
32757
|
const manifestEntry = releaseManifest ? ReleaseManifestLoader.findFile(releaseManifest, installedPath) : null;
|
|
31967
32758
|
const ownership = manifestEntry ? "ck" : "user";
|
|
31968
32759
|
filesToTrack.push({
|
|
@@ -31983,8 +32774,8 @@ async function initCommand(options) {
|
|
|
31983
32774
|
trackingSpinner.succeed(`Tracked ${trackResult.success} files`);
|
|
31984
32775
|
await manifestWriter.writeManifest(claudeDir, kitConfig.name, release.tag_name, validOptions.global ? "global" : "local");
|
|
31985
32776
|
if (validOptions.global) {
|
|
31986
|
-
const claudeMdSource =
|
|
31987
|
-
const claudeMdDest =
|
|
32777
|
+
const claudeMdSource = join29(extractDir, "CLAUDE.md");
|
|
32778
|
+
const claudeMdDest = join29(resolvedDir, "CLAUDE.md");
|
|
31988
32779
|
if (await import_fs_extra17.pathExists(claudeMdSource)) {
|
|
31989
32780
|
if (!await import_fs_extra17.pathExists(claudeMdDest)) {
|
|
31990
32781
|
await import_fs_extra17.copy(claudeMdSource, claudeMdDest);
|
|
@@ -32004,7 +32795,7 @@ async function initCommand(options) {
|
|
|
32004
32795
|
await handleSkillsInstallation2(skillsDir);
|
|
32005
32796
|
}
|
|
32006
32797
|
if (!validOptions.skipSetup && !isNonInteractive2) {
|
|
32007
|
-
const envPath =
|
|
32798
|
+
const envPath = join29(claudeDir, ".env");
|
|
32008
32799
|
if (!await import_fs_extra17.pathExists(envPath)) {
|
|
32009
32800
|
const shouldSetup = await prompts.confirm("Set up API keys now? (Gemini API key for ai-multimodal skill, optional webhooks)");
|
|
32010
32801
|
if (shouldSetup) {
|
|
@@ -32036,7 +32827,7 @@ Protected files (.env, etc.) were not modified.`;
|
|
|
32036
32827
|
|
|
32037
32828
|
// src/commands/new.ts
|
|
32038
32829
|
var import_fs_extra18 = __toESM(require_lib(), 1);
|
|
32039
|
-
import { join as
|
|
32830
|
+
import { join as join30, resolve as resolve6 } from "node:path";
|
|
32040
32831
|
init_types2();
|
|
32041
32832
|
init_environment();
|
|
32042
32833
|
init_logger();
|
|
@@ -32065,7 +32856,7 @@ async function newCommand(options) {
|
|
|
32065
32856
|
targetDir = await prompts.getDirectory(targetDir);
|
|
32066
32857
|
}
|
|
32067
32858
|
}
|
|
32068
|
-
const resolvedDir =
|
|
32859
|
+
const resolvedDir = resolve6(targetDir);
|
|
32069
32860
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
32070
32861
|
if (await import_fs_extra18.pathExists(resolvedDir)) {
|
|
32071
32862
|
const files = await import_fs_extra18.readdir(resolvedDir);
|
|
@@ -32207,7 +32998,7 @@ async function newCommand(options) {
|
|
|
32207
32998
|
await CommandsPrefix.cleanupCommandsDirectory(resolvedDir, false);
|
|
32208
32999
|
}
|
|
32209
33000
|
await merger.merge(extractDir, resolvedDir, true);
|
|
32210
|
-
const claudeDir =
|
|
33001
|
+
const claudeDir = join30(resolvedDir, ".claude");
|
|
32211
33002
|
const manifestWriter = new ManifestWriter;
|
|
32212
33003
|
const releaseManifest = await ReleaseManifestLoader.load(extractDir);
|
|
32213
33004
|
const installedFiles = merger.getAllInstalledFiles();
|
|
@@ -32216,7 +33007,7 @@ async function newCommand(options) {
|
|
|
32216
33007
|
if (!installedPath.startsWith(".claude/"))
|
|
32217
33008
|
continue;
|
|
32218
33009
|
const relativePath = installedPath.replace(/^\.claude\//, "");
|
|
32219
|
-
const filePath =
|
|
33010
|
+
const filePath = join30(claudeDir, relativePath);
|
|
32220
33011
|
const manifestEntry = releaseManifest ? ReleaseManifestLoader.findFile(releaseManifest, installedPath) : null;
|
|
32221
33012
|
const ownership = manifestEntry ? "ck" : "user";
|
|
32222
33013
|
filesToTrack.push({
|
|
@@ -32272,7 +33063,7 @@ init_dist2();
|
|
|
32272
33063
|
var import_fs_extra19 = __toESM(require_lib(), 1);
|
|
32273
33064
|
var import_picocolors10 = __toESM(require_picocolors(), 1);
|
|
32274
33065
|
import { readdirSync, rmSync } from "node:fs";
|
|
32275
|
-
import { dirname as
|
|
33066
|
+
import { dirname as dirname5, join as join31 } from "node:path";
|
|
32276
33067
|
init_types2();
|
|
32277
33068
|
init_logger();
|
|
32278
33069
|
async function detectInstallations() {
|
|
@@ -32332,7 +33123,7 @@ async function confirmUninstall(scope) {
|
|
|
32332
33123
|
}
|
|
32333
33124
|
async function cleanupEmptyDirectories(filePath, installationRoot) {
|
|
32334
33125
|
let cleaned = 0;
|
|
32335
|
-
let currentDir =
|
|
33126
|
+
let currentDir = dirname5(filePath);
|
|
32336
33127
|
while (currentDir !== installationRoot && currentDir.startsWith(installationRoot)) {
|
|
32337
33128
|
try {
|
|
32338
33129
|
const entries = readdirSync(currentDir);
|
|
@@ -32340,7 +33131,7 @@ async function cleanupEmptyDirectories(filePath, installationRoot) {
|
|
|
32340
33131
|
rmSync(currentDir, { recursive: true });
|
|
32341
33132
|
cleaned++;
|
|
32342
33133
|
logger.debug(`Removed empty directory: ${currentDir}`);
|
|
32343
|
-
currentDir =
|
|
33134
|
+
currentDir = dirname5(currentDir);
|
|
32344
33135
|
} else {
|
|
32345
33136
|
break;
|
|
32346
33137
|
}
|
|
@@ -32363,7 +33154,7 @@ async function analyzeInstallation(installation, forceOverwrite) {
|
|
|
32363
33154
|
return result;
|
|
32364
33155
|
}
|
|
32365
33156
|
for (const trackedFile of metadata.files) {
|
|
32366
|
-
const filePath =
|
|
33157
|
+
const filePath = join31(installation.path, trackedFile.path);
|
|
32367
33158
|
const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
|
|
32368
33159
|
if (!ownershipResult.exists)
|
|
32369
33160
|
continue;
|
|
@@ -32421,7 +33212,7 @@ async function removeInstallations(installations, options) {
|
|
|
32421
33212
|
let removedCount = 0;
|
|
32422
33213
|
let cleanedDirs = 0;
|
|
32423
33214
|
for (const item of analysis.toDelete) {
|
|
32424
|
-
const filePath =
|
|
33215
|
+
const filePath = join31(installation.path, item.path);
|
|
32425
33216
|
if (await import_fs_extra19.pathExists(filePath)) {
|
|
32426
33217
|
await import_fs_extra19.remove(filePath);
|
|
32427
33218
|
removedCount++;
|
|
@@ -32523,7 +33314,7 @@ import { promisify as promisify6 } from "node:util";
|
|
|
32523
33314
|
// package.json
|
|
32524
33315
|
var package_default2 = {
|
|
32525
33316
|
name: "claudekit-cli",
|
|
32526
|
-
version: "3.
|
|
33317
|
+
version: "3.7.0",
|
|
32527
33318
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
32528
33319
|
type: "module",
|
|
32529
33320
|
repository: {
|
|
@@ -32969,14 +33760,14 @@ var import_picocolors12 = __toESM(require_picocolors(), 1);
|
|
|
32969
33760
|
// src/lib/version-cache.ts
|
|
32970
33761
|
init_logger();
|
|
32971
33762
|
import { existsSync as existsSync7 } from "node:fs";
|
|
32972
|
-
import { mkdir as
|
|
32973
|
-
import { join as
|
|
33763
|
+
import { mkdir as mkdir10, readFile as readFile15, writeFile as writeFile13 } from "node:fs/promises";
|
|
33764
|
+
import { join as join32 } from "node:path";
|
|
32974
33765
|
class VersionCacheManager {
|
|
32975
33766
|
static CACHE_FILENAME = "version-check.json";
|
|
32976
33767
|
static CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
32977
33768
|
static getCacheFile() {
|
|
32978
33769
|
const cacheDir = PathResolver.getCacheDir(false);
|
|
32979
|
-
return
|
|
33770
|
+
return join32(cacheDir, VersionCacheManager.CACHE_FILENAME);
|
|
32980
33771
|
}
|
|
32981
33772
|
static async load() {
|
|
32982
33773
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
@@ -32985,7 +33776,7 @@ class VersionCacheManager {
|
|
|
32985
33776
|
logger.debug("Version check cache not found");
|
|
32986
33777
|
return null;
|
|
32987
33778
|
}
|
|
32988
|
-
const content = await
|
|
33779
|
+
const content = await readFile15(cacheFile, "utf-8");
|
|
32989
33780
|
const cache2 = JSON.parse(content);
|
|
32990
33781
|
if (!cache2.lastCheck || !cache2.currentVersion || !cache2.latestVersion) {
|
|
32991
33782
|
logger.debug("Invalid cache structure, ignoring");
|
|
@@ -33003,9 +33794,9 @@ class VersionCacheManager {
|
|
|
33003
33794
|
const cacheDir = PathResolver.getCacheDir(false);
|
|
33004
33795
|
try {
|
|
33005
33796
|
if (!existsSync7(cacheDir)) {
|
|
33006
|
-
await
|
|
33797
|
+
await mkdir10(cacheDir, { recursive: true, mode: 448 });
|
|
33007
33798
|
}
|
|
33008
|
-
await
|
|
33799
|
+
await writeFile13(cacheFile, JSON.stringify(cache2, null, 2), "utf-8");
|
|
33009
33800
|
logger.debug(`Version check cache saved to ${cacheFile}`);
|
|
33010
33801
|
} catch (error) {
|
|
33011
33802
|
logger.debug(`Failed to save version check cache: ${error}`);
|
|
@@ -33451,8 +34242,8 @@ class Logger2 {
|
|
|
33451
34242
|
var logger2 = new Logger2;
|
|
33452
34243
|
|
|
33453
34244
|
// src/utils/path-resolver.ts
|
|
33454
|
-
import { homedir as
|
|
33455
|
-
import { join as
|
|
34245
|
+
import { homedir as homedir4, platform as platform10 } from "node:os";
|
|
34246
|
+
import { join as join33, normalize as normalize6 } from "node:path";
|
|
33456
34247
|
|
|
33457
34248
|
class PathResolver2 {
|
|
33458
34249
|
static getTestHomeDir() {
|
|
@@ -33471,7 +34262,7 @@ class PathResolver2 {
|
|
|
33471
34262
|
return false;
|
|
33472
34263
|
}
|
|
33473
34264
|
}
|
|
33474
|
-
const normalized =
|
|
34265
|
+
const normalized = normalize6(path9);
|
|
33475
34266
|
for (const pattern of dangerousPatterns) {
|
|
33476
34267
|
if (normalized.includes(pattern)) {
|
|
33477
34268
|
return false;
|
|
@@ -33485,50 +34276,50 @@ class PathResolver2 {
|
|
|
33485
34276
|
static getConfigDir(global3 = false) {
|
|
33486
34277
|
const testHome = PathResolver2.getTestHomeDir();
|
|
33487
34278
|
if (testHome) {
|
|
33488
|
-
return global3 ?
|
|
34279
|
+
return global3 ? join33(testHome, ".config", "claude") : join33(testHome, ".claudekit");
|
|
33489
34280
|
}
|
|
33490
34281
|
if (!global3) {
|
|
33491
|
-
return
|
|
34282
|
+
return join33(homedir4(), ".claudekit");
|
|
33492
34283
|
}
|
|
33493
|
-
const os2 =
|
|
34284
|
+
const os2 = platform10();
|
|
33494
34285
|
if (os2 === "win32") {
|
|
33495
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
33496
|
-
return
|
|
34286
|
+
const localAppData = process.env.LOCALAPPDATA || join33(homedir4(), "AppData", "Local");
|
|
34287
|
+
return join33(localAppData, "claude");
|
|
33497
34288
|
}
|
|
33498
34289
|
const xdgConfigHome = process.env.XDG_CONFIG_HOME;
|
|
33499
34290
|
if (xdgConfigHome) {
|
|
33500
|
-
return
|
|
34291
|
+
return join33(xdgConfigHome, "claude");
|
|
33501
34292
|
}
|
|
33502
|
-
return
|
|
34293
|
+
return join33(homedir4(), ".config", "claude");
|
|
33503
34294
|
}
|
|
33504
34295
|
static getConfigFile(global3 = false) {
|
|
33505
|
-
return
|
|
34296
|
+
return join33(PathResolver2.getConfigDir(global3), "config.json");
|
|
33506
34297
|
}
|
|
33507
34298
|
static getCacheDir(global3 = false) {
|
|
33508
34299
|
const testHome = PathResolver2.getTestHomeDir();
|
|
33509
34300
|
if (testHome) {
|
|
33510
|
-
return global3 ?
|
|
34301
|
+
return global3 ? join33(testHome, ".cache", "claude") : join33(testHome, ".claudekit", "cache");
|
|
33511
34302
|
}
|
|
33512
34303
|
if (!global3) {
|
|
33513
|
-
return
|
|
34304
|
+
return join33(homedir4(), ".claudekit", "cache");
|
|
33514
34305
|
}
|
|
33515
|
-
const os2 =
|
|
34306
|
+
const os2 = platform10();
|
|
33516
34307
|
if (os2 === "win32") {
|
|
33517
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
33518
|
-
return
|
|
34308
|
+
const localAppData = process.env.LOCALAPPDATA || join33(homedir4(), "AppData", "Local");
|
|
34309
|
+
return join33(localAppData, "claude", "cache");
|
|
33519
34310
|
}
|
|
33520
34311
|
const xdgCacheHome = process.env.XDG_CACHE_HOME;
|
|
33521
34312
|
if (xdgCacheHome) {
|
|
33522
|
-
return
|
|
34313
|
+
return join33(xdgCacheHome, "claude");
|
|
33523
34314
|
}
|
|
33524
|
-
return
|
|
34315
|
+
return join33(homedir4(), ".cache", "claude");
|
|
33525
34316
|
}
|
|
33526
34317
|
static getGlobalKitDir() {
|
|
33527
34318
|
const testHome = PathResolver2.getTestHomeDir();
|
|
33528
34319
|
if (testHome) {
|
|
33529
|
-
return
|
|
34320
|
+
return join33(testHome, ".claude");
|
|
33530
34321
|
}
|
|
33531
|
-
return
|
|
34322
|
+
return join33(homedir4(), ".claude");
|
|
33532
34323
|
}
|
|
33533
34324
|
static getPathPrefix(global3) {
|
|
33534
34325
|
return global3 ? "" : ".claude";
|
|
@@ -33536,9 +34327,9 @@ class PathResolver2 {
|
|
|
33536
34327
|
static buildSkillsPath(baseDir, global3) {
|
|
33537
34328
|
const prefix = PathResolver2.getPathPrefix(global3);
|
|
33538
34329
|
if (prefix) {
|
|
33539
|
-
return
|
|
34330
|
+
return join33(baseDir, prefix, "skills");
|
|
33540
34331
|
}
|
|
33541
|
-
return
|
|
34332
|
+
return join33(baseDir, "skills");
|
|
33542
34333
|
}
|
|
33543
34334
|
static buildComponentPath(baseDir, component, global3) {
|
|
33544
34335
|
if (!PathResolver2.isPathSafe(component)) {
|
|
@@ -33546,9 +34337,9 @@ class PathResolver2 {
|
|
|
33546
34337
|
}
|
|
33547
34338
|
const prefix = PathResolver2.getPathPrefix(global3);
|
|
33548
34339
|
if (prefix) {
|
|
33549
|
-
return
|
|
34340
|
+
return join33(baseDir, prefix, component);
|
|
33550
34341
|
}
|
|
33551
|
-
return
|
|
34342
|
+
return join33(baseDir, component);
|
|
33552
34343
|
}
|
|
33553
34344
|
}
|
|
33554
34345
|
|
|
@@ -33566,9 +34357,9 @@ async function displayVersion() {
|
|
|
33566
34357
|
let localKitVersion = null;
|
|
33567
34358
|
let isGlobalOnlyKit = false;
|
|
33568
34359
|
const globalKitDir = PathResolver2.getGlobalKitDir();
|
|
33569
|
-
const globalMetadataPath =
|
|
34360
|
+
const globalMetadataPath = join34(globalKitDir, "metadata.json");
|
|
33570
34361
|
const prefix = PathResolver2.getPathPrefix(false);
|
|
33571
|
-
const localMetadataPath = prefix ?
|
|
34362
|
+
const localMetadataPath = prefix ? join34(process.cwd(), prefix, "metadata.json") : join34(process.cwd(), "metadata.json");
|
|
33572
34363
|
const isLocalSameAsGlobal = localMetadataPath === globalMetadataPath;
|
|
33573
34364
|
if (!isLocalSameAsGlobal && existsSync8(localMetadataPath)) {
|
|
33574
34365
|
try {
|
|
@@ -33668,7 +34459,7 @@ cli.command("update", "Update ClaudeKit CLI to the latest version").option("-r,
|
|
|
33668
34459
|
cli.command("versions", "List available versions of ClaudeKit repositories").option("--kit <kit>", "Filter by specific kit (engineer, marketing)").option("--limit <limit>", "Number of releases to show (default: 30)").option("--all", "Show all releases including prereleases").action(async (options) => {
|
|
33669
34460
|
await versionCommand(options);
|
|
33670
34461
|
});
|
|
33671
|
-
cli.command("doctor", "Comprehensive health check for ClaudeKit").option("--report", "Generate shareable diagnostic report").option("--fix", "Auto-fix all fixable issues").option("--check-only", "CI mode: no prompts, exit 1 on failures").option("--json", "Output JSON format").action(async (options) => {
|
|
34462
|
+
cli.command("doctor", "Comprehensive health check for ClaudeKit").option("--report", "Generate shareable diagnostic report").option("--fix", "Auto-fix all fixable issues").option("--check-only", "CI mode: no prompts, exit 1 on failures").option("--json", "Output JSON format").option("--full", "Include extended priority checks (slower)").action(async (options) => {
|
|
33672
34463
|
await doctorCommand(options);
|
|
33673
34464
|
});
|
|
33674
34465
|
cli.command("uninstall", "Remove ClaudeKit installations").option("-y, --yes", "Skip confirmation prompt").option("-l, --local", "Uninstall only local installation (current project)").option("-g, --global", "Uninstall only global installation (~/.claude/)").option("-A, --all", "Uninstall from both local and global locations").option("--dry-run", "Preview what would be removed without deleting").option("--force-overwrite", "Delete even user-modified files (requires confirmation)").action(async (options) => {
|