claudekit-cli 3.6.2 → 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 +1152 -382
- 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);
|
|
@@ -16284,6 +16300,8 @@ class PackageManagerDetector {
|
|
|
16284
16300
|
}
|
|
16285
16301
|
|
|
16286
16302
|
// src/lib/health-checks/claudekit-checker.ts
|
|
16303
|
+
var HOOK_EXTENSIONS = [".js", ".cjs", ".mjs", ".ts", ".sh", ".ps1"];
|
|
16304
|
+
|
|
16287
16305
|
class ClaudekitChecker {
|
|
16288
16306
|
group = "claudekit";
|
|
16289
16307
|
projectDir;
|
|
@@ -16311,6 +16329,18 @@ class ClaudekitChecker {
|
|
|
16311
16329
|
results.push(...this.checkSkillsScripts(setup));
|
|
16312
16330
|
logger.verbose("ClaudekitChecker: Checking component counts");
|
|
16313
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));
|
|
16314
16344
|
logger.verbose("ClaudekitChecker: All checks complete");
|
|
16315
16345
|
return results;
|
|
16316
16346
|
}
|
|
@@ -16323,6 +16353,7 @@ class ClaudekitChecker {
|
|
|
16323
16353
|
id: "ck-cli-install-method",
|
|
16324
16354
|
name: "CLI Installed Via",
|
|
16325
16355
|
group: "claudekit",
|
|
16356
|
+
priority: "standard",
|
|
16326
16357
|
status: pm !== "unknown" ? "pass" : "warn",
|
|
16327
16358
|
message: pmVersion ? `${displayName} (v${pmVersion})` : displayName,
|
|
16328
16359
|
suggestion: pm === "unknown" ? "Run: npm install -g claudekit-cli" : undefined,
|
|
@@ -16338,6 +16369,7 @@ class ClaudekitChecker {
|
|
|
16338
16369
|
id: "ck-global-install",
|
|
16339
16370
|
name: "Global CK",
|
|
16340
16371
|
group: "claudekit",
|
|
16372
|
+
priority: "critical",
|
|
16341
16373
|
status: hasGlobal ? "pass" : "warn",
|
|
16342
16374
|
message: hasGlobal ? `${kitName} ${version}` : "Not installed",
|
|
16343
16375
|
details: hasGlobal ? setup.global.path : undefined,
|
|
@@ -16354,6 +16386,7 @@ class ClaudekitChecker {
|
|
|
16354
16386
|
id: "ck-project-install",
|
|
16355
16387
|
name: "Project CK",
|
|
16356
16388
|
group: "claudekit",
|
|
16389
|
+
priority: "standard",
|
|
16357
16390
|
status: hasProject ? "pass" : "info",
|
|
16358
16391
|
message: hasProject ? `${kitName} ${version}` : "Not a ClaudeKit project",
|
|
16359
16392
|
details: hasProject ? setup.project.path : undefined,
|
|
@@ -16382,6 +16415,7 @@ class ClaudekitChecker {
|
|
|
16382
16415
|
id,
|
|
16383
16416
|
name,
|
|
16384
16417
|
group: "claudekit",
|
|
16418
|
+
priority: "standard",
|
|
16385
16419
|
status: "warn",
|
|
16386
16420
|
message: "Missing",
|
|
16387
16421
|
suggestion: "Create CLAUDE.md with project instructions",
|
|
@@ -16396,6 +16430,7 @@ class ClaudekitChecker {
|
|
|
16396
16430
|
id,
|
|
16397
16431
|
name,
|
|
16398
16432
|
group: "claudekit",
|
|
16433
|
+
priority: "standard",
|
|
16399
16434
|
status: "warn",
|
|
16400
16435
|
message: "Empty (0 bytes)",
|
|
16401
16436
|
details: path,
|
|
@@ -16407,6 +16442,7 @@ class ClaudekitChecker {
|
|
|
16407
16442
|
id,
|
|
16408
16443
|
name,
|
|
16409
16444
|
group: "claudekit",
|
|
16445
|
+
priority: "standard",
|
|
16410
16446
|
status: "pass",
|
|
16411
16447
|
message: `Found (${sizeKB}KB)`,
|
|
16412
16448
|
details: path,
|
|
@@ -16417,6 +16453,7 @@ class ClaudekitChecker {
|
|
|
16417
16453
|
id,
|
|
16418
16454
|
name,
|
|
16419
16455
|
group: "claudekit",
|
|
16456
|
+
priority: "standard",
|
|
16420
16457
|
status: "warn",
|
|
16421
16458
|
message: "Unreadable",
|
|
16422
16459
|
details: path,
|
|
@@ -16432,6 +16469,7 @@ class ClaudekitChecker {
|
|
|
16432
16469
|
id: "ck-active-plan",
|
|
16433
16470
|
name: "Active Plan",
|
|
16434
16471
|
group: "claudekit",
|
|
16472
|
+
priority: "standard",
|
|
16435
16473
|
status: "info",
|
|
16436
16474
|
message: "None",
|
|
16437
16475
|
autoFixable: false
|
|
@@ -16445,6 +16483,7 @@ class ClaudekitChecker {
|
|
|
16445
16483
|
id: "ck-active-plan",
|
|
16446
16484
|
name: "Active Plan",
|
|
16447
16485
|
group: "claudekit",
|
|
16486
|
+
priority: "standard",
|
|
16448
16487
|
status: "warn",
|
|
16449
16488
|
message: "Orphaned (target missing)",
|
|
16450
16489
|
details: targetPath,
|
|
@@ -16456,6 +16495,7 @@ class ClaudekitChecker {
|
|
|
16456
16495
|
id: "ck-active-plan",
|
|
16457
16496
|
name: "Active Plan",
|
|
16458
16497
|
group: "claudekit",
|
|
16498
|
+
priority: "standard",
|
|
16459
16499
|
status: "pass",
|
|
16460
16500
|
message: targetPath,
|
|
16461
16501
|
autoFixable: false
|
|
@@ -16465,6 +16505,7 @@ class ClaudekitChecker {
|
|
|
16465
16505
|
id: "ck-active-plan",
|
|
16466
16506
|
name: "Active Plan",
|
|
16467
16507
|
group: "claudekit",
|
|
16508
|
+
priority: "standard",
|
|
16468
16509
|
status: "warn",
|
|
16469
16510
|
message: "Unreadable",
|
|
16470
16511
|
details: activePlanPath,
|
|
@@ -16483,6 +16524,7 @@ class ClaudekitChecker {
|
|
|
16483
16524
|
id: "ck-global-skills-script",
|
|
16484
16525
|
name: "Global Skills Script",
|
|
16485
16526
|
group: "claudekit",
|
|
16527
|
+
priority: "standard",
|
|
16486
16528
|
status: hasGlobalScript ? "pass" : "info",
|
|
16487
16529
|
message: hasGlobalScript ? "Available" : "Not found",
|
|
16488
16530
|
details: hasGlobalScript ? globalScriptPath : undefined,
|
|
@@ -16497,6 +16539,7 @@ class ClaudekitChecker {
|
|
|
16497
16539
|
id: "ck-project-skills-script",
|
|
16498
16540
|
name: "Project Skills Script",
|
|
16499
16541
|
group: "claudekit",
|
|
16542
|
+
priority: "standard",
|
|
16500
16543
|
status: hasProjectScript ? "pass" : "info",
|
|
16501
16544
|
message: hasProjectScript ? "Available" : "Not found",
|
|
16502
16545
|
details: hasProjectScript ? projectScriptPath : undefined,
|
|
@@ -16518,12 +16561,349 @@ class ClaudekitChecker {
|
|
|
16518
16561
|
id: "ck-component-counts",
|
|
16519
16562
|
name: "ClaudeKit Components",
|
|
16520
16563
|
group: "claudekit",
|
|
16564
|
+
priority: "standard",
|
|
16521
16565
|
status: totalComponents > 0 ? "info" : "warn",
|
|
16522
16566
|
message: totalComponents > 0 ? `${totalAgents} agents, ${totalCommands} commands, ${totalWorkflows} workflows, ${totalSkills} skills` : "No components found",
|
|
16523
16567
|
suggestion: totalComponents === 0 ? "Install ClaudeKit: ck new --kit engineer" : undefined,
|
|
16524
16568
|
autoFixable: false
|
|
16525
16569
|
};
|
|
16526
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
|
+
}
|
|
16527
16907
|
}
|
|
16528
16908
|
// src/lib/health-checks/auth-checker.ts
|
|
16529
16909
|
init_types2();
|
|
@@ -16685,7 +17065,7 @@ import { Octokit } from "@octokit/rest";
|
|
|
16685
17065
|
init_zod();
|
|
16686
17066
|
init_logger();
|
|
16687
17067
|
import { existsSync as existsSync4 } from "node:fs";
|
|
16688
|
-
import { mkdir as mkdir2, readFile as
|
|
17068
|
+
import { mkdir as mkdir2, readFile as readFile4, unlink as unlink2, writeFile as writeFile3 } from "node:fs/promises";
|
|
16689
17069
|
import { join as join5 } from "node:path";
|
|
16690
17070
|
var ReleaseCacheEntrySchema = exports_external.object({
|
|
16691
17071
|
timestamp: exports_external.number(),
|
|
@@ -16706,7 +17086,7 @@ class ReleaseCache {
|
|
|
16706
17086
|
logger.debug(`Release cache not found for key: ${key}`);
|
|
16707
17087
|
return null;
|
|
16708
17088
|
}
|
|
16709
|
-
const content = await
|
|
17089
|
+
const content = await readFile4(cacheFile, "utf-8");
|
|
16710
17090
|
const parsed = JSON.parse(content);
|
|
16711
17091
|
const cacheEntry = ReleaseCacheEntrySchema.parse(parsed);
|
|
16712
17092
|
if (this.isExpired(cacheEntry.timestamp)) {
|
|
@@ -16732,7 +17112,7 @@ class ReleaseCache {
|
|
|
16732
17112
|
timestamp: Date.now(),
|
|
16733
17113
|
releases
|
|
16734
17114
|
};
|
|
16735
|
-
await
|
|
17115
|
+
await writeFile3(cacheFile, JSON.stringify(cacheEntry, null, 2), "utf-8");
|
|
16736
17116
|
logger.debug(`Release cache set for key: ${key}, cached ${releases.length} releases`);
|
|
16737
17117
|
} catch (error) {
|
|
16738
17118
|
logger.debug(`Failed to set release cache for key ${key}: ${error}`);
|
|
@@ -16743,7 +17123,7 @@ class ReleaseCache {
|
|
|
16743
17123
|
const cacheFile = this.getCachePath(key);
|
|
16744
17124
|
try {
|
|
16745
17125
|
if (existsSync4(cacheFile)) {
|
|
16746
|
-
await
|
|
17126
|
+
await unlink2(cacheFile);
|
|
16747
17127
|
logger.debug(`Release cache cleared for key: ${key}`);
|
|
16748
17128
|
}
|
|
16749
17129
|
} catch (error) {
|
|
@@ -16751,11 +17131,11 @@ class ReleaseCache {
|
|
|
16751
17131
|
}
|
|
16752
17132
|
} else {
|
|
16753
17133
|
try {
|
|
16754
|
-
const { readdir:
|
|
16755
|
-
const files = await
|
|
17134
|
+
const { readdir: readdir3 } = await import("node:fs/promises");
|
|
17135
|
+
const files = await readdir3(this.cacheDir);
|
|
16756
17136
|
for (const file of files) {
|
|
16757
17137
|
if (file.endsWith(".json")) {
|
|
16758
|
-
await
|
|
17138
|
+
await unlink2(join5(this.cacheDir, file));
|
|
16759
17139
|
}
|
|
16760
17140
|
}
|
|
16761
17141
|
logger.debug("All release cache cleared");
|
|
@@ -17356,6 +17736,7 @@ class AuthChecker {
|
|
|
17356
17736
|
}
|
|
17357
17737
|
}
|
|
17358
17738
|
async checkGhToken() {
|
|
17739
|
+
if (false) {}
|
|
17359
17740
|
try {
|
|
17360
17741
|
logger.verbose("AuthChecker: Getting GitHub token via AuthManager");
|
|
17361
17742
|
const { token } = await AuthManager.getToken();
|
|
@@ -17448,6 +17829,392 @@ class AuthChecker {
|
|
|
17448
17829
|
};
|
|
17449
17830
|
}
|
|
17450
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
|
+
}
|
|
17451
18218
|
// src/lib/health-checks/auto-healer.ts
|
|
17452
18219
|
class AutoHealer {
|
|
17453
18220
|
timeout;
|
|
@@ -17527,14 +18294,14 @@ init_dist2();
|
|
|
17527
18294
|
import { execSync as execSync3, spawnSync } from "node:child_process";
|
|
17528
18295
|
import { readFileSync as readFileSync3, unlinkSync, writeFileSync } from "node:fs";
|
|
17529
18296
|
import { tmpdir } from "node:os";
|
|
17530
|
-
import { dirname, join as
|
|
18297
|
+
import { dirname as dirname2, join as join7 } from "node:path";
|
|
17531
18298
|
import { fileURLToPath } from "node:url";
|
|
17532
18299
|
init_environment();
|
|
17533
18300
|
init_logger();
|
|
17534
18301
|
function getCliVersion() {
|
|
17535
18302
|
try {
|
|
17536
|
-
const __dirname2 =
|
|
17537
|
-
const pkgPath =
|
|
18303
|
+
const __dirname2 = dirname2(fileURLToPath(import.meta.url));
|
|
18304
|
+
const pkgPath = join7(__dirname2, "../../../package.json");
|
|
17538
18305
|
const pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
|
|
17539
18306
|
return pkg.version || "unknown";
|
|
17540
18307
|
} catch (err) {
|
|
@@ -17673,7 +18440,7 @@ class ReportGenerator {
|
|
|
17673
18440
|
return null;
|
|
17674
18441
|
}
|
|
17675
18442
|
}
|
|
17676
|
-
const tmpFile =
|
|
18443
|
+
const tmpFile = join7(tmpdir(), `ck-report-${Date.now()}.txt`);
|
|
17677
18444
|
writeFileSync(tmpFile, report);
|
|
17678
18445
|
try {
|
|
17679
18446
|
const result = spawnSync("gh", ["gist", "create", tmpFile, "--desc", "ClaudeKit Diagnostic Report"], {
|
|
@@ -17878,12 +18645,13 @@ class DoctorUIRenderer {
|
|
|
17878
18645
|
init_environment();
|
|
17879
18646
|
init_logger();
|
|
17880
18647
|
async function doctorCommand(options = {}) {
|
|
17881
|
-
const { report, fix, checkOnly, json } = options;
|
|
18648
|
+
const { report, fix, checkOnly, json, full } = options;
|
|
17882
18649
|
const runnerOptions = {
|
|
17883
18650
|
fix: fix ?? false,
|
|
17884
18651
|
checkOnly: checkOnly ?? false,
|
|
17885
18652
|
json: json ?? false,
|
|
17886
|
-
verbose: logger.isVerbose()
|
|
18653
|
+
verbose: logger.isVerbose(),
|
|
18654
|
+
full: full ?? false
|
|
17887
18655
|
};
|
|
17888
18656
|
if (!json && !report) {
|
|
17889
18657
|
oe("ClaudeKit Health Check");
|
|
@@ -17892,6 +18660,8 @@ async function doctorCommand(options = {}) {
|
|
|
17892
18660
|
runner.registerChecker(new SystemChecker);
|
|
17893
18661
|
runner.registerChecker(new ClaudekitChecker);
|
|
17894
18662
|
runner.registerChecker(new AuthChecker);
|
|
18663
|
+
runner.registerChecker(new PlatformChecker);
|
|
18664
|
+
runner.registerChecker(new NetworkChecker);
|
|
17895
18665
|
const summary = await runner.run();
|
|
17896
18666
|
if (json) {
|
|
17897
18667
|
const generator = new ReportGenerator;
|
|
@@ -17946,17 +18716,17 @@ async function doctorCommand(options = {}) {
|
|
|
17946
18716
|
|
|
17947
18717
|
// src/commands/init.ts
|
|
17948
18718
|
var import_fs_extra17 = __toESM(require_lib(), 1);
|
|
17949
|
-
import { join as
|
|
18719
|
+
import { join as join29, resolve as resolve5 } from "node:path";
|
|
17950
18720
|
|
|
17951
18721
|
// src/lib/commands-prefix.ts
|
|
17952
18722
|
init_logger();
|
|
17953
18723
|
var import_fs_extra3 = __toESM(require_lib(), 1);
|
|
17954
|
-
import { lstat, mkdir as
|
|
17955
|
-
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";
|
|
17956
18726
|
|
|
17957
18727
|
// src/utils/manifest-writer.ts
|
|
17958
18728
|
var import_fs_extra2 = __toESM(require_lib(), 1);
|
|
17959
|
-
import { join as
|
|
18729
|
+
import { join as join8 } from "node:path";
|
|
17960
18730
|
|
|
17961
18731
|
// node_modules/yocto-queue/index.js
|
|
17962
18732
|
class Node {
|
|
@@ -18040,24 +18810,24 @@ function pLimit(concurrency) {
|
|
|
18040
18810
|
activeCount--;
|
|
18041
18811
|
resumeNext();
|
|
18042
18812
|
};
|
|
18043
|
-
const run = async (function_,
|
|
18813
|
+
const run = async (function_, resolve2, arguments_) => {
|
|
18044
18814
|
const result = (async () => function_(...arguments_))();
|
|
18045
|
-
|
|
18815
|
+
resolve2(result);
|
|
18046
18816
|
try {
|
|
18047
18817
|
await result;
|
|
18048
18818
|
} catch {}
|
|
18049
18819
|
next();
|
|
18050
18820
|
};
|
|
18051
|
-
const enqueue = (function_,
|
|
18821
|
+
const enqueue = (function_, resolve2, arguments_) => {
|
|
18052
18822
|
new Promise((internalResolve) => {
|
|
18053
18823
|
queue.enqueue(internalResolve);
|
|
18054
|
-
}).then(run.bind(undefined, function_,
|
|
18824
|
+
}).then(run.bind(undefined, function_, resolve2, arguments_));
|
|
18055
18825
|
if (activeCount < concurrency) {
|
|
18056
18826
|
resumeNext();
|
|
18057
18827
|
}
|
|
18058
18828
|
};
|
|
18059
|
-
const generator = (function_, ...arguments_) => new Promise((
|
|
18060
|
-
enqueue(function_,
|
|
18829
|
+
const generator = (function_, ...arguments_) => new Promise((resolve2) => {
|
|
18830
|
+
enqueue(function_, resolve2, arguments_);
|
|
18061
18831
|
});
|
|
18062
18832
|
Object.defineProperties(generator, {
|
|
18063
18833
|
activeCount: {
|
|
@@ -18106,12 +18876,12 @@ import { relative } from "node:path";
|
|
|
18106
18876
|
|
|
18107
18877
|
class OwnershipChecker {
|
|
18108
18878
|
static async calculateChecksum(filePath) {
|
|
18109
|
-
return new Promise((
|
|
18879
|
+
return new Promise((resolve2, reject) => {
|
|
18110
18880
|
const hash = createHash("sha256");
|
|
18111
18881
|
const stream = createReadStream(filePath);
|
|
18112
18882
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
18113
18883
|
stream.on("end", () => {
|
|
18114
|
-
|
|
18884
|
+
resolve2(hash.digest("hex"));
|
|
18115
18885
|
});
|
|
18116
18886
|
stream.on("error", (err) => {
|
|
18117
18887
|
stream.destroy();
|
|
@@ -18237,7 +19007,7 @@ class ManifestWriter {
|
|
|
18237
19007
|
return Array.from(this.trackedFiles.values()).sort((a3, b3) => a3.path.localeCompare(b3.path));
|
|
18238
19008
|
}
|
|
18239
19009
|
async writeManifest(claudeDir, kitName, version, scope) {
|
|
18240
|
-
const metadataPath =
|
|
19010
|
+
const metadataPath = join8(claudeDir, "metadata.json");
|
|
18241
19011
|
let existingMetadata = {};
|
|
18242
19012
|
if (await import_fs_extra2.pathExists(metadataPath)) {
|
|
18243
19013
|
try {
|
|
@@ -18263,7 +19033,7 @@ class ManifestWriter {
|
|
|
18263
19033
|
logger.debug(`Wrote manifest with ${this.installedFiles.size} installed files, ${trackedFiles.length} tracked`);
|
|
18264
19034
|
}
|
|
18265
19035
|
static async readManifest(claudeDir) {
|
|
18266
|
-
const metadataPath =
|
|
19036
|
+
const metadataPath = join8(claudeDir, "metadata.json");
|
|
18267
19037
|
if (!await import_fs_extra2.pathExists(metadataPath)) {
|
|
18268
19038
|
return null;
|
|
18269
19039
|
}
|
|
@@ -18334,22 +19104,22 @@ function validatePath(path, paramName) {
|
|
|
18334
19104
|
class CommandsPrefix {
|
|
18335
19105
|
static async applyPrefix(extractDir) {
|
|
18336
19106
|
validatePath(extractDir, "extractDir");
|
|
18337
|
-
const commandsDir =
|
|
19107
|
+
const commandsDir = join9(extractDir, ".claude", "commands");
|
|
18338
19108
|
if (!await import_fs_extra3.pathExists(commandsDir)) {
|
|
18339
19109
|
logger.verbose("No commands directory found, skipping prefix application");
|
|
18340
19110
|
return;
|
|
18341
19111
|
}
|
|
18342
19112
|
logger.info("Applying /ck: prefix to slash commands...");
|
|
18343
|
-
const backupDir =
|
|
18344
|
-
const tempDir =
|
|
19113
|
+
const backupDir = join9(extractDir, ".commands-backup");
|
|
19114
|
+
const tempDir = join9(extractDir, ".commands-prefix-temp");
|
|
18345
19115
|
try {
|
|
18346
|
-
const entries = await
|
|
19116
|
+
const entries = await readdir3(commandsDir);
|
|
18347
19117
|
if (entries.length === 0) {
|
|
18348
19118
|
logger.verbose("Commands directory is empty, skipping prefix application");
|
|
18349
19119
|
return;
|
|
18350
19120
|
}
|
|
18351
19121
|
if (entries.length === 1 && entries[0] === "ck") {
|
|
18352
|
-
const ckDir2 =
|
|
19122
|
+
const ckDir2 = join9(commandsDir, "ck");
|
|
18353
19123
|
const ckStat = await stat2(ckDir2);
|
|
18354
19124
|
if (ckStat.isDirectory()) {
|
|
18355
19125
|
logger.verbose("Commands already have /ck: prefix, skipping");
|
|
@@ -18358,18 +19128,18 @@ class CommandsPrefix {
|
|
|
18358
19128
|
}
|
|
18359
19129
|
await import_fs_extra3.copy(commandsDir, backupDir);
|
|
18360
19130
|
logger.verbose("Created backup of commands directory");
|
|
18361
|
-
await
|
|
18362
|
-
const ckDir =
|
|
18363
|
-
await
|
|
19131
|
+
await mkdir4(tempDir, { recursive: true });
|
|
19132
|
+
const ckDir = join9(tempDir, "ck");
|
|
19133
|
+
await mkdir4(ckDir, { recursive: true });
|
|
18364
19134
|
let processedCount = 0;
|
|
18365
19135
|
for (const entry of entries) {
|
|
18366
|
-
const sourcePath =
|
|
19136
|
+
const sourcePath = join9(commandsDir, entry);
|
|
18367
19137
|
const stats = await lstat(sourcePath);
|
|
18368
19138
|
if (stats.isSymbolicLink()) {
|
|
18369
19139
|
logger.warning(`Skipping symlink for security: ${entry}`);
|
|
18370
19140
|
continue;
|
|
18371
19141
|
}
|
|
18372
|
-
const destPath =
|
|
19142
|
+
const destPath = join9(ckDir, entry);
|
|
18373
19143
|
await import_fs_extra3.copy(sourcePath, destPath, {
|
|
18374
19144
|
overwrite: false,
|
|
18375
19145
|
errorOnExist: true
|
|
@@ -18417,8 +19187,8 @@ class CommandsPrefix {
|
|
|
18417
19187
|
static async cleanupCommandsDirectory(targetDir, isGlobal, options = {}) {
|
|
18418
19188
|
const { dryRun = false, forceOverwrite = false } = options;
|
|
18419
19189
|
validatePath(targetDir, "targetDir");
|
|
18420
|
-
const claudeDir = isGlobal ? targetDir :
|
|
18421
|
-
const commandsDir =
|
|
19190
|
+
const claudeDir = isGlobal ? targetDir : join9(targetDir, ".claude");
|
|
19191
|
+
const commandsDir = join9(claudeDir, "commands");
|
|
18422
19192
|
const result = {
|
|
18423
19193
|
results: [],
|
|
18424
19194
|
deletedCount: 0,
|
|
@@ -18440,13 +19210,13 @@ class CommandsPrefix {
|
|
|
18440
19210
|
logger.verbose("All existing files will be preserved as user-owned");
|
|
18441
19211
|
return result;
|
|
18442
19212
|
}
|
|
18443
|
-
const entries = await
|
|
19213
|
+
const entries = await readdir3(commandsDir);
|
|
18444
19214
|
if (entries.length === 0) {
|
|
18445
19215
|
logger.verbose("Commands directory is empty");
|
|
18446
19216
|
return result;
|
|
18447
19217
|
}
|
|
18448
19218
|
for (const entry of entries) {
|
|
18449
|
-
const entryPath =
|
|
19219
|
+
const entryPath = join9(commandsDir, entry);
|
|
18450
19220
|
const stats = await lstat(entryPath);
|
|
18451
19221
|
if (stats.isSymbolicLink()) {
|
|
18452
19222
|
logger.warning(`Skipping symlink: ${entry}`);
|
|
@@ -18610,9 +19380,9 @@ class CommandsPrefix {
|
|
|
18610
19380
|
}
|
|
18611
19381
|
static async scanDirectoryFiles(dir) {
|
|
18612
19382
|
const files = [];
|
|
18613
|
-
const entries = await
|
|
19383
|
+
const entries = await readdir3(dir);
|
|
18614
19384
|
for (const entry of entries) {
|
|
18615
|
-
const fullPath =
|
|
19385
|
+
const fullPath = join9(dir, entry);
|
|
18616
19386
|
const stats = await lstat(fullPath);
|
|
18617
19387
|
if (stats.isSymbolicLink()) {
|
|
18618
19388
|
continue;
|
|
@@ -18634,9 +19404,9 @@ var import_ignore = __toESM(require_ignore(), 1);
|
|
|
18634
19404
|
import { Buffer as Buffer3 } from "node:buffer";
|
|
18635
19405
|
import { execFile } from "node:child_process";
|
|
18636
19406
|
import { createWriteStream as createWriteStream2 } from "node:fs";
|
|
18637
|
-
import { mkdir as
|
|
19407
|
+
import { mkdir as mkdir6 } from "node:fs/promises";
|
|
18638
19408
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
18639
|
-
import { join as
|
|
19409
|
+
import { join as join11, relative as relative2, resolve as resolve2 } from "node:path";
|
|
18640
19410
|
import { TextDecoder } from "node:util";
|
|
18641
19411
|
|
|
18642
19412
|
// node_modules/@isaacs/fs-minipass/dist/esm/index.js
|
|
@@ -19185,10 +19955,10 @@ class Minipass extends EventEmitter2 {
|
|
|
19185
19955
|
return this[ENCODING] ? buf.join("") : Buffer.concat(buf, buf.dataLength);
|
|
19186
19956
|
}
|
|
19187
19957
|
async promise() {
|
|
19188
|
-
return new Promise((
|
|
19958
|
+
return new Promise((resolve2, reject) => {
|
|
19189
19959
|
this.on(DESTROYED, () => reject(new Error("stream destroyed")));
|
|
19190
19960
|
this.on("error", (er) => reject(er));
|
|
19191
|
-
this.on("end", () =>
|
|
19961
|
+
this.on("end", () => resolve2());
|
|
19192
19962
|
});
|
|
19193
19963
|
}
|
|
19194
19964
|
[Symbol.asyncIterator]() {
|
|
@@ -19207,7 +19977,7 @@ class Minipass extends EventEmitter2 {
|
|
|
19207
19977
|
return Promise.resolve({ done: false, value: res });
|
|
19208
19978
|
if (this[EOF])
|
|
19209
19979
|
return stop();
|
|
19210
|
-
let
|
|
19980
|
+
let resolve2;
|
|
19211
19981
|
let reject;
|
|
19212
19982
|
const onerr = (er) => {
|
|
19213
19983
|
this.off("data", ondata);
|
|
@@ -19221,19 +19991,19 @@ class Minipass extends EventEmitter2 {
|
|
|
19221
19991
|
this.off("end", onend);
|
|
19222
19992
|
this.off(DESTROYED, ondestroy);
|
|
19223
19993
|
this.pause();
|
|
19224
|
-
|
|
19994
|
+
resolve2({ value, done: !!this[EOF] });
|
|
19225
19995
|
};
|
|
19226
19996
|
const onend = () => {
|
|
19227
19997
|
this.off("error", onerr);
|
|
19228
19998
|
this.off("data", ondata);
|
|
19229
19999
|
this.off(DESTROYED, ondestroy);
|
|
19230
20000
|
stop();
|
|
19231
|
-
|
|
20001
|
+
resolve2({ done: true, value: undefined });
|
|
19232
20002
|
};
|
|
19233
20003
|
const ondestroy = () => onerr(new Error("stream destroyed"));
|
|
19234
20004
|
return new Promise((res2, rej) => {
|
|
19235
20005
|
reject = rej;
|
|
19236
|
-
|
|
20006
|
+
resolve2 = res2;
|
|
19237
20007
|
this.once(DESTROYED, ondestroy);
|
|
19238
20008
|
this.once("error", onerr);
|
|
19239
20009
|
this.once("end", onend);
|
|
@@ -19690,7 +20460,7 @@ import path3 from "node:path";
|
|
|
19690
20460
|
|
|
19691
20461
|
// node_modules/tar/dist/esm/list.js
|
|
19692
20462
|
import fs3 from "node:fs";
|
|
19693
|
-
import { dirname as
|
|
20463
|
+
import { dirname as dirname3, parse as parse2 } from "path";
|
|
19694
20464
|
|
|
19695
20465
|
// node_modules/tar/dist/esm/options.js
|
|
19696
20466
|
var argmap = new Map([
|
|
@@ -20339,10 +21109,10 @@ class Minipass2 extends EventEmitter3 {
|
|
|
20339
21109
|
return this[ENCODING2] ? buf.join("") : Buffer.concat(buf, buf.dataLength);
|
|
20340
21110
|
}
|
|
20341
21111
|
async promise() {
|
|
20342
|
-
return new Promise((
|
|
21112
|
+
return new Promise((resolve2, reject) => {
|
|
20343
21113
|
this.on(DESTROYED2, () => reject(new Error("stream destroyed")));
|
|
20344
21114
|
this.on("error", (er) => reject(er));
|
|
20345
|
-
this.on("end", () =>
|
|
21115
|
+
this.on("end", () => resolve2());
|
|
20346
21116
|
});
|
|
20347
21117
|
}
|
|
20348
21118
|
[Symbol.asyncIterator]() {
|
|
@@ -20361,7 +21131,7 @@ class Minipass2 extends EventEmitter3 {
|
|
|
20361
21131
|
return Promise.resolve({ done: false, value: res });
|
|
20362
21132
|
if (this[EOF2])
|
|
20363
21133
|
return stop();
|
|
20364
|
-
let
|
|
21134
|
+
let resolve2;
|
|
20365
21135
|
let reject;
|
|
20366
21136
|
const onerr = (er) => {
|
|
20367
21137
|
this.off("data", ondata);
|
|
@@ -20375,19 +21145,19 @@ class Minipass2 extends EventEmitter3 {
|
|
|
20375
21145
|
this.off("end", onend);
|
|
20376
21146
|
this.off(DESTROYED2, ondestroy);
|
|
20377
21147
|
this.pause();
|
|
20378
|
-
|
|
21148
|
+
resolve2({ value, done: !!this[EOF2] });
|
|
20379
21149
|
};
|
|
20380
21150
|
const onend = () => {
|
|
20381
21151
|
this.off("error", onerr);
|
|
20382
21152
|
this.off("data", ondata);
|
|
20383
21153
|
this.off(DESTROYED2, ondestroy);
|
|
20384
21154
|
stop();
|
|
20385
|
-
|
|
21155
|
+
resolve2({ done: true, value: undefined });
|
|
20386
21156
|
};
|
|
20387
21157
|
const ondestroy = () => onerr(new Error("stream destroyed"));
|
|
20388
21158
|
return new Promise((res2, rej) => {
|
|
20389
21159
|
reject = rej;
|
|
20390
|
-
|
|
21160
|
+
resolve2 = res2;
|
|
20391
21161
|
this.once(DESTROYED2, ondestroy);
|
|
20392
21162
|
this.once("error", onerr);
|
|
20393
21163
|
this.once("end", onend);
|
|
@@ -20464,7 +21234,7 @@ import * as realZlib2 from "zlib";
|
|
|
20464
21234
|
// node_modules/minizlib/dist/esm/constants.js
|
|
20465
21235
|
import realZlib from "zlib";
|
|
20466
21236
|
var realZlibConstants = realZlib.constants || { ZLIB_VERNUM: 4736 };
|
|
20467
|
-
var
|
|
21237
|
+
var constants3 = Object.freeze(Object.assign(Object.create(null), {
|
|
20468
21238
|
Z_NO_FLUSH: 0,
|
|
20469
21239
|
Z_PARTIAL_FLUSH: 1,
|
|
20470
21240
|
Z_SYNC_FLUSH: 2,
|
|
@@ -20743,9 +21513,9 @@ class Zlib extends ZlibBase {
|
|
|
20743
21513
|
#strategy;
|
|
20744
21514
|
constructor(opts, mode) {
|
|
20745
21515
|
opts = opts || {};
|
|
20746
|
-
opts.flush = opts.flush ||
|
|
20747
|
-
opts.finishFlush = opts.finishFlush ||
|
|
20748
|
-
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;
|
|
20749
21519
|
super(opts, mode);
|
|
20750
21520
|
this.#level = opts.level;
|
|
20751
21521
|
this.#strategy = opts.strategy;
|
|
@@ -20758,7 +21528,7 @@ class Zlib extends ZlibBase {
|
|
|
20758
21528
|
if (!this.handle.params)
|
|
20759
21529
|
throw new Error("not supported in this implementation");
|
|
20760
21530
|
if (this.#level !== level || this.#strategy !== strategy) {
|
|
20761
|
-
this.flush(
|
|
21531
|
+
this.flush(constants3.Z_SYNC_FLUSH);
|
|
20762
21532
|
assert(this.handle, "zlib binding closed");
|
|
20763
21533
|
const origFlush = this.handle.flush;
|
|
20764
21534
|
this.handle.flush = (flushFlag, cb) => {
|
|
@@ -20804,9 +21574,9 @@ class Unzip extends Zlib {
|
|
|
20804
21574
|
class Brotli extends ZlibBase {
|
|
20805
21575
|
constructor(opts, mode) {
|
|
20806
21576
|
opts = opts || {};
|
|
20807
|
-
opts.flush = opts.flush ||
|
|
20808
|
-
opts.finishFlush = opts.finishFlush ||
|
|
20809
|
-
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;
|
|
20810
21580
|
super(opts, mode);
|
|
20811
21581
|
}
|
|
20812
21582
|
}
|
|
@@ -20826,9 +21596,9 @@ class BrotliDecompress extends Brotli {
|
|
|
20826
21596
|
class Zstd extends ZlibBase {
|
|
20827
21597
|
constructor(opts, mode) {
|
|
20828
21598
|
opts = opts || {};
|
|
20829
|
-
opts.flush = opts.flush ||
|
|
20830
|
-
opts.finishFlush = opts.finishFlush ||
|
|
20831
|
-
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;
|
|
20832
21602
|
super(opts, mode);
|
|
20833
21603
|
}
|
|
20834
21604
|
}
|
|
@@ -21815,10 +22585,10 @@ class Minipass3 extends EventEmitter4 {
|
|
|
21815
22585
|
return this[ENCODING3] ? buf.join("") : Buffer.concat(buf, buf.dataLength);
|
|
21816
22586
|
}
|
|
21817
22587
|
async promise() {
|
|
21818
|
-
return new Promise((
|
|
22588
|
+
return new Promise((resolve2, reject) => {
|
|
21819
22589
|
this.on(DESTROYED3, () => reject(new Error("stream destroyed")));
|
|
21820
22590
|
this.on("error", (er) => reject(er));
|
|
21821
|
-
this.on("end", () =>
|
|
22591
|
+
this.on("end", () => resolve2());
|
|
21822
22592
|
});
|
|
21823
22593
|
}
|
|
21824
22594
|
[Symbol.asyncIterator]() {
|
|
@@ -21837,7 +22607,7 @@ class Minipass3 extends EventEmitter4 {
|
|
|
21837
22607
|
return Promise.resolve({ done: false, value: res });
|
|
21838
22608
|
if (this[EOF3])
|
|
21839
22609
|
return stop();
|
|
21840
|
-
let
|
|
22610
|
+
let resolve2;
|
|
21841
22611
|
let reject;
|
|
21842
22612
|
const onerr = (er) => {
|
|
21843
22613
|
this.off("data", ondata);
|
|
@@ -21851,19 +22621,19 @@ class Minipass3 extends EventEmitter4 {
|
|
|
21851
22621
|
this.off("end", onend);
|
|
21852
22622
|
this.off(DESTROYED3, ondestroy);
|
|
21853
22623
|
this.pause();
|
|
21854
|
-
|
|
22624
|
+
resolve2({ value, done: !!this[EOF3] });
|
|
21855
22625
|
};
|
|
21856
22626
|
const onend = () => {
|
|
21857
22627
|
this.off("error", onerr);
|
|
21858
22628
|
this.off("data", ondata);
|
|
21859
22629
|
this.off(DESTROYED3, ondestroy);
|
|
21860
22630
|
stop();
|
|
21861
|
-
|
|
22631
|
+
resolve2({ done: true, value: undefined });
|
|
21862
22632
|
};
|
|
21863
22633
|
const ondestroy = () => onerr(new Error("stream destroyed"));
|
|
21864
22634
|
return new Promise((res2, rej) => {
|
|
21865
22635
|
reject = rej;
|
|
21866
|
-
|
|
22636
|
+
resolve2 = res2;
|
|
21867
22637
|
this.once(DESTROYED3, ondestroy);
|
|
21868
22638
|
this.once("error", onerr);
|
|
21869
22639
|
this.once("end", onend);
|
|
@@ -21935,8 +22705,8 @@ class Minipass3 extends EventEmitter4 {
|
|
|
21935
22705
|
}
|
|
21936
22706
|
|
|
21937
22707
|
// node_modules/tar/dist/esm/normalize-windows-path.js
|
|
21938
|
-
var
|
|
21939
|
-
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, "/");
|
|
21940
22710
|
|
|
21941
22711
|
// node_modules/tar/dist/esm/read-entry.js
|
|
21942
22712
|
class ReadEntry extends Minipass3 {
|
|
@@ -22590,7 +23360,7 @@ var filesFilter = (opt, files) => {
|
|
|
22590
23360
|
if (m2 !== undefined) {
|
|
22591
23361
|
ret = m2;
|
|
22592
23362
|
} else {
|
|
22593
|
-
ret = mapHas(
|
|
23363
|
+
ret = mapHas(dirname3(file), root);
|
|
22594
23364
|
}
|
|
22595
23365
|
}
|
|
22596
23366
|
map.set(file, ret);
|
|
@@ -22634,9 +23404,9 @@ var listFile = (opt, _files) => {
|
|
|
22634
23404
|
const parse3 = new Parser(opt);
|
|
22635
23405
|
const readSize = opt.maxReadSize || 16 * 1024 * 1024;
|
|
22636
23406
|
const file = opt.file;
|
|
22637
|
-
const p = new Promise((
|
|
23407
|
+
const p = new Promise((resolve2, reject) => {
|
|
22638
23408
|
parse3.on("error", reject);
|
|
22639
|
-
parse3.on("end",
|
|
23409
|
+
parse3.on("end", resolve2);
|
|
22640
23410
|
fs3.stat(file, (er, stat3) => {
|
|
22641
23411
|
if (er) {
|
|
22642
23412
|
reject(er);
|
|
@@ -24134,8 +24904,8 @@ import path6 from "node:path";
|
|
|
24134
24904
|
|
|
24135
24905
|
// node_modules/tar/dist/esm/get-write-flag.js
|
|
24136
24906
|
import fs6 from "fs";
|
|
24137
|
-
var
|
|
24138
|
-
var isWindows2 =
|
|
24907
|
+
var platform5 = process.env.__FAKE_PLATFORM__ || process.platform;
|
|
24908
|
+
var isWindows2 = platform5 === "win32";
|
|
24139
24909
|
var { O_CREAT, O_TRUNC, O_WRONLY } = fs6.constants;
|
|
24140
24910
|
var UV_FS_O_FILEMAP = Number(process.env.__FAKE_FS_O_FILENAME__) || fs6.constants.UV_FS_O_FILEMAP || 0;
|
|
24141
24911
|
var fMapEnabled = isWindows2 && !!UV_FS_O_FILEMAP;
|
|
@@ -24247,9 +25017,9 @@ class SymlinkError extends Error {
|
|
|
24247
25017
|
symlink;
|
|
24248
25018
|
syscall = "symlink";
|
|
24249
25019
|
code = "TAR_SYMLINK_ERROR";
|
|
24250
|
-
constructor(
|
|
25020
|
+
constructor(symlink2, path5) {
|
|
24251
25021
|
super("TAR_SYMLINK_ERROR: Cannot extract through symbolic link");
|
|
24252
|
-
this.symlink =
|
|
25022
|
+
this.symlink = symlink2;
|
|
24253
25023
|
this.path = path5;
|
|
24254
25024
|
}
|
|
24255
25025
|
get name() {
|
|
@@ -24266,7 +25036,7 @@ var checkCwd = (dir, cb) => {
|
|
|
24266
25036
|
cb(er);
|
|
24267
25037
|
});
|
|
24268
25038
|
};
|
|
24269
|
-
var
|
|
25039
|
+
var mkdir5 = (dir, opt, cb) => {
|
|
24270
25040
|
dir = normalizeWindowsPath(dir);
|
|
24271
25041
|
const umask = opt.umask ?? 18;
|
|
24272
25042
|
const mode = opt.mode | 448;
|
|
@@ -24275,7 +25045,7 @@ var mkdir4 = (dir, opt, cb) => {
|
|
|
24275
25045
|
const gid = opt.gid;
|
|
24276
25046
|
const doChown = typeof uid === "number" && typeof gid === "number" && (uid !== opt.processUid || gid !== opt.processGid);
|
|
24277
25047
|
const preserve = opt.preserve;
|
|
24278
|
-
const
|
|
25048
|
+
const unlink4 = opt.unlink;
|
|
24279
25049
|
const cwd = normalizeWindowsPath(opt.cwd);
|
|
24280
25050
|
const done = (er, created) => {
|
|
24281
25051
|
if (er) {
|
|
@@ -24298,30 +25068,30 @@ var mkdir4 = (dir, opt, cb) => {
|
|
|
24298
25068
|
}
|
|
24299
25069
|
const sub = normalizeWindowsPath(path5.relative(cwd, dir));
|
|
24300
25070
|
const parts = sub.split("/");
|
|
24301
|
-
mkdir_(cwd, parts, mode,
|
|
25071
|
+
mkdir_(cwd, parts, mode, unlink4, cwd, undefined, done);
|
|
24302
25072
|
};
|
|
24303
|
-
var mkdir_ = (base, parts, mode,
|
|
25073
|
+
var mkdir_ = (base, parts, mode, unlink4, cwd, created, cb) => {
|
|
24304
25074
|
if (!parts.length) {
|
|
24305
25075
|
return cb(null, created);
|
|
24306
25076
|
}
|
|
24307
25077
|
const p = parts.shift();
|
|
24308
25078
|
const part = normalizeWindowsPath(path5.resolve(base + "/" + p));
|
|
24309
|
-
fs8.mkdir(part, mode, onmkdir(part, parts, mode,
|
|
25079
|
+
fs8.mkdir(part, mode, onmkdir(part, parts, mode, unlink4, cwd, created, cb));
|
|
24310
25080
|
};
|
|
24311
|
-
var onmkdir = (part, parts, mode,
|
|
25081
|
+
var onmkdir = (part, parts, mode, unlink4, cwd, created, cb) => (er) => {
|
|
24312
25082
|
if (er) {
|
|
24313
25083
|
fs8.lstat(part, (statEr, st) => {
|
|
24314
25084
|
if (statEr) {
|
|
24315
25085
|
statEr.path = statEr.path && normalizeWindowsPath(statEr.path);
|
|
24316
25086
|
cb(statEr);
|
|
24317
25087
|
} else if (st.isDirectory()) {
|
|
24318
|
-
mkdir_(part, parts, mode,
|
|
24319
|
-
} else if (
|
|
25088
|
+
mkdir_(part, parts, mode, unlink4, cwd, created, cb);
|
|
25089
|
+
} else if (unlink4) {
|
|
24320
25090
|
fs8.unlink(part, (er2) => {
|
|
24321
25091
|
if (er2) {
|
|
24322
25092
|
return cb(er2);
|
|
24323
25093
|
}
|
|
24324
|
-
fs8.mkdir(part, mode, onmkdir(part, parts, mode,
|
|
25094
|
+
fs8.mkdir(part, mode, onmkdir(part, parts, mode, unlink4, cwd, created, cb));
|
|
24325
25095
|
});
|
|
24326
25096
|
} else if (st.isSymbolicLink()) {
|
|
24327
25097
|
return cb(new SymlinkError(part, part + "/" + parts.join("/")));
|
|
@@ -24331,7 +25101,7 @@ var onmkdir = (part, parts, mode, unlink2, cwd, created, cb) => (er) => {
|
|
|
24331
25101
|
});
|
|
24332
25102
|
} else {
|
|
24333
25103
|
created = created || part;
|
|
24334
|
-
mkdir_(part, parts, mode,
|
|
25104
|
+
mkdir_(part, parts, mode, unlink4, cwd, created, cb);
|
|
24335
25105
|
}
|
|
24336
25106
|
};
|
|
24337
25107
|
var checkCwdSync = (dir) => {
|
|
@@ -24356,7 +25126,7 @@ var mkdirSync = (dir, opt) => {
|
|
|
24356
25126
|
const gid = opt.gid;
|
|
24357
25127
|
const doChown = typeof uid === "number" && typeof gid === "number" && (uid !== opt.processUid || gid !== opt.processGid);
|
|
24358
25128
|
const preserve = opt.preserve;
|
|
24359
|
-
const
|
|
25129
|
+
const unlink4 = opt.unlink;
|
|
24360
25130
|
const cwd = normalizeWindowsPath(opt.cwd);
|
|
24361
25131
|
const done = (created2) => {
|
|
24362
25132
|
if (created2 && doChown) {
|
|
@@ -24385,7 +25155,7 @@ var mkdirSync = (dir, opt) => {
|
|
|
24385
25155
|
const st = fs8.lstatSync(part);
|
|
24386
25156
|
if (st.isDirectory()) {
|
|
24387
25157
|
continue;
|
|
24388
|
-
} else if (
|
|
25158
|
+
} else if (unlink4) {
|
|
24389
25159
|
fs8.unlinkSync(part);
|
|
24390
25160
|
fs8.mkdirSync(part, mode);
|
|
24391
25161
|
created = created || part;
|
|
@@ -24399,7 +25169,7 @@ var mkdirSync = (dir, opt) => {
|
|
|
24399
25169
|
};
|
|
24400
25170
|
|
|
24401
25171
|
// node_modules/tar/dist/esm/path-reservations.js
|
|
24402
|
-
import { join as
|
|
25172
|
+
import { join as join10 } from "node:path";
|
|
24403
25173
|
|
|
24404
25174
|
// node_modules/tar/dist/esm/normalize-unicode.js
|
|
24405
25175
|
var normalizeCache = Object.create(null);
|
|
@@ -24426,13 +25196,13 @@ var normalizeUnicode = (s) => {
|
|
|
24426
25196
|
};
|
|
24427
25197
|
|
|
24428
25198
|
// node_modules/tar/dist/esm/path-reservations.js
|
|
24429
|
-
var
|
|
24430
|
-
var isWindows3 =
|
|
25199
|
+
var platform6 = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform;
|
|
25200
|
+
var isWindows3 = platform6 === "win32";
|
|
24431
25201
|
var getDirs = (path6) => {
|
|
24432
25202
|
const dirs = path6.split("/").slice(0, -1).reduce((set, path7) => {
|
|
24433
25203
|
const s = set[set.length - 1];
|
|
24434
25204
|
if (s !== undefined) {
|
|
24435
|
-
path7 =
|
|
25205
|
+
path7 = join10(s, path7);
|
|
24436
25206
|
}
|
|
24437
25207
|
set.push(path7 || "/");
|
|
24438
25208
|
return set;
|
|
@@ -24446,7 +25216,7 @@ class PathReservations {
|
|
|
24446
25216
|
#running = new Set;
|
|
24447
25217
|
reserve(paths, fn) {
|
|
24448
25218
|
paths = isWindows3 ? ["win32 parallelization disabled"] : paths.map((p) => {
|
|
24449
|
-
return stripTrailingSlashes(
|
|
25219
|
+
return stripTrailingSlashes(join10(normalizeUnicode(p))).toLowerCase();
|
|
24450
25220
|
});
|
|
24451
25221
|
const dirs = new Set(paths.map((path6) => getDirs(path6)).reduce((a3, b3) => a3.concat(b3)));
|
|
24452
25222
|
this.#reservations.set(fn, { dirs, paths });
|
|
@@ -24573,8 +25343,8 @@ var DOCHOWN = Symbol("doChown");
|
|
|
24573
25343
|
var UID = Symbol("uid");
|
|
24574
25344
|
var GID = Symbol("gid");
|
|
24575
25345
|
var CHECKED_CWD = Symbol("checkedCwd");
|
|
24576
|
-
var
|
|
24577
|
-
var isWindows4 =
|
|
25346
|
+
var platform7 = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform;
|
|
25347
|
+
var isWindows4 = platform7 === "win32";
|
|
24578
25348
|
var DEFAULT_MAX_DEPTH = 1024;
|
|
24579
25349
|
var unlinkFile = (path7, cb) => {
|
|
24580
25350
|
if (!isWindows4) {
|
|
@@ -24789,7 +25559,7 @@ class Unpack extends Parser {
|
|
|
24789
25559
|
}
|
|
24790
25560
|
}
|
|
24791
25561
|
[MKDIR](dir, mode, cb) {
|
|
24792
|
-
|
|
25562
|
+
mkdir5(normalizeWindowsPath(dir), {
|
|
24793
25563
|
uid: this.uid,
|
|
24794
25564
|
gid: this.gid,
|
|
24795
25565
|
processUid: this.processUid,
|
|
@@ -25216,9 +25986,9 @@ var extractFile = (opt, _3) => {
|
|
|
25216
25986
|
const u = new Unpack(opt);
|
|
25217
25987
|
const readSize = opt.maxReadSize || 16 * 1024 * 1024;
|
|
25218
25988
|
const file = opt.file;
|
|
25219
|
-
const p = new Promise((
|
|
25989
|
+
const p = new Promise((resolve2, reject) => {
|
|
25220
25990
|
u.on("error", reject);
|
|
25221
|
-
u.on("close",
|
|
25991
|
+
u.on("close", resolve2);
|
|
25222
25992
|
fs10.stat(file, (er, stat3) => {
|
|
25223
25993
|
if (er) {
|
|
25224
25994
|
reject(er);
|
|
@@ -25351,7 +26121,7 @@ var replaceAsync = (opt, files) => {
|
|
|
25351
26121
|
};
|
|
25352
26122
|
fs11.read(fd, headBuf, 0, 512, position, onread);
|
|
25353
26123
|
};
|
|
25354
|
-
const promise = new Promise((
|
|
26124
|
+
const promise = new Promise((resolve2, reject) => {
|
|
25355
26125
|
p.on("error", reject);
|
|
25356
26126
|
let flag = "r+";
|
|
25357
26127
|
const onopen = (er, fd) => {
|
|
@@ -25376,7 +26146,7 @@ var replaceAsync = (opt, files) => {
|
|
|
25376
26146
|
});
|
|
25377
26147
|
p.pipe(stream);
|
|
25378
26148
|
stream.on("error", reject);
|
|
25379
|
-
stream.on("close",
|
|
26149
|
+
stream.on("close", resolve2);
|
|
25380
26150
|
addFilesAsync2(p, files);
|
|
25381
26151
|
});
|
|
25382
26152
|
});
|
|
@@ -26843,8 +27613,8 @@ class DownloadManager {
|
|
|
26843
27613
|
}
|
|
26844
27614
|
}
|
|
26845
27615
|
isPathSafe(basePath, targetPath) {
|
|
26846
|
-
const resolvedBase =
|
|
26847
|
-
const resolvedTarget =
|
|
27616
|
+
const resolvedBase = resolve2(basePath);
|
|
27617
|
+
const resolvedTarget = resolve2(targetPath);
|
|
26848
27618
|
const relativePath = relative2(resolvedBase, resolvedTarget);
|
|
26849
27619
|
return !relativePath.startsWith("..") && !relativePath.startsWith("/") && resolvedTarget.startsWith(resolvedBase);
|
|
26850
27620
|
}
|
|
@@ -26859,8 +27629,8 @@ class DownloadManager {
|
|
|
26859
27629
|
}
|
|
26860
27630
|
async downloadAsset(asset, destDir) {
|
|
26861
27631
|
try {
|
|
26862
|
-
const destPath =
|
|
26863
|
-
await
|
|
27632
|
+
const destPath = join11(destDir, asset.name);
|
|
27633
|
+
await mkdir6(destDir, { recursive: true });
|
|
26864
27634
|
logger.info(`Downloading ${asset.name} (${this.formatBytes(asset.size)})...`);
|
|
26865
27635
|
const progressBar = new import_cli_progress.default.SingleBar({
|
|
26866
27636
|
format: "Progress |{bar}| {percentage}% | {value}/{total} MB",
|
|
@@ -26909,8 +27679,8 @@ class DownloadManager {
|
|
|
26909
27679
|
}
|
|
26910
27680
|
async downloadFile(params) {
|
|
26911
27681
|
const { url, name: name2, size, destDir, token } = params;
|
|
26912
|
-
const destPath =
|
|
26913
|
-
await
|
|
27682
|
+
const destPath = join11(destDir, name2);
|
|
27683
|
+
await mkdir6(destDir, { recursive: true });
|
|
26914
27684
|
logger.info(`Downloading ${name2}${size ? ` (${this.formatBytes(size)})` : ""}...`);
|
|
26915
27685
|
const headers = {};
|
|
26916
27686
|
if (token && url.includes("api.github.com")) {
|
|
@@ -26974,7 +27744,7 @@ class DownloadManager {
|
|
|
26974
27744
|
try {
|
|
26975
27745
|
this.resetExtractionSize();
|
|
26976
27746
|
const detectedType = archiveType || this.detectArchiveType(archivePath);
|
|
26977
|
-
await
|
|
27747
|
+
await mkdir6(destDir, { recursive: true });
|
|
26978
27748
|
if (detectedType === "tar.gz") {
|
|
26979
27749
|
await this.extractTarGz(archivePath, destDir);
|
|
26980
27750
|
} else if (detectedType === "zip") {
|
|
@@ -26994,7 +27764,7 @@ class DownloadManager {
|
|
|
26994
27764
|
}
|
|
26995
27765
|
}
|
|
26996
27766
|
async extractTarGz(archivePath, destDir) {
|
|
26997
|
-
const { readdir:
|
|
27767
|
+
const { readdir: readdir4, stat: stat3, mkdir: mkdirPromise, copyFile, rm } = await import("node:fs/promises");
|
|
26998
27768
|
const { join: pathJoin } = await import("node:path");
|
|
26999
27769
|
const tempExtractDir = `${destDir}-temp`;
|
|
27000
27770
|
await mkdirPromise(tempExtractDir, { recursive: true });
|
|
@@ -27013,14 +27783,14 @@ class DownloadManager {
|
|
|
27013
27783
|
}
|
|
27014
27784
|
});
|
|
27015
27785
|
logger.debug(`Extracted TAR.GZ to temp: ${tempExtractDir}`);
|
|
27016
|
-
const entries = await
|
|
27786
|
+
const entries = await readdir4(tempExtractDir, { encoding: "utf8" });
|
|
27017
27787
|
logger.debug(`Root entries: ${entries.join(", ")}`);
|
|
27018
27788
|
if (entries.length === 1) {
|
|
27019
27789
|
const rootEntry = entries[0];
|
|
27020
27790
|
const rootPath = pathJoin(tempExtractDir, rootEntry);
|
|
27021
27791
|
const rootStat = await stat3(rootPath);
|
|
27022
27792
|
if (rootStat.isDirectory()) {
|
|
27023
|
-
const rootContents = await
|
|
27793
|
+
const rootContents = await readdir4(rootPath, { encoding: "utf8" });
|
|
27024
27794
|
logger.debug(`Root directory '${rootEntry}' contains: ${rootContents.join(", ")}`);
|
|
27025
27795
|
const isWrapper = this.isWrapperDirectory(rootEntry);
|
|
27026
27796
|
logger.debug(`Is wrapper directory: ${isWrapper}`);
|
|
@@ -27057,26 +27827,26 @@ class DownloadManager {
|
|
|
27057
27827
|
if (!isMacOS()) {
|
|
27058
27828
|
return false;
|
|
27059
27829
|
}
|
|
27060
|
-
return new Promise((
|
|
27830
|
+
return new Promise((resolve3) => {
|
|
27061
27831
|
const { mkdir: mkdirPromise } = __require("node:fs/promises");
|
|
27062
27832
|
mkdirPromise(destDir, { recursive: true }).then(() => {
|
|
27063
27833
|
execFile("unzip", ["-o", "-q", archivePath, "-d", destDir], (error, _stdout, stderr) => {
|
|
27064
27834
|
if (error) {
|
|
27065
27835
|
logger.debug(`Native unzip failed: ${stderr || error.message}`);
|
|
27066
|
-
|
|
27836
|
+
resolve3(false);
|
|
27067
27837
|
return;
|
|
27068
27838
|
}
|
|
27069
27839
|
logger.debug("Native unzip succeeded");
|
|
27070
|
-
|
|
27840
|
+
resolve3(true);
|
|
27071
27841
|
});
|
|
27072
27842
|
}).catch((err) => {
|
|
27073
27843
|
logger.debug(`Failed to create directory for native unzip: ${err.message}`);
|
|
27074
|
-
|
|
27844
|
+
resolve3(false);
|
|
27075
27845
|
});
|
|
27076
27846
|
});
|
|
27077
27847
|
}
|
|
27078
27848
|
async extractZip(archivePath, destDir) {
|
|
27079
|
-
const { readdir:
|
|
27849
|
+
const { readdir: readdir4, stat: stat3, mkdir: mkdirPromise, copyFile, rm } = await import("node:fs/promises");
|
|
27080
27850
|
const { join: pathJoin } = await import("node:path");
|
|
27081
27851
|
const tempExtractDir = `${destDir}-temp`;
|
|
27082
27852
|
await mkdirPromise(tempExtractDir, { recursive: true });
|
|
@@ -27095,14 +27865,14 @@ class DownloadManager {
|
|
|
27095
27865
|
await import_extract_zip.default(archivePath, zipOptions);
|
|
27096
27866
|
}
|
|
27097
27867
|
logger.debug(`Extracted ZIP to temp: ${tempExtractDir}`);
|
|
27098
|
-
const entries = await
|
|
27868
|
+
const entries = await readdir4(tempExtractDir, { encoding: "utf8" });
|
|
27099
27869
|
logger.debug(`Root entries: ${entries.join(", ")}`);
|
|
27100
27870
|
if (entries.length === 1) {
|
|
27101
27871
|
const rootEntry = entries[0];
|
|
27102
27872
|
const rootPath = pathJoin(tempExtractDir, rootEntry);
|
|
27103
27873
|
const rootStat = await stat3(rootPath);
|
|
27104
27874
|
if (rootStat.isDirectory()) {
|
|
27105
|
-
const rootContents = await
|
|
27875
|
+
const rootContents = await readdir4(rootPath, { encoding: "utf8" });
|
|
27106
27876
|
logger.debug(`Root directory '${rootEntry}' contains: ${rootContents.join(", ")}`);
|
|
27107
27877
|
const isWrapper = this.isWrapperDirectory(rootEntry);
|
|
27108
27878
|
logger.debug(`Is wrapper directory: ${isWrapper}`);
|
|
@@ -27131,10 +27901,10 @@ class DownloadManager {
|
|
|
27131
27901
|
}
|
|
27132
27902
|
}
|
|
27133
27903
|
async moveDirectoryContents(sourceDir, destDir) {
|
|
27134
|
-
const { readdir:
|
|
27904
|
+
const { readdir: readdir4, stat: stat3, mkdir: mkdirPromise, copyFile } = await import("node:fs/promises");
|
|
27135
27905
|
const { join: pathJoin, relative: relative3 } = await import("node:path");
|
|
27136
27906
|
await mkdirPromise(destDir, { recursive: true });
|
|
27137
|
-
const entries = await
|
|
27907
|
+
const entries = await readdir4(sourceDir, { encoding: "utf8" });
|
|
27138
27908
|
for (const entry of entries) {
|
|
27139
27909
|
const sourcePath = pathJoin(sourceDir, entry);
|
|
27140
27910
|
const destPath = pathJoin(destDir, entry);
|
|
@@ -27157,10 +27927,10 @@ class DownloadManager {
|
|
|
27157
27927
|
}
|
|
27158
27928
|
}
|
|
27159
27929
|
async copyDirectory(sourceDir, destDir) {
|
|
27160
|
-
const { readdir:
|
|
27930
|
+
const { readdir: readdir4, stat: stat3, mkdir: mkdirPromise, copyFile } = await import("node:fs/promises");
|
|
27161
27931
|
const { join: pathJoin, relative: relative3 } = await import("node:path");
|
|
27162
27932
|
await mkdirPromise(destDir, { recursive: true });
|
|
27163
|
-
const entries = await
|
|
27933
|
+
const entries = await readdir4(sourceDir, { encoding: "utf8" });
|
|
27164
27934
|
for (const entry of entries) {
|
|
27165
27935
|
const sourcePath = pathJoin(sourceDir, entry);
|
|
27166
27936
|
const destPath = pathJoin(destDir, entry);
|
|
@@ -27192,11 +27962,11 @@ class DownloadManager {
|
|
|
27192
27962
|
throw new ExtractionError(`Cannot detect archive type from filename: ${filename}`);
|
|
27193
27963
|
}
|
|
27194
27964
|
async validateExtraction(extractDir) {
|
|
27195
|
-
const { readdir:
|
|
27965
|
+
const { readdir: readdir4, access: access3 } = await import("node:fs/promises");
|
|
27196
27966
|
const { join: pathJoin } = await import("node:path");
|
|
27197
|
-
const { constants:
|
|
27967
|
+
const { constants: constants4 } = await import("node:fs");
|
|
27198
27968
|
try {
|
|
27199
|
-
const entries = await
|
|
27969
|
+
const entries = await readdir4(extractDir, { encoding: "utf8" });
|
|
27200
27970
|
logger.debug(`Extracted files: ${entries.join(", ")}`);
|
|
27201
27971
|
if (entries.length === 0) {
|
|
27202
27972
|
throw new ExtractionError("Extraction resulted in no files");
|
|
@@ -27205,7 +27975,7 @@ class DownloadManager {
|
|
|
27205
27975
|
const missingPaths = [];
|
|
27206
27976
|
for (const path8 of criticalPaths) {
|
|
27207
27977
|
try {
|
|
27208
|
-
await
|
|
27978
|
+
await access3(pathJoin(extractDir, path8), constants4.F_OK);
|
|
27209
27979
|
logger.debug(`✓ Found: ${path8}`);
|
|
27210
27980
|
} catch {
|
|
27211
27981
|
logger.warning(`Expected path not found: ${path8}`);
|
|
@@ -27226,9 +27996,9 @@ class DownloadManager {
|
|
|
27226
27996
|
async createTempDir() {
|
|
27227
27997
|
const timestamp = Date.now();
|
|
27228
27998
|
const counter = DownloadManager.tempDirCounter++;
|
|
27229
|
-
const primaryTempDir =
|
|
27999
|
+
const primaryTempDir = join11(tmpdir2(), `claudekit-${timestamp}-${counter}`);
|
|
27230
28000
|
try {
|
|
27231
|
-
await
|
|
28001
|
+
await mkdir6(primaryTempDir, { recursive: true });
|
|
27232
28002
|
logger.debug(`Created temp directory: ${primaryTempDir}`);
|
|
27233
28003
|
return primaryTempDir;
|
|
27234
28004
|
} catch (primaryError) {
|
|
@@ -27242,9 +28012,9 @@ Solutions:
|
|
|
27242
28012
|
2. Set HOME environment variable
|
|
27243
28013
|
3. Try running from a different directory`);
|
|
27244
28014
|
}
|
|
27245
|
-
const fallbackTempDir =
|
|
28015
|
+
const fallbackTempDir = join11(homeDir, ".claudekit", "tmp", `claudekit-${timestamp}-${counter}`);
|
|
27246
28016
|
try {
|
|
27247
|
-
await
|
|
28017
|
+
await mkdir6(fallbackTempDir, { recursive: true });
|
|
27248
28018
|
logger.debug(`Created temp directory (fallback): ${fallbackTempDir}`);
|
|
27249
28019
|
logger.warning(`Using fallback temp directory: ${fallbackTempDir}
|
|
27250
28020
|
(OS temp directory was not accessible)`);
|
|
@@ -27279,8 +28049,8 @@ Solutions:
|
|
|
27279
28049
|
init_types2();
|
|
27280
28050
|
init_logger();
|
|
27281
28051
|
var import_fs_extra4 = __toESM(require_lib(), 1);
|
|
27282
|
-
import { readFile as
|
|
27283
|
-
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";
|
|
27284
28054
|
var TRANSFORMABLE_FILE_PATTERNS = [
|
|
27285
28055
|
".md",
|
|
27286
28056
|
".txt",
|
|
@@ -27326,34 +28096,34 @@ async function transformFolderPaths(extractDir, folders, options = {}) {
|
|
|
27326
28096
|
}
|
|
27327
28097
|
const dirsToRename = [];
|
|
27328
28098
|
if (folders.docs !== DEFAULT_FOLDERS.docs) {
|
|
27329
|
-
const docsPath =
|
|
28099
|
+
const docsPath = join12(extractDir, DEFAULT_FOLDERS.docs);
|
|
27330
28100
|
if (await import_fs_extra4.pathExists(docsPath)) {
|
|
27331
28101
|
dirsToRename.push({
|
|
27332
28102
|
from: docsPath,
|
|
27333
|
-
to:
|
|
28103
|
+
to: join12(extractDir, folders.docs)
|
|
27334
28104
|
});
|
|
27335
28105
|
}
|
|
27336
|
-
const claudeDocsPath =
|
|
28106
|
+
const claudeDocsPath = join12(extractDir, ".claude", DEFAULT_FOLDERS.docs);
|
|
27337
28107
|
if (await import_fs_extra4.pathExists(claudeDocsPath)) {
|
|
27338
28108
|
dirsToRename.push({
|
|
27339
28109
|
from: claudeDocsPath,
|
|
27340
|
-
to:
|
|
28110
|
+
to: join12(extractDir, ".claude", folders.docs)
|
|
27341
28111
|
});
|
|
27342
28112
|
}
|
|
27343
28113
|
}
|
|
27344
28114
|
if (folders.plans !== DEFAULT_FOLDERS.plans) {
|
|
27345
|
-
const plansPath =
|
|
28115
|
+
const plansPath = join12(extractDir, DEFAULT_FOLDERS.plans);
|
|
27346
28116
|
if (await import_fs_extra4.pathExists(plansPath)) {
|
|
27347
28117
|
dirsToRename.push({
|
|
27348
28118
|
from: plansPath,
|
|
27349
|
-
to:
|
|
28119
|
+
to: join12(extractDir, folders.plans)
|
|
27350
28120
|
});
|
|
27351
28121
|
}
|
|
27352
|
-
const claudePlansPath =
|
|
28122
|
+
const claudePlansPath = join12(extractDir, ".claude", DEFAULT_FOLDERS.plans);
|
|
27353
28123
|
if (await import_fs_extra4.pathExists(claudePlansPath)) {
|
|
27354
28124
|
dirsToRename.push({
|
|
27355
28125
|
from: claudePlansPath,
|
|
27356
|
-
to:
|
|
28126
|
+
to: join12(extractDir, ".claude", folders.plans)
|
|
27357
28127
|
});
|
|
27358
28128
|
}
|
|
27359
28129
|
}
|
|
@@ -27388,9 +28158,9 @@ async function transformFolderPaths(extractDir, folders, options = {}) {
|
|
|
27388
28158
|
async function transformFileContents(dir, compiledReplacements, options) {
|
|
27389
28159
|
let filesChanged = 0;
|
|
27390
28160
|
let replacementsCount = 0;
|
|
27391
|
-
const entries = await
|
|
28161
|
+
const entries = await readdir4(dir, { withFileTypes: true });
|
|
27392
28162
|
for (const entry of entries) {
|
|
27393
|
-
const fullPath =
|
|
28163
|
+
const fullPath = join12(dir, entry.name);
|
|
27394
28164
|
if (entry.isDirectory()) {
|
|
27395
28165
|
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
27396
28166
|
continue;
|
|
@@ -27403,7 +28173,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
27403
28173
|
if (!shouldTransform)
|
|
27404
28174
|
continue;
|
|
27405
28175
|
try {
|
|
27406
|
-
const content = await
|
|
28176
|
+
const content = await readFile7(fullPath, "utf-8");
|
|
27407
28177
|
let newContent = content;
|
|
27408
28178
|
let changeCount = 0;
|
|
27409
28179
|
for (const { regex: regex2, replacement } of compiledReplacements) {
|
|
@@ -27419,7 +28189,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
27419
28189
|
if (options.dryRun) {
|
|
27420
28190
|
logger.debug(`[dry-run] Would update ${relative3(dir, fullPath)}: ${changeCount} replacement(s)`);
|
|
27421
28191
|
} else {
|
|
27422
|
-
await
|
|
28192
|
+
await writeFile6(fullPath, newContent, "utf-8");
|
|
27423
28193
|
logger.debug(`Updated ${relative3(dir, fullPath)}: ${changeCount} replacement(s)`);
|
|
27424
28194
|
}
|
|
27425
28195
|
filesChanged++;
|
|
@@ -27500,7 +28270,7 @@ function validateFolderName(name2) {
|
|
|
27500
28270
|
// src/lib/fresh-installer.ts
|
|
27501
28271
|
init_logger();
|
|
27502
28272
|
var import_fs_extra5 = __toESM(require_lib(), 1);
|
|
27503
|
-
import { join as
|
|
28273
|
+
import { join as join13 } from "node:path";
|
|
27504
28274
|
var CLAUDEKIT_SUBDIRECTORIES = ["commands", "agents", "skills", "workflows", "hooks"];
|
|
27505
28275
|
async function handleFreshInstallation(claudeDir, prompts) {
|
|
27506
28276
|
if (!await import_fs_extra5.pathExists(claudeDir)) {
|
|
@@ -27518,7 +28288,7 @@ async function handleFreshInstallation(claudeDir, prompts) {
|
|
|
27518
28288
|
const { rmSync } = await import("node:fs");
|
|
27519
28289
|
let removedCount = 0;
|
|
27520
28290
|
for (const subdir of CLAUDEKIT_SUBDIRECTORIES) {
|
|
27521
|
-
const subdirPath =
|
|
28291
|
+
const subdirPath = join13(claudeDir, subdir);
|
|
27522
28292
|
if (await import_fs_extra5.pathExists(subdirPath)) {
|
|
27523
28293
|
rmSync(subdirPath, { recursive: true, force: true });
|
|
27524
28294
|
removedCount++;
|
|
@@ -27535,11 +28305,11 @@ async function handleFreshInstallation(claudeDir, prompts) {
|
|
|
27535
28305
|
|
|
27536
28306
|
// src/lib/global-path-transformer.ts
|
|
27537
28307
|
init_logger();
|
|
27538
|
-
import { readFile as
|
|
27539
|
-
import { platform as
|
|
27540
|
-
import { extname, join as
|
|
27541
|
-
var
|
|
27542
|
-
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";
|
|
27543
28313
|
function getHomeDirPrefix() {
|
|
27544
28314
|
return HOME_PREFIX;
|
|
27545
28315
|
}
|
|
@@ -27560,7 +28330,7 @@ function transformContent(content) {
|
|
|
27560
28330
|
let transformed = content;
|
|
27561
28331
|
const homePrefix = getHomeDirPrefix();
|
|
27562
28332
|
const claudePath = `${homePrefix}/.claude/`;
|
|
27563
|
-
if (
|
|
28333
|
+
if (IS_WINDOWS2) {
|
|
27564
28334
|
transformed = transformed.replace(/\$HOME\/\.claude\//g, () => {
|
|
27565
28335
|
changes++;
|
|
27566
28336
|
return claudePath;
|
|
@@ -27627,9 +28397,9 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
|
27627
28397
|
let filesSkipped = 0;
|
|
27628
28398
|
const skippedFiles = [];
|
|
27629
28399
|
async function processDirectory(dir) {
|
|
27630
|
-
const entries = await
|
|
28400
|
+
const entries = await readdir5(dir, { withFileTypes: true });
|
|
27631
28401
|
for (const entry of entries) {
|
|
27632
|
-
const fullPath =
|
|
28402
|
+
const fullPath = join14(dir, entry.name);
|
|
27633
28403
|
if (entry.isDirectory()) {
|
|
27634
28404
|
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
27635
28405
|
continue;
|
|
@@ -27637,10 +28407,10 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
|
27637
28407
|
await processDirectory(fullPath);
|
|
27638
28408
|
} else if (entry.isFile() && shouldTransformFile(entry.name)) {
|
|
27639
28409
|
try {
|
|
27640
|
-
const content = await
|
|
28410
|
+
const content = await readFile8(fullPath, "utf-8");
|
|
27641
28411
|
const { transformed, changes } = transformContent(content);
|
|
27642
28412
|
if (changes > 0) {
|
|
27643
|
-
await
|
|
28413
|
+
await writeFile7(fullPath, transformed, "utf-8");
|
|
27644
28414
|
filesTransformed++;
|
|
27645
28415
|
totalChanges += changes;
|
|
27646
28416
|
if (options.verbose) {
|
|
@@ -27670,7 +28440,7 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
|
27670
28440
|
init_dist2();
|
|
27671
28441
|
var import_fs_extra6 = __toESM(require_lib(), 1);
|
|
27672
28442
|
var import_ignore2 = __toESM(require_ignore(), 1);
|
|
27673
|
-
import { dirname as
|
|
28443
|
+
import { dirname as dirname4, join as join15, relative as relative4 } from "node:path";
|
|
27674
28444
|
|
|
27675
28445
|
// node_modules/@isaacs/balanced-match/dist/esm/index.js
|
|
27676
28446
|
var balanced = (a3, b3, str) => {
|
|
@@ -29146,7 +29916,7 @@ class FileMerger {
|
|
|
29146
29916
|
for (const file of files) {
|
|
29147
29917
|
const relativePath = relative4(sourceDir, file);
|
|
29148
29918
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
29149
|
-
const destPath =
|
|
29919
|
+
const destPath = join15(destDir, relativePath);
|
|
29150
29920
|
if (await import_fs_extra6.pathExists(destPath)) {
|
|
29151
29921
|
if (this.neverCopyChecker.ignores(normalizedRelativePath)) {
|
|
29152
29922
|
logger.debug(`Security-sensitive file exists but won't be overwritten: ${normalizedRelativePath}`);
|
|
@@ -29168,7 +29938,7 @@ class FileMerger {
|
|
|
29168
29938
|
for (const file of files) {
|
|
29169
29939
|
const relativePath = relative4(sourceDir, file);
|
|
29170
29940
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
29171
|
-
const destPath =
|
|
29941
|
+
const destPath = join15(destDir, relativePath);
|
|
29172
29942
|
if (this.neverCopyChecker.ignores(normalizedRelativePath)) {
|
|
29173
29943
|
logger.debug(`Skipping security-sensitive file: ${normalizedRelativePath}`);
|
|
29174
29944
|
skippedCount++;
|
|
@@ -29238,7 +30008,7 @@ class FileMerger {
|
|
|
29238
30008
|
const files = [];
|
|
29239
30009
|
const entries = await import_fs_extra6.readdir(dir, { encoding: "utf8" });
|
|
29240
30010
|
for (const entry of entries) {
|
|
29241
|
-
const fullPath =
|
|
30011
|
+
const fullPath = join15(dir, entry);
|
|
29242
30012
|
const relativePath = relative4(baseDir, fullPath);
|
|
29243
30013
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
29244
30014
|
const stats = await import_fs_extra6.lstat(fullPath);
|
|
@@ -29289,10 +30059,10 @@ class FileMerger {
|
|
|
29289
30059
|
}
|
|
29290
30060
|
trackInstalledFile(relativePath) {
|
|
29291
30061
|
this.installedFiles.add(relativePath);
|
|
29292
|
-
let dir =
|
|
30062
|
+
let dir = dirname4(relativePath);
|
|
29293
30063
|
while (dir && dir !== "." && dir !== "/") {
|
|
29294
30064
|
this.installedDirectories.add(`${dir}/`);
|
|
29295
|
-
dir =
|
|
30065
|
+
dir = dirname4(dir);
|
|
29296
30066
|
}
|
|
29297
30067
|
}
|
|
29298
30068
|
}
|
|
@@ -29300,14 +30070,14 @@ class FileMerger {
|
|
|
29300
30070
|
// src/lib/migration/legacy-migration.ts
|
|
29301
30071
|
init_logger();
|
|
29302
30072
|
var import_fs_extra8 = __toESM(require_lib(), 1);
|
|
29303
|
-
import { readdir as
|
|
29304
|
-
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";
|
|
29305
30075
|
|
|
29306
30076
|
// src/lib/migration/release-manifest.ts
|
|
29307
30077
|
init_zod();
|
|
29308
30078
|
init_logger();
|
|
29309
30079
|
var import_fs_extra7 = __toESM(require_lib(), 1);
|
|
29310
|
-
import { join as
|
|
30080
|
+
import { join as join16 } from "node:path";
|
|
29311
30081
|
var ReleaseManifestFileSchema = exports_external.object({
|
|
29312
30082
|
path: exports_external.string(),
|
|
29313
30083
|
checksum: exports_external.string().regex(/^[a-f0-9]{64}$/),
|
|
@@ -29321,7 +30091,7 @@ var ReleaseManifestSchema = exports_external.object({
|
|
|
29321
30091
|
|
|
29322
30092
|
class ReleaseManifestLoader {
|
|
29323
30093
|
static async load(extractDir) {
|
|
29324
|
-
const manifestPath =
|
|
30094
|
+
const manifestPath = join16(extractDir, "release-manifest.json");
|
|
29325
30095
|
try {
|
|
29326
30096
|
const content = await import_fs_extra7.readFile(manifestPath, "utf-8");
|
|
29327
30097
|
const parsed = JSON.parse(content);
|
|
@@ -29352,7 +30122,7 @@ class LegacyMigration {
|
|
|
29352
30122
|
const files = [];
|
|
29353
30123
|
let entries;
|
|
29354
30124
|
try {
|
|
29355
|
-
entries = await
|
|
30125
|
+
entries = await readdir7(dir);
|
|
29356
30126
|
} catch (err) {
|
|
29357
30127
|
const error = err;
|
|
29358
30128
|
if (error.code === "ENOENT") {
|
|
@@ -29367,7 +30137,7 @@ class LegacyMigration {
|
|
|
29367
30137
|
for (const entry of entries) {
|
|
29368
30138
|
if (entry === "metadata.json")
|
|
29369
30139
|
continue;
|
|
29370
|
-
const fullPath =
|
|
30140
|
+
const fullPath = join17(dir, entry);
|
|
29371
30141
|
let stats;
|
|
29372
30142
|
try {
|
|
29373
30143
|
stats = await stat3(fullPath);
|
|
@@ -29469,7 +30239,7 @@ User-created files (sample):`);
|
|
|
29469
30239
|
];
|
|
29470
30240
|
if (filesToChecksum.length > 0) {
|
|
29471
30241
|
const checksumResults = await Promise.all(filesToChecksum.map(async ({ relativePath, ownership }) => {
|
|
29472
|
-
const fullPath =
|
|
30242
|
+
const fullPath = join17(claudeDir, relativePath);
|
|
29473
30243
|
const checksum = await OwnershipChecker.calculateChecksum(fullPath);
|
|
29474
30244
|
return { relativePath, checksum, ownership };
|
|
29475
30245
|
}));
|
|
@@ -29490,7 +30260,7 @@ User-created files (sample):`);
|
|
|
29490
30260
|
installedAt: new Date().toISOString(),
|
|
29491
30261
|
files: trackedFiles
|
|
29492
30262
|
};
|
|
29493
|
-
const metadataPath =
|
|
30263
|
+
const metadataPath = join17(claudeDir, "metadata.json");
|
|
29494
30264
|
await import_fs_extra8.writeFile(metadataPath, JSON.stringify(updatedMetadata, null, 2));
|
|
29495
30265
|
logger.success(`Migration complete: tracked ${trackedFiles.length} files`);
|
|
29496
30266
|
return true;
|
|
@@ -30099,11 +30869,11 @@ class PromptsManager {
|
|
|
30099
30869
|
init_dist2();
|
|
30100
30870
|
init_logger();
|
|
30101
30871
|
var import_fs_extra10 = __toESM(require_lib(), 1);
|
|
30102
|
-
import { join as
|
|
30872
|
+
import { join as join21 } from "node:path";
|
|
30103
30873
|
|
|
30104
30874
|
// src/lib/config-generator.ts
|
|
30105
30875
|
var import_fs_extra9 = __toESM(require_lib(), 1);
|
|
30106
|
-
import { join as
|
|
30876
|
+
import { join as join20 } from "node:path";
|
|
30107
30877
|
async function generateEnvFile(targetDir, values) {
|
|
30108
30878
|
const lines = [
|
|
30109
30879
|
"# Generated by ClaudeKit CLI setup wizard",
|
|
@@ -30115,7 +30885,7 @@ async function generateEnvFile(targetDir, values) {
|
|
|
30115
30885
|
lines.push(`${key}=${value}`);
|
|
30116
30886
|
}
|
|
30117
30887
|
}
|
|
30118
|
-
const envPath =
|
|
30888
|
+
const envPath = join20(targetDir, ".env");
|
|
30119
30889
|
await import_fs_extra9.writeFile(envPath, `${lines.join(`
|
|
30120
30890
|
`)}
|
|
30121
30891
|
`, { mode: 384 });
|
|
@@ -30186,7 +30956,7 @@ async function parseEnvFile(path9) {
|
|
|
30186
30956
|
}
|
|
30187
30957
|
}
|
|
30188
30958
|
async function checkGlobalConfig() {
|
|
30189
|
-
const globalEnvPath =
|
|
30959
|
+
const globalEnvPath = join21(PathResolver.getGlobalKitDir(), ".env");
|
|
30190
30960
|
if (!await import_fs_extra10.pathExists(globalEnvPath))
|
|
30191
30961
|
return false;
|
|
30192
30962
|
const env2 = await parseEnvFile(globalEnvPath);
|
|
@@ -30202,7 +30972,7 @@ async function runSetupWizard(options) {
|
|
|
30202
30972
|
let globalEnv = {};
|
|
30203
30973
|
const hasGlobalConfig = !isGlobal && await checkGlobalConfig();
|
|
30204
30974
|
if (!isGlobal) {
|
|
30205
|
-
const globalEnvPath =
|
|
30975
|
+
const globalEnvPath = join21(PathResolver.getGlobalKitDir(), ".env");
|
|
30206
30976
|
if (await import_fs_extra10.pathExists(globalEnvPath)) {
|
|
30207
30977
|
globalEnv = await parseEnvFile(globalEnvPath);
|
|
30208
30978
|
}
|
|
@@ -30255,23 +31025,23 @@ async function runSetupWizard(options) {
|
|
|
30255
31025
|
}
|
|
30256
31026
|
}
|
|
30257
31027
|
await generateEnvFile(targetDir, values);
|
|
30258
|
-
f2.success(`Configuration saved to ${
|
|
31028
|
+
f2.success(`Configuration saved to ${join21(targetDir, ".env")}`);
|
|
30259
31029
|
return true;
|
|
30260
31030
|
}
|
|
30261
31031
|
|
|
30262
31032
|
// src/lib/skills-detector.ts
|
|
30263
31033
|
init_logger();
|
|
30264
31034
|
var import_fs_extra12 = __toESM(require_lib(), 1);
|
|
30265
|
-
import { readdir as
|
|
30266
|
-
import { join as
|
|
31035
|
+
import { readdir as readdir9 } from "node:fs/promises";
|
|
31036
|
+
import { join as join23 } from "node:path";
|
|
30267
31037
|
|
|
30268
31038
|
// src/lib/skills-manifest.ts
|
|
30269
31039
|
init_types2();
|
|
30270
31040
|
init_logger();
|
|
30271
31041
|
var import_fs_extra11 = __toESM(require_lib(), 1);
|
|
30272
31042
|
import { createHash as createHash2 } from "node:crypto";
|
|
30273
|
-
import { readFile as
|
|
30274
|
-
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";
|
|
30275
31045
|
|
|
30276
31046
|
class SkillsManifestManager {
|
|
30277
31047
|
static MANIFEST_FILENAME = ".skills-manifest.json";
|
|
@@ -30293,18 +31063,18 @@ class SkillsManifestManager {
|
|
|
30293
31063
|
return manifest;
|
|
30294
31064
|
}
|
|
30295
31065
|
static async writeManifest(skillsDir, manifest) {
|
|
30296
|
-
const manifestPath =
|
|
30297
|
-
await
|
|
31066
|
+
const manifestPath = join22(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
|
|
31067
|
+
await writeFile11(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
30298
31068
|
logger.debug(`Wrote manifest to: ${manifestPath}`);
|
|
30299
31069
|
}
|
|
30300
31070
|
static async readManifest(skillsDir) {
|
|
30301
|
-
const manifestPath =
|
|
31071
|
+
const manifestPath = join22(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
|
|
30302
31072
|
if (!await import_fs_extra11.pathExists(manifestPath)) {
|
|
30303
31073
|
logger.debug(`No manifest found at: ${manifestPath}`);
|
|
30304
31074
|
return null;
|
|
30305
31075
|
}
|
|
30306
31076
|
try {
|
|
30307
|
-
const content = await
|
|
31077
|
+
const content = await readFile12(manifestPath, "utf-8");
|
|
30308
31078
|
const data = JSON.parse(content);
|
|
30309
31079
|
const manifest = SkillsManifestSchema.parse(data);
|
|
30310
31080
|
logger.debug(`Read manifest from: ${manifestPath}`);
|
|
@@ -30315,14 +31085,14 @@ class SkillsManifestManager {
|
|
|
30315
31085
|
}
|
|
30316
31086
|
}
|
|
30317
31087
|
static async detectStructure(skillsDir) {
|
|
30318
|
-
const entries = await
|
|
31088
|
+
const entries = await readdir8(skillsDir, { withFileTypes: true });
|
|
30319
31089
|
const dirs = entries.filter((entry) => entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith("."));
|
|
30320
31090
|
if (dirs.length === 0) {
|
|
30321
31091
|
return "flat";
|
|
30322
31092
|
}
|
|
30323
31093
|
for (const dir of dirs.slice(0, 3)) {
|
|
30324
|
-
const dirPath =
|
|
30325
|
-
const subEntries = await
|
|
31094
|
+
const dirPath = join22(skillsDir, dir.name);
|
|
31095
|
+
const subEntries = await readdir8(dirPath, { withFileTypes: true });
|
|
30326
31096
|
const hasSubdirs = subEntries.some((entry) => entry.isDirectory());
|
|
30327
31097
|
if (hasSubdirs) {
|
|
30328
31098
|
return "categorized";
|
|
@@ -30337,10 +31107,10 @@ class SkillsManifestManager {
|
|
|
30337
31107
|
static async scanSkills(skillsDir, structure) {
|
|
30338
31108
|
const skills = [];
|
|
30339
31109
|
if (structure === "flat") {
|
|
30340
|
-
const entries = await
|
|
31110
|
+
const entries = await readdir8(skillsDir, { withFileTypes: true });
|
|
30341
31111
|
for (const entry of entries) {
|
|
30342
31112
|
if (entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith(".")) {
|
|
30343
|
-
const skillPath =
|
|
31113
|
+
const skillPath = join22(skillsDir, entry.name);
|
|
30344
31114
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
30345
31115
|
skills.push({
|
|
30346
31116
|
name: entry.name,
|
|
@@ -30349,14 +31119,14 @@ class SkillsManifestManager {
|
|
|
30349
31119
|
}
|
|
30350
31120
|
}
|
|
30351
31121
|
} else {
|
|
30352
|
-
const categories = await
|
|
31122
|
+
const categories = await readdir8(skillsDir, { withFileTypes: true });
|
|
30353
31123
|
for (const category of categories) {
|
|
30354
31124
|
if (category.isDirectory() && category.name !== "node_modules" && !category.name.startsWith(".")) {
|
|
30355
|
-
const categoryPath =
|
|
30356
|
-
const skillEntries = await
|
|
31125
|
+
const categoryPath = join22(skillsDir, category.name);
|
|
31126
|
+
const skillEntries = await readdir8(categoryPath, { withFileTypes: true });
|
|
30357
31127
|
for (const skillEntry of skillEntries) {
|
|
30358
31128
|
if (skillEntry.isDirectory() && !skillEntry.name.startsWith(".")) {
|
|
30359
|
-
const skillPath =
|
|
31129
|
+
const skillPath = join22(categoryPath, skillEntry.name);
|
|
30360
31130
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
30361
31131
|
skills.push({
|
|
30362
31132
|
name: skillEntry.name,
|
|
@@ -30376,7 +31146,7 @@ class SkillsManifestManager {
|
|
|
30376
31146
|
files.sort();
|
|
30377
31147
|
for (const file of files) {
|
|
30378
31148
|
const relativePath = relative6(dirPath, file);
|
|
30379
|
-
const content = await
|
|
31149
|
+
const content = await readFile12(file);
|
|
30380
31150
|
hash.update(relativePath);
|
|
30381
31151
|
hash.update(content);
|
|
30382
31152
|
}
|
|
@@ -30384,9 +31154,9 @@ class SkillsManifestManager {
|
|
|
30384
31154
|
}
|
|
30385
31155
|
static async getAllFiles(dirPath) {
|
|
30386
31156
|
const files = [];
|
|
30387
|
-
const entries = await
|
|
31157
|
+
const entries = await readdir8(dirPath, { withFileTypes: true });
|
|
30388
31158
|
for (const entry of entries) {
|
|
30389
|
-
const fullPath =
|
|
31159
|
+
const fullPath = join22(dirPath, entry.name);
|
|
30390
31160
|
if (entry.name.startsWith(".") || entry.name === "node_modules") {
|
|
30391
31161
|
continue;
|
|
30392
31162
|
}
|
|
@@ -30621,7 +31391,7 @@ class SkillsMigrationDetector {
|
|
|
30621
31391
|
if (!await import_fs_extra12.pathExists(skillsDir)) {
|
|
30622
31392
|
return ["flat", []];
|
|
30623
31393
|
}
|
|
30624
|
-
const entries = await
|
|
31394
|
+
const entries = await readdir9(skillsDir, { withFileTypes: true });
|
|
30625
31395
|
const dirs = entries.filter((entry) => entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith("."));
|
|
30626
31396
|
if (dirs.length === 0) {
|
|
30627
31397
|
return ["flat", []];
|
|
@@ -30629,13 +31399,13 @@ class SkillsMigrationDetector {
|
|
|
30629
31399
|
let totalSkillLikeCount = 0;
|
|
30630
31400
|
const allSkills = [];
|
|
30631
31401
|
for (const dir of dirs) {
|
|
30632
|
-
const dirPath =
|
|
30633
|
-
const subEntries = await
|
|
31402
|
+
const dirPath = join23(skillsDir, dir.name);
|
|
31403
|
+
const subEntries = await readdir9(dirPath, { withFileTypes: true });
|
|
30634
31404
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
30635
31405
|
if (subdirs.length > 0) {
|
|
30636
31406
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
30637
|
-
const subdirPath =
|
|
30638
|
-
const subdirFiles = await
|
|
31407
|
+
const subdirPath = join23(dirPath, subdir.name);
|
|
31408
|
+
const subdirFiles = await readdir9(subdirPath, { withFileTypes: true });
|
|
30639
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"));
|
|
30640
31410
|
if (hasSkillMarker) {
|
|
30641
31411
|
totalSkillLikeCount++;
|
|
@@ -30672,21 +31442,21 @@ class SkillsMigrationDetector {
|
|
|
30672
31442
|
init_types2();
|
|
30673
31443
|
init_logger();
|
|
30674
31444
|
var import_fs_extra15 = __toESM(require_lib(), 1);
|
|
30675
|
-
import { copyFile as copyFile2, mkdir as
|
|
30676
|
-
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";
|
|
30677
31447
|
|
|
30678
31448
|
// src/lib/skills-backup-manager.ts
|
|
30679
31449
|
init_types2();
|
|
30680
31450
|
init_logger();
|
|
30681
31451
|
var import_fs_extra13 = __toESM(require_lib(), 1);
|
|
30682
|
-
import { copyFile, mkdir as
|
|
30683
|
-
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";
|
|
30684
31454
|
function validatePath2(path9, paramName) {
|
|
30685
31455
|
if (!path9 || typeof path9 !== "string") {
|
|
30686
31456
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
30687
31457
|
}
|
|
30688
31458
|
if (path9.includes("..")) {
|
|
30689
|
-
const normalized =
|
|
31459
|
+
const normalized = normalize4(path9);
|
|
30690
31460
|
if (normalized.startsWith("..")) {
|
|
30691
31461
|
throw new SkillsMigrationError(`${paramName} contains invalid path traversal: ${path9}`);
|
|
30692
31462
|
}
|
|
@@ -30706,10 +31476,10 @@ class SkillsBackupManager {
|
|
|
30706
31476
|
const timestamp = Date.now();
|
|
30707
31477
|
const randomSuffix = Math.random().toString(36).substring(2, 8);
|
|
30708
31478
|
const backupDirName = `${SkillsBackupManager.BACKUP_PREFIX}${timestamp}-${randomSuffix}`;
|
|
30709
|
-
const backupDir = parentDir ?
|
|
31479
|
+
const backupDir = parentDir ? join24(parentDir, backupDirName) : join24(skillsDir, "..", backupDirName);
|
|
30710
31480
|
logger.info(`Creating backup at: ${backupDir}`);
|
|
30711
31481
|
try {
|
|
30712
|
-
await
|
|
31482
|
+
await mkdir7(backupDir, { recursive: true });
|
|
30713
31483
|
await SkillsBackupManager.copyDirectory(skillsDir, backupDir);
|
|
30714
31484
|
logger.success("Backup created successfully");
|
|
30715
31485
|
return backupDir;
|
|
@@ -30731,7 +31501,7 @@ class SkillsBackupManager {
|
|
|
30731
31501
|
if (await import_fs_extra13.pathExists(targetDir)) {
|
|
30732
31502
|
await rm(targetDir, { recursive: true, force: true });
|
|
30733
31503
|
}
|
|
30734
|
-
await
|
|
31504
|
+
await mkdir7(targetDir, { recursive: true });
|
|
30735
31505
|
await SkillsBackupManager.copyDirectory(backupDir, targetDir);
|
|
30736
31506
|
logger.success("Backup restored successfully");
|
|
30737
31507
|
} catch (error) {
|
|
@@ -30756,8 +31526,8 @@ class SkillsBackupManager {
|
|
|
30756
31526
|
return [];
|
|
30757
31527
|
}
|
|
30758
31528
|
try {
|
|
30759
|
-
const entries = await
|
|
30760
|
-
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));
|
|
30761
31531
|
backups.sort().reverse();
|
|
30762
31532
|
return backups;
|
|
30763
31533
|
} catch (error) {
|
|
@@ -30783,15 +31553,15 @@ class SkillsBackupManager {
|
|
|
30783
31553
|
return await SkillsBackupManager.getDirectorySize(backupDir);
|
|
30784
31554
|
}
|
|
30785
31555
|
static async copyDirectory(sourceDir, destDir) {
|
|
30786
|
-
const entries = await
|
|
31556
|
+
const entries = await readdir10(sourceDir, { withFileTypes: true });
|
|
30787
31557
|
for (const entry of entries) {
|
|
30788
|
-
const sourcePath =
|
|
30789
|
-
const destPath =
|
|
31558
|
+
const sourcePath = join24(sourceDir, entry.name);
|
|
31559
|
+
const destPath = join24(destDir, entry.name);
|
|
30790
31560
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
30791
31561
|
continue;
|
|
30792
31562
|
}
|
|
30793
31563
|
if (entry.isDirectory()) {
|
|
30794
|
-
await
|
|
31564
|
+
await mkdir7(destPath, { recursive: true });
|
|
30795
31565
|
await SkillsBackupManager.copyDirectory(sourcePath, destPath);
|
|
30796
31566
|
} else if (entry.isFile()) {
|
|
30797
31567
|
await copyFile(sourcePath, destPath);
|
|
@@ -30800,9 +31570,9 @@ class SkillsBackupManager {
|
|
|
30800
31570
|
}
|
|
30801
31571
|
static async getDirectorySize(dirPath) {
|
|
30802
31572
|
let size = 0;
|
|
30803
|
-
const entries = await
|
|
31573
|
+
const entries = await readdir10(dirPath, { withFileTypes: true });
|
|
30804
31574
|
for (const entry of entries) {
|
|
30805
|
-
const fullPath =
|
|
31575
|
+
const fullPath = join24(dirPath, entry.name);
|
|
30806
31576
|
if (entry.isSymbolicLink()) {
|
|
30807
31577
|
continue;
|
|
30808
31578
|
}
|
|
@@ -30832,14 +31602,14 @@ init_logger();
|
|
|
30832
31602
|
var import_fs_extra14 = __toESM(require_lib(), 1);
|
|
30833
31603
|
import { createHash as createHash3 } from "node:crypto";
|
|
30834
31604
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
30835
|
-
import { readFile as
|
|
30836
|
-
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";
|
|
30837
31607
|
function validatePath3(path9, paramName) {
|
|
30838
31608
|
if (!path9 || typeof path9 !== "string") {
|
|
30839
31609
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
30840
31610
|
}
|
|
30841
31611
|
if (path9.includes("..")) {
|
|
30842
|
-
const normalized =
|
|
31612
|
+
const normalized = normalize5(path9);
|
|
30843
31613
|
if (normalized.startsWith("..")) {
|
|
30844
31614
|
throw new SkillsMigrationError(`${paramName} contains invalid path traversal: ${path9}`);
|
|
30845
31615
|
}
|
|
@@ -30975,19 +31745,19 @@ class SkillsCustomizationScanner {
|
|
|
30975
31745
|
if (!await import_fs_extra14.pathExists(skillsDir)) {
|
|
30976
31746
|
return ["flat", []];
|
|
30977
31747
|
}
|
|
30978
|
-
const entries = await
|
|
31748
|
+
const entries = await readdir11(skillsDir, { withFileTypes: true });
|
|
30979
31749
|
const dirs = entries.filter((entry) => entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith("."));
|
|
30980
31750
|
if (dirs.length === 0) {
|
|
30981
31751
|
return ["flat", []];
|
|
30982
31752
|
}
|
|
30983
|
-
const firstDirPath =
|
|
30984
|
-
const subEntries = await
|
|
31753
|
+
const firstDirPath = join25(skillsDir, dirs[0].name);
|
|
31754
|
+
const subEntries = await readdir11(firstDirPath, { withFileTypes: true });
|
|
30985
31755
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
30986
31756
|
if (subdirs.length > 0) {
|
|
30987
31757
|
let skillLikeCount = 0;
|
|
30988
31758
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
30989
|
-
const subdirPath =
|
|
30990
|
-
const subdirFiles = await
|
|
31759
|
+
const subdirPath = join25(firstDirPath, subdir.name);
|
|
31760
|
+
const subdirFiles = await readdir11(subdirPath, { withFileTypes: true });
|
|
30991
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"));
|
|
30992
31762
|
if (hasSkillMarker) {
|
|
30993
31763
|
skillLikeCount++;
|
|
@@ -30996,8 +31766,8 @@ class SkillsCustomizationScanner {
|
|
|
30996
31766
|
if (skillLikeCount > 0) {
|
|
30997
31767
|
const skills = [];
|
|
30998
31768
|
for (const dir of dirs) {
|
|
30999
|
-
const categoryPath =
|
|
31000
|
-
const skillDirs = await
|
|
31769
|
+
const categoryPath = join25(skillsDir, dir.name);
|
|
31770
|
+
const skillDirs = await readdir11(categoryPath, { withFileTypes: true });
|
|
31001
31771
|
skills.push(...skillDirs.filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name));
|
|
31002
31772
|
}
|
|
31003
31773
|
return ["categorized", skills];
|
|
@@ -31006,17 +31776,17 @@ class SkillsCustomizationScanner {
|
|
|
31006
31776
|
return ["flat", dirs.map((dir) => dir.name)];
|
|
31007
31777
|
}
|
|
31008
31778
|
static async findSkillPath(skillsDir, skillName) {
|
|
31009
|
-
const flatPath =
|
|
31779
|
+
const flatPath = join25(skillsDir, skillName);
|
|
31010
31780
|
if (await import_fs_extra14.pathExists(flatPath)) {
|
|
31011
31781
|
return { path: flatPath, category: undefined };
|
|
31012
31782
|
}
|
|
31013
|
-
const entries = await
|
|
31783
|
+
const entries = await readdir11(skillsDir, { withFileTypes: true });
|
|
31014
31784
|
for (const entry of entries) {
|
|
31015
31785
|
if (!entry.isDirectory() || entry.name.startsWith(".") || entry.name === "node_modules") {
|
|
31016
31786
|
continue;
|
|
31017
31787
|
}
|
|
31018
|
-
const categoryPath =
|
|
31019
|
-
const skillPath =
|
|
31788
|
+
const categoryPath = join25(skillsDir, entry.name);
|
|
31789
|
+
const skillPath = join25(categoryPath, skillName);
|
|
31020
31790
|
if (await import_fs_extra14.pathExists(skillPath)) {
|
|
31021
31791
|
return { path: skillPath, category: entry.name };
|
|
31022
31792
|
}
|
|
@@ -31025,9 +31795,9 @@ class SkillsCustomizationScanner {
|
|
|
31025
31795
|
}
|
|
31026
31796
|
static async getAllFiles(dirPath) {
|
|
31027
31797
|
const files = [];
|
|
31028
|
-
const entries = await
|
|
31798
|
+
const entries = await readdir11(dirPath, { withFileTypes: true });
|
|
31029
31799
|
for (const entry of entries) {
|
|
31030
|
-
const fullPath =
|
|
31800
|
+
const fullPath = join25(dirPath, entry.name);
|
|
31031
31801
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
31032
31802
|
continue;
|
|
31033
31803
|
}
|
|
@@ -31041,12 +31811,12 @@ class SkillsCustomizationScanner {
|
|
|
31041
31811
|
return files;
|
|
31042
31812
|
}
|
|
31043
31813
|
static async hashFile(filePath) {
|
|
31044
|
-
return new Promise((
|
|
31814
|
+
return new Promise((resolve4, reject) => {
|
|
31045
31815
|
const hash = createHash3("sha256");
|
|
31046
31816
|
const stream = createReadStream2(filePath);
|
|
31047
31817
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
31048
31818
|
stream.on("end", () => {
|
|
31049
|
-
|
|
31819
|
+
resolve4(hash.digest("hex"));
|
|
31050
31820
|
});
|
|
31051
31821
|
stream.on("error", (error) => {
|
|
31052
31822
|
stream.destroy();
|
|
@@ -31060,7 +31830,7 @@ class SkillsCustomizationScanner {
|
|
|
31060
31830
|
files.sort();
|
|
31061
31831
|
for (const file of files) {
|
|
31062
31832
|
const relativePath = relative7(dirPath, file);
|
|
31063
|
-
const content = await
|
|
31833
|
+
const content = await readFile13(file);
|
|
31064
31834
|
hash.update(relativePath);
|
|
31065
31835
|
hash.update(content);
|
|
31066
31836
|
}
|
|
@@ -31270,7 +32040,7 @@ class SkillsMigrator {
|
|
|
31270
32040
|
}
|
|
31271
32041
|
}
|
|
31272
32042
|
if (options.backup && !options.dryRun) {
|
|
31273
|
-
const claudeDir =
|
|
32043
|
+
const claudeDir = join26(currentSkillsDir, "..");
|
|
31274
32044
|
result.backupPath = await SkillsBackupManager.createBackup(currentSkillsDir, claudeDir);
|
|
31275
32045
|
logger.success(`Backup created at: ${result.backupPath}`);
|
|
31276
32046
|
}
|
|
@@ -31322,8 +32092,8 @@ class SkillsMigrator {
|
|
|
31322
32092
|
const migrated = [];
|
|
31323
32093
|
const preserved = [];
|
|
31324
32094
|
const errors2 = [];
|
|
31325
|
-
const tempDir =
|
|
31326
|
-
await
|
|
32095
|
+
const tempDir = join26(currentSkillsDir, "..", ".skills-migration-temp");
|
|
32096
|
+
await mkdir8(tempDir, { recursive: true });
|
|
31327
32097
|
try {
|
|
31328
32098
|
for (const mapping of mappings) {
|
|
31329
32099
|
try {
|
|
@@ -31343,9 +32113,9 @@ class SkillsMigrator {
|
|
|
31343
32113
|
}
|
|
31344
32114
|
}
|
|
31345
32115
|
const category = mapping.category;
|
|
31346
|
-
const targetPath = category ?
|
|
32116
|
+
const targetPath = category ? join26(tempDir, category, skillName) : join26(tempDir, skillName);
|
|
31347
32117
|
if (category) {
|
|
31348
|
-
await
|
|
32118
|
+
await mkdir8(join26(tempDir, category), { recursive: true });
|
|
31349
32119
|
}
|
|
31350
32120
|
await SkillsMigrator.copySkillDirectory(currentSkillPath, targetPath);
|
|
31351
32121
|
migrated.push(skillName);
|
|
@@ -31364,7 +32134,7 @@ class SkillsMigrator {
|
|
|
31364
32134
|
}
|
|
31365
32135
|
}
|
|
31366
32136
|
await rm2(currentSkillsDir, { recursive: true, force: true });
|
|
31367
|
-
await
|
|
32137
|
+
await mkdir8(currentSkillsDir, { recursive: true });
|
|
31368
32138
|
await SkillsMigrator.copySkillDirectory(tempDir, currentSkillsDir);
|
|
31369
32139
|
await rm2(tempDir, { recursive: true, force: true });
|
|
31370
32140
|
return { migrated, preserved, errors: errors2 };
|
|
@@ -31376,11 +32146,11 @@ class SkillsMigrator {
|
|
|
31376
32146
|
}
|
|
31377
32147
|
}
|
|
31378
32148
|
static async copySkillDirectory(sourceDir, destDir) {
|
|
31379
|
-
await
|
|
31380
|
-
const entries = await
|
|
32149
|
+
await mkdir8(destDir, { recursive: true });
|
|
32150
|
+
const entries = await readdir12(sourceDir, { withFileTypes: true });
|
|
31381
32151
|
for (const entry of entries) {
|
|
31382
|
-
const sourcePath =
|
|
31383
|
-
const destPath =
|
|
32152
|
+
const sourcePath = join26(sourceDir, entry.name);
|
|
32153
|
+
const destPath = join26(destDir, entry.name);
|
|
31384
32154
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
31385
32155
|
continue;
|
|
31386
32156
|
}
|
|
@@ -31400,17 +32170,17 @@ init_types2();
|
|
|
31400
32170
|
init_types2();
|
|
31401
32171
|
init_logger();
|
|
31402
32172
|
import { existsSync as existsSync6 } from "node:fs";
|
|
31403
|
-
import { mkdir as
|
|
32173
|
+
import { mkdir as mkdir9, readFile as readFile14, rename as rename2, rm as rm3, writeFile as writeFile12 } from "node:fs/promises";
|
|
31404
32174
|
import { chmod as chmod2 } from "node:fs/promises";
|
|
31405
|
-
import { platform as
|
|
31406
|
-
import { join as
|
|
32175
|
+
import { platform as platform9 } from "node:os";
|
|
32176
|
+
import { join as join27 } from "node:path";
|
|
31407
32177
|
var PROJECT_CONFIG_FILE = ".ck.json";
|
|
31408
32178
|
|
|
31409
32179
|
class ConfigManager {
|
|
31410
32180
|
static config = null;
|
|
31411
32181
|
static globalFlag = false;
|
|
31412
32182
|
static getProjectConfigDir(projectDir, global3) {
|
|
31413
|
-
return global3 ? projectDir :
|
|
32183
|
+
return global3 ? projectDir : join27(projectDir, ".claude");
|
|
31414
32184
|
}
|
|
31415
32185
|
static setGlobalFlag(global3) {
|
|
31416
32186
|
ConfigManager.globalFlag = global3;
|
|
@@ -31426,7 +32196,7 @@ class ConfigManager {
|
|
|
31426
32196
|
const configFile = PathResolver.getConfigFile(ConfigManager.globalFlag);
|
|
31427
32197
|
try {
|
|
31428
32198
|
if (existsSync6(configFile)) {
|
|
31429
|
-
const content = await
|
|
32199
|
+
const content = await readFile14(configFile, "utf-8");
|
|
31430
32200
|
const data = JSON.parse(content);
|
|
31431
32201
|
ConfigManager.config = ConfigSchema.parse(data);
|
|
31432
32202
|
logger.debug(`Config loaded from ${configFile}`);
|
|
@@ -31444,13 +32214,13 @@ class ConfigManager {
|
|
|
31444
32214
|
const configDir = PathResolver.getConfigDir(ConfigManager.globalFlag);
|
|
31445
32215
|
const configFile = PathResolver.getConfigFile(ConfigManager.globalFlag);
|
|
31446
32216
|
if (!existsSync6(configDir)) {
|
|
31447
|
-
await
|
|
31448
|
-
if (
|
|
32217
|
+
await mkdir9(configDir, { recursive: true });
|
|
32218
|
+
if (platform9() !== "win32") {
|
|
31449
32219
|
await chmod2(configDir, 448);
|
|
31450
32220
|
}
|
|
31451
32221
|
}
|
|
31452
|
-
await
|
|
31453
|
-
if (
|
|
32222
|
+
await writeFile12(configFile, JSON.stringify(validConfig, null, 2), "utf-8");
|
|
32223
|
+
if (platform9() !== "win32") {
|
|
31454
32224
|
await chmod2(configFile, 384);
|
|
31455
32225
|
}
|
|
31456
32226
|
ConfigManager.config = validConfig;
|
|
@@ -31477,10 +32247,10 @@ class ConfigManager {
|
|
|
31477
32247
|
}
|
|
31478
32248
|
static async loadProjectConfig(projectDir, global3 = false) {
|
|
31479
32249
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
31480
|
-
const configPath =
|
|
32250
|
+
const configPath = join27(configDir, PROJECT_CONFIG_FILE);
|
|
31481
32251
|
try {
|
|
31482
32252
|
if (existsSync6(configPath)) {
|
|
31483
|
-
const content = await
|
|
32253
|
+
const content = await readFile14(configPath, "utf-8");
|
|
31484
32254
|
const data = JSON.parse(content);
|
|
31485
32255
|
const folders = FoldersConfigSchema.parse(data.paths || data);
|
|
31486
32256
|
logger.debug(`Project config loaded from ${configPath}`);
|
|
@@ -31493,13 +32263,13 @@ class ConfigManager {
|
|
|
31493
32263
|
}
|
|
31494
32264
|
static async saveProjectConfig(projectDir, folders, global3 = false) {
|
|
31495
32265
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
31496
|
-
const configPath =
|
|
32266
|
+
const configPath = join27(configDir, PROJECT_CONFIG_FILE);
|
|
31497
32267
|
try {
|
|
31498
32268
|
if (!existsSync6(configDir)) {
|
|
31499
|
-
await
|
|
32269
|
+
await mkdir9(configDir, { recursive: true });
|
|
31500
32270
|
}
|
|
31501
32271
|
const validFolders = FoldersConfigSchema.parse(folders);
|
|
31502
|
-
await
|
|
32272
|
+
await writeFile12(configPath, JSON.stringify({ paths: validFolders }, null, 2), "utf-8");
|
|
31503
32273
|
logger.debug(`Project config saved to ${configPath}`);
|
|
31504
32274
|
} catch (error) {
|
|
31505
32275
|
throw new Error(`Failed to save project config: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
@@ -31525,11 +32295,11 @@ class ConfigManager {
|
|
|
31525
32295
|
}
|
|
31526
32296
|
static projectConfigExists(projectDir, global3 = false) {
|
|
31527
32297
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
31528
|
-
return existsSync6(
|
|
32298
|
+
return existsSync6(join27(configDir, PROJECT_CONFIG_FILE));
|
|
31529
32299
|
}
|
|
31530
32300
|
static async migrateNestedConfig(globalDir) {
|
|
31531
|
-
const correctPath =
|
|
31532
|
-
const incorrectPath =
|
|
32301
|
+
const correctPath = join27(globalDir, PROJECT_CONFIG_FILE);
|
|
32302
|
+
const incorrectPath = join27(globalDir, ".claude", PROJECT_CONFIG_FILE);
|
|
31533
32303
|
if (existsSync6(correctPath)) {
|
|
31534
32304
|
logger.debug("Config already exists at correct location, skipping migration");
|
|
31535
32305
|
return false;
|
|
@@ -31539,7 +32309,7 @@ class ConfigManager {
|
|
|
31539
32309
|
logger.info("Migrating .ck.json from nested location to correct location...");
|
|
31540
32310
|
await rename2(incorrectPath, correctPath);
|
|
31541
32311
|
logger.success(`Migrated ${PROJECT_CONFIG_FILE} to ${correctPath}`);
|
|
31542
|
-
const nestedClaudeDir =
|
|
32312
|
+
const nestedClaudeDir = join27(globalDir, ".claude");
|
|
31543
32313
|
try {
|
|
31544
32314
|
await rm3(nestedClaudeDir, { recursive: false });
|
|
31545
32315
|
logger.debug("Removed empty nested .claude directory");
|
|
@@ -31562,7 +32332,7 @@ init_environment();
|
|
|
31562
32332
|
// src/utils/file-scanner.ts
|
|
31563
32333
|
init_logger();
|
|
31564
32334
|
var import_fs_extra16 = __toESM(require_lib(), 1);
|
|
31565
|
-
import { join as
|
|
32335
|
+
import { join as join28, relative as relative8, resolve as resolve4 } from "node:path";
|
|
31566
32336
|
var SKIP_DIRS2 = [
|
|
31567
32337
|
"node_modules",
|
|
31568
32338
|
".venv",
|
|
@@ -31597,7 +32367,7 @@ class FileScanner {
|
|
|
31597
32367
|
logger.debug(`Skipping directory: ${entry}`);
|
|
31598
32368
|
continue;
|
|
31599
32369
|
}
|
|
31600
|
-
const fullPath =
|
|
32370
|
+
const fullPath = join28(dirPath, entry);
|
|
31601
32371
|
if (!FileScanner.isSafePath(basePath, fullPath)) {
|
|
31602
32372
|
logger.warning(`Skipping potentially unsafe path: ${entry}`);
|
|
31603
32373
|
continue;
|
|
@@ -31632,8 +32402,8 @@ class FileScanner {
|
|
|
31632
32402
|
return files;
|
|
31633
32403
|
}
|
|
31634
32404
|
static async findCustomFiles(destDir, sourceDir, subPath) {
|
|
31635
|
-
const destSubDir =
|
|
31636
|
-
const sourceSubDir =
|
|
32405
|
+
const destSubDir = join28(destDir, subPath);
|
|
32406
|
+
const sourceSubDir = join28(sourceDir, subPath);
|
|
31637
32407
|
logger.debug(`findCustomFiles - destDir: ${destDir}`);
|
|
31638
32408
|
logger.debug(`findCustomFiles - sourceDir: ${sourceDir}`);
|
|
31639
32409
|
logger.debug(`findCustomFiles - subPath: "${subPath}"`);
|
|
@@ -31661,8 +32431,8 @@ class FileScanner {
|
|
|
31661
32431
|
return customFiles;
|
|
31662
32432
|
}
|
|
31663
32433
|
static isSafePath(basePath, targetPath) {
|
|
31664
|
-
const resolvedBase =
|
|
31665
|
-
const resolvedTarget =
|
|
32434
|
+
const resolvedBase = resolve4(basePath);
|
|
32435
|
+
const resolvedTarget = resolve4(targetPath);
|
|
31666
32436
|
return resolvedTarget.startsWith(resolvedBase);
|
|
31667
32437
|
}
|
|
31668
32438
|
static toPosixPath(path9) {
|
|
@@ -31688,9 +32458,9 @@ async function initCommand(options) {
|
|
|
31688
32458
|
}
|
|
31689
32459
|
if (validOptions.global) {
|
|
31690
32460
|
const globalKitDir = PathResolver.getGlobalKitDir();
|
|
31691
|
-
const cwdResolved =
|
|
31692
|
-
const isInGlobalDir = cwdResolved === globalKitDir || cwdResolved ===
|
|
31693
|
-
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");
|
|
31694
32464
|
if (!isInGlobalDir && await import_fs_extra17.pathExists(localSettingsPath)) {
|
|
31695
32465
|
if (isNonInteractive2) {
|
|
31696
32466
|
logger.warning("Local .claude/settings.json detected. Local settings take precedence over global.");
|
|
@@ -31702,7 +32472,7 @@ async function initCommand(options) {
|
|
|
31702
32472
|
return;
|
|
31703
32473
|
}
|
|
31704
32474
|
if (choice === "remove") {
|
|
31705
|
-
const localClaudeDir =
|
|
32475
|
+
const localClaudeDir = join29(process.cwd(), ".claude");
|
|
31706
32476
|
try {
|
|
31707
32477
|
await import_fs_extra17.remove(localClaudeDir);
|
|
31708
32478
|
logger.success("Removed local .claude/ directory");
|
|
@@ -31746,12 +32516,12 @@ async function initCommand(options) {
|
|
|
31746
32516
|
}
|
|
31747
32517
|
}
|
|
31748
32518
|
}
|
|
31749
|
-
const resolvedDir =
|
|
32519
|
+
const resolvedDir = resolve5(targetDir);
|
|
31750
32520
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
31751
32521
|
if (!await import_fs_extra17.pathExists(resolvedDir)) {
|
|
31752
32522
|
if (validOptions.global) {
|
|
31753
|
-
const { mkdir:
|
|
31754
|
-
await
|
|
32523
|
+
const { mkdir: mkdir10 } = await import("node:fs/promises");
|
|
32524
|
+
await mkdir10(resolvedDir, { recursive: true });
|
|
31755
32525
|
logger.info(`Created global directory: ${resolvedDir}`);
|
|
31756
32526
|
} else {
|
|
31757
32527
|
logger.error(`Directory does not exist: ${resolvedDir}`);
|
|
@@ -31761,7 +32531,7 @@ async function initCommand(options) {
|
|
|
31761
32531
|
}
|
|
31762
32532
|
if (validOptions.fresh) {
|
|
31763
32533
|
const prefix = PathResolver.getPathPrefix(validOptions.global);
|
|
31764
|
-
const claudeDir2 = prefix ?
|
|
32534
|
+
const claudeDir2 = prefix ? join29(resolvedDir, prefix) : resolvedDir;
|
|
31765
32535
|
const canProceed = await handleFreshInstallation(claudeDir2, prompts);
|
|
31766
32536
|
if (!canProceed) {
|
|
31767
32537
|
return;
|
|
@@ -31898,7 +32668,7 @@ async function initCommand(options) {
|
|
|
31898
32668
|
}
|
|
31899
32669
|
}
|
|
31900
32670
|
if (!validOptions.fresh) {
|
|
31901
|
-
const newSkillsDir =
|
|
32671
|
+
const newSkillsDir = join29(extractDir, ".claude", "skills");
|
|
31902
32672
|
const currentSkillsDir = PathResolver.buildSkillsPath(resolvedDir, validOptions.global);
|
|
31903
32673
|
if (await import_fs_extra17.pathExists(newSkillsDir) && await import_fs_extra17.pathExists(currentSkillsDir)) {
|
|
31904
32674
|
logger.info("Checking for skills directory migration...");
|
|
@@ -31923,7 +32693,7 @@ async function initCommand(options) {
|
|
|
31923
32693
|
let customClaudeFiles = [];
|
|
31924
32694
|
if (!validOptions.fresh) {
|
|
31925
32695
|
logger.info("Scanning for custom .claude files...");
|
|
31926
|
-
const scanSourceDir = validOptions.global ?
|
|
32696
|
+
const scanSourceDir = validOptions.global ? join29(extractDir, ".claude") : extractDir;
|
|
31927
32697
|
const scanTargetSubdir = validOptions.global ? "" : ".claude";
|
|
31928
32698
|
customClaudeFiles = await FileScanner.findCustomFiles(resolvedDir, scanSourceDir, scanTargetSubdir);
|
|
31929
32699
|
} else {
|
|
@@ -31952,7 +32722,7 @@ async function initCommand(options) {
|
|
|
31952
32722
|
merger.addIgnorePatterns(validOptions.exclude);
|
|
31953
32723
|
}
|
|
31954
32724
|
merger.setGlobalFlag(validOptions.global);
|
|
31955
|
-
const claudeDir = validOptions.global ? resolvedDir :
|
|
32725
|
+
const claudeDir = validOptions.global ? resolvedDir : join29(resolvedDir, ".claude");
|
|
31956
32726
|
const releaseManifest = await ReleaseManifestLoader.load(extractDir);
|
|
31957
32727
|
if (!validOptions.fresh && await import_fs_extra17.pathExists(claudeDir)) {
|
|
31958
32728
|
const legacyDetection = await LegacyMigration.detectLegacy(claudeDir);
|
|
@@ -31974,7 +32744,7 @@ async function initCommand(options) {
|
|
|
31974
32744
|
return;
|
|
31975
32745
|
}
|
|
31976
32746
|
}
|
|
31977
|
-
const sourceDir = validOptions.global ?
|
|
32747
|
+
const sourceDir = validOptions.global ? join29(extractDir, ".claude") : extractDir;
|
|
31978
32748
|
await merger.merge(sourceDir, resolvedDir, false);
|
|
31979
32749
|
const manifestWriter = new ManifestWriter;
|
|
31980
32750
|
const installedFiles = merger.getAllInstalledFiles();
|
|
@@ -31983,7 +32753,7 @@ async function initCommand(options) {
|
|
|
31983
32753
|
if (!validOptions.global && !installedPath.startsWith(".claude/"))
|
|
31984
32754
|
continue;
|
|
31985
32755
|
const relativePath = validOptions.global ? installedPath : installedPath.replace(/^\.claude\//, "");
|
|
31986
|
-
const filePath =
|
|
32756
|
+
const filePath = join29(claudeDir, relativePath);
|
|
31987
32757
|
const manifestEntry = releaseManifest ? ReleaseManifestLoader.findFile(releaseManifest, installedPath) : null;
|
|
31988
32758
|
const ownership = manifestEntry ? "ck" : "user";
|
|
31989
32759
|
filesToTrack.push({
|
|
@@ -32004,8 +32774,8 @@ async function initCommand(options) {
|
|
|
32004
32774
|
trackingSpinner.succeed(`Tracked ${trackResult.success} files`);
|
|
32005
32775
|
await manifestWriter.writeManifest(claudeDir, kitConfig.name, release.tag_name, validOptions.global ? "global" : "local");
|
|
32006
32776
|
if (validOptions.global) {
|
|
32007
|
-
const claudeMdSource =
|
|
32008
|
-
const claudeMdDest =
|
|
32777
|
+
const claudeMdSource = join29(extractDir, "CLAUDE.md");
|
|
32778
|
+
const claudeMdDest = join29(resolvedDir, "CLAUDE.md");
|
|
32009
32779
|
if (await import_fs_extra17.pathExists(claudeMdSource)) {
|
|
32010
32780
|
if (!await import_fs_extra17.pathExists(claudeMdDest)) {
|
|
32011
32781
|
await import_fs_extra17.copy(claudeMdSource, claudeMdDest);
|
|
@@ -32025,7 +32795,7 @@ async function initCommand(options) {
|
|
|
32025
32795
|
await handleSkillsInstallation2(skillsDir);
|
|
32026
32796
|
}
|
|
32027
32797
|
if (!validOptions.skipSetup && !isNonInteractive2) {
|
|
32028
|
-
const envPath =
|
|
32798
|
+
const envPath = join29(claudeDir, ".env");
|
|
32029
32799
|
if (!await import_fs_extra17.pathExists(envPath)) {
|
|
32030
32800
|
const shouldSetup = await prompts.confirm("Set up API keys now? (Gemini API key for ai-multimodal skill, optional webhooks)");
|
|
32031
32801
|
if (shouldSetup) {
|
|
@@ -32057,7 +32827,7 @@ Protected files (.env, etc.) were not modified.`;
|
|
|
32057
32827
|
|
|
32058
32828
|
// src/commands/new.ts
|
|
32059
32829
|
var import_fs_extra18 = __toESM(require_lib(), 1);
|
|
32060
|
-
import { join as
|
|
32830
|
+
import { join as join30, resolve as resolve6 } from "node:path";
|
|
32061
32831
|
init_types2();
|
|
32062
32832
|
init_environment();
|
|
32063
32833
|
init_logger();
|
|
@@ -32086,7 +32856,7 @@ async function newCommand(options) {
|
|
|
32086
32856
|
targetDir = await prompts.getDirectory(targetDir);
|
|
32087
32857
|
}
|
|
32088
32858
|
}
|
|
32089
|
-
const resolvedDir =
|
|
32859
|
+
const resolvedDir = resolve6(targetDir);
|
|
32090
32860
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
32091
32861
|
if (await import_fs_extra18.pathExists(resolvedDir)) {
|
|
32092
32862
|
const files = await import_fs_extra18.readdir(resolvedDir);
|
|
@@ -32228,7 +32998,7 @@ async function newCommand(options) {
|
|
|
32228
32998
|
await CommandsPrefix.cleanupCommandsDirectory(resolvedDir, false);
|
|
32229
32999
|
}
|
|
32230
33000
|
await merger.merge(extractDir, resolvedDir, true);
|
|
32231
|
-
const claudeDir =
|
|
33001
|
+
const claudeDir = join30(resolvedDir, ".claude");
|
|
32232
33002
|
const manifestWriter = new ManifestWriter;
|
|
32233
33003
|
const releaseManifest = await ReleaseManifestLoader.load(extractDir);
|
|
32234
33004
|
const installedFiles = merger.getAllInstalledFiles();
|
|
@@ -32237,7 +33007,7 @@ async function newCommand(options) {
|
|
|
32237
33007
|
if (!installedPath.startsWith(".claude/"))
|
|
32238
33008
|
continue;
|
|
32239
33009
|
const relativePath = installedPath.replace(/^\.claude\//, "");
|
|
32240
|
-
const filePath =
|
|
33010
|
+
const filePath = join30(claudeDir, relativePath);
|
|
32241
33011
|
const manifestEntry = releaseManifest ? ReleaseManifestLoader.findFile(releaseManifest, installedPath) : null;
|
|
32242
33012
|
const ownership = manifestEntry ? "ck" : "user";
|
|
32243
33013
|
filesToTrack.push({
|
|
@@ -32293,7 +33063,7 @@ init_dist2();
|
|
|
32293
33063
|
var import_fs_extra19 = __toESM(require_lib(), 1);
|
|
32294
33064
|
var import_picocolors10 = __toESM(require_picocolors(), 1);
|
|
32295
33065
|
import { readdirSync, rmSync } from "node:fs";
|
|
32296
|
-
import { dirname as
|
|
33066
|
+
import { dirname as dirname5, join as join31 } from "node:path";
|
|
32297
33067
|
init_types2();
|
|
32298
33068
|
init_logger();
|
|
32299
33069
|
async function detectInstallations() {
|
|
@@ -32353,7 +33123,7 @@ async function confirmUninstall(scope) {
|
|
|
32353
33123
|
}
|
|
32354
33124
|
async function cleanupEmptyDirectories(filePath, installationRoot) {
|
|
32355
33125
|
let cleaned = 0;
|
|
32356
|
-
let currentDir =
|
|
33126
|
+
let currentDir = dirname5(filePath);
|
|
32357
33127
|
while (currentDir !== installationRoot && currentDir.startsWith(installationRoot)) {
|
|
32358
33128
|
try {
|
|
32359
33129
|
const entries = readdirSync(currentDir);
|
|
@@ -32361,7 +33131,7 @@ async function cleanupEmptyDirectories(filePath, installationRoot) {
|
|
|
32361
33131
|
rmSync(currentDir, { recursive: true });
|
|
32362
33132
|
cleaned++;
|
|
32363
33133
|
logger.debug(`Removed empty directory: ${currentDir}`);
|
|
32364
|
-
currentDir =
|
|
33134
|
+
currentDir = dirname5(currentDir);
|
|
32365
33135
|
} else {
|
|
32366
33136
|
break;
|
|
32367
33137
|
}
|
|
@@ -32384,7 +33154,7 @@ async function analyzeInstallation(installation, forceOverwrite) {
|
|
|
32384
33154
|
return result;
|
|
32385
33155
|
}
|
|
32386
33156
|
for (const trackedFile of metadata.files) {
|
|
32387
|
-
const filePath =
|
|
33157
|
+
const filePath = join31(installation.path, trackedFile.path);
|
|
32388
33158
|
const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
|
|
32389
33159
|
if (!ownershipResult.exists)
|
|
32390
33160
|
continue;
|
|
@@ -32442,7 +33212,7 @@ async function removeInstallations(installations, options) {
|
|
|
32442
33212
|
let removedCount = 0;
|
|
32443
33213
|
let cleanedDirs = 0;
|
|
32444
33214
|
for (const item of analysis.toDelete) {
|
|
32445
|
-
const filePath =
|
|
33215
|
+
const filePath = join31(installation.path, item.path);
|
|
32446
33216
|
if (await import_fs_extra19.pathExists(filePath)) {
|
|
32447
33217
|
await import_fs_extra19.remove(filePath);
|
|
32448
33218
|
removedCount++;
|
|
@@ -32544,7 +33314,7 @@ import { promisify as promisify6 } from "node:util";
|
|
|
32544
33314
|
// package.json
|
|
32545
33315
|
var package_default2 = {
|
|
32546
33316
|
name: "claudekit-cli",
|
|
32547
|
-
version: "3.
|
|
33317
|
+
version: "3.7.0",
|
|
32548
33318
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
32549
33319
|
type: "module",
|
|
32550
33320
|
repository: {
|
|
@@ -32990,14 +33760,14 @@ var import_picocolors12 = __toESM(require_picocolors(), 1);
|
|
|
32990
33760
|
// src/lib/version-cache.ts
|
|
32991
33761
|
init_logger();
|
|
32992
33762
|
import { existsSync as existsSync7 } from "node:fs";
|
|
32993
|
-
import { mkdir as
|
|
32994
|
-
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";
|
|
32995
33765
|
class VersionCacheManager {
|
|
32996
33766
|
static CACHE_FILENAME = "version-check.json";
|
|
32997
33767
|
static CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
32998
33768
|
static getCacheFile() {
|
|
32999
33769
|
const cacheDir = PathResolver.getCacheDir(false);
|
|
33000
|
-
return
|
|
33770
|
+
return join32(cacheDir, VersionCacheManager.CACHE_FILENAME);
|
|
33001
33771
|
}
|
|
33002
33772
|
static async load() {
|
|
33003
33773
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
@@ -33006,7 +33776,7 @@ class VersionCacheManager {
|
|
|
33006
33776
|
logger.debug("Version check cache not found");
|
|
33007
33777
|
return null;
|
|
33008
33778
|
}
|
|
33009
|
-
const content = await
|
|
33779
|
+
const content = await readFile15(cacheFile, "utf-8");
|
|
33010
33780
|
const cache2 = JSON.parse(content);
|
|
33011
33781
|
if (!cache2.lastCheck || !cache2.currentVersion || !cache2.latestVersion) {
|
|
33012
33782
|
logger.debug("Invalid cache structure, ignoring");
|
|
@@ -33024,9 +33794,9 @@ class VersionCacheManager {
|
|
|
33024
33794
|
const cacheDir = PathResolver.getCacheDir(false);
|
|
33025
33795
|
try {
|
|
33026
33796
|
if (!existsSync7(cacheDir)) {
|
|
33027
|
-
await
|
|
33797
|
+
await mkdir10(cacheDir, { recursive: true, mode: 448 });
|
|
33028
33798
|
}
|
|
33029
|
-
await
|
|
33799
|
+
await writeFile13(cacheFile, JSON.stringify(cache2, null, 2), "utf-8");
|
|
33030
33800
|
logger.debug(`Version check cache saved to ${cacheFile}`);
|
|
33031
33801
|
} catch (error) {
|
|
33032
33802
|
logger.debug(`Failed to save version check cache: ${error}`);
|
|
@@ -33472,8 +34242,8 @@ class Logger2 {
|
|
|
33472
34242
|
var logger2 = new Logger2;
|
|
33473
34243
|
|
|
33474
34244
|
// src/utils/path-resolver.ts
|
|
33475
|
-
import { homedir as
|
|
33476
|
-
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";
|
|
33477
34247
|
|
|
33478
34248
|
class PathResolver2 {
|
|
33479
34249
|
static getTestHomeDir() {
|
|
@@ -33492,7 +34262,7 @@ class PathResolver2 {
|
|
|
33492
34262
|
return false;
|
|
33493
34263
|
}
|
|
33494
34264
|
}
|
|
33495
|
-
const normalized =
|
|
34265
|
+
const normalized = normalize6(path9);
|
|
33496
34266
|
for (const pattern of dangerousPatterns) {
|
|
33497
34267
|
if (normalized.includes(pattern)) {
|
|
33498
34268
|
return false;
|
|
@@ -33506,50 +34276,50 @@ class PathResolver2 {
|
|
|
33506
34276
|
static getConfigDir(global3 = false) {
|
|
33507
34277
|
const testHome = PathResolver2.getTestHomeDir();
|
|
33508
34278
|
if (testHome) {
|
|
33509
|
-
return global3 ?
|
|
34279
|
+
return global3 ? join33(testHome, ".config", "claude") : join33(testHome, ".claudekit");
|
|
33510
34280
|
}
|
|
33511
34281
|
if (!global3) {
|
|
33512
|
-
return
|
|
34282
|
+
return join33(homedir4(), ".claudekit");
|
|
33513
34283
|
}
|
|
33514
|
-
const os2 =
|
|
34284
|
+
const os2 = platform10();
|
|
33515
34285
|
if (os2 === "win32") {
|
|
33516
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
33517
|
-
return
|
|
34286
|
+
const localAppData = process.env.LOCALAPPDATA || join33(homedir4(), "AppData", "Local");
|
|
34287
|
+
return join33(localAppData, "claude");
|
|
33518
34288
|
}
|
|
33519
34289
|
const xdgConfigHome = process.env.XDG_CONFIG_HOME;
|
|
33520
34290
|
if (xdgConfigHome) {
|
|
33521
|
-
return
|
|
34291
|
+
return join33(xdgConfigHome, "claude");
|
|
33522
34292
|
}
|
|
33523
|
-
return
|
|
34293
|
+
return join33(homedir4(), ".config", "claude");
|
|
33524
34294
|
}
|
|
33525
34295
|
static getConfigFile(global3 = false) {
|
|
33526
|
-
return
|
|
34296
|
+
return join33(PathResolver2.getConfigDir(global3), "config.json");
|
|
33527
34297
|
}
|
|
33528
34298
|
static getCacheDir(global3 = false) {
|
|
33529
34299
|
const testHome = PathResolver2.getTestHomeDir();
|
|
33530
34300
|
if (testHome) {
|
|
33531
|
-
return global3 ?
|
|
34301
|
+
return global3 ? join33(testHome, ".cache", "claude") : join33(testHome, ".claudekit", "cache");
|
|
33532
34302
|
}
|
|
33533
34303
|
if (!global3) {
|
|
33534
|
-
return
|
|
34304
|
+
return join33(homedir4(), ".claudekit", "cache");
|
|
33535
34305
|
}
|
|
33536
|
-
const os2 =
|
|
34306
|
+
const os2 = platform10();
|
|
33537
34307
|
if (os2 === "win32") {
|
|
33538
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
33539
|
-
return
|
|
34308
|
+
const localAppData = process.env.LOCALAPPDATA || join33(homedir4(), "AppData", "Local");
|
|
34309
|
+
return join33(localAppData, "claude", "cache");
|
|
33540
34310
|
}
|
|
33541
34311
|
const xdgCacheHome = process.env.XDG_CACHE_HOME;
|
|
33542
34312
|
if (xdgCacheHome) {
|
|
33543
|
-
return
|
|
34313
|
+
return join33(xdgCacheHome, "claude");
|
|
33544
34314
|
}
|
|
33545
|
-
return
|
|
34315
|
+
return join33(homedir4(), ".cache", "claude");
|
|
33546
34316
|
}
|
|
33547
34317
|
static getGlobalKitDir() {
|
|
33548
34318
|
const testHome = PathResolver2.getTestHomeDir();
|
|
33549
34319
|
if (testHome) {
|
|
33550
|
-
return
|
|
34320
|
+
return join33(testHome, ".claude");
|
|
33551
34321
|
}
|
|
33552
|
-
return
|
|
34322
|
+
return join33(homedir4(), ".claude");
|
|
33553
34323
|
}
|
|
33554
34324
|
static getPathPrefix(global3) {
|
|
33555
34325
|
return global3 ? "" : ".claude";
|
|
@@ -33557,9 +34327,9 @@ class PathResolver2 {
|
|
|
33557
34327
|
static buildSkillsPath(baseDir, global3) {
|
|
33558
34328
|
const prefix = PathResolver2.getPathPrefix(global3);
|
|
33559
34329
|
if (prefix) {
|
|
33560
|
-
return
|
|
34330
|
+
return join33(baseDir, prefix, "skills");
|
|
33561
34331
|
}
|
|
33562
|
-
return
|
|
34332
|
+
return join33(baseDir, "skills");
|
|
33563
34333
|
}
|
|
33564
34334
|
static buildComponentPath(baseDir, component, global3) {
|
|
33565
34335
|
if (!PathResolver2.isPathSafe(component)) {
|
|
@@ -33567,9 +34337,9 @@ class PathResolver2 {
|
|
|
33567
34337
|
}
|
|
33568
34338
|
const prefix = PathResolver2.getPathPrefix(global3);
|
|
33569
34339
|
if (prefix) {
|
|
33570
|
-
return
|
|
34340
|
+
return join33(baseDir, prefix, component);
|
|
33571
34341
|
}
|
|
33572
|
-
return
|
|
34342
|
+
return join33(baseDir, component);
|
|
33573
34343
|
}
|
|
33574
34344
|
}
|
|
33575
34345
|
|
|
@@ -33587,9 +34357,9 @@ async function displayVersion() {
|
|
|
33587
34357
|
let localKitVersion = null;
|
|
33588
34358
|
let isGlobalOnlyKit = false;
|
|
33589
34359
|
const globalKitDir = PathResolver2.getGlobalKitDir();
|
|
33590
|
-
const globalMetadataPath =
|
|
34360
|
+
const globalMetadataPath = join34(globalKitDir, "metadata.json");
|
|
33591
34361
|
const prefix = PathResolver2.getPathPrefix(false);
|
|
33592
|
-
const localMetadataPath = prefix ?
|
|
34362
|
+
const localMetadataPath = prefix ? join34(process.cwd(), prefix, "metadata.json") : join34(process.cwd(), "metadata.json");
|
|
33593
34363
|
const isLocalSameAsGlobal = localMetadataPath === globalMetadataPath;
|
|
33594
34364
|
if (!isLocalSameAsGlobal && existsSync8(localMetadataPath)) {
|
|
33595
34365
|
try {
|
|
@@ -33689,7 +34459,7 @@ cli.command("update", "Update ClaudeKit CLI to the latest version").option("-r,
|
|
|
33689
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) => {
|
|
33690
34460
|
await versionCommand(options);
|
|
33691
34461
|
});
|
|
33692
|
-
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) => {
|
|
33693
34463
|
await doctorCommand(options);
|
|
33694
34464
|
});
|
|
33695
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) => {
|