claudekit-cli 3.34.1-dev.5 → 3.35.0-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1191 -389
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -45277,7 +45277,7 @@ var package_default;
|
|
|
45277
45277
|
var init_package = __esm(() => {
|
|
45278
45278
|
package_default = {
|
|
45279
45279
|
name: "claudekit-cli",
|
|
45280
|
-
version: "3.
|
|
45280
|
+
version: "3.35.0-dev.1",
|
|
45281
45281
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
45282
45282
|
type: "module",
|
|
45283
45283
|
repository: {
|
|
@@ -50617,7 +50617,7 @@ __export(exports_github_api_checker, {
|
|
|
50617
50617
|
checkRepositoryAccess: () => checkRepositoryAccess,
|
|
50618
50618
|
checkRateLimit: () => checkRateLimit
|
|
50619
50619
|
});
|
|
50620
|
-
import { spawnSync } from "node:child_process";
|
|
50620
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
50621
50621
|
async function checkRateLimit() {
|
|
50622
50622
|
if (false) {}
|
|
50623
50623
|
const apiEndpoint = "api.github.com/rate_limit";
|
|
@@ -50712,7 +50712,7 @@ async function checkTokenScopes() {
|
|
|
50712
50712
|
if (false) {}
|
|
50713
50713
|
const checkCommand = "gh auth status -h github.com";
|
|
50714
50714
|
try {
|
|
50715
|
-
const result =
|
|
50715
|
+
const result = spawnSync2("gh", ["auth", "status", "-h", "github.com"], {
|
|
50716
50716
|
encoding: "utf8",
|
|
50717
50717
|
timeout: COMMAND_TIMEOUT_MS
|
|
50718
50718
|
});
|
|
@@ -52280,7 +52280,7 @@ var require_picomatch2 = __commonJS((exports, module) => {
|
|
|
52280
52280
|
import { exec as exec7, execFile as execFile7, spawn as spawn3 } from "node:child_process";
|
|
52281
52281
|
import { promisify as promisify13 } from "node:util";
|
|
52282
52282
|
function executeInteractiveScript(command, args, options2) {
|
|
52283
|
-
return new Promise((
|
|
52283
|
+
return new Promise((resolve9, reject) => {
|
|
52284
52284
|
const child = spawn3(command, args, {
|
|
52285
52285
|
stdio: ["ignore", "inherit", "inherit"],
|
|
52286
52286
|
cwd: options2?.cwd,
|
|
@@ -52301,7 +52301,7 @@ function executeInteractiveScript(command, args, options2) {
|
|
|
52301
52301
|
} else if (code !== 0) {
|
|
52302
52302
|
reject(new Error(`Command exited with code ${code}`));
|
|
52303
52303
|
} else {
|
|
52304
|
-
|
|
52304
|
+
resolve9();
|
|
52305
52305
|
}
|
|
52306
52306
|
});
|
|
52307
52307
|
child.on("error", (error) => {
|
|
@@ -52322,7 +52322,7 @@ var init_process_executor = __esm(() => {
|
|
|
52322
52322
|
});
|
|
52323
52323
|
|
|
52324
52324
|
// src/services/package-installer/validators.ts
|
|
52325
|
-
import { resolve as
|
|
52325
|
+
import { resolve as resolve9 } from "node:path";
|
|
52326
52326
|
function validatePackageName(packageName) {
|
|
52327
52327
|
if (!packageName || typeof packageName !== "string") {
|
|
52328
52328
|
throw new Error("Package name must be a non-empty string");
|
|
@@ -52335,8 +52335,8 @@ function validatePackageName(packageName) {
|
|
|
52335
52335
|
}
|
|
52336
52336
|
}
|
|
52337
52337
|
function validateScriptPath(skillsDir2, scriptPath) {
|
|
52338
|
-
const skillsDirResolved =
|
|
52339
|
-
const scriptPathResolved =
|
|
52338
|
+
const skillsDirResolved = resolve9(skillsDir2);
|
|
52339
|
+
const scriptPathResolved = resolve9(scriptPath);
|
|
52340
52340
|
const skillsDirNormalized = isWindows() ? skillsDirResolved.toLowerCase() : skillsDirResolved;
|
|
52341
52341
|
const scriptPathNormalized = isWindows() ? scriptPathResolved.toLowerCase() : scriptPathResolved;
|
|
52342
52342
|
if (!scriptPathNormalized.startsWith(skillsDirNormalized)) {
|
|
@@ -52500,7 +52500,7 @@ var init_gemini_installer = __esm(() => {
|
|
|
52500
52500
|
});
|
|
52501
52501
|
|
|
52502
52502
|
// src/services/package-installer/opencode-installer.ts
|
|
52503
|
-
import { join as
|
|
52503
|
+
import { join as join48 } from "node:path";
|
|
52504
52504
|
async function isOpenCodeInstalled() {
|
|
52505
52505
|
try {
|
|
52506
52506
|
await execAsync7("opencode --version", { timeout: 5000 });
|
|
@@ -52522,8 +52522,8 @@ async function installOpenCode() {
|
|
|
52522
52522
|
try {
|
|
52523
52523
|
logger.info(`Installing ${displayName}...`);
|
|
52524
52524
|
const { unlink: unlink8 } = await import("node:fs/promises");
|
|
52525
|
-
const { tmpdir:
|
|
52526
|
-
const tempScriptPath =
|
|
52525
|
+
const { tmpdir: tmpdir4 } = await import("node:os");
|
|
52526
|
+
const tempScriptPath = join48(tmpdir4(), "opencode-install.sh");
|
|
52527
52527
|
try {
|
|
52528
52528
|
logger.info("Downloading OpenCode installation script...");
|
|
52529
52529
|
await execFileAsync5("curl", ["-fsSL", "https://opencode.ai/install", "-o", tempScriptPath], {
|
|
@@ -52574,8 +52574,8 @@ var init_opencode_installer = __esm(() => {
|
|
|
52574
52574
|
var PARTIAL_INSTALL_VERSION = "partial", EXIT_CODE_CRITICAL_FAILURE = 1, EXIT_CODE_PARTIAL_SUCCESS = 2;
|
|
52575
52575
|
|
|
52576
52576
|
// src/services/package-installer/install-error-handler.ts
|
|
52577
|
-
import { existsSync as
|
|
52578
|
-
import { join as
|
|
52577
|
+
import { existsSync as existsSync32, readFileSync as readFileSync8, unlinkSync as unlinkSync2 } from "node:fs";
|
|
52578
|
+
import { join as join49 } from "node:path";
|
|
52579
52579
|
function parseNameReason(str2) {
|
|
52580
52580
|
const colonIndex = str2.indexOf(":");
|
|
52581
52581
|
if (colonIndex === -1) {
|
|
@@ -52584,14 +52584,14 @@ function parseNameReason(str2) {
|
|
|
52584
52584
|
return [str2.slice(0, colonIndex).trim(), str2.slice(colonIndex + 1).trim()];
|
|
52585
52585
|
}
|
|
52586
52586
|
function displayInstallErrors(skillsDir2) {
|
|
52587
|
-
const summaryPath =
|
|
52588
|
-
if (!
|
|
52587
|
+
const summaryPath = join49(skillsDir2, ".install-error-summary.json");
|
|
52588
|
+
if (!existsSync32(summaryPath)) {
|
|
52589
52589
|
logger.error("Skills installation failed. Run with --verbose for details.");
|
|
52590
52590
|
return;
|
|
52591
52591
|
}
|
|
52592
52592
|
let summary;
|
|
52593
52593
|
try {
|
|
52594
|
-
summary = JSON.parse(
|
|
52594
|
+
summary = JSON.parse(readFileSync8(summaryPath, "utf-8"));
|
|
52595
52595
|
} catch (parseError) {
|
|
52596
52596
|
logger.error("Failed to parse error summary. File may be corrupted.");
|
|
52597
52597
|
logger.debug(`Parse error: ${parseError instanceof Error ? parseError.message : String(parseError)}`);
|
|
@@ -52675,8 +52675,8 @@ async function checkNeedsSudoPackages() {
|
|
|
52675
52675
|
}
|
|
52676
52676
|
}
|
|
52677
52677
|
function hasInstallState(skillsDir2) {
|
|
52678
|
-
const stateFilePath =
|
|
52679
|
-
return
|
|
52678
|
+
const stateFilePath = join49(skillsDir2, ".install-state.json");
|
|
52679
|
+
return existsSync32(stateFilePath);
|
|
52680
52680
|
}
|
|
52681
52681
|
var WHICH_COMMAND_TIMEOUT_MS = 5000;
|
|
52682
52682
|
var init_install_error_handler = __esm(() => {
|
|
@@ -52684,7 +52684,7 @@ var init_install_error_handler = __esm(() => {
|
|
|
52684
52684
|
});
|
|
52685
52685
|
|
|
52686
52686
|
// src/services/package-installer/skills-installer.ts
|
|
52687
|
-
import { join as
|
|
52687
|
+
import { join as join50 } from "node:path";
|
|
52688
52688
|
async function installSkillsDependencies(skillsDir2, options2 = {}) {
|
|
52689
52689
|
const { skipConfirm = false, withSudo = false } = options2;
|
|
52690
52690
|
const displayName = "Skills Dependencies";
|
|
@@ -52706,11 +52706,11 @@ async function installSkillsDependencies(skillsDir2, options2 = {}) {
|
|
|
52706
52706
|
};
|
|
52707
52707
|
}
|
|
52708
52708
|
try {
|
|
52709
|
-
const { existsSync:
|
|
52709
|
+
const { existsSync: existsSync33 } = await import("node:fs");
|
|
52710
52710
|
const clack = await Promise.resolve().then(() => (init_dist2(), exports_dist));
|
|
52711
52711
|
const platform7 = process.platform;
|
|
52712
52712
|
const scriptName = platform7 === "win32" ? "install.ps1" : "install.sh";
|
|
52713
|
-
const scriptPath =
|
|
52713
|
+
const scriptPath = join50(skillsDir2, scriptName);
|
|
52714
52714
|
try {
|
|
52715
52715
|
validateScriptPath(skillsDir2, scriptPath);
|
|
52716
52716
|
} catch (error) {
|
|
@@ -52722,11 +52722,11 @@ async function installSkillsDependencies(skillsDir2, options2 = {}) {
|
|
|
52722
52722
|
error: `Path validation failed: ${errorMessage}`
|
|
52723
52723
|
};
|
|
52724
52724
|
}
|
|
52725
|
-
if (!
|
|
52725
|
+
if (!existsSync33(scriptPath)) {
|
|
52726
52726
|
logger.warning(`Skills installation script not found: ${scriptPath}`);
|
|
52727
52727
|
logger.info("");
|
|
52728
52728
|
logger.info("\uD83D\uDCD6 Manual Installation Instructions:");
|
|
52729
|
-
logger.info(` See: ${
|
|
52729
|
+
logger.info(` See: ${join50(skillsDir2, "INSTALLATION.md")}`);
|
|
52730
52730
|
logger.info("");
|
|
52731
52731
|
logger.info("Quick start:");
|
|
52732
52732
|
logger.info(" cd .claude/skills/ai-multimodal/scripts");
|
|
@@ -52773,7 +52773,7 @@ async function installSkillsDependencies(skillsDir2, options2 = {}) {
|
|
|
52773
52773
|
logger.info(` ${platform7 === "win32" ? `powershell -File "${scriptPath}"` : `bash ${scriptPath}`}`);
|
|
52774
52774
|
logger.info("");
|
|
52775
52775
|
logger.info("Or see complete guide:");
|
|
52776
|
-
logger.info(` ${
|
|
52776
|
+
logger.info(` ${join50(skillsDir2, "INSTALLATION.md")}`);
|
|
52777
52777
|
return {
|
|
52778
52778
|
success: false,
|
|
52779
52779
|
package: displayName,
|
|
@@ -52894,7 +52894,7 @@ async function installSkillsDependencies(skillsDir2, options2 = {}) {
|
|
|
52894
52894
|
logger.info("\uD83D\uDCD6 Manual Installation Instructions:");
|
|
52895
52895
|
logger.info("");
|
|
52896
52896
|
logger.info("See complete guide:");
|
|
52897
|
-
logger.info(` cat ${
|
|
52897
|
+
logger.info(` cat ${join50(skillsDir2, "INSTALLATION.md")}`);
|
|
52898
52898
|
logger.info("");
|
|
52899
52899
|
logger.info("Quick start:");
|
|
52900
52900
|
logger.info(" cd .claude/skills/ai-multimodal/scripts");
|
|
@@ -52938,9 +52938,9 @@ var init_skills_installer2 = __esm(() => {
|
|
|
52938
52938
|
});
|
|
52939
52939
|
|
|
52940
52940
|
// src/services/package-installer/gemini-mcp/config-manager.ts
|
|
52941
|
-
import { existsSync as
|
|
52941
|
+
import { existsSync as existsSync33 } from "node:fs";
|
|
52942
52942
|
import { mkdir as mkdir12, readFile as readFile26, writeFile as writeFile15 } from "node:fs/promises";
|
|
52943
|
-
import { dirname as dirname11, join as
|
|
52943
|
+
import { dirname as dirname11, join as join51 } from "node:path";
|
|
52944
52944
|
async function readJsonFile(filePath) {
|
|
52945
52945
|
try {
|
|
52946
52946
|
const content = await readFile26(filePath, "utf-8");
|
|
@@ -52952,11 +52952,11 @@ async function readJsonFile(filePath) {
|
|
|
52952
52952
|
}
|
|
52953
52953
|
}
|
|
52954
52954
|
async function addGeminiToGitignore(projectDir) {
|
|
52955
|
-
const gitignorePath =
|
|
52955
|
+
const gitignorePath = join51(projectDir, ".gitignore");
|
|
52956
52956
|
const geminiPattern = ".gemini/";
|
|
52957
52957
|
try {
|
|
52958
52958
|
let content = "";
|
|
52959
|
-
if (
|
|
52959
|
+
if (existsSync33(gitignorePath)) {
|
|
52960
52960
|
content = await readFile26(gitignorePath, "utf-8");
|
|
52961
52961
|
const lines = content.split(`
|
|
52962
52962
|
`).map((line) => line.trim()).filter((line) => !line.startsWith("#"));
|
|
@@ -52981,7 +52981,7 @@ ${geminiPattern}
|
|
|
52981
52981
|
}
|
|
52982
52982
|
async function createNewSettingsWithMerge(geminiSettingsPath, mcpConfigPath) {
|
|
52983
52983
|
const linkDir = dirname11(geminiSettingsPath);
|
|
52984
|
-
if (!
|
|
52984
|
+
if (!existsSync33(linkDir)) {
|
|
52985
52985
|
await mkdir12(linkDir, { recursive: true });
|
|
52986
52986
|
logger.debug(`Created directory: ${linkDir}`);
|
|
52987
52987
|
}
|
|
@@ -53042,23 +53042,23 @@ var init_config_manager2 = __esm(() => {
|
|
|
53042
53042
|
});
|
|
53043
53043
|
|
|
53044
53044
|
// src/services/package-installer/gemini-mcp/validation.ts
|
|
53045
|
-
import { existsSync as
|
|
53045
|
+
import { existsSync as existsSync34, lstatSync, readlinkSync } from "node:fs";
|
|
53046
53046
|
import { homedir as homedir17 } from "node:os";
|
|
53047
|
-
import { join as
|
|
53047
|
+
import { join as join52 } from "node:path";
|
|
53048
53048
|
function getGlobalMcpConfigPath() {
|
|
53049
|
-
return
|
|
53049
|
+
return join52(homedir17(), ".claude", ".mcp.json");
|
|
53050
53050
|
}
|
|
53051
53051
|
function getLocalMcpConfigPath(projectDir) {
|
|
53052
|
-
return
|
|
53052
|
+
return join52(projectDir, ".mcp.json");
|
|
53053
53053
|
}
|
|
53054
53054
|
function findMcpConfigPath(projectDir) {
|
|
53055
53055
|
const localPath = getLocalMcpConfigPath(projectDir);
|
|
53056
|
-
if (
|
|
53056
|
+
if (existsSync34(localPath)) {
|
|
53057
53057
|
logger.debug(`Found local MCP config: ${localPath}`);
|
|
53058
53058
|
return localPath;
|
|
53059
53059
|
}
|
|
53060
53060
|
const globalPath = getGlobalMcpConfigPath();
|
|
53061
|
-
if (
|
|
53061
|
+
if (existsSync34(globalPath)) {
|
|
53062
53062
|
logger.debug(`Found global MCP config: ${globalPath}`);
|
|
53063
53063
|
return globalPath;
|
|
53064
53064
|
}
|
|
@@ -53067,13 +53067,13 @@ function findMcpConfigPath(projectDir) {
|
|
|
53067
53067
|
}
|
|
53068
53068
|
function getGeminiSettingsPath(projectDir, isGlobal) {
|
|
53069
53069
|
if (isGlobal) {
|
|
53070
|
-
return
|
|
53070
|
+
return join52(homedir17(), ".gemini", "settings.json");
|
|
53071
53071
|
}
|
|
53072
|
-
return
|
|
53072
|
+
return join52(projectDir, ".gemini", "settings.json");
|
|
53073
53073
|
}
|
|
53074
53074
|
function checkExistingGeminiConfig(projectDir, isGlobal = false) {
|
|
53075
53075
|
const geminiSettingsPath = getGeminiSettingsPath(projectDir, isGlobal);
|
|
53076
|
-
if (!
|
|
53076
|
+
if (!existsSync34(geminiSettingsPath)) {
|
|
53077
53077
|
return { exists: false, isSymlink: false, settingsPath: geminiSettingsPath };
|
|
53078
53078
|
}
|
|
53079
53079
|
try {
|
|
@@ -53097,12 +53097,12 @@ var init_validation = __esm(() => {
|
|
|
53097
53097
|
});
|
|
53098
53098
|
|
|
53099
53099
|
// src/services/package-installer/gemini-mcp/linker-core.ts
|
|
53100
|
-
import { existsSync as
|
|
53100
|
+
import { existsSync as existsSync35 } from "node:fs";
|
|
53101
53101
|
import { mkdir as mkdir13, symlink as symlink2 } from "node:fs/promises";
|
|
53102
|
-
import { dirname as dirname12, join as
|
|
53102
|
+
import { dirname as dirname12, join as join53 } from "node:path";
|
|
53103
53103
|
async function createSymlink(targetPath, linkPath, projectDir, isGlobal) {
|
|
53104
53104
|
const linkDir = dirname12(linkPath);
|
|
53105
|
-
if (!
|
|
53105
|
+
if (!existsSync35(linkDir)) {
|
|
53106
53106
|
await mkdir13(linkDir, { recursive: true });
|
|
53107
53107
|
logger.debug(`Created directory: ${linkDir}`);
|
|
53108
53108
|
}
|
|
@@ -53110,7 +53110,7 @@ async function createSymlink(targetPath, linkPath, projectDir, isGlobal) {
|
|
|
53110
53110
|
if (isGlobal) {
|
|
53111
53111
|
symlinkTarget = getGlobalMcpConfigPath();
|
|
53112
53112
|
} else {
|
|
53113
|
-
const localMcpPath =
|
|
53113
|
+
const localMcpPath = join53(projectDir, ".mcp.json");
|
|
53114
53114
|
const isLocalConfig = targetPath === localMcpPath;
|
|
53115
53115
|
symlinkTarget = isLocalConfig ? "../.mcp.json" : targetPath;
|
|
53116
53116
|
}
|
|
@@ -53143,10 +53143,10 @@ __export(exports_gemini_mcp_linker, {
|
|
|
53143
53143
|
checkExistingGeminiConfig: () => checkExistingGeminiConfig,
|
|
53144
53144
|
addGeminiToGitignore: () => addGeminiToGitignore
|
|
53145
53145
|
});
|
|
53146
|
-
import { resolve as
|
|
53146
|
+
import { resolve as resolve10 } from "node:path";
|
|
53147
53147
|
async function linkGeminiMcpConfig(projectDir, options2 = {}) {
|
|
53148
53148
|
const { skipGitignore = false, isGlobal = false } = options2;
|
|
53149
|
-
const resolvedProjectDir =
|
|
53149
|
+
const resolvedProjectDir = resolve10(projectDir);
|
|
53150
53150
|
const geminiSettingsPath = getGeminiSettingsPath(resolvedProjectDir, isGlobal);
|
|
53151
53151
|
const mcpConfigPath = findMcpConfigPath(resolvedProjectDir);
|
|
53152
53152
|
if (!mcpConfigPath) {
|
|
@@ -53944,12 +53944,12 @@ var require_adapter = __commonJS((exports, module) => {
|
|
|
53944
53944
|
return newFs;
|
|
53945
53945
|
}
|
|
53946
53946
|
function toPromise(method) {
|
|
53947
|
-
return (...args) => new Promise((
|
|
53947
|
+
return (...args) => new Promise((resolve11, reject) => {
|
|
53948
53948
|
args.push((err, result) => {
|
|
53949
53949
|
if (err) {
|
|
53950
53950
|
reject(err);
|
|
53951
53951
|
} else {
|
|
53952
|
-
|
|
53952
|
+
resolve11(result);
|
|
53953
53953
|
}
|
|
53954
53954
|
});
|
|
53955
53955
|
method(...args);
|
|
@@ -54519,7 +54519,7 @@ var require_get_stream = __commonJS((exports, module) => {
|
|
|
54519
54519
|
};
|
|
54520
54520
|
const { maxBuffer } = options2;
|
|
54521
54521
|
let stream;
|
|
54522
|
-
await new Promise((
|
|
54522
|
+
await new Promise((resolve12, reject) => {
|
|
54523
54523
|
const rejectPromise = (error) => {
|
|
54524
54524
|
if (error && stream.getBufferedLength() <= BufferConstants.MAX_LENGTH) {
|
|
54525
54525
|
error.bufferedData = stream.getBufferedValue();
|
|
@@ -54531,7 +54531,7 @@ var require_get_stream = __commonJS((exports, module) => {
|
|
|
54531
54531
|
rejectPromise(error);
|
|
54532
54532
|
return;
|
|
54533
54533
|
}
|
|
54534
|
-
|
|
54534
|
+
resolve12();
|
|
54535
54535
|
});
|
|
54536
54536
|
stream.on("data", () => {
|
|
54537
54537
|
if (stream.getBufferedLength() > maxBuffer) {
|
|
@@ -55892,7 +55892,7 @@ var require_extract_zip = __commonJS((exports, module) => {
|
|
|
55892
55892
|
debug("opening", this.zipPath, "with opts", this.opts);
|
|
55893
55893
|
this.zipfile = await openZip(this.zipPath, { lazyEntries: true });
|
|
55894
55894
|
this.canceled = false;
|
|
55895
|
-
return new Promise((
|
|
55895
|
+
return new Promise((resolve12, reject) => {
|
|
55896
55896
|
this.zipfile.on("error", (err) => {
|
|
55897
55897
|
this.canceled = true;
|
|
55898
55898
|
reject(err);
|
|
@@ -55901,7 +55901,7 @@ var require_extract_zip = __commonJS((exports, module) => {
|
|
|
55901
55901
|
this.zipfile.on("close", () => {
|
|
55902
55902
|
if (!this.canceled) {
|
|
55903
55903
|
debug("zip extraction complete");
|
|
55904
|
-
|
|
55904
|
+
resolve12();
|
|
55905
55905
|
}
|
|
55906
55906
|
});
|
|
55907
55907
|
this.zipfile.on("entry", async (entry) => {
|
|
@@ -58609,7 +58609,7 @@ function getPagerArgs(pagerCmd) {
|
|
|
58609
58609
|
return [];
|
|
58610
58610
|
}
|
|
58611
58611
|
async function trySystemPager(content) {
|
|
58612
|
-
return new Promise((
|
|
58612
|
+
return new Promise((resolve21) => {
|
|
58613
58613
|
const pagerCmd = process.env.PAGER || "less";
|
|
58614
58614
|
const pagerArgs = getPagerArgs(pagerCmd);
|
|
58615
58615
|
try {
|
|
@@ -58619,20 +58619,20 @@ async function trySystemPager(content) {
|
|
|
58619
58619
|
});
|
|
58620
58620
|
const timeout2 = setTimeout(() => {
|
|
58621
58621
|
pager.kill();
|
|
58622
|
-
|
|
58622
|
+
resolve21(false);
|
|
58623
58623
|
}, 30000);
|
|
58624
58624
|
pager.stdin.write(content);
|
|
58625
58625
|
pager.stdin.end();
|
|
58626
58626
|
pager.on("close", (code2) => {
|
|
58627
58627
|
clearTimeout(timeout2);
|
|
58628
|
-
|
|
58628
|
+
resolve21(code2 === 0);
|
|
58629
58629
|
});
|
|
58630
58630
|
pager.on("error", () => {
|
|
58631
58631
|
clearTimeout(timeout2);
|
|
58632
|
-
|
|
58632
|
+
resolve21(false);
|
|
58633
58633
|
});
|
|
58634
58634
|
} catch {
|
|
58635
|
-
|
|
58635
|
+
resolve21(false);
|
|
58636
58636
|
}
|
|
58637
58637
|
});
|
|
58638
58638
|
}
|
|
@@ -58659,16 +58659,16 @@ async function basicPager(content) {
|
|
|
58659
58659
|
break;
|
|
58660
58660
|
}
|
|
58661
58661
|
const remaining = lines.length - currentLine;
|
|
58662
|
-
await new Promise((
|
|
58662
|
+
await new Promise((resolve21) => {
|
|
58663
58663
|
rl.question(`-- More (${remaining} lines) [Enter/q] --`, (answer) => {
|
|
58664
58664
|
if (answer.toLowerCase() === "q") {
|
|
58665
58665
|
rl.close();
|
|
58666
58666
|
process.exitCode = 0;
|
|
58667
|
-
|
|
58667
|
+
resolve21();
|
|
58668
58668
|
return;
|
|
58669
58669
|
}
|
|
58670
58670
|
process.stdout.write("\x1B[1A\x1B[2K");
|
|
58671
|
-
|
|
58671
|
+
resolve21();
|
|
58672
58672
|
});
|
|
58673
58673
|
});
|
|
58674
58674
|
}
|
|
@@ -61616,6 +61616,794 @@ async function checkEnvKeys(setup) {
|
|
|
61616
61616
|
}
|
|
61617
61617
|
return results;
|
|
61618
61618
|
}
|
|
61619
|
+
// src/domains/health-checks/checkers/hook-health-checker.ts
|
|
61620
|
+
init_logger();
|
|
61621
|
+
init_path_resolver();
|
|
61622
|
+
import { spawnSync } from "node:child_process";
|
|
61623
|
+
import { existsSync as existsSync30, readFileSync as readFileSync6, statSync as statSync5, writeFileSync } from "node:fs";
|
|
61624
|
+
import { readdir as readdir9 } from "node:fs/promises";
|
|
61625
|
+
import { tmpdir } from "node:os";
|
|
61626
|
+
import { join as join41, resolve as resolve8 } from "node:path";
|
|
61627
|
+
var HOOK_CHECK_TIMEOUT_MS = 5000;
|
|
61628
|
+
var PYTHON_CHECK_TIMEOUT_MS = 3000;
|
|
61629
|
+
var MAX_LOG_FILE_SIZE_BYTES = 10 * 1024 * 1024;
|
|
61630
|
+
function getHooksDir(projectDir) {
|
|
61631
|
+
const projectHooksDir = resolve8(projectDir, ".claude", "hooks");
|
|
61632
|
+
const globalHooksDir = resolve8(PathResolver.getGlobalKitDir(), "hooks");
|
|
61633
|
+
if (existsSync30(projectHooksDir))
|
|
61634
|
+
return projectHooksDir;
|
|
61635
|
+
if (existsSync30(globalHooksDir))
|
|
61636
|
+
return globalHooksDir;
|
|
61637
|
+
return null;
|
|
61638
|
+
}
|
|
61639
|
+
function isPathWithin(filePath, parentDir) {
|
|
61640
|
+
return resolve8(filePath).startsWith(resolve8(parentDir));
|
|
61641
|
+
}
|
|
61642
|
+
async function checkHookSyntax(projectDir) {
|
|
61643
|
+
const hooksDir = getHooksDir(projectDir);
|
|
61644
|
+
if (!hooksDir) {
|
|
61645
|
+
return {
|
|
61646
|
+
id: "hook-syntax",
|
|
61647
|
+
name: "Hook Syntax",
|
|
61648
|
+
group: "claudekit",
|
|
61649
|
+
priority: "critical",
|
|
61650
|
+
status: "info",
|
|
61651
|
+
message: "No hooks directory",
|
|
61652
|
+
autoFixable: false
|
|
61653
|
+
};
|
|
61654
|
+
}
|
|
61655
|
+
try {
|
|
61656
|
+
const files = await readdir9(hooksDir);
|
|
61657
|
+
const cjsFiles = files.filter((f3) => f3.endsWith(".cjs"));
|
|
61658
|
+
if (cjsFiles.length === 0) {
|
|
61659
|
+
return {
|
|
61660
|
+
id: "hook-syntax",
|
|
61661
|
+
name: "Hook Syntax",
|
|
61662
|
+
group: "claudekit",
|
|
61663
|
+
priority: "critical",
|
|
61664
|
+
status: "info",
|
|
61665
|
+
message: "No .cjs hooks found",
|
|
61666
|
+
autoFixable: false
|
|
61667
|
+
};
|
|
61668
|
+
}
|
|
61669
|
+
const errors2 = [];
|
|
61670
|
+
for (const file of cjsFiles) {
|
|
61671
|
+
const filePath = join41(hooksDir, file);
|
|
61672
|
+
if (!isPathWithin(filePath, hooksDir))
|
|
61673
|
+
continue;
|
|
61674
|
+
const result = spawnSync("node", ["--check", filePath], {
|
|
61675
|
+
timeout: HOOK_CHECK_TIMEOUT_MS,
|
|
61676
|
+
encoding: "utf-8"
|
|
61677
|
+
});
|
|
61678
|
+
if (result.status !== 0) {
|
|
61679
|
+
errors2.push(`${file}: ${result.stderr?.trim() || "syntax error"}`);
|
|
61680
|
+
}
|
|
61681
|
+
}
|
|
61682
|
+
if (errors2.length > 0) {
|
|
61683
|
+
return {
|
|
61684
|
+
id: "hook-syntax",
|
|
61685
|
+
name: "Hook Syntax",
|
|
61686
|
+
group: "claudekit",
|
|
61687
|
+
priority: "critical",
|
|
61688
|
+
status: "fail",
|
|
61689
|
+
message: `${errors2.length} hook(s) with syntax errors`,
|
|
61690
|
+
details: errors2.join(`
|
|
61691
|
+
`),
|
|
61692
|
+
suggestion: "Run: ck init",
|
|
61693
|
+
autoFixable: true,
|
|
61694
|
+
fix: {
|
|
61695
|
+
id: "fix-hook-syntax",
|
|
61696
|
+
description: "Reinstall hooks via ck init",
|
|
61697
|
+
execute: async () => ({
|
|
61698
|
+
success: false,
|
|
61699
|
+
message: "Manual fix required: run 'ck init'"
|
|
61700
|
+
})
|
|
61701
|
+
}
|
|
61702
|
+
};
|
|
61703
|
+
}
|
|
61704
|
+
return {
|
|
61705
|
+
id: "hook-syntax",
|
|
61706
|
+
name: "Hook Syntax",
|
|
61707
|
+
group: "claudekit",
|
|
61708
|
+
priority: "critical",
|
|
61709
|
+
status: "pass",
|
|
61710
|
+
message: `${cjsFiles.length} hook(s) valid`,
|
|
61711
|
+
autoFixable: false
|
|
61712
|
+
};
|
|
61713
|
+
} catch (error) {
|
|
61714
|
+
logger.debug(`Hook syntax check failed: ${error}`);
|
|
61715
|
+
return {
|
|
61716
|
+
id: "hook-syntax",
|
|
61717
|
+
name: "Hook Syntax",
|
|
61718
|
+
group: "claudekit",
|
|
61719
|
+
priority: "critical",
|
|
61720
|
+
status: "fail",
|
|
61721
|
+
message: "Failed to check hook syntax",
|
|
61722
|
+
details: error instanceof Error ? error.message : String(error),
|
|
61723
|
+
autoFixable: false
|
|
61724
|
+
};
|
|
61725
|
+
}
|
|
61726
|
+
}
|
|
61727
|
+
async function checkHookDeps(projectDir) {
|
|
61728
|
+
const hooksDir = getHooksDir(projectDir);
|
|
61729
|
+
if (!hooksDir) {
|
|
61730
|
+
return {
|
|
61731
|
+
id: "hook-deps",
|
|
61732
|
+
name: "Hook Dependencies",
|
|
61733
|
+
group: "claudekit",
|
|
61734
|
+
priority: "critical",
|
|
61735
|
+
status: "info",
|
|
61736
|
+
message: "No hooks directory",
|
|
61737
|
+
autoFixable: false
|
|
61738
|
+
};
|
|
61739
|
+
}
|
|
61740
|
+
try {
|
|
61741
|
+
const files = await readdir9(hooksDir);
|
|
61742
|
+
const cjsFiles = files.filter((f3) => f3.endsWith(".cjs"));
|
|
61743
|
+
if (cjsFiles.length === 0) {
|
|
61744
|
+
return {
|
|
61745
|
+
id: "hook-deps",
|
|
61746
|
+
name: "Hook Dependencies",
|
|
61747
|
+
group: "claudekit",
|
|
61748
|
+
priority: "critical",
|
|
61749
|
+
status: "info",
|
|
61750
|
+
message: "No .cjs hooks found",
|
|
61751
|
+
autoFixable: false
|
|
61752
|
+
};
|
|
61753
|
+
}
|
|
61754
|
+
const missingDeps = [];
|
|
61755
|
+
const requireRegex = /require\(['"]([^'"]+)['"]\)/g;
|
|
61756
|
+
for (const file of cjsFiles) {
|
|
61757
|
+
const filePath = join41(hooksDir, file);
|
|
61758
|
+
if (!isPathWithin(filePath, hooksDir))
|
|
61759
|
+
continue;
|
|
61760
|
+
const content = readFileSync6(filePath, "utf-8");
|
|
61761
|
+
for (let match = requireRegex.exec(content);match !== null; match = requireRegex.exec(content)) {
|
|
61762
|
+
const depPath = match[1];
|
|
61763
|
+
if (depPath.startsWith("node:") || isNodeBuiltin(depPath)) {
|
|
61764
|
+
continue;
|
|
61765
|
+
}
|
|
61766
|
+
if (depPath.startsWith(".")) {
|
|
61767
|
+
const resolvedPath = join41(hooksDir, depPath);
|
|
61768
|
+
const extensions = [".js", ".cjs", ".mjs", ".json"];
|
|
61769
|
+
const indexFiles = ["index.js", "index.cjs", "index.mjs"];
|
|
61770
|
+
const exists = existsSync30(resolvedPath) || extensions.some((ext) => existsSync30(resolvedPath + ext)) || indexFiles.some((idx) => existsSync30(join41(resolvedPath, idx)));
|
|
61771
|
+
if (!exists) {
|
|
61772
|
+
missingDeps.push(`${file}: ${depPath}`);
|
|
61773
|
+
}
|
|
61774
|
+
}
|
|
61775
|
+
}
|
|
61776
|
+
}
|
|
61777
|
+
if (missingDeps.length > 0) {
|
|
61778
|
+
return {
|
|
61779
|
+
id: "hook-deps",
|
|
61780
|
+
name: "Hook Dependencies",
|
|
61781
|
+
group: "claudekit",
|
|
61782
|
+
priority: "critical",
|
|
61783
|
+
status: "fail",
|
|
61784
|
+
message: `${missingDeps.length} missing dependency(ies)`,
|
|
61785
|
+
details: missingDeps.join(`
|
|
61786
|
+
`),
|
|
61787
|
+
suggestion: "Run: ck init",
|
|
61788
|
+
autoFixable: true,
|
|
61789
|
+
fix: {
|
|
61790
|
+
id: "fix-hook-deps",
|
|
61791
|
+
description: "Reinstall hooks via ck init",
|
|
61792
|
+
execute: async () => ({
|
|
61793
|
+
success: false,
|
|
61794
|
+
message: "Manual fix required: run 'ck init'"
|
|
61795
|
+
})
|
|
61796
|
+
}
|
|
61797
|
+
};
|
|
61798
|
+
}
|
|
61799
|
+
return {
|
|
61800
|
+
id: "hook-deps",
|
|
61801
|
+
name: "Hook Dependencies",
|
|
61802
|
+
group: "claudekit",
|
|
61803
|
+
priority: "critical",
|
|
61804
|
+
status: "pass",
|
|
61805
|
+
message: "All dependencies resolved",
|
|
61806
|
+
autoFixable: false
|
|
61807
|
+
};
|
|
61808
|
+
} catch (error) {
|
|
61809
|
+
logger.debug(`Hook deps check failed: ${error}`);
|
|
61810
|
+
return {
|
|
61811
|
+
id: "hook-deps",
|
|
61812
|
+
name: "Hook Dependencies",
|
|
61813
|
+
group: "claudekit",
|
|
61814
|
+
priority: "critical",
|
|
61815
|
+
status: "fail",
|
|
61816
|
+
message: "Failed to check dependencies",
|
|
61817
|
+
details: error instanceof Error ? error.message : String(error),
|
|
61818
|
+
autoFixable: false
|
|
61819
|
+
};
|
|
61820
|
+
}
|
|
61821
|
+
}
|
|
61822
|
+
function isNodeBuiltin(mod) {
|
|
61823
|
+
try {
|
|
61824
|
+
const { builtinModules } = __require("node:module");
|
|
61825
|
+
return builtinModules.includes(mod);
|
|
61826
|
+
} catch {
|
|
61827
|
+
const builtins = [
|
|
61828
|
+
"fs",
|
|
61829
|
+
"path",
|
|
61830
|
+
"os",
|
|
61831
|
+
"child_process",
|
|
61832
|
+
"util",
|
|
61833
|
+
"stream",
|
|
61834
|
+
"events",
|
|
61835
|
+
"crypto",
|
|
61836
|
+
"http",
|
|
61837
|
+
"https",
|
|
61838
|
+
"net",
|
|
61839
|
+
"dns",
|
|
61840
|
+
"url",
|
|
61841
|
+
"querystring",
|
|
61842
|
+
"readline",
|
|
61843
|
+
"process",
|
|
61844
|
+
"buffer",
|
|
61845
|
+
"console",
|
|
61846
|
+
"timers",
|
|
61847
|
+
"assert",
|
|
61848
|
+
"zlib",
|
|
61849
|
+
"worker_threads",
|
|
61850
|
+
"perf_hooks",
|
|
61851
|
+
"v8",
|
|
61852
|
+
"vm",
|
|
61853
|
+
"tls"
|
|
61854
|
+
];
|
|
61855
|
+
return builtins.includes(mod);
|
|
61856
|
+
}
|
|
61857
|
+
}
|
|
61858
|
+
async function checkHookRuntime(projectDir) {
|
|
61859
|
+
const hooksDir = getHooksDir(projectDir);
|
|
61860
|
+
if (!hooksDir) {
|
|
61861
|
+
return {
|
|
61862
|
+
id: "hook-runtime",
|
|
61863
|
+
name: "Hook Runtime",
|
|
61864
|
+
group: "claudekit",
|
|
61865
|
+
priority: "standard",
|
|
61866
|
+
status: "info",
|
|
61867
|
+
message: "No hooks directory",
|
|
61868
|
+
autoFixable: false
|
|
61869
|
+
};
|
|
61870
|
+
}
|
|
61871
|
+
try {
|
|
61872
|
+
const files = await readdir9(hooksDir);
|
|
61873
|
+
const cjsFiles = files.filter((f3) => f3.endsWith(".cjs"));
|
|
61874
|
+
if (cjsFiles.length === 0) {
|
|
61875
|
+
return {
|
|
61876
|
+
id: "hook-runtime",
|
|
61877
|
+
name: "Hook Runtime",
|
|
61878
|
+
group: "claudekit",
|
|
61879
|
+
priority: "standard",
|
|
61880
|
+
status: "info",
|
|
61881
|
+
message: "No .cjs hooks found",
|
|
61882
|
+
autoFixable: false
|
|
61883
|
+
};
|
|
61884
|
+
}
|
|
61885
|
+
const syntheticPayload = JSON.stringify({
|
|
61886
|
+
tool_name: "Read",
|
|
61887
|
+
tool_input: { file_path: join41(tmpdir(), "ck-doctor-test.txt") }
|
|
61888
|
+
});
|
|
61889
|
+
const failures = [];
|
|
61890
|
+
for (const file of cjsFiles) {
|
|
61891
|
+
const filePath = join41(hooksDir, file);
|
|
61892
|
+
if (!isPathWithin(filePath, hooksDir))
|
|
61893
|
+
continue;
|
|
61894
|
+
const result = spawnSync("node", [filePath], {
|
|
61895
|
+
input: syntheticPayload,
|
|
61896
|
+
timeout: HOOK_CHECK_TIMEOUT_MS,
|
|
61897
|
+
encoding: "utf-8"
|
|
61898
|
+
});
|
|
61899
|
+
if (result.status !== null && result.status !== 0 && result.status !== 2) {
|
|
61900
|
+
const error = result.error?.message || result.stderr?.trim() || `exit code ${result.status}`;
|
|
61901
|
+
failures.push(`${file}: ${error}`);
|
|
61902
|
+
} else if (result.status === null && result.error) {
|
|
61903
|
+
const error = result.error.message || "failed to execute";
|
|
61904
|
+
failures.push(`${file}: ${error}`);
|
|
61905
|
+
}
|
|
61906
|
+
}
|
|
61907
|
+
if (failures.length > 0) {
|
|
61908
|
+
return {
|
|
61909
|
+
id: "hook-runtime",
|
|
61910
|
+
name: "Hook Runtime",
|
|
61911
|
+
group: "claudekit",
|
|
61912
|
+
priority: "standard",
|
|
61913
|
+
status: "fail",
|
|
61914
|
+
message: `${failures.length} hook(s) failed dry-run`,
|
|
61915
|
+
details: failures.join(`
|
|
61916
|
+
`),
|
|
61917
|
+
suggestion: "Run: ck init",
|
|
61918
|
+
autoFixable: true,
|
|
61919
|
+
fix: {
|
|
61920
|
+
id: "fix-hook-runtime",
|
|
61921
|
+
description: "Reinstall hooks via ck init",
|
|
61922
|
+
execute: async () => ({
|
|
61923
|
+
success: false,
|
|
61924
|
+
message: "Manual fix required: run 'ck init'"
|
|
61925
|
+
})
|
|
61926
|
+
}
|
|
61927
|
+
};
|
|
61928
|
+
}
|
|
61929
|
+
return {
|
|
61930
|
+
id: "hook-runtime",
|
|
61931
|
+
name: "Hook Runtime",
|
|
61932
|
+
group: "claudekit",
|
|
61933
|
+
priority: "standard",
|
|
61934
|
+
status: "pass",
|
|
61935
|
+
message: `${cjsFiles.length} hook(s) passed dry-run`,
|
|
61936
|
+
autoFixable: false
|
|
61937
|
+
};
|
|
61938
|
+
} catch (error) {
|
|
61939
|
+
logger.debug(`Hook runtime check failed: ${error}`);
|
|
61940
|
+
return {
|
|
61941
|
+
id: "hook-runtime",
|
|
61942
|
+
name: "Hook Runtime",
|
|
61943
|
+
group: "claudekit",
|
|
61944
|
+
priority: "standard",
|
|
61945
|
+
status: "fail",
|
|
61946
|
+
message: "Failed to check hook runtime",
|
|
61947
|
+
details: error instanceof Error ? error.message : String(error),
|
|
61948
|
+
autoFixable: false
|
|
61949
|
+
};
|
|
61950
|
+
}
|
|
61951
|
+
}
|
|
61952
|
+
async function checkHookConfig(projectDir) {
|
|
61953
|
+
const projectConfigPath = join41(projectDir, ".claude", ".ck.json");
|
|
61954
|
+
const globalConfigPath = join41(PathResolver.getGlobalKitDir(), ".ck.json");
|
|
61955
|
+
const configPath = existsSync30(projectConfigPath) ? projectConfigPath : existsSync30(globalConfigPath) ? globalConfigPath : null;
|
|
61956
|
+
if (!configPath) {
|
|
61957
|
+
return {
|
|
61958
|
+
id: "hook-config",
|
|
61959
|
+
name: "Hook Config",
|
|
61960
|
+
group: "claudekit",
|
|
61961
|
+
priority: "standard",
|
|
61962
|
+
status: "info",
|
|
61963
|
+
message: "No .ck.json config",
|
|
61964
|
+
autoFixable: false
|
|
61965
|
+
};
|
|
61966
|
+
}
|
|
61967
|
+
const hooksDir = getHooksDir(projectDir);
|
|
61968
|
+
if (!hooksDir) {
|
|
61969
|
+
return {
|
|
61970
|
+
id: "hook-config",
|
|
61971
|
+
name: "Hook Config",
|
|
61972
|
+
group: "claudekit",
|
|
61973
|
+
priority: "standard",
|
|
61974
|
+
status: "info",
|
|
61975
|
+
message: "No hooks directory",
|
|
61976
|
+
autoFixable: false
|
|
61977
|
+
};
|
|
61978
|
+
}
|
|
61979
|
+
try {
|
|
61980
|
+
const configContent = readFileSync6(configPath, "utf-8");
|
|
61981
|
+
const config = JSON.parse(configContent);
|
|
61982
|
+
if (!config.hooks || typeof config.hooks !== "object") {
|
|
61983
|
+
return {
|
|
61984
|
+
id: "hook-config",
|
|
61985
|
+
name: "Hook Config",
|
|
61986
|
+
group: "claudekit",
|
|
61987
|
+
priority: "standard",
|
|
61988
|
+
status: "pass",
|
|
61989
|
+
message: "No hooks configured",
|
|
61990
|
+
autoFixable: false
|
|
61991
|
+
};
|
|
61992
|
+
}
|
|
61993
|
+
const files = await readdir9(hooksDir);
|
|
61994
|
+
const hookBaseNames = new Set(files.filter((f3) => HOOK_EXTENSIONS.some((ext) => f3.endsWith(ext))).map((f3) => {
|
|
61995
|
+
for (const ext of HOOK_EXTENSIONS) {
|
|
61996
|
+
if (f3.endsWith(ext))
|
|
61997
|
+
return f3.slice(0, -ext.length);
|
|
61998
|
+
}
|
|
61999
|
+
return f3;
|
|
62000
|
+
}));
|
|
62001
|
+
const orphanedEntries = [];
|
|
62002
|
+
for (const hookName of Object.keys(config.hooks)) {
|
|
62003
|
+
if (!hookBaseNames.has(hookName)) {
|
|
62004
|
+
orphanedEntries.push(hookName);
|
|
62005
|
+
}
|
|
62006
|
+
}
|
|
62007
|
+
if (orphanedEntries.length > 0) {
|
|
62008
|
+
return {
|
|
62009
|
+
id: "hook-config",
|
|
62010
|
+
name: "Hook Config",
|
|
62011
|
+
group: "claudekit",
|
|
62012
|
+
priority: "standard",
|
|
62013
|
+
status: "warn",
|
|
62014
|
+
message: `${orphanedEntries.length} orphaned config entry(ies)`,
|
|
62015
|
+
details: orphanedEntries.join(", "),
|
|
62016
|
+
suggestion: "Remove orphaned entries from .ck.json",
|
|
62017
|
+
autoFixable: true,
|
|
62018
|
+
fix: {
|
|
62019
|
+
id: "fix-hook-config",
|
|
62020
|
+
description: "Remove orphaned entries from .ck.json",
|
|
62021
|
+
execute: async () => {
|
|
62022
|
+
try {
|
|
62023
|
+
for (const entry of orphanedEntries) {
|
|
62024
|
+
delete config.hooks[entry];
|
|
62025
|
+
}
|
|
62026
|
+
const updatedConfig = JSON.stringify(config, null, 2);
|
|
62027
|
+
writeFileSync(configPath, updatedConfig, "utf-8");
|
|
62028
|
+
return {
|
|
62029
|
+
success: true,
|
|
62030
|
+
message: `Removed ${orphanedEntries.length} orphaned entry(ies)`
|
|
62031
|
+
};
|
|
62032
|
+
} catch (err) {
|
|
62033
|
+
return {
|
|
62034
|
+
success: false,
|
|
62035
|
+
message: `Failed to update .ck.json: ${err}`
|
|
62036
|
+
};
|
|
62037
|
+
}
|
|
62038
|
+
}
|
|
62039
|
+
}
|
|
62040
|
+
};
|
|
62041
|
+
}
|
|
62042
|
+
return {
|
|
62043
|
+
id: "hook-config",
|
|
62044
|
+
name: "Hook Config",
|
|
62045
|
+
group: "claudekit",
|
|
62046
|
+
priority: "standard",
|
|
62047
|
+
status: "pass",
|
|
62048
|
+
message: "All config entries valid",
|
|
62049
|
+
autoFixable: false
|
|
62050
|
+
};
|
|
62051
|
+
} catch (error) {
|
|
62052
|
+
logger.debug(`Hook config check failed: ${error}`);
|
|
62053
|
+
return {
|
|
62054
|
+
id: "hook-config",
|
|
62055
|
+
name: "Hook Config",
|
|
62056
|
+
group: "claudekit",
|
|
62057
|
+
priority: "standard",
|
|
62058
|
+
status: "fail",
|
|
62059
|
+
message: "Failed to validate config",
|
|
62060
|
+
details: error instanceof Error ? error.message : String(error),
|
|
62061
|
+
autoFixable: false
|
|
62062
|
+
};
|
|
62063
|
+
}
|
|
62064
|
+
}
|
|
62065
|
+
async function checkHookLogs(projectDir) {
|
|
62066
|
+
const hooksDir = getHooksDir(projectDir);
|
|
62067
|
+
if (!hooksDir) {
|
|
62068
|
+
return {
|
|
62069
|
+
id: "hook-logs",
|
|
62070
|
+
name: "Hook Crash Logs",
|
|
62071
|
+
group: "claudekit",
|
|
62072
|
+
priority: "standard",
|
|
62073
|
+
status: "info",
|
|
62074
|
+
message: "No hooks directory",
|
|
62075
|
+
autoFixable: false
|
|
62076
|
+
};
|
|
62077
|
+
}
|
|
62078
|
+
const logPath = join41(hooksDir, ".logs", "hook-log.jsonl");
|
|
62079
|
+
if (!existsSync30(logPath)) {
|
|
62080
|
+
return {
|
|
62081
|
+
id: "hook-logs",
|
|
62082
|
+
name: "Hook Crash Logs",
|
|
62083
|
+
group: "claudekit",
|
|
62084
|
+
priority: "standard",
|
|
62085
|
+
status: "pass",
|
|
62086
|
+
message: "No crash logs",
|
|
62087
|
+
autoFixable: false
|
|
62088
|
+
};
|
|
62089
|
+
}
|
|
62090
|
+
try {
|
|
62091
|
+
const logStats = statSync5(logPath);
|
|
62092
|
+
if (logStats.size > MAX_LOG_FILE_SIZE_BYTES) {
|
|
62093
|
+
return {
|
|
62094
|
+
id: "hook-logs",
|
|
62095
|
+
name: "Hook Crash Logs",
|
|
62096
|
+
group: "claudekit",
|
|
62097
|
+
priority: "standard",
|
|
62098
|
+
status: "warn",
|
|
62099
|
+
message: `Log file too large (${Math.round(logStats.size / 1024 / 1024)}MB)`,
|
|
62100
|
+
suggestion: "Delete .claude/hooks/.logs/hook-log.jsonl and run: ck init",
|
|
62101
|
+
autoFixable: true,
|
|
62102
|
+
fix: {
|
|
62103
|
+
id: "fix-hook-logs",
|
|
62104
|
+
description: "Clear oversized log file",
|
|
62105
|
+
execute: async () => {
|
|
62106
|
+
try {
|
|
62107
|
+
writeFileSync(logPath, "", "utf-8");
|
|
62108
|
+
return { success: true, message: "Cleared oversized log file" };
|
|
62109
|
+
} catch (err) {
|
|
62110
|
+
return { success: false, message: `Failed to clear log: ${err}` };
|
|
62111
|
+
}
|
|
62112
|
+
}
|
|
62113
|
+
}
|
|
62114
|
+
};
|
|
62115
|
+
}
|
|
62116
|
+
const logContent = readFileSync6(logPath, "utf-8");
|
|
62117
|
+
const lines = logContent.trim().split(`
|
|
62118
|
+
`).filter(Boolean);
|
|
62119
|
+
const now = Date.now();
|
|
62120
|
+
const oneDayAgo = now - 24 * 60 * 60 * 1000;
|
|
62121
|
+
const crashes = [];
|
|
62122
|
+
for (const line of lines) {
|
|
62123
|
+
try {
|
|
62124
|
+
const entry = JSON.parse(line);
|
|
62125
|
+
const timestamp = new Date(entry.ts || entry.timestamp).getTime();
|
|
62126
|
+
if (timestamp >= oneDayAgo && entry.status === "crash") {
|
|
62127
|
+
crashes.push({
|
|
62128
|
+
hook: entry.hook || "unknown",
|
|
62129
|
+
error: entry.error || "unknown error"
|
|
62130
|
+
});
|
|
62131
|
+
}
|
|
62132
|
+
} catch {}
|
|
62133
|
+
}
|
|
62134
|
+
if (crashes.length === 0) {
|
|
62135
|
+
return {
|
|
62136
|
+
id: "hook-logs",
|
|
62137
|
+
name: "Hook Crash Logs",
|
|
62138
|
+
group: "claudekit",
|
|
62139
|
+
priority: "standard",
|
|
62140
|
+
status: "pass",
|
|
62141
|
+
message: "No crashes in last 24h",
|
|
62142
|
+
autoFixable: false
|
|
62143
|
+
};
|
|
62144
|
+
}
|
|
62145
|
+
if (crashes.length <= 5) {
|
|
62146
|
+
const hookList = crashes.map((c2) => `${c2.hook}: ${c2.error}`).join(`
|
|
62147
|
+
`);
|
|
62148
|
+
return {
|
|
62149
|
+
id: "hook-logs",
|
|
62150
|
+
name: "Hook Crash Logs",
|
|
62151
|
+
group: "claudekit",
|
|
62152
|
+
priority: "standard",
|
|
62153
|
+
status: "warn",
|
|
62154
|
+
message: `${crashes.length} crash(es) in last 24h`,
|
|
62155
|
+
details: hookList,
|
|
62156
|
+
suggestion: "Run: ck init",
|
|
62157
|
+
autoFixable: true,
|
|
62158
|
+
fix: {
|
|
62159
|
+
id: "fix-hook-logs",
|
|
62160
|
+
description: "Clear log file",
|
|
62161
|
+
execute: async () => {
|
|
62162
|
+
try {
|
|
62163
|
+
writeFileSync(logPath, "", "utf-8");
|
|
62164
|
+
return {
|
|
62165
|
+
success: true,
|
|
62166
|
+
message: "Cleared crash log file"
|
|
62167
|
+
};
|
|
62168
|
+
} catch (err) {
|
|
62169
|
+
return {
|
|
62170
|
+
success: false,
|
|
62171
|
+
message: `Failed to clear log: ${err}`
|
|
62172
|
+
};
|
|
62173
|
+
}
|
|
62174
|
+
}
|
|
62175
|
+
}
|
|
62176
|
+
};
|
|
62177
|
+
}
|
|
62178
|
+
const hookCounts = crashes.reduce((acc, c2) => {
|
|
62179
|
+
acc[c2.hook] = (acc[c2.hook] || 0) + 1;
|
|
62180
|
+
return acc;
|
|
62181
|
+
}, {});
|
|
62182
|
+
const topCrashers = Object.entries(hookCounts).sort((a3, b3) => b3[1] - a3[1]).slice(0, 5).map(([hook, count]) => `${hook} (${count}x)`).join(", ");
|
|
62183
|
+
return {
|
|
62184
|
+
id: "hook-logs",
|
|
62185
|
+
name: "Hook Crash Logs",
|
|
62186
|
+
group: "claudekit",
|
|
62187
|
+
priority: "standard",
|
|
62188
|
+
status: "fail",
|
|
62189
|
+
message: `${crashes.length} crashes in last 24h`,
|
|
62190
|
+
details: `Most frequent: ${topCrashers}`,
|
|
62191
|
+
suggestion: "Run: ck init",
|
|
62192
|
+
autoFixable: true,
|
|
62193
|
+
fix: {
|
|
62194
|
+
id: "fix-hook-logs",
|
|
62195
|
+
description: "Clear log file and suggest reinstall",
|
|
62196
|
+
execute: async () => {
|
|
62197
|
+
try {
|
|
62198
|
+
writeFileSync(logPath, "", "utf-8");
|
|
62199
|
+
return {
|
|
62200
|
+
success: true,
|
|
62201
|
+
message: "Cleared crash log. Run 'ck init' to reinstall hooks."
|
|
62202
|
+
};
|
|
62203
|
+
} catch (err) {
|
|
62204
|
+
return {
|
|
62205
|
+
success: false,
|
|
62206
|
+
message: `Failed to clear log: ${err}`
|
|
62207
|
+
};
|
|
62208
|
+
}
|
|
62209
|
+
}
|
|
62210
|
+
}
|
|
62211
|
+
};
|
|
62212
|
+
} catch (error) {
|
|
62213
|
+
logger.debug(`Hook logs check failed: ${error}`);
|
|
62214
|
+
return {
|
|
62215
|
+
id: "hook-logs",
|
|
62216
|
+
name: "Hook Crash Logs",
|
|
62217
|
+
group: "claudekit",
|
|
62218
|
+
priority: "standard",
|
|
62219
|
+
status: "fail",
|
|
62220
|
+
message: "Failed to check crash logs",
|
|
62221
|
+
details: error instanceof Error ? error.message : String(error),
|
|
62222
|
+
autoFixable: false
|
|
62223
|
+
};
|
|
62224
|
+
}
|
|
62225
|
+
}
|
|
62226
|
+
async function checkCliVersion() {
|
|
62227
|
+
try {
|
|
62228
|
+
const versionResult = spawnSync("ck", ["-V"], {
|
|
62229
|
+
timeout: HOOK_CHECK_TIMEOUT_MS,
|
|
62230
|
+
encoding: "utf-8"
|
|
62231
|
+
});
|
|
62232
|
+
let installedVersion = "unknown";
|
|
62233
|
+
if (versionResult.status === 0 && versionResult.stdout) {
|
|
62234
|
+
installedVersion = versionResult.stdout.trim();
|
|
62235
|
+
}
|
|
62236
|
+
if (installedVersion === "unknown") {
|
|
62237
|
+
return {
|
|
62238
|
+
id: "cli-version",
|
|
62239
|
+
name: "CLI Version",
|
|
62240
|
+
group: "claudekit",
|
|
62241
|
+
priority: "critical",
|
|
62242
|
+
status: "warn",
|
|
62243
|
+
message: "Cannot determine installed version",
|
|
62244
|
+
autoFixable: false
|
|
62245
|
+
};
|
|
62246
|
+
}
|
|
62247
|
+
const npmResult = spawnSync("npm", ["view", "claudekit-cli", "version"], {
|
|
62248
|
+
timeout: HOOK_CHECK_TIMEOUT_MS,
|
|
62249
|
+
encoding: "utf-8"
|
|
62250
|
+
});
|
|
62251
|
+
if (npmResult.status !== 0) {
|
|
62252
|
+
return {
|
|
62253
|
+
id: "cli-version",
|
|
62254
|
+
name: "CLI Version",
|
|
62255
|
+
group: "claudekit",
|
|
62256
|
+
priority: "critical",
|
|
62257
|
+
status: "warn",
|
|
62258
|
+
message: `v${installedVersion} (unable to check for updates)`,
|
|
62259
|
+
autoFixable: false
|
|
62260
|
+
};
|
|
62261
|
+
}
|
|
62262
|
+
const latestVersion = npmResult.stdout?.trim() || installedVersion;
|
|
62263
|
+
const parseVersion = (v2) => v2.replace(/-.*$/, "").split(".").map(Number);
|
|
62264
|
+
const [installedMajor, installedMinor] = parseVersion(installedVersion);
|
|
62265
|
+
const [latestMajor, latestMinor] = parseVersion(latestVersion);
|
|
62266
|
+
if (installedMajor < latestMajor) {
|
|
62267
|
+
return {
|
|
62268
|
+
id: "cli-version",
|
|
62269
|
+
name: "CLI Version",
|
|
62270
|
+
group: "claudekit",
|
|
62271
|
+
priority: "critical",
|
|
62272
|
+
status: "fail",
|
|
62273
|
+
message: `v${installedVersion} (latest: v${latestVersion})`,
|
|
62274
|
+
details: "Major version behind",
|
|
62275
|
+
suggestion: "Run: ck update",
|
|
62276
|
+
autoFixable: true,
|
|
62277
|
+
fix: {
|
|
62278
|
+
id: "fix-cli-version",
|
|
62279
|
+
description: "Update CLI to latest version",
|
|
62280
|
+
execute: async () => ({
|
|
62281
|
+
success: false,
|
|
62282
|
+
message: "Manual fix required: run 'ck update'"
|
|
62283
|
+
})
|
|
62284
|
+
}
|
|
62285
|
+
};
|
|
62286
|
+
}
|
|
62287
|
+
if (installedMajor === latestMajor && installedMinor < latestMinor) {
|
|
62288
|
+
return {
|
|
62289
|
+
id: "cli-version",
|
|
62290
|
+
name: "CLI Version",
|
|
62291
|
+
group: "claudekit",
|
|
62292
|
+
priority: "critical",
|
|
62293
|
+
status: "warn",
|
|
62294
|
+
message: `v${installedVersion} (latest: v${latestVersion})`,
|
|
62295
|
+
details: "Minor version behind",
|
|
62296
|
+
suggestion: "Run: ck update",
|
|
62297
|
+
autoFixable: true,
|
|
62298
|
+
fix: {
|
|
62299
|
+
id: "fix-cli-version",
|
|
62300
|
+
description: "Update CLI to latest version",
|
|
62301
|
+
execute: async () => ({
|
|
62302
|
+
success: false,
|
|
62303
|
+
message: "Manual fix required: run 'ck update'"
|
|
62304
|
+
})
|
|
62305
|
+
}
|
|
62306
|
+
};
|
|
62307
|
+
}
|
|
62308
|
+
return {
|
|
62309
|
+
id: "cli-version",
|
|
62310
|
+
name: "CLI Version",
|
|
62311
|
+
group: "claudekit",
|
|
62312
|
+
priority: "critical",
|
|
62313
|
+
status: "pass",
|
|
62314
|
+
message: `v${installedVersion} (up to date)`,
|
|
62315
|
+
autoFixable: false
|
|
62316
|
+
};
|
|
62317
|
+
} catch (error) {
|
|
62318
|
+
logger.debug(`CLI version check failed: ${error}`);
|
|
62319
|
+
return {
|
|
62320
|
+
id: "cli-version",
|
|
62321
|
+
name: "CLI Version",
|
|
62322
|
+
group: "claudekit",
|
|
62323
|
+
priority: "critical",
|
|
62324
|
+
status: "warn",
|
|
62325
|
+
message: "Failed to check version",
|
|
62326
|
+
details: error instanceof Error ? error.message : String(error),
|
|
62327
|
+
autoFixable: false
|
|
62328
|
+
};
|
|
62329
|
+
}
|
|
62330
|
+
}
|
|
62331
|
+
async function checkPythonVenv(projectDir) {
|
|
62332
|
+
const isWindows3 = process.platform === "win32";
|
|
62333
|
+
const venvBin = isWindows3 ? join41("Scripts", "python.exe") : join41("bin", "python3");
|
|
62334
|
+
const projectVenvPath = join41(projectDir, ".claude", "skills", ".venv", venvBin);
|
|
62335
|
+
const globalVenvPath = join41(PathResolver.getGlobalKitDir(), "skills", ".venv", venvBin);
|
|
62336
|
+
const venvPath = existsSync30(projectVenvPath) ? projectVenvPath : existsSync30(globalVenvPath) ? globalVenvPath : null;
|
|
62337
|
+
if (!venvPath) {
|
|
62338
|
+
return {
|
|
62339
|
+
id: "python-venv",
|
|
62340
|
+
name: "Python Venv",
|
|
62341
|
+
group: "claudekit",
|
|
62342
|
+
priority: "standard",
|
|
62343
|
+
status: "warn",
|
|
62344
|
+
message: "Virtual environment not found",
|
|
62345
|
+
suggestion: "Delete .venv and run install.sh",
|
|
62346
|
+
autoFixable: true,
|
|
62347
|
+
fix: {
|
|
62348
|
+
id: "fix-python-venv",
|
|
62349
|
+
description: "Delete .venv and suggest reinstall",
|
|
62350
|
+
execute: async () => ({
|
|
62351
|
+
success: false,
|
|
62352
|
+
message: "Manual fix required: delete .venv and run install.sh"
|
|
62353
|
+
})
|
|
62354
|
+
}
|
|
62355
|
+
};
|
|
62356
|
+
}
|
|
62357
|
+
try {
|
|
62358
|
+
const result = spawnSync(venvPath, ["--version"], {
|
|
62359
|
+
timeout: PYTHON_CHECK_TIMEOUT_MS,
|
|
62360
|
+
encoding: "utf-8"
|
|
62361
|
+
});
|
|
62362
|
+
if (result.status !== 0) {
|
|
62363
|
+
return {
|
|
62364
|
+
id: "python-venv",
|
|
62365
|
+
name: "Python Venv",
|
|
62366
|
+
group: "claudekit",
|
|
62367
|
+
priority: "standard",
|
|
62368
|
+
status: "fail",
|
|
62369
|
+
message: "Python venv exists but broken",
|
|
62370
|
+
details: result.stderr?.trim() || "Failed to run python3 --version",
|
|
62371
|
+
suggestion: "Delete .venv and run install.sh",
|
|
62372
|
+
autoFixable: true,
|
|
62373
|
+
fix: {
|
|
62374
|
+
id: "fix-python-venv",
|
|
62375
|
+
description: "Delete .venv",
|
|
62376
|
+
execute: async () => ({
|
|
62377
|
+
success: false,
|
|
62378
|
+
message: "Manual fix required: delete .venv and run install.sh"
|
|
62379
|
+
})
|
|
62380
|
+
}
|
|
62381
|
+
};
|
|
62382
|
+
}
|
|
62383
|
+
const version = result.stdout?.trim() || "unknown";
|
|
62384
|
+
return {
|
|
62385
|
+
id: "python-venv",
|
|
62386
|
+
name: "Python Venv",
|
|
62387
|
+
group: "claudekit",
|
|
62388
|
+
priority: "standard",
|
|
62389
|
+
status: "pass",
|
|
62390
|
+
message: version,
|
|
62391
|
+
autoFixable: false
|
|
62392
|
+
};
|
|
62393
|
+
} catch (error) {
|
|
62394
|
+
logger.debug(`Python venv check failed: ${error}`);
|
|
62395
|
+
return {
|
|
62396
|
+
id: "python-venv",
|
|
62397
|
+
name: "Python Venv",
|
|
62398
|
+
group: "claudekit",
|
|
62399
|
+
priority: "standard",
|
|
62400
|
+
status: "fail",
|
|
62401
|
+
message: "Failed to check venv",
|
|
62402
|
+
details: error instanceof Error ? error.message : String(error),
|
|
62403
|
+
autoFixable: false
|
|
62404
|
+
};
|
|
62405
|
+
}
|
|
62406
|
+
}
|
|
61619
62407
|
// src/domains/health-checks/claudekit-checker.ts
|
|
61620
62408
|
class ClaudekitChecker {
|
|
61621
62409
|
group = "claudekit";
|
|
@@ -61630,6 +62418,8 @@ class ClaudekitChecker {
|
|
|
61630
62418
|
const setup = await getClaudeKitSetup(this.projectDir);
|
|
61631
62419
|
logger.verbose("ClaudekitChecker: Setup scan complete");
|
|
61632
62420
|
const results = [];
|
|
62421
|
+
logger.verbose("ClaudekitChecker: Checking CLI version");
|
|
62422
|
+
results.push(await checkCliVersion());
|
|
61633
62423
|
logger.verbose("ClaudekitChecker: Checking CLI install method");
|
|
61634
62424
|
results.push(await checkCliInstallMethod());
|
|
61635
62425
|
logger.verbose("ClaudekitChecker: Checking global install");
|
|
@@ -61652,6 +62442,18 @@ class ClaudekitChecker {
|
|
|
61652
62442
|
results.push(await checkGlobalDirWritable());
|
|
61653
62443
|
logger.verbose("ClaudekitChecker: Checking hooks directory");
|
|
61654
62444
|
results.push(await checkHooksExist(this.projectDir));
|
|
62445
|
+
logger.verbose("ClaudekitChecker: Checking hook syntax");
|
|
62446
|
+
results.push(await checkHookSyntax(this.projectDir));
|
|
62447
|
+
logger.verbose("ClaudekitChecker: Checking hook dependencies");
|
|
62448
|
+
results.push(await checkHookDeps(this.projectDir));
|
|
62449
|
+
logger.verbose("ClaudekitChecker: Checking hook runtime");
|
|
62450
|
+
results.push(await checkHookRuntime(this.projectDir));
|
|
62451
|
+
logger.verbose("ClaudekitChecker: Checking hook config");
|
|
62452
|
+
results.push(await checkHookConfig(this.projectDir));
|
|
62453
|
+
logger.verbose("ClaudekitChecker: Checking hook crash logs");
|
|
62454
|
+
results.push(await checkHookLogs(this.projectDir));
|
|
62455
|
+
logger.verbose("ClaudekitChecker: Checking Python venv");
|
|
62456
|
+
results.push(await checkPythonVenv(this.projectDir));
|
|
61655
62457
|
logger.verbose("ClaudekitChecker: Checking settings.json validity");
|
|
61656
62458
|
results.push(await checkSettingsValid(this.projectDir));
|
|
61657
62459
|
logger.verbose("ClaudekitChecker: Checking path references");
|
|
@@ -61664,7 +62466,7 @@ class ClaudekitChecker {
|
|
|
61664
62466
|
}
|
|
61665
62467
|
// src/domains/health-checks/auth-checker.ts
|
|
61666
62468
|
init_github_auth();
|
|
61667
|
-
import { spawnSync as
|
|
62469
|
+
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
61668
62470
|
|
|
61669
62471
|
// src/domains/installation/git-clone-manager.ts
|
|
61670
62472
|
init_logger();
|
|
@@ -61931,7 +62733,7 @@ class AuthChecker {
|
|
|
61931
62733
|
if (false) {}
|
|
61932
62734
|
try {
|
|
61933
62735
|
logger.verbose("AuthChecker: Running 'gh auth status -h github.com' command");
|
|
61934
|
-
const result =
|
|
62736
|
+
const result = spawnSync3("gh", ["auth", "status", "-h", "github.com"], {
|
|
61935
62737
|
encoding: "utf8",
|
|
61936
62738
|
timeout: COMMAND_TIMEOUT_MS2
|
|
61937
62739
|
});
|
|
@@ -62010,7 +62812,7 @@ import { platform as platform6 } from "node:os";
|
|
|
62010
62812
|
init_path_resolver();
|
|
62011
62813
|
import { constants as constants3, access as access3, mkdir as mkdir9, readFile as readFile23, unlink as unlink5, writeFile as writeFile12 } from "node:fs/promises";
|
|
62012
62814
|
import { arch as arch2, homedir as homedir16, platform as platform5 } from "node:os";
|
|
62013
|
-
import { join as
|
|
62815
|
+
import { join as join43, normalize as normalize6 } from "node:path";
|
|
62014
62816
|
var IS_WINDOWS = platform5() === "win32";
|
|
62015
62817
|
function shouldSkipExpensiveOperations4() {
|
|
62016
62818
|
if (process.env.CK_TEST_HOME) {
|
|
@@ -62104,7 +62906,7 @@ async function checkGlobalDirAccess() {
|
|
|
62104
62906
|
autoFixable: false
|
|
62105
62907
|
};
|
|
62106
62908
|
}
|
|
62107
|
-
const testFile =
|
|
62909
|
+
const testFile = join43(globalDir, ".ck-doctor-access-test");
|
|
62108
62910
|
try {
|
|
62109
62911
|
await mkdir9(globalDir, { recursive: true });
|
|
62110
62912
|
await writeFile12(testFile, "test", "utf-8");
|
|
@@ -62182,7 +62984,7 @@ async function checkWSLBoundary() {
|
|
|
62182
62984
|
// src/domains/health-checks/platform/windows-checker.ts
|
|
62183
62985
|
init_path_resolver();
|
|
62184
62986
|
import { mkdir as mkdir10, symlink, unlink as unlink6, writeFile as writeFile13 } from "node:fs/promises";
|
|
62185
|
-
import { join as
|
|
62987
|
+
import { join as join44 } from "node:path";
|
|
62186
62988
|
async function checkLongPathSupport() {
|
|
62187
62989
|
if (shouldSkipExpensiveOperations4()) {
|
|
62188
62990
|
return {
|
|
@@ -62234,8 +63036,8 @@ async function checkSymlinkSupport() {
|
|
|
62234
63036
|
};
|
|
62235
63037
|
}
|
|
62236
63038
|
const testDir = PathResolver.getGlobalKitDir();
|
|
62237
|
-
const target =
|
|
62238
|
-
const link =
|
|
63039
|
+
const target = join44(testDir, ".ck-symlink-test-target");
|
|
63040
|
+
const link = join44(testDir, ".ck-symlink-test-link");
|
|
62239
63041
|
try {
|
|
62240
63042
|
await mkdir10(testDir, { recursive: true });
|
|
62241
63043
|
await writeFile13(target, "test", "utf-8");
|
|
@@ -62518,10 +63320,10 @@ class AutoHealer {
|
|
|
62518
63320
|
}
|
|
62519
63321
|
}
|
|
62520
63322
|
// src/domains/health-checks/report-generator.ts
|
|
62521
|
-
import { execSync as execSync3, spawnSync as
|
|
62522
|
-
import { readFileSync as
|
|
62523
|
-
import { tmpdir as
|
|
62524
|
-
import { dirname as dirname10, join as
|
|
63323
|
+
import { execSync as execSync3, spawnSync as spawnSync4 } from "node:child_process";
|
|
63324
|
+
import { readFileSync as readFileSync7, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
63325
|
+
import { tmpdir as tmpdir3 } from "node:os";
|
|
63326
|
+
import { dirname as dirname10, join as join45 } from "node:path";
|
|
62525
63327
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
62526
63328
|
init_environment();
|
|
62527
63329
|
init_logger();
|
|
@@ -62529,8 +63331,8 @@ init_dist2();
|
|
|
62529
63331
|
function getCliVersion2() {
|
|
62530
63332
|
try {
|
|
62531
63333
|
const __dirname4 = dirname10(fileURLToPath3(import.meta.url));
|
|
62532
|
-
const pkgPath =
|
|
62533
|
-
const pkg = JSON.parse(
|
|
63334
|
+
const pkgPath = join45(__dirname4, "../../../package.json");
|
|
63335
|
+
const pkg = JSON.parse(readFileSync7(pkgPath, "utf-8"));
|
|
62534
63336
|
return pkg.version || "unknown";
|
|
62535
63337
|
} catch (err) {
|
|
62536
63338
|
logger.debug(`Failed to read CLI version: ${err}`);
|
|
@@ -62668,10 +63470,10 @@ class ReportGenerator {
|
|
|
62668
63470
|
return null;
|
|
62669
63471
|
}
|
|
62670
63472
|
}
|
|
62671
|
-
const tmpFile =
|
|
62672
|
-
|
|
63473
|
+
const tmpFile = join45(tmpdir3(), `ck-report-${Date.now()}.txt`);
|
|
63474
|
+
writeFileSync2(tmpFile, report);
|
|
62673
63475
|
try {
|
|
62674
|
-
const result =
|
|
63476
|
+
const result = spawnSync4("gh", ["gist", "create", tmpFile, "--desc", "ClaudeKit Diagnostic Report"], {
|
|
62675
63477
|
encoding: "utf-8"
|
|
62676
63478
|
});
|
|
62677
63479
|
if (result.status !== 0) {
|
|
@@ -62993,7 +63795,7 @@ init_logger();
|
|
|
62993
63795
|
init_path_resolver();
|
|
62994
63796
|
var import_compare_versions5 = __toESM(require_umd(), 1);
|
|
62995
63797
|
import { mkdir as mkdir11, readFile as readFile24, unlink as unlink7, writeFile as writeFile14 } from "node:fs/promises";
|
|
62996
|
-
import { join as
|
|
63798
|
+
import { join as join46 } from "node:path";
|
|
62997
63799
|
var CACHE_TTL_HOURS = 24;
|
|
62998
63800
|
var DEFAULT_CACHE_TTL_MS = CACHE_TTL_HOURS * 60 * 60 * 1000;
|
|
62999
63801
|
var MIN_CACHE_TTL_MS = 60 * 1000;
|
|
@@ -63030,7 +63832,7 @@ var KIT_REPOS = {
|
|
|
63030
63832
|
class ConfigVersionChecker {
|
|
63031
63833
|
static getCacheFilePath(kitType, global3) {
|
|
63032
63834
|
const cacheDir = PathResolver.getCacheDir(global3);
|
|
63033
|
-
return
|
|
63835
|
+
return join46(cacheDir, `${kitType}-${CACHE_FILENAME}`);
|
|
63034
63836
|
}
|
|
63035
63837
|
static async loadCache(kitType, global3) {
|
|
63036
63838
|
try {
|
|
@@ -63117,7 +63919,7 @@ class ConfigVersionChecker {
|
|
|
63117
63919
|
return null;
|
|
63118
63920
|
}
|
|
63119
63921
|
const delay = baseBackoff * 2 ** attempt;
|
|
63120
|
-
await new Promise((
|
|
63922
|
+
await new Promise((resolve9) => setTimeout(resolve9, delay));
|
|
63121
63923
|
}
|
|
63122
63924
|
}
|
|
63123
63925
|
return null;
|
|
@@ -63193,7 +63995,7 @@ class ConfigVersionChecker {
|
|
|
63193
63995
|
}
|
|
63194
63996
|
// src/domains/sync/sync-engine.ts
|
|
63195
63997
|
import { lstat as lstat3, readFile as readFile25, readlink, realpath as realpath2, stat as stat9 } from "node:fs/promises";
|
|
63196
|
-
import { isAbsolute as isAbsolute2, join as
|
|
63998
|
+
import { isAbsolute as isAbsolute2, join as join47, normalize as normalize7, relative as relative4 } from "node:path";
|
|
63197
63999
|
|
|
63198
64000
|
// src/services/file-operations/ownership-checker.ts
|
|
63199
64001
|
init_metadata_migration();
|
|
@@ -63284,24 +64086,24 @@ function pLimit(concurrency) {
|
|
|
63284
64086
|
activeCount--;
|
|
63285
64087
|
resumeNext();
|
|
63286
64088
|
};
|
|
63287
|
-
const run = async (function_,
|
|
64089
|
+
const run = async (function_, resolve9, arguments_) => {
|
|
63288
64090
|
const result = (async () => function_(...arguments_))();
|
|
63289
|
-
|
|
64091
|
+
resolve9(result);
|
|
63290
64092
|
try {
|
|
63291
64093
|
await result;
|
|
63292
64094
|
} catch {}
|
|
63293
64095
|
next();
|
|
63294
64096
|
};
|
|
63295
|
-
const enqueue = (function_,
|
|
64097
|
+
const enqueue = (function_, resolve9, arguments_) => {
|
|
63296
64098
|
new Promise((internalResolve) => {
|
|
63297
64099
|
queue.enqueue(internalResolve);
|
|
63298
|
-
}).then(run.bind(undefined, function_,
|
|
64100
|
+
}).then(run.bind(undefined, function_, resolve9, arguments_));
|
|
63299
64101
|
if (activeCount < concurrency) {
|
|
63300
64102
|
resumeNext();
|
|
63301
64103
|
}
|
|
63302
64104
|
};
|
|
63303
|
-
const generator = (function_, ...arguments_) => new Promise((
|
|
63304
|
-
enqueue(function_,
|
|
64105
|
+
const generator = (function_, ...arguments_) => new Promise((resolve9) => {
|
|
64106
|
+
enqueue(function_, resolve9, arguments_);
|
|
63305
64107
|
});
|
|
63306
64108
|
Object.defineProperties(generator, {
|
|
63307
64109
|
activeCount: {
|
|
@@ -63352,12 +64154,12 @@ async function mapWithLimit(items, fn, concurrency = DEFAULT_CONCURRENCY) {
|
|
|
63352
64154
|
// src/services/file-operations/ownership-checker.ts
|
|
63353
64155
|
class OwnershipChecker {
|
|
63354
64156
|
static async calculateChecksum(filePath) {
|
|
63355
|
-
return new Promise((
|
|
64157
|
+
return new Promise((resolve9, reject) => {
|
|
63356
64158
|
const hash = createHash("sha256");
|
|
63357
64159
|
const stream = createReadStream2(filePath);
|
|
63358
64160
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
63359
64161
|
stream.on("end", () => {
|
|
63360
|
-
|
|
64162
|
+
resolve9(hash.digest("hex"));
|
|
63361
64163
|
});
|
|
63362
64164
|
stream.on("error", (err) => {
|
|
63363
64165
|
stream.destroy();
|
|
@@ -64481,7 +65283,7 @@ async function validateSymlinkChain(path3, basePath, maxDepth = MAX_SYMLINK_DEPT
|
|
|
64481
65283
|
if (!stats.isSymbolicLink())
|
|
64482
65284
|
break;
|
|
64483
65285
|
const target = await readlink(current);
|
|
64484
|
-
const resolvedTarget = isAbsolute2(target) ? target :
|
|
65286
|
+
const resolvedTarget = isAbsolute2(target) ? target : join47(current, "..", target);
|
|
64485
65287
|
const normalizedTarget = normalize7(resolvedTarget);
|
|
64486
65288
|
const rel = relative4(basePath, normalizedTarget);
|
|
64487
65289
|
if (rel.startsWith("..") || isAbsolute2(rel)) {
|
|
@@ -64517,7 +65319,7 @@ async function validateSyncPath(basePath, filePath) {
|
|
|
64517
65319
|
if (normalized.startsWith("..") || normalized.includes("/../")) {
|
|
64518
65320
|
throw new Error(`Path traversal not allowed: ${filePath}`);
|
|
64519
65321
|
}
|
|
64520
|
-
const fullPath =
|
|
65322
|
+
const fullPath = join47(basePath, normalized);
|
|
64521
65323
|
const rel = relative4(basePath, fullPath);
|
|
64522
65324
|
if (rel.startsWith("..") || isAbsolute2(rel)) {
|
|
64523
65325
|
throw new Error(`Path escapes base directory: ${filePath}`);
|
|
@@ -64532,7 +65334,7 @@ async function validateSyncPath(basePath, filePath) {
|
|
|
64532
65334
|
}
|
|
64533
65335
|
} catch (error) {
|
|
64534
65336
|
if (error.code === "ENOENT") {
|
|
64535
|
-
const parentPath =
|
|
65337
|
+
const parentPath = join47(fullPath, "..");
|
|
64536
65338
|
try {
|
|
64537
65339
|
const resolvedBase = await realpath2(basePath);
|
|
64538
65340
|
const resolvedParent = await realpath2(parentPath);
|
|
@@ -65714,7 +66516,7 @@ init_logger();
|
|
|
65714
66516
|
var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
|
|
65715
66517
|
import { mkdir as mkdir14 } from "node:fs/promises";
|
|
65716
66518
|
import os5 from "node:os";
|
|
65717
|
-
import { join as
|
|
66519
|
+
import { join as join54 } from "node:path";
|
|
65718
66520
|
var LOCK_CONFIG = {
|
|
65719
66521
|
stale: 60000,
|
|
65720
66522
|
retries: 0
|
|
@@ -65722,12 +66524,12 @@ var LOCK_CONFIG = {
|
|
|
65722
66524
|
var activeLocks = new Set;
|
|
65723
66525
|
var cleanupRegistered = false;
|
|
65724
66526
|
function getLocksDir() {
|
|
65725
|
-
return
|
|
66527
|
+
return join54(os5.homedir(), ".claudekit", "locks");
|
|
65726
66528
|
}
|
|
65727
66529
|
function cleanupLocks() {
|
|
65728
66530
|
for (const name of activeLocks) {
|
|
65729
66531
|
try {
|
|
65730
|
-
const lockPath =
|
|
66532
|
+
const lockPath = join54(getLocksDir(), `${name}.lock`);
|
|
65731
66533
|
import_proper_lockfile.default.unlockSync(lockPath, { realpath: false });
|
|
65732
66534
|
} catch {
|
|
65733
66535
|
try {
|
|
@@ -65750,7 +66552,7 @@ async function ensureLocksDir() {
|
|
|
65750
66552
|
async function withProcessLock(lockName, fn) {
|
|
65751
66553
|
registerCleanupHandlers();
|
|
65752
66554
|
await ensureLocksDir();
|
|
65753
|
-
const lockPath =
|
|
66555
|
+
const lockPath = join54(getLocksDir(), `${lockName}.lock`);
|
|
65754
66556
|
let release;
|
|
65755
66557
|
try {
|
|
65756
66558
|
release = await import_proper_lockfile.default.lock(lockPath, { ...LOCK_CONFIG, realpath: false });
|
|
@@ -65781,7 +66583,7 @@ init_logger();
|
|
|
65781
66583
|
init_logger();
|
|
65782
66584
|
init_path_resolver();
|
|
65783
66585
|
var import_fs_extra7 = __toESM(require_lib3(), 1);
|
|
65784
|
-
import { join as
|
|
66586
|
+
import { join as join55 } from "node:path";
|
|
65785
66587
|
async function handleConflicts(ctx) {
|
|
65786
66588
|
if (ctx.cancelled)
|
|
65787
66589
|
return ctx;
|
|
@@ -65790,7 +66592,7 @@ async function handleConflicts(ctx) {
|
|
|
65790
66592
|
if (PathResolver.isLocalSameAsGlobal()) {
|
|
65791
66593
|
return ctx;
|
|
65792
66594
|
}
|
|
65793
|
-
const localSettingsPath =
|
|
66595
|
+
const localSettingsPath = join55(process.cwd(), ".claude", "settings.json");
|
|
65794
66596
|
if (!await import_fs_extra7.pathExists(localSettingsPath)) {
|
|
65795
66597
|
return ctx;
|
|
65796
66598
|
}
|
|
@@ -65805,7 +66607,7 @@ async function handleConflicts(ctx) {
|
|
|
65805
66607
|
return { ...ctx, cancelled: true };
|
|
65806
66608
|
}
|
|
65807
66609
|
if (choice === "remove") {
|
|
65808
|
-
const localClaudeDir =
|
|
66610
|
+
const localClaudeDir = join55(process.cwd(), ".claude");
|
|
65809
66611
|
try {
|
|
65810
66612
|
await import_fs_extra7.remove(localClaudeDir);
|
|
65811
66613
|
logger.success("Removed local .claude/ directory");
|
|
@@ -65901,8 +66703,8 @@ init_environment();
|
|
|
65901
66703
|
init_logger();
|
|
65902
66704
|
init_safe_spinner();
|
|
65903
66705
|
import { mkdir as mkdir20, stat as stat12 } from "node:fs/promises";
|
|
65904
|
-
import { tmpdir as
|
|
65905
|
-
import { join as
|
|
66706
|
+
import { tmpdir as tmpdir4 } from "node:os";
|
|
66707
|
+
import { join as join62 } from "node:path";
|
|
65906
66708
|
|
|
65907
66709
|
// src/shared/temp-cleanup.ts
|
|
65908
66710
|
init_logger();
|
|
@@ -65921,7 +66723,7 @@ init_logger();
|
|
|
65921
66723
|
init_output_manager();
|
|
65922
66724
|
import { createWriteStream as createWriteStream2, rmSync } from "node:fs";
|
|
65923
66725
|
import { mkdir as mkdir15 } from "node:fs/promises";
|
|
65924
|
-
import { join as
|
|
66726
|
+
import { join as join56 } from "node:path";
|
|
65925
66727
|
|
|
65926
66728
|
// src/shared/progress-bar.ts
|
|
65927
66729
|
init_output_manager();
|
|
@@ -66086,10 +66888,10 @@ init_types2();
|
|
|
66086
66888
|
// src/domains/installation/utils/path-security.ts
|
|
66087
66889
|
init_types2();
|
|
66088
66890
|
import { lstatSync as lstatSync2, realpathSync as realpathSync2 } from "node:fs";
|
|
66089
|
-
import { relative as relative5, resolve as
|
|
66891
|
+
import { relative as relative5, resolve as resolve11 } from "node:path";
|
|
66090
66892
|
var MAX_EXTRACTION_SIZE = 500 * 1024 * 1024;
|
|
66091
66893
|
function isPathSafe(basePath, targetPath) {
|
|
66092
|
-
const resolvedBase =
|
|
66894
|
+
const resolvedBase = resolve11(basePath);
|
|
66093
66895
|
try {
|
|
66094
66896
|
const stat10 = lstatSync2(targetPath);
|
|
66095
66897
|
if (stat10.isSymbolicLink()) {
|
|
@@ -66099,7 +66901,7 @@ function isPathSafe(basePath, targetPath) {
|
|
|
66099
66901
|
}
|
|
66100
66902
|
}
|
|
66101
66903
|
} catch {}
|
|
66102
|
-
const resolvedTarget =
|
|
66904
|
+
const resolvedTarget = resolve11(targetPath);
|
|
66103
66905
|
const relativePath = relative5(resolvedBase, resolvedTarget);
|
|
66104
66906
|
return !relativePath.startsWith("..") && !relativePath.startsWith("/") && resolvedTarget.startsWith(resolvedBase);
|
|
66105
66907
|
}
|
|
@@ -66131,7 +66933,7 @@ var MAX_DOWNLOAD_SIZE = 500 * 1024 * 1024;
|
|
|
66131
66933
|
class FileDownloader {
|
|
66132
66934
|
async downloadAsset(asset, destDir) {
|
|
66133
66935
|
try {
|
|
66134
|
-
const destPath =
|
|
66936
|
+
const destPath = join56(destDir, asset.name);
|
|
66135
66937
|
await mkdir15(destDir, { recursive: true });
|
|
66136
66938
|
output.info(`Downloading ${asset.name} (${formatBytes(asset.size)})...`);
|
|
66137
66939
|
logger.verbose("Download details", {
|
|
@@ -66187,7 +66989,7 @@ class FileDownloader {
|
|
|
66187
66989
|
}
|
|
66188
66990
|
if (downloadedSize !== totalSize) {
|
|
66189
66991
|
fileStream.end();
|
|
66190
|
-
await new Promise((
|
|
66992
|
+
await new Promise((resolve12) => fileStream.once("close", resolve12));
|
|
66191
66993
|
try {
|
|
66192
66994
|
rmSync(destPath, { force: true });
|
|
66193
66995
|
} catch (cleanupError) {
|
|
@@ -66201,7 +67003,7 @@ class FileDownloader {
|
|
|
66201
67003
|
return destPath;
|
|
66202
67004
|
} catch (error) {
|
|
66203
67005
|
fileStream.end();
|
|
66204
|
-
await new Promise((
|
|
67006
|
+
await new Promise((resolve12) => fileStream.once("close", resolve12));
|
|
66205
67007
|
try {
|
|
66206
67008
|
rmSync(destPath, { force: true });
|
|
66207
67009
|
} catch (cleanupError) {
|
|
@@ -66216,7 +67018,7 @@ class FileDownloader {
|
|
|
66216
67018
|
}
|
|
66217
67019
|
async downloadFile(params) {
|
|
66218
67020
|
const { url, name, size, destDir, token } = params;
|
|
66219
|
-
const destPath =
|
|
67021
|
+
const destPath = join56(destDir, name);
|
|
66220
67022
|
await mkdir15(destDir, { recursive: true });
|
|
66221
67023
|
output.info(`Downloading ${name}${size ? ` (${formatBytes(size)})` : ""}...`);
|
|
66222
67024
|
const headers = {};
|
|
@@ -66267,7 +67069,7 @@ class FileDownloader {
|
|
|
66267
67069
|
const expectedSize = Number(response.headers.get("content-length"));
|
|
66268
67070
|
if (expectedSize > 0 && downloadedSize !== expectedSize) {
|
|
66269
67071
|
fileStream.end();
|
|
66270
|
-
await new Promise((
|
|
67072
|
+
await new Promise((resolve12) => fileStream.once("close", resolve12));
|
|
66271
67073
|
try {
|
|
66272
67074
|
rmSync(destPath, { force: true });
|
|
66273
67075
|
} catch (cleanupError) {
|
|
@@ -66285,7 +67087,7 @@ class FileDownloader {
|
|
|
66285
67087
|
return destPath;
|
|
66286
67088
|
} catch (error) {
|
|
66287
67089
|
fileStream.end();
|
|
66288
|
-
await new Promise((
|
|
67090
|
+
await new Promise((resolve12) => fileStream.once("close", resolve12));
|
|
66289
67091
|
try {
|
|
66290
67092
|
rmSync(destPath, { force: true });
|
|
66291
67093
|
} catch (cleanupError) {
|
|
@@ -66301,11 +67103,11 @@ class FileDownloader {
|
|
|
66301
67103
|
init_logger();
|
|
66302
67104
|
init_types2();
|
|
66303
67105
|
import { constants as constants4 } from "node:fs";
|
|
66304
|
-
import { access as access4, readdir as
|
|
66305
|
-
import { join as
|
|
67106
|
+
import { access as access4, readdir as readdir10 } from "node:fs/promises";
|
|
67107
|
+
import { join as join57 } from "node:path";
|
|
66306
67108
|
async function validateExtraction(extractDir) {
|
|
66307
67109
|
try {
|
|
66308
|
-
const entries = await
|
|
67110
|
+
const entries = await readdir10(extractDir, { encoding: "utf8" });
|
|
66309
67111
|
logger.debug(`Extracted files: ${entries.join(", ")}`);
|
|
66310
67112
|
if (entries.length === 0) {
|
|
66311
67113
|
throw new ExtractionError("Extraction resulted in no files");
|
|
@@ -66314,7 +67116,7 @@ async function validateExtraction(extractDir) {
|
|
|
66314
67116
|
const missingPaths = [];
|
|
66315
67117
|
for (const path3 of criticalPaths) {
|
|
66316
67118
|
try {
|
|
66317
|
-
await access4(
|
|
67119
|
+
await access4(join57(extractDir, path3), constants4.F_OK);
|
|
66318
67120
|
logger.debug(`Found: ${path3}`);
|
|
66319
67121
|
} catch {
|
|
66320
67122
|
logger.warning(`Expected path not found: ${path3}`);
|
|
@@ -66335,8 +67137,8 @@ async function validateExtraction(extractDir) {
|
|
|
66335
67137
|
|
|
66336
67138
|
// src/domains/installation/extraction/tar-extractor.ts
|
|
66337
67139
|
init_logger();
|
|
66338
|
-
import { copyFile as copyFile3, mkdir as mkdir18, readdir as
|
|
66339
|
-
import { join as
|
|
67140
|
+
import { copyFile as copyFile3, mkdir as mkdir18, readdir as readdir12, rm as rm3, stat as stat10 } from "node:fs/promises";
|
|
67141
|
+
import { join as join60 } from "node:path";
|
|
66340
67142
|
|
|
66341
67143
|
// node_modules/@isaacs/fs-minipass/dist/esm/index.js
|
|
66342
67144
|
import EE from "events";
|
|
@@ -66884,10 +67686,10 @@ class Minipass extends EventEmitter3 {
|
|
|
66884
67686
|
return this[ENCODING] ? buf.join("") : Buffer.concat(buf, buf.dataLength);
|
|
66885
67687
|
}
|
|
66886
67688
|
async promise() {
|
|
66887
|
-
return new Promise((
|
|
67689
|
+
return new Promise((resolve12, reject) => {
|
|
66888
67690
|
this.on(DESTROYED, () => reject(new Error("stream destroyed")));
|
|
66889
67691
|
this.on("error", (er) => reject(er));
|
|
66890
|
-
this.on("end", () =>
|
|
67692
|
+
this.on("end", () => resolve12());
|
|
66891
67693
|
});
|
|
66892
67694
|
}
|
|
66893
67695
|
[Symbol.asyncIterator]() {
|
|
@@ -66906,7 +67708,7 @@ class Minipass extends EventEmitter3 {
|
|
|
66906
67708
|
return Promise.resolve({ done: false, value: res });
|
|
66907
67709
|
if (this[EOF])
|
|
66908
67710
|
return stop();
|
|
66909
|
-
let
|
|
67711
|
+
let resolve12;
|
|
66910
67712
|
let reject;
|
|
66911
67713
|
const onerr = (er) => {
|
|
66912
67714
|
this.off("data", ondata);
|
|
@@ -66920,19 +67722,19 @@ class Minipass extends EventEmitter3 {
|
|
|
66920
67722
|
this.off("end", onend);
|
|
66921
67723
|
this.off(DESTROYED, ondestroy);
|
|
66922
67724
|
this.pause();
|
|
66923
|
-
|
|
67725
|
+
resolve12({ value, done: !!this[EOF] });
|
|
66924
67726
|
};
|
|
66925
67727
|
const onend = () => {
|
|
66926
67728
|
this.off("error", onerr);
|
|
66927
67729
|
this.off("data", ondata);
|
|
66928
67730
|
this.off(DESTROYED, ondestroy);
|
|
66929
67731
|
stop();
|
|
66930
|
-
|
|
67732
|
+
resolve12({ done: true, value: undefined });
|
|
66931
67733
|
};
|
|
66932
67734
|
const ondestroy = () => onerr(new Error("stream destroyed"));
|
|
66933
67735
|
return new Promise((res2, rej) => {
|
|
66934
67736
|
reject = rej;
|
|
66935
|
-
|
|
67737
|
+
resolve12 = res2;
|
|
66936
67738
|
this.once(DESTROYED, ondestroy);
|
|
66937
67739
|
this.once("error", onerr);
|
|
66938
67740
|
this.once("end", onend);
|
|
@@ -68038,10 +68840,10 @@ class Minipass2 extends EventEmitter4 {
|
|
|
68038
68840
|
return this[ENCODING2] ? buf.join("") : Buffer.concat(buf, buf.dataLength);
|
|
68039
68841
|
}
|
|
68040
68842
|
async promise() {
|
|
68041
|
-
return new Promise((
|
|
68843
|
+
return new Promise((resolve12, reject) => {
|
|
68042
68844
|
this.on(DESTROYED2, () => reject(new Error("stream destroyed")));
|
|
68043
68845
|
this.on("error", (er) => reject(er));
|
|
68044
|
-
this.on("end", () =>
|
|
68846
|
+
this.on("end", () => resolve12());
|
|
68045
68847
|
});
|
|
68046
68848
|
}
|
|
68047
68849
|
[Symbol.asyncIterator]() {
|
|
@@ -68060,7 +68862,7 @@ class Minipass2 extends EventEmitter4 {
|
|
|
68060
68862
|
return Promise.resolve({ done: false, value: res });
|
|
68061
68863
|
if (this[EOF2])
|
|
68062
68864
|
return stop();
|
|
68063
|
-
let
|
|
68865
|
+
let resolve12;
|
|
68064
68866
|
let reject;
|
|
68065
68867
|
const onerr = (er) => {
|
|
68066
68868
|
this.off("data", ondata);
|
|
@@ -68074,19 +68876,19 @@ class Minipass2 extends EventEmitter4 {
|
|
|
68074
68876
|
this.off("end", onend);
|
|
68075
68877
|
this.off(DESTROYED2, ondestroy);
|
|
68076
68878
|
this.pause();
|
|
68077
|
-
|
|
68879
|
+
resolve12({ value, done: !!this[EOF2] });
|
|
68078
68880
|
};
|
|
68079
68881
|
const onend = () => {
|
|
68080
68882
|
this.off("error", onerr);
|
|
68081
68883
|
this.off("data", ondata);
|
|
68082
68884
|
this.off(DESTROYED2, ondestroy);
|
|
68083
68885
|
stop();
|
|
68084
|
-
|
|
68886
|
+
resolve12({ done: true, value: undefined });
|
|
68085
68887
|
};
|
|
68086
68888
|
const ondestroy = () => onerr(new Error("stream destroyed"));
|
|
68087
68889
|
return new Promise((res2, rej) => {
|
|
68088
68890
|
reject = rej;
|
|
68089
|
-
|
|
68891
|
+
resolve12 = res2;
|
|
68090
68892
|
this.once(DESTROYED2, ondestroy);
|
|
68091
68893
|
this.once("error", onerr);
|
|
68092
68894
|
this.once("end", onend);
|
|
@@ -69514,10 +70316,10 @@ class Minipass3 extends EventEmitter5 {
|
|
|
69514
70316
|
return this[ENCODING3] ? buf.join("") : Buffer.concat(buf, buf.dataLength);
|
|
69515
70317
|
}
|
|
69516
70318
|
async promise() {
|
|
69517
|
-
return new Promise((
|
|
70319
|
+
return new Promise((resolve12, reject) => {
|
|
69518
70320
|
this.on(DESTROYED3, () => reject(new Error("stream destroyed")));
|
|
69519
70321
|
this.on("error", (er) => reject(er));
|
|
69520
|
-
this.on("end", () =>
|
|
70322
|
+
this.on("end", () => resolve12());
|
|
69521
70323
|
});
|
|
69522
70324
|
}
|
|
69523
70325
|
[Symbol.asyncIterator]() {
|
|
@@ -69536,7 +70338,7 @@ class Minipass3 extends EventEmitter5 {
|
|
|
69536
70338
|
return Promise.resolve({ done: false, value: res });
|
|
69537
70339
|
if (this[EOF3])
|
|
69538
70340
|
return stop();
|
|
69539
|
-
let
|
|
70341
|
+
let resolve12;
|
|
69540
70342
|
let reject;
|
|
69541
70343
|
const onerr = (er) => {
|
|
69542
70344
|
this.off("data", ondata);
|
|
@@ -69550,19 +70352,19 @@ class Minipass3 extends EventEmitter5 {
|
|
|
69550
70352
|
this.off("end", onend);
|
|
69551
70353
|
this.off(DESTROYED3, ondestroy);
|
|
69552
70354
|
this.pause();
|
|
69553
|
-
|
|
70355
|
+
resolve12({ value, done: !!this[EOF3] });
|
|
69554
70356
|
};
|
|
69555
70357
|
const onend = () => {
|
|
69556
70358
|
this.off("error", onerr);
|
|
69557
70359
|
this.off("data", ondata);
|
|
69558
70360
|
this.off(DESTROYED3, ondestroy);
|
|
69559
70361
|
stop();
|
|
69560
|
-
|
|
70362
|
+
resolve12({ done: true, value: undefined });
|
|
69561
70363
|
};
|
|
69562
70364
|
const ondestroy = () => onerr(new Error("stream destroyed"));
|
|
69563
70365
|
return new Promise((res2, rej) => {
|
|
69564
70366
|
reject = rej;
|
|
69565
|
-
|
|
70367
|
+
resolve12 = res2;
|
|
69566
70368
|
this.once(DESTROYED3, ondestroy);
|
|
69567
70369
|
this.once("error", onerr);
|
|
69568
70370
|
this.once("end", onend);
|
|
@@ -70333,9 +71135,9 @@ var listFile = (opt, _files) => {
|
|
|
70333
71135
|
const parse4 = new Parser(opt);
|
|
70334
71136
|
const readSize = opt.maxReadSize || 16 * 1024 * 1024;
|
|
70335
71137
|
const file = opt.file;
|
|
70336
|
-
const p = new Promise((
|
|
71138
|
+
const p = new Promise((resolve12, reject) => {
|
|
70337
71139
|
parse4.on("error", reject);
|
|
70338
|
-
parse4.on("end",
|
|
71140
|
+
parse4.on("end", resolve12);
|
|
70339
71141
|
fs9.stat(file, (er, stat10) => {
|
|
70340
71142
|
if (er) {
|
|
70341
71143
|
reject(er);
|
|
@@ -72098,7 +72900,7 @@ var mkdirSync = (dir, opt) => {
|
|
|
72098
72900
|
};
|
|
72099
72901
|
|
|
72100
72902
|
// node_modules/tar/dist/esm/path-reservations.js
|
|
72101
|
-
import { join as
|
|
72903
|
+
import { join as join58 } from "node:path";
|
|
72102
72904
|
|
|
72103
72905
|
// node_modules/tar/dist/esm/normalize-unicode.js
|
|
72104
72906
|
var normalizeCache = Object.create(null);
|
|
@@ -72131,7 +72933,7 @@ var getDirs = (path8) => {
|
|
|
72131
72933
|
const dirs = path8.split("/").slice(0, -1).reduce((set, path9) => {
|
|
72132
72934
|
const s = set[set.length - 1];
|
|
72133
72935
|
if (s !== undefined) {
|
|
72134
|
-
path9 =
|
|
72936
|
+
path9 = join58(s, path9);
|
|
72135
72937
|
}
|
|
72136
72938
|
set.push(path9 || "/");
|
|
72137
72939
|
return set;
|
|
@@ -72145,7 +72947,7 @@ class PathReservations {
|
|
|
72145
72947
|
#running = new Set;
|
|
72146
72948
|
reserve(paths, fn) {
|
|
72147
72949
|
paths = isWindows4 ? ["win32 parallelization disabled"] : paths.map((p) => {
|
|
72148
|
-
return stripTrailingSlashes(
|
|
72950
|
+
return stripTrailingSlashes(join58(normalizeUnicode(p))).toLowerCase();
|
|
72149
72951
|
});
|
|
72150
72952
|
const dirs = new Set(paths.map((path8) => getDirs(path8)).reduce((a3, b3) => a3.concat(b3)));
|
|
72151
72953
|
this.#reservations.set(fn, { dirs, paths });
|
|
@@ -72915,9 +73717,9 @@ var extractFile = (opt, _3) => {
|
|
|
72915
73717
|
const u = new Unpack(opt);
|
|
72916
73718
|
const readSize = opt.maxReadSize || 16 * 1024 * 1024;
|
|
72917
73719
|
const file = opt.file;
|
|
72918
|
-
const p = new Promise((
|
|
73720
|
+
const p = new Promise((resolve12, reject) => {
|
|
72919
73721
|
u.on("error", reject);
|
|
72920
|
-
u.on("close",
|
|
73722
|
+
u.on("close", resolve12);
|
|
72921
73723
|
fs16.stat(file, (er, stat10) => {
|
|
72922
73724
|
if (er) {
|
|
72923
73725
|
reject(er);
|
|
@@ -73050,7 +73852,7 @@ var replaceAsync = (opt, files) => {
|
|
|
73050
73852
|
};
|
|
73051
73853
|
fs17.read(fd, headBuf, 0, 512, position, onread);
|
|
73052
73854
|
};
|
|
73053
|
-
const promise = new Promise((
|
|
73855
|
+
const promise = new Promise((resolve12, reject) => {
|
|
73054
73856
|
p.on("error", reject);
|
|
73055
73857
|
let flag = "r+";
|
|
73056
73858
|
const onopen = (er, fd) => {
|
|
@@ -73075,7 +73877,7 @@ var replaceAsync = (opt, files) => {
|
|
|
73075
73877
|
});
|
|
73076
73878
|
p.pipe(stream);
|
|
73077
73879
|
stream.on("error", reject);
|
|
73078
|
-
stream.on("close",
|
|
73880
|
+
stream.on("close", resolve12);
|
|
73079
73881
|
addFilesAsync2(p, files);
|
|
73080
73882
|
});
|
|
73081
73883
|
});
|
|
@@ -73204,8 +74006,8 @@ function decodeFilePath(path10) {
|
|
|
73204
74006
|
// src/domains/installation/utils/file-utils.ts
|
|
73205
74007
|
init_logger();
|
|
73206
74008
|
init_types2();
|
|
73207
|
-
import { copyFile as copyFile2, lstat as lstat4, mkdir as mkdir17, readdir as
|
|
73208
|
-
import { join as
|
|
74009
|
+
import { copyFile as copyFile2, lstat as lstat4, mkdir as mkdir17, readdir as readdir11 } from "node:fs/promises";
|
|
74010
|
+
import { join as join59, relative as relative6 } from "node:path";
|
|
73209
74011
|
async function withRetry(fn, retries = 3) {
|
|
73210
74012
|
for (let i = 0;i < retries; i++) {
|
|
73211
74013
|
try {
|
|
@@ -73225,10 +74027,10 @@ var isRetryable = (e2) => {
|
|
|
73225
74027
|
var delay = (ms) => new Promise((r2) => setTimeout(r2, ms));
|
|
73226
74028
|
async function moveDirectoryContents(sourceDir, destDir, shouldExclude, sizeTracker) {
|
|
73227
74029
|
await mkdir17(destDir, { recursive: true });
|
|
73228
|
-
const entries = await
|
|
74030
|
+
const entries = await readdir11(sourceDir, { encoding: "utf8" });
|
|
73229
74031
|
for (const entry of entries) {
|
|
73230
|
-
const sourcePath =
|
|
73231
|
-
const destPath =
|
|
74032
|
+
const sourcePath = join59(sourceDir, entry);
|
|
74033
|
+
const destPath = join59(destDir, entry);
|
|
73232
74034
|
const relativePath = relative6(sourceDir, sourcePath);
|
|
73233
74035
|
if (!isPathSafe(destDir, destPath)) {
|
|
73234
74036
|
logger.warning(`Skipping unsafe path: ${relativePath}`);
|
|
@@ -73253,10 +74055,10 @@ async function moveDirectoryContents(sourceDir, destDir, shouldExclude, sizeTrac
|
|
|
73253
74055
|
}
|
|
73254
74056
|
async function copyDirectory(sourceDir, destDir, shouldExclude, sizeTracker) {
|
|
73255
74057
|
await mkdir17(destDir, { recursive: true });
|
|
73256
|
-
const entries = await
|
|
74058
|
+
const entries = await readdir11(sourceDir, { encoding: "utf8" });
|
|
73257
74059
|
for (const entry of entries) {
|
|
73258
|
-
const sourcePath =
|
|
73259
|
-
const destPath =
|
|
74060
|
+
const sourcePath = join59(sourceDir, entry);
|
|
74061
|
+
const destPath = join59(destDir, entry);
|
|
73260
74062
|
const relativePath = relative6(sourceDir, sourcePath);
|
|
73261
74063
|
if (!isPathSafe(destDir, destPath)) {
|
|
73262
74064
|
logger.warning(`Skipping unsafe path: ${relativePath}`);
|
|
@@ -73300,14 +74102,14 @@ class TarExtractor {
|
|
|
73300
74102
|
}
|
|
73301
74103
|
});
|
|
73302
74104
|
logger.debug(`Extracted TAR.GZ to temp: ${tempExtractDir}`);
|
|
73303
|
-
const entries = await
|
|
74105
|
+
const entries = await readdir12(tempExtractDir, { encoding: "utf8" });
|
|
73304
74106
|
logger.debug(`Root entries: ${entries.join(", ")}`);
|
|
73305
74107
|
if (entries.length === 1) {
|
|
73306
74108
|
const rootEntry = entries[0];
|
|
73307
|
-
const rootPath =
|
|
74109
|
+
const rootPath = join60(tempExtractDir, rootEntry);
|
|
73308
74110
|
const rootStat = await stat10(rootPath);
|
|
73309
74111
|
if (rootStat.isDirectory()) {
|
|
73310
|
-
const rootContents = await
|
|
74112
|
+
const rootContents = await readdir12(rootPath, { encoding: "utf8" });
|
|
73311
74113
|
logger.debug(`Root directory '${rootEntry}' contains: ${rootContents.join(", ")}`);
|
|
73312
74114
|
const isWrapper = isWrapperDirectory(rootEntry);
|
|
73313
74115
|
logger.debug(`Is wrapper directory: ${isWrapper}`);
|
|
@@ -73320,7 +74122,7 @@ class TarExtractor {
|
|
|
73320
74122
|
}
|
|
73321
74123
|
} else {
|
|
73322
74124
|
await mkdir18(destDir, { recursive: true });
|
|
73323
|
-
await copyFile3(rootPath,
|
|
74125
|
+
await copyFile3(rootPath, join60(destDir, rootEntry));
|
|
73324
74126
|
}
|
|
73325
74127
|
} else {
|
|
73326
74128
|
logger.debug("Multiple root entries - moving all");
|
|
@@ -73342,27 +74144,27 @@ init_environment();
|
|
|
73342
74144
|
init_logger();
|
|
73343
74145
|
var import_extract_zip = __toESM(require_extract_zip(), 1);
|
|
73344
74146
|
import { execFile as execFile8 } from "node:child_process";
|
|
73345
|
-
import { copyFile as copyFile4, mkdir as mkdir19, readdir as
|
|
73346
|
-
import { join as
|
|
74147
|
+
import { copyFile as copyFile4, mkdir as mkdir19, readdir as readdir13, rm as rm4, stat as stat11 } from "node:fs/promises";
|
|
74148
|
+
import { join as join61 } from "node:path";
|
|
73347
74149
|
class ZipExtractor {
|
|
73348
74150
|
async tryNativeUnzip(archivePath, destDir) {
|
|
73349
74151
|
if (!isMacOS()) {
|
|
73350
74152
|
return false;
|
|
73351
74153
|
}
|
|
73352
|
-
return new Promise((
|
|
74154
|
+
return new Promise((resolve12) => {
|
|
73353
74155
|
mkdir19(destDir, { recursive: true }).then(() => {
|
|
73354
74156
|
execFile8("unzip", ["-o", "-q", archivePath, "-d", destDir], (error, _stdout, stderr) => {
|
|
73355
74157
|
if (error) {
|
|
73356
74158
|
logger.debug(`Native unzip failed: ${stderr || error.message}`);
|
|
73357
|
-
|
|
74159
|
+
resolve12(false);
|
|
73358
74160
|
return;
|
|
73359
74161
|
}
|
|
73360
74162
|
logger.debug("Native unzip succeeded");
|
|
73361
|
-
|
|
74163
|
+
resolve12(true);
|
|
73362
74164
|
});
|
|
73363
74165
|
}).catch((err) => {
|
|
73364
74166
|
logger.debug(`Failed to create directory for native unzip: ${err.message}`);
|
|
73365
|
-
|
|
74167
|
+
resolve12(false);
|
|
73366
74168
|
});
|
|
73367
74169
|
});
|
|
73368
74170
|
}
|
|
@@ -73387,14 +74189,14 @@ class ZipExtractor {
|
|
|
73387
74189
|
logger.verbose(`Extracted ${extractedCount} files`);
|
|
73388
74190
|
}
|
|
73389
74191
|
logger.debug(`Extracted ZIP to temp: ${tempExtractDir}`);
|
|
73390
|
-
const entries = await
|
|
74192
|
+
const entries = await readdir13(tempExtractDir, { encoding: "utf8" });
|
|
73391
74193
|
logger.debug(`Root entries: ${entries.join(", ")}`);
|
|
73392
74194
|
if (entries.length === 1) {
|
|
73393
74195
|
const rootEntry = entries[0];
|
|
73394
|
-
const rootPath =
|
|
74196
|
+
const rootPath = join61(tempExtractDir, rootEntry);
|
|
73395
74197
|
const rootStat = await stat11(rootPath);
|
|
73396
74198
|
if (rootStat.isDirectory()) {
|
|
73397
|
-
const rootContents = await
|
|
74199
|
+
const rootContents = await readdir13(rootPath, { encoding: "utf8" });
|
|
73398
74200
|
logger.debug(`Root directory '${rootEntry}' contains: ${rootContents.join(", ")}`);
|
|
73399
74201
|
const isWrapper = isWrapperDirectory(rootEntry);
|
|
73400
74202
|
logger.debug(`Is wrapper directory: ${isWrapper}`);
|
|
@@ -73407,7 +74209,7 @@ class ZipExtractor {
|
|
|
73407
74209
|
}
|
|
73408
74210
|
} else {
|
|
73409
74211
|
await mkdir19(destDir, { recursive: true });
|
|
73410
|
-
await copyFile4(rootPath,
|
|
74212
|
+
await copyFile4(rootPath, join61(destDir, rootEntry));
|
|
73411
74213
|
}
|
|
73412
74214
|
} else {
|
|
73413
74215
|
logger.debug("Multiple root entries - moving all");
|
|
@@ -73506,7 +74308,7 @@ class DownloadManager {
|
|
|
73506
74308
|
async createTempDir() {
|
|
73507
74309
|
const timestamp = Date.now();
|
|
73508
74310
|
const counter = DownloadManager.tempDirCounter++;
|
|
73509
|
-
const primaryTempDir =
|
|
74311
|
+
const primaryTempDir = join62(tmpdir4(), `claudekit-${timestamp}-${counter}`);
|
|
73510
74312
|
try {
|
|
73511
74313
|
await mkdir20(primaryTempDir, { recursive: true });
|
|
73512
74314
|
logger.debug(`Created temp directory: ${primaryTempDir}`);
|
|
@@ -73523,7 +74325,7 @@ Solutions:
|
|
|
73523
74325
|
2. Set HOME environment variable
|
|
73524
74326
|
3. Try running from a different directory`);
|
|
73525
74327
|
}
|
|
73526
|
-
const fallbackTempDir =
|
|
74328
|
+
const fallbackTempDir = join62(homeDir, ".claudekit", "tmp", `claudekit-${timestamp}-${counter}`);
|
|
73527
74329
|
try {
|
|
73528
74330
|
await mkdir20(fallbackTempDir, { recursive: true });
|
|
73529
74331
|
logger.debug(`Created temp directory (fallback): ${fallbackTempDir}`);
|
|
@@ -73872,20 +74674,20 @@ async function handleDownload(ctx) {
|
|
|
73872
74674
|
};
|
|
73873
74675
|
}
|
|
73874
74676
|
// src/commands/init/phases/merge-handler.ts
|
|
73875
|
-
import { join as
|
|
74677
|
+
import { join as join78 } from "node:path";
|
|
73876
74678
|
|
|
73877
74679
|
// src/domains/installation/deletion-handler.ts
|
|
73878
|
-
import { existsSync as
|
|
73879
|
-
import { dirname as dirname14, join as
|
|
74680
|
+
import { existsSync as existsSync36, lstatSync as lstatSync3, readdirSync as readdirSync2, rmSync as rmSync2, rmdirSync, unlinkSync as unlinkSync3 } from "node:fs";
|
|
74681
|
+
import { dirname as dirname14, join as join65, relative as relative7, resolve as resolve13, sep as sep2 } from "node:path";
|
|
73880
74682
|
|
|
73881
74683
|
// src/services/file-operations/manifest/manifest-reader.ts
|
|
73882
74684
|
init_metadata_migration();
|
|
73883
74685
|
init_logger();
|
|
73884
74686
|
init_types2();
|
|
73885
74687
|
var import_fs_extra8 = __toESM(require_lib3(), 1);
|
|
73886
|
-
import { join as
|
|
74688
|
+
import { join as join64 } from "node:path";
|
|
73887
74689
|
async function readManifest(claudeDir2) {
|
|
73888
|
-
const metadataPath =
|
|
74690
|
+
const metadataPath = join64(claudeDir2, "metadata.json");
|
|
73889
74691
|
if (!await import_fs_extra8.pathExists(metadataPath)) {
|
|
73890
74692
|
return null;
|
|
73891
74693
|
}
|
|
@@ -74058,12 +74860,12 @@ function shouldDeletePath(path11, metadata) {
|
|
|
74058
74860
|
}
|
|
74059
74861
|
function collectFilesRecursively(dir, baseDir) {
|
|
74060
74862
|
const results = [];
|
|
74061
|
-
if (!
|
|
74863
|
+
if (!existsSync36(dir))
|
|
74062
74864
|
return results;
|
|
74063
74865
|
try {
|
|
74064
74866
|
const entries = readdirSync2(dir, { withFileTypes: true });
|
|
74065
74867
|
for (const entry of entries) {
|
|
74066
|
-
const fullPath =
|
|
74868
|
+
const fullPath = join65(dir, entry.name);
|
|
74067
74869
|
const relativePath = relative7(baseDir, fullPath);
|
|
74068
74870
|
if (entry.isDirectory()) {
|
|
74069
74871
|
results.push(...collectFilesRecursively(fullPath, baseDir));
|
|
@@ -74093,8 +74895,8 @@ function expandGlobPatterns(patterns, claudeDir2) {
|
|
|
74093
74895
|
}
|
|
74094
74896
|
var MAX_CLEANUP_ITERATIONS = 50;
|
|
74095
74897
|
function cleanupEmptyDirectories(filePath, claudeDir2) {
|
|
74096
|
-
const normalizedClaudeDir =
|
|
74097
|
-
let currentDir =
|
|
74898
|
+
const normalizedClaudeDir = resolve13(claudeDir2);
|
|
74899
|
+
let currentDir = resolve13(dirname14(filePath));
|
|
74098
74900
|
let iterations = 0;
|
|
74099
74901
|
while (currentDir !== normalizedClaudeDir && currentDir.startsWith(normalizedClaudeDir) && iterations < MAX_CLEANUP_ITERATIONS) {
|
|
74100
74902
|
iterations++;
|
|
@@ -74103,7 +74905,7 @@ function cleanupEmptyDirectories(filePath, claudeDir2) {
|
|
|
74103
74905
|
if (entries.length === 0) {
|
|
74104
74906
|
rmdirSync(currentDir);
|
|
74105
74907
|
logger.debug(`Removed empty directory: ${currentDir}`);
|
|
74106
|
-
currentDir =
|
|
74908
|
+
currentDir = resolve13(dirname14(currentDir));
|
|
74107
74909
|
} else {
|
|
74108
74910
|
break;
|
|
74109
74911
|
}
|
|
@@ -74113,8 +74915,8 @@ function cleanupEmptyDirectories(filePath, claudeDir2) {
|
|
|
74113
74915
|
}
|
|
74114
74916
|
}
|
|
74115
74917
|
function deletePath(fullPath, claudeDir2) {
|
|
74116
|
-
const normalizedPath =
|
|
74117
|
-
const normalizedClaudeDir =
|
|
74918
|
+
const normalizedPath = resolve13(fullPath);
|
|
74919
|
+
const normalizedClaudeDir = resolve13(claudeDir2);
|
|
74118
74920
|
if (!normalizedPath.startsWith(`${normalizedClaudeDir}${sep2}`) && normalizedPath !== normalizedClaudeDir) {
|
|
74119
74921
|
throw new Error(`Path traversal detected: ${fullPath}`);
|
|
74120
74922
|
}
|
|
@@ -74131,7 +74933,7 @@ function deletePath(fullPath, claudeDir2) {
|
|
|
74131
74933
|
}
|
|
74132
74934
|
}
|
|
74133
74935
|
async function updateMetadataAfterDeletion(claudeDir2, deletedPaths) {
|
|
74134
|
-
const metadataPath =
|
|
74936
|
+
const metadataPath = join65(claudeDir2, "metadata.json");
|
|
74135
74937
|
if (!await import_fs_extra9.pathExists(metadataPath)) {
|
|
74136
74938
|
return;
|
|
74137
74939
|
}
|
|
@@ -74186,9 +74988,9 @@ async function handleDeletions(sourceMetadata, claudeDir2) {
|
|
|
74186
74988
|
const userMetadata = await readManifest(claudeDir2);
|
|
74187
74989
|
const result = { deletedPaths: [], preservedPaths: [], errors: [] };
|
|
74188
74990
|
for (const path11 of deletions) {
|
|
74189
|
-
const fullPath =
|
|
74190
|
-
const normalizedPath =
|
|
74191
|
-
const normalizedClaudeDir =
|
|
74991
|
+
const fullPath = join65(claudeDir2, path11);
|
|
74992
|
+
const normalizedPath = resolve13(fullPath);
|
|
74993
|
+
const normalizedClaudeDir = resolve13(claudeDir2);
|
|
74192
74994
|
if (!normalizedPath.startsWith(`${normalizedClaudeDir}${sep2}`)) {
|
|
74193
74995
|
logger.warning(`Skipping invalid path: ${path11}`);
|
|
74194
74996
|
result.errors.push(path11);
|
|
@@ -74199,7 +75001,7 @@ async function handleDeletions(sourceMetadata, claudeDir2) {
|
|
|
74199
75001
|
logger.verbose(`Preserved user file: ${path11}`);
|
|
74200
75002
|
continue;
|
|
74201
75003
|
}
|
|
74202
|
-
if (
|
|
75004
|
+
if (existsSync36(fullPath)) {
|
|
74203
75005
|
try {
|
|
74204
75006
|
deletePath(fullPath, claudeDir2);
|
|
74205
75007
|
result.deletedPaths.push(path11);
|
|
@@ -74226,7 +75028,7 @@ init_logger();
|
|
|
74226
75028
|
init_types2();
|
|
74227
75029
|
var import_fs_extra12 = __toESM(require_lib3(), 1);
|
|
74228
75030
|
var import_ignore3 = __toESM(require_ignore(), 1);
|
|
74229
|
-
import { dirname as dirname16, join as
|
|
75031
|
+
import { dirname as dirname16, join as join68, relative as relative9 } from "node:path";
|
|
74230
75032
|
|
|
74231
75033
|
// src/domains/installation/selective-merger.ts
|
|
74232
75034
|
import { stat as stat13 } from "node:fs/promises";
|
|
@@ -74405,7 +75207,7 @@ init_logger();
|
|
|
74405
75207
|
var import_fs_extra10 = __toESM(require_lib3(), 1);
|
|
74406
75208
|
var import_ignore2 = __toESM(require_ignore(), 1);
|
|
74407
75209
|
import { relative as relative8 } from "node:path";
|
|
74408
|
-
import { join as
|
|
75210
|
+
import { join as join66 } from "node:path";
|
|
74409
75211
|
|
|
74410
75212
|
// node_modules/@isaacs/balanced-match/dist/esm/index.js
|
|
74411
75213
|
var balanced = (a3, b3, str2) => {
|
|
@@ -75861,7 +76663,7 @@ class FileScanner {
|
|
|
75861
76663
|
const files = [];
|
|
75862
76664
|
const entries = await import_fs_extra10.readdir(dir, { encoding: "utf8" });
|
|
75863
76665
|
for (const entry of entries) {
|
|
75864
|
-
const fullPath =
|
|
76666
|
+
const fullPath = join66(dir, entry);
|
|
75865
76667
|
const relativePath = relative8(baseDir, fullPath);
|
|
75866
76668
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
75867
76669
|
const stats = await import_fs_extra10.lstat(fullPath);
|
|
@@ -75899,9 +76701,9 @@ import { execSync as execSync4 } from "node:child_process";
|
|
|
75899
76701
|
|
|
75900
76702
|
// src/domains/config/installed-settings-tracker.ts
|
|
75901
76703
|
init_shared();
|
|
75902
|
-
import { existsSync as
|
|
76704
|
+
import { existsSync as existsSync37 } from "node:fs";
|
|
75903
76705
|
import { mkdir as mkdir21, readFile as readFile29, writeFile as writeFile17 } from "node:fs/promises";
|
|
75904
|
-
import { dirname as dirname15, join as
|
|
76706
|
+
import { dirname as dirname15, join as join67 } from "node:path";
|
|
75905
76707
|
var CK_JSON_FILE = ".ck.json";
|
|
75906
76708
|
|
|
75907
76709
|
class InstalledSettingsTracker {
|
|
@@ -75915,13 +76717,13 @@ class InstalledSettingsTracker {
|
|
|
75915
76717
|
}
|
|
75916
76718
|
getCkJsonPath() {
|
|
75917
76719
|
if (this.isGlobal) {
|
|
75918
|
-
return
|
|
76720
|
+
return join67(this.projectDir, CK_JSON_FILE);
|
|
75919
76721
|
}
|
|
75920
|
-
return
|
|
76722
|
+
return join67(this.projectDir, ".claude", CK_JSON_FILE);
|
|
75921
76723
|
}
|
|
75922
76724
|
async loadInstalledSettings() {
|
|
75923
76725
|
const ckJsonPath = this.getCkJsonPath();
|
|
75924
|
-
if (!
|
|
76726
|
+
if (!existsSync37(ckJsonPath)) {
|
|
75925
76727
|
return { hooks: [], mcpServers: [] };
|
|
75926
76728
|
}
|
|
75927
76729
|
try {
|
|
@@ -75941,7 +76743,7 @@ class InstalledSettingsTracker {
|
|
|
75941
76743
|
const ckJsonPath = this.getCkJsonPath();
|
|
75942
76744
|
try {
|
|
75943
76745
|
let data = {};
|
|
75944
|
-
if (
|
|
76746
|
+
if (existsSync37(ckJsonPath)) {
|
|
75945
76747
|
const content = await readFile29(ckJsonPath, "utf-8");
|
|
75946
76748
|
data = JSON.parse(content);
|
|
75947
76749
|
}
|
|
@@ -76348,7 +77150,7 @@ class CopyExecutor {
|
|
|
76348
77150
|
for (const file of files) {
|
|
76349
77151
|
const relativePath = relative9(sourceDir, file);
|
|
76350
77152
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
76351
|
-
const destPath =
|
|
77153
|
+
const destPath = join68(destDir, relativePath);
|
|
76352
77154
|
if (await import_fs_extra12.pathExists(destPath)) {
|
|
76353
77155
|
if (this.fileScanner.shouldNeverCopy(normalizedRelativePath)) {
|
|
76354
77156
|
logger.debug(`Security-sensitive file exists but won't be overwritten: ${normalizedRelativePath}`);
|
|
@@ -76370,7 +77172,7 @@ class CopyExecutor {
|
|
|
76370
77172
|
for (const file of files) {
|
|
76371
77173
|
const relativePath = relative9(sourceDir, file);
|
|
76372
77174
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
76373
|
-
const destPath =
|
|
77175
|
+
const destPath = join68(destDir, relativePath);
|
|
76374
77176
|
if (this.fileScanner.shouldNeverCopy(normalizedRelativePath)) {
|
|
76375
77177
|
logger.debug(`Skipping security-sensitive file: ${normalizedRelativePath}`);
|
|
76376
77178
|
skippedCount++;
|
|
@@ -76539,16 +77341,16 @@ class FileMerger {
|
|
|
76539
77341
|
}
|
|
76540
77342
|
|
|
76541
77343
|
// src/domains/migration/legacy-migration.ts
|
|
76542
|
-
import { readdir as
|
|
76543
|
-
import { join as
|
|
77344
|
+
import { readdir as readdir15, stat as stat14 } from "node:fs/promises";
|
|
77345
|
+
import { join as join72, relative as relative10 } from "node:path";
|
|
76544
77346
|
// src/services/file-operations/manifest/manifest-tracker.ts
|
|
76545
|
-
import { join as
|
|
77347
|
+
import { join as join71 } from "node:path";
|
|
76546
77348
|
|
|
76547
77349
|
// src/domains/migration/release-manifest.ts
|
|
76548
77350
|
init_logger();
|
|
76549
77351
|
init_zod();
|
|
76550
77352
|
var import_fs_extra13 = __toESM(require_lib3(), 1);
|
|
76551
|
-
import { join as
|
|
77353
|
+
import { join as join69 } from "node:path";
|
|
76552
77354
|
var ReleaseManifestFileSchema = exports_external.object({
|
|
76553
77355
|
path: exports_external.string(),
|
|
76554
77356
|
checksum: exports_external.string().regex(/^[a-f0-9]{64}$/),
|
|
@@ -76563,7 +77365,7 @@ var ReleaseManifestSchema = exports_external.object({
|
|
|
76563
77365
|
|
|
76564
77366
|
class ReleaseManifestLoader {
|
|
76565
77367
|
static async load(extractDir) {
|
|
76566
|
-
const manifestPath =
|
|
77368
|
+
const manifestPath = join69(extractDir, "release-manifest.json");
|
|
76567
77369
|
try {
|
|
76568
77370
|
const content = await import_fs_extra13.readFile(manifestPath, "utf-8");
|
|
76569
77371
|
const parsed = JSON.parse(content);
|
|
@@ -76589,9 +77391,9 @@ init_logger();
|
|
|
76589
77391
|
init_types2();
|
|
76590
77392
|
var import_fs_extra14 = __toESM(require_lib3(), 1);
|
|
76591
77393
|
var import_proper_lockfile2 = __toESM(require_proper_lockfile(), 1);
|
|
76592
|
-
import { join as
|
|
77394
|
+
import { join as join70 } from "node:path";
|
|
76593
77395
|
async function writeManifest(claudeDir2, kitName, version, scope, kitType, trackedFiles, userConfigFiles) {
|
|
76594
|
-
const metadataPath =
|
|
77396
|
+
const metadataPath = join70(claudeDir2, "metadata.json");
|
|
76595
77397
|
const kit = kitType || (/\bmarketing\b/i.test(kitName) ? "marketing" : "engineer");
|
|
76596
77398
|
await import_fs_extra14.ensureFile(metadataPath);
|
|
76597
77399
|
let release = null;
|
|
@@ -76647,7 +77449,7 @@ async function writeManifest(claudeDir2, kitName, version, scope, kitType, track
|
|
|
76647
77449
|
}
|
|
76648
77450
|
}
|
|
76649
77451
|
async function removeKitFromManifest(claudeDir2, kit) {
|
|
76650
|
-
const metadataPath =
|
|
77452
|
+
const metadataPath = join70(claudeDir2, "metadata.json");
|
|
76651
77453
|
if (!await import_fs_extra14.pathExists(metadataPath))
|
|
76652
77454
|
return false;
|
|
76653
77455
|
let release = null;
|
|
@@ -76777,7 +77579,7 @@ function buildFileTrackingList(options2) {
|
|
|
76777
77579
|
if (!isGlobal && !installedPath.startsWith(".claude/"))
|
|
76778
77580
|
continue;
|
|
76779
77581
|
const relativePath = isGlobal ? installedPath : installedPath.replace(/^\.claude\//, "");
|
|
76780
|
-
const filePath =
|
|
77582
|
+
const filePath = join71(claudeDir2, relativePath);
|
|
76781
77583
|
const manifestEntry = releaseManifest ? ReleaseManifestLoader.findFile(releaseManifest, installedPath) : null;
|
|
76782
77584
|
const ownership = manifestEntry ? "ck" : "user";
|
|
76783
77585
|
filesToTrack.push({
|
|
@@ -76867,7 +77669,7 @@ class LegacyMigration {
|
|
|
76867
77669
|
const files = [];
|
|
76868
77670
|
let entries;
|
|
76869
77671
|
try {
|
|
76870
|
-
entries = await
|
|
77672
|
+
entries = await readdir15(dir);
|
|
76871
77673
|
} catch (err) {
|
|
76872
77674
|
const error = err;
|
|
76873
77675
|
if (error.code === "ENOENT") {
|
|
@@ -76884,7 +77686,7 @@ class LegacyMigration {
|
|
|
76884
77686
|
continue;
|
|
76885
77687
|
if (SKIP_DIRS_ALL.includes(entry))
|
|
76886
77688
|
continue;
|
|
76887
|
-
const fullPath =
|
|
77689
|
+
const fullPath = join72(dir, entry);
|
|
76888
77690
|
let stats;
|
|
76889
77691
|
try {
|
|
76890
77692
|
stats = await stat14(fullPath);
|
|
@@ -76986,7 +77788,7 @@ User-created files (sample):`);
|
|
|
76986
77788
|
];
|
|
76987
77789
|
if (filesToChecksum.length > 0) {
|
|
76988
77790
|
const checksumResults = await mapWithLimit(filesToChecksum, async ({ relativePath, ownership }) => {
|
|
76989
|
-
const fullPath =
|
|
77791
|
+
const fullPath = join72(claudeDir2, relativePath);
|
|
76990
77792
|
const checksum = await OwnershipChecker.calculateChecksum(fullPath);
|
|
76991
77793
|
return { relativePath, checksum, ownership };
|
|
76992
77794
|
});
|
|
@@ -77007,7 +77809,7 @@ User-created files (sample):`);
|
|
|
77007
77809
|
installedAt: new Date().toISOString(),
|
|
77008
77810
|
files: trackedFiles
|
|
77009
77811
|
};
|
|
77010
|
-
const metadataPath =
|
|
77812
|
+
const metadataPath = join72(claudeDir2, "metadata.json");
|
|
77011
77813
|
await import_fs_extra15.writeFile(metadataPath, JSON.stringify(updatedMetadata, null, 2));
|
|
77012
77814
|
logger.success(`Migration complete: tracked ${trackedFiles.length} files`);
|
|
77013
77815
|
return true;
|
|
@@ -77113,7 +77915,7 @@ function buildConflictSummary(fileConflicts, hookConflicts, mcpConflicts) {
|
|
|
77113
77915
|
init_logger();
|
|
77114
77916
|
init_skip_directories();
|
|
77115
77917
|
var import_fs_extra16 = __toESM(require_lib3(), 1);
|
|
77116
|
-
import { join as
|
|
77918
|
+
import { join as join73, relative as relative11, resolve as resolve14 } from "node:path";
|
|
77117
77919
|
|
|
77118
77920
|
class FileScanner2 {
|
|
77119
77921
|
static async getFiles(dirPath, relativeTo) {
|
|
@@ -77129,7 +77931,7 @@ class FileScanner2 {
|
|
|
77129
77931
|
logger.debug(`Skipping directory: ${entry}`);
|
|
77130
77932
|
continue;
|
|
77131
77933
|
}
|
|
77132
|
-
const fullPath =
|
|
77934
|
+
const fullPath = join73(dirPath, entry);
|
|
77133
77935
|
if (!FileScanner2.isSafePath(basePath, fullPath)) {
|
|
77134
77936
|
logger.warning(`Skipping potentially unsafe path: ${entry}`);
|
|
77135
77937
|
continue;
|
|
@@ -77164,8 +77966,8 @@ class FileScanner2 {
|
|
|
77164
77966
|
return files;
|
|
77165
77967
|
}
|
|
77166
77968
|
static async findCustomFiles(destDir, sourceDir, subPath) {
|
|
77167
|
-
const destSubDir =
|
|
77168
|
-
const sourceSubDir =
|
|
77969
|
+
const destSubDir = join73(destDir, subPath);
|
|
77970
|
+
const sourceSubDir = join73(sourceDir, subPath);
|
|
77169
77971
|
logger.debug(`findCustomFiles - destDir: ${destDir}`);
|
|
77170
77972
|
logger.debug(`findCustomFiles - sourceDir: ${sourceDir}`);
|
|
77171
77973
|
logger.debug(`findCustomFiles - subPath: "${subPath}"`);
|
|
@@ -77193,8 +77995,8 @@ class FileScanner2 {
|
|
|
77193
77995
|
return customFiles;
|
|
77194
77996
|
}
|
|
77195
77997
|
static isSafePath(basePath, targetPath) {
|
|
77196
|
-
const resolvedBase =
|
|
77197
|
-
const resolvedTarget =
|
|
77998
|
+
const resolvedBase = resolve14(basePath);
|
|
77999
|
+
const resolvedTarget = resolve14(targetPath);
|
|
77198
78000
|
return resolvedTarget.startsWith(resolvedBase);
|
|
77199
78001
|
}
|
|
77200
78002
|
static toPosixPath(path12) {
|
|
@@ -77205,13 +78007,13 @@ class FileScanner2 {
|
|
|
77205
78007
|
// src/services/transformers/commands-prefix/prefix-applier.ts
|
|
77206
78008
|
init_logger();
|
|
77207
78009
|
var import_fs_extra17 = __toESM(require_lib3(), 1);
|
|
77208
|
-
import { lstat as lstat7, mkdir as mkdir22, readdir as
|
|
77209
|
-
import { join as
|
|
78010
|
+
import { lstat as lstat7, mkdir as mkdir22, readdir as readdir18, stat as stat15 } from "node:fs/promises";
|
|
78011
|
+
import { join as join75 } from "node:path";
|
|
77210
78012
|
|
|
77211
78013
|
// src/services/transformers/commands-prefix/content-transformer.ts
|
|
77212
78014
|
init_logger();
|
|
77213
|
-
import { readFile as readFile33, readdir as
|
|
77214
|
-
import { join as
|
|
78015
|
+
import { readFile as readFile33, readdir as readdir17, writeFile as writeFile21 } from "node:fs/promises";
|
|
78016
|
+
import { join as join74 } from "node:path";
|
|
77215
78017
|
var TRANSFORMABLE_EXTENSIONS = new Set([
|
|
77216
78018
|
".md",
|
|
77217
78019
|
".txt",
|
|
@@ -77270,9 +78072,9 @@ async function transformCommandReferences(directory, options2 = {}) {
|
|
|
77270
78072
|
let filesTransformed = 0;
|
|
77271
78073
|
let totalReplacements = 0;
|
|
77272
78074
|
async function processDirectory(dir) {
|
|
77273
|
-
const entries = await
|
|
78075
|
+
const entries = await readdir17(dir, { withFileTypes: true });
|
|
77274
78076
|
for (const entry of entries) {
|
|
77275
|
-
const fullPath =
|
|
78077
|
+
const fullPath = join74(dir, entry.name);
|
|
77276
78078
|
if (entry.isDirectory()) {
|
|
77277
78079
|
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
77278
78080
|
continue;
|
|
@@ -77347,22 +78149,22 @@ function shouldApplyPrefix(options2) {
|
|
|
77347
78149
|
// src/services/transformers/commands-prefix/prefix-applier.ts
|
|
77348
78150
|
async function applyPrefix(extractDir) {
|
|
77349
78151
|
validatePath(extractDir, "extractDir");
|
|
77350
|
-
const commandsDir =
|
|
78152
|
+
const commandsDir = join75(extractDir, ".claude", "commands");
|
|
77351
78153
|
if (!await import_fs_extra17.pathExists(commandsDir)) {
|
|
77352
78154
|
logger.verbose("No commands directory found, skipping prefix application");
|
|
77353
78155
|
return;
|
|
77354
78156
|
}
|
|
77355
78157
|
logger.info("Applying /ck: prefix to slash commands...");
|
|
77356
|
-
const backupDir =
|
|
77357
|
-
const tempDir =
|
|
78158
|
+
const backupDir = join75(extractDir, ".commands-backup");
|
|
78159
|
+
const tempDir = join75(extractDir, ".commands-prefix-temp");
|
|
77358
78160
|
try {
|
|
77359
|
-
const entries = await
|
|
78161
|
+
const entries = await readdir18(commandsDir);
|
|
77360
78162
|
if (entries.length === 0) {
|
|
77361
78163
|
logger.verbose("Commands directory is empty, skipping prefix application");
|
|
77362
78164
|
return;
|
|
77363
78165
|
}
|
|
77364
78166
|
if (entries.length === 1 && entries[0] === "ck") {
|
|
77365
|
-
const ckDir2 =
|
|
78167
|
+
const ckDir2 = join75(commandsDir, "ck");
|
|
77366
78168
|
const ckStat = await stat15(ckDir2);
|
|
77367
78169
|
if (ckStat.isDirectory()) {
|
|
77368
78170
|
logger.verbose("Commands already have /ck: prefix, skipping");
|
|
@@ -77372,17 +78174,17 @@ async function applyPrefix(extractDir) {
|
|
|
77372
78174
|
await import_fs_extra17.copy(commandsDir, backupDir);
|
|
77373
78175
|
logger.verbose("Created backup of commands directory");
|
|
77374
78176
|
await mkdir22(tempDir, { recursive: true });
|
|
77375
|
-
const ckDir =
|
|
78177
|
+
const ckDir = join75(tempDir, "ck");
|
|
77376
78178
|
await mkdir22(ckDir, { recursive: true });
|
|
77377
78179
|
let processedCount = 0;
|
|
77378
78180
|
for (const entry of entries) {
|
|
77379
|
-
const sourcePath =
|
|
78181
|
+
const sourcePath = join75(commandsDir, entry);
|
|
77380
78182
|
const stats = await lstat7(sourcePath);
|
|
77381
78183
|
if (stats.isSymbolicLink()) {
|
|
77382
78184
|
logger.warning(`Skipping symlink for security: ${entry}`);
|
|
77383
78185
|
continue;
|
|
77384
78186
|
}
|
|
77385
|
-
const destPath =
|
|
78187
|
+
const destPath = join75(ckDir, entry);
|
|
77386
78188
|
await import_fs_extra17.copy(sourcePath, destPath, {
|
|
77387
78189
|
overwrite: false,
|
|
77388
78190
|
errorOnExist: true
|
|
@@ -77400,7 +78202,7 @@ async function applyPrefix(extractDir) {
|
|
|
77400
78202
|
await import_fs_extra17.move(tempDir, commandsDir);
|
|
77401
78203
|
await import_fs_extra17.remove(backupDir);
|
|
77402
78204
|
logger.success("Successfully reorganized commands to /ck: prefix");
|
|
77403
|
-
const claudeDir2 =
|
|
78205
|
+
const claudeDir2 = join75(extractDir, ".claude");
|
|
77404
78206
|
logger.info("Transforming command references in file contents...");
|
|
77405
78207
|
const transformResult = await transformCommandReferences(claudeDir2, {
|
|
77406
78208
|
verbose: logger.isVerbose()
|
|
@@ -77437,21 +78239,21 @@ async function applyPrefix(extractDir) {
|
|
|
77437
78239
|
|
|
77438
78240
|
// src/services/transformers/commands-prefix/prefix-cleaner.ts
|
|
77439
78241
|
init_metadata_migration();
|
|
77440
|
-
import { lstat as lstat9, readdir as
|
|
77441
|
-
import { join as
|
|
78242
|
+
import { lstat as lstat9, readdir as readdir20 } from "node:fs/promises";
|
|
78243
|
+
import { join as join77 } from "node:path";
|
|
77442
78244
|
init_logger();
|
|
77443
78245
|
var import_fs_extra19 = __toESM(require_lib3(), 1);
|
|
77444
78246
|
|
|
77445
78247
|
// src/services/transformers/commands-prefix/file-processor.ts
|
|
77446
|
-
import { lstat as lstat8, readdir as
|
|
77447
|
-
import { join as
|
|
78248
|
+
import { lstat as lstat8, readdir as readdir19 } from "node:fs/promises";
|
|
78249
|
+
import { join as join76 } from "node:path";
|
|
77448
78250
|
init_logger();
|
|
77449
78251
|
var import_fs_extra18 = __toESM(require_lib3(), 1);
|
|
77450
78252
|
async function scanDirectoryFiles(dir) {
|
|
77451
78253
|
const files = [];
|
|
77452
|
-
const entries = await
|
|
78254
|
+
const entries = await readdir19(dir);
|
|
77453
78255
|
for (const entry of entries) {
|
|
77454
|
-
const fullPath =
|
|
78256
|
+
const fullPath = join76(dir, entry);
|
|
77455
78257
|
const stats = await lstat8(fullPath);
|
|
77456
78258
|
if (stats.isSymbolicLink()) {
|
|
77457
78259
|
continue;
|
|
@@ -77579,8 +78381,8 @@ function isDifferentKitDirectory(dirName, currentKit) {
|
|
|
77579
78381
|
async function cleanupCommandsDirectory(targetDir, isGlobal, options2 = {}) {
|
|
77580
78382
|
const { dryRun = false } = options2;
|
|
77581
78383
|
validatePath(targetDir, "targetDir");
|
|
77582
|
-
const claudeDir2 = isGlobal ? targetDir :
|
|
77583
|
-
const commandsDir =
|
|
78384
|
+
const claudeDir2 = isGlobal ? targetDir : join77(targetDir, ".claude");
|
|
78385
|
+
const commandsDir = join77(claudeDir2, "commands");
|
|
77584
78386
|
const accumulator = {
|
|
77585
78387
|
results: [],
|
|
77586
78388
|
deletedCount: 0,
|
|
@@ -77615,14 +78417,14 @@ async function cleanupCommandsDirectory(targetDir, isGlobal, options2 = {}) {
|
|
|
77615
78417
|
if (options2.kitType) {
|
|
77616
78418
|
logger.verbose(`Kit-aware cleanup: only cleaning files owned by '${options2.kitType}'`);
|
|
77617
78419
|
}
|
|
77618
|
-
const entries = await
|
|
78420
|
+
const entries = await readdir20(commandsDir);
|
|
77619
78421
|
if (entries.length === 0) {
|
|
77620
78422
|
logger.verbose("Commands directory is empty");
|
|
77621
78423
|
return result;
|
|
77622
78424
|
}
|
|
77623
78425
|
const metadataForChecks = options2.kitType ? createKitSpecificMetadata(metadata, options2.kitType) : metadata;
|
|
77624
78426
|
for (const entry of entries) {
|
|
77625
|
-
const entryPath =
|
|
78427
|
+
const entryPath = join77(commandsDir, entry);
|
|
77626
78428
|
const stats = await lstat9(entryPath);
|
|
77627
78429
|
if (stats.isSymbolicLink()) {
|
|
77628
78430
|
addSymlinkSkip(entry, accumulator);
|
|
@@ -77679,7 +78481,7 @@ async function handleMerge(ctx) {
|
|
|
77679
78481
|
let customClaudeFiles = [];
|
|
77680
78482
|
if (!ctx.options.fresh) {
|
|
77681
78483
|
logger.info("Scanning for custom .claude files...");
|
|
77682
|
-
const scanSourceDir = ctx.options.global ?
|
|
78484
|
+
const scanSourceDir = ctx.options.global ? join78(ctx.extractDir, ".claude") : ctx.extractDir;
|
|
77683
78485
|
const scanTargetSubdir = ctx.options.global ? "" : ".claude";
|
|
77684
78486
|
customClaudeFiles = await FileScanner2.findCustomFiles(ctx.resolvedDir, scanSourceDir, scanTargetSubdir);
|
|
77685
78487
|
} else {
|
|
@@ -77744,7 +78546,7 @@ async function handleMerge(ctx) {
|
|
|
77744
78546
|
return { ...ctx, cancelled: true };
|
|
77745
78547
|
}
|
|
77746
78548
|
}
|
|
77747
|
-
const sourceDir = ctx.options.global ?
|
|
78549
|
+
const sourceDir = ctx.options.global ? join78(ctx.extractDir, ".claude") : ctx.extractDir;
|
|
77748
78550
|
await merger.merge(sourceDir, ctx.resolvedDir, ctx.isNonInteractive);
|
|
77749
78551
|
const fileConflicts = merger.getFileConflicts();
|
|
77750
78552
|
if (fileConflicts.length > 0 && !ctx.isNonInteractive) {
|
|
@@ -77752,7 +78554,7 @@ async function handleMerge(ctx) {
|
|
|
77752
78554
|
displayConflictSummary(summary);
|
|
77753
78555
|
}
|
|
77754
78556
|
try {
|
|
77755
|
-
const sourceMetadataPath = ctx.options.global ?
|
|
78557
|
+
const sourceMetadataPath = ctx.options.global ? join78(sourceDir, "metadata.json") : join78(sourceDir, ".claude", "metadata.json");
|
|
77756
78558
|
if (await import_fs_extra20.pathExists(sourceMetadataPath)) {
|
|
77757
78559
|
const metadataContent = await import_fs_extra20.readFile(sourceMetadataPath, "utf-8");
|
|
77758
78560
|
const sourceMetadata = JSON.parse(metadataContent);
|
|
@@ -77796,7 +78598,7 @@ async function handleMerge(ctx) {
|
|
|
77796
78598
|
};
|
|
77797
78599
|
}
|
|
77798
78600
|
// src/commands/init/phases/migration-handler.ts
|
|
77799
|
-
import { join as
|
|
78601
|
+
import { join as join86 } from "node:path";
|
|
77800
78602
|
|
|
77801
78603
|
// src/domains/skills/skills-detector.ts
|
|
77802
78604
|
init_logger();
|
|
@@ -77811,8 +78613,8 @@ init_skip_directories();
|
|
|
77811
78613
|
init_types2();
|
|
77812
78614
|
var import_fs_extra21 = __toESM(require_lib3(), 1);
|
|
77813
78615
|
import { createHash as createHash2 } from "node:crypto";
|
|
77814
|
-
import { readFile as readFile35, readdir as
|
|
77815
|
-
import { join as
|
|
78616
|
+
import { readFile as readFile35, readdir as readdir21, writeFile as writeFile22 } from "node:fs/promises";
|
|
78617
|
+
import { join as join79, relative as relative12 } from "node:path";
|
|
77816
78618
|
|
|
77817
78619
|
class SkillsManifestManager {
|
|
77818
78620
|
static MANIFEST_FILENAME = ".skills-manifest.json";
|
|
@@ -77834,12 +78636,12 @@ class SkillsManifestManager {
|
|
|
77834
78636
|
return manifest;
|
|
77835
78637
|
}
|
|
77836
78638
|
static async writeManifest(skillsDir2, manifest) {
|
|
77837
|
-
const manifestPath =
|
|
78639
|
+
const manifestPath = join79(skillsDir2, SkillsManifestManager.MANIFEST_FILENAME);
|
|
77838
78640
|
await writeFile22(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
77839
78641
|
logger.debug(`Wrote manifest to: ${manifestPath}`);
|
|
77840
78642
|
}
|
|
77841
78643
|
static async readManifest(skillsDir2) {
|
|
77842
|
-
const manifestPath =
|
|
78644
|
+
const manifestPath = join79(skillsDir2, SkillsManifestManager.MANIFEST_FILENAME);
|
|
77843
78645
|
if (!await import_fs_extra21.pathExists(manifestPath)) {
|
|
77844
78646
|
logger.debug(`No manifest found at: ${manifestPath}`);
|
|
77845
78647
|
return null;
|
|
@@ -77856,14 +78658,14 @@ class SkillsManifestManager {
|
|
|
77856
78658
|
}
|
|
77857
78659
|
}
|
|
77858
78660
|
static async detectStructure(skillsDir2) {
|
|
77859
|
-
const entries = await
|
|
78661
|
+
const entries = await readdir21(skillsDir2, { withFileTypes: true });
|
|
77860
78662
|
const dirs = entries.filter((entry) => entry.isDirectory() && !BUILD_ARTIFACT_DIRS.includes(entry.name) && !entry.name.startsWith("."));
|
|
77861
78663
|
if (dirs.length === 0) {
|
|
77862
78664
|
return "flat";
|
|
77863
78665
|
}
|
|
77864
78666
|
for (const dir of dirs.slice(0, 3)) {
|
|
77865
|
-
const dirPath =
|
|
77866
|
-
const subEntries = await
|
|
78667
|
+
const dirPath = join79(skillsDir2, dir.name);
|
|
78668
|
+
const subEntries = await readdir21(dirPath, { withFileTypes: true });
|
|
77867
78669
|
const hasSubdirs = subEntries.some((entry) => entry.isDirectory());
|
|
77868
78670
|
if (hasSubdirs) {
|
|
77869
78671
|
return "categorized";
|
|
@@ -77878,10 +78680,10 @@ class SkillsManifestManager {
|
|
|
77878
78680
|
static async scanSkills(skillsDir2, structure) {
|
|
77879
78681
|
const skills = [];
|
|
77880
78682
|
if (structure === "flat") {
|
|
77881
|
-
const entries = await
|
|
78683
|
+
const entries = await readdir21(skillsDir2, { withFileTypes: true });
|
|
77882
78684
|
for (const entry of entries) {
|
|
77883
78685
|
if (entry.isDirectory() && !BUILD_ARTIFACT_DIRS.includes(entry.name) && !entry.name.startsWith(".")) {
|
|
77884
|
-
const skillPath =
|
|
78686
|
+
const skillPath = join79(skillsDir2, entry.name);
|
|
77885
78687
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
77886
78688
|
skills.push({
|
|
77887
78689
|
name: entry.name,
|
|
@@ -77890,14 +78692,14 @@ class SkillsManifestManager {
|
|
|
77890
78692
|
}
|
|
77891
78693
|
}
|
|
77892
78694
|
} else {
|
|
77893
|
-
const categories = await
|
|
78695
|
+
const categories = await readdir21(skillsDir2, { withFileTypes: true });
|
|
77894
78696
|
for (const category of categories) {
|
|
77895
78697
|
if (category.isDirectory() && !BUILD_ARTIFACT_DIRS.includes(category.name) && !category.name.startsWith(".")) {
|
|
77896
|
-
const categoryPath =
|
|
77897
|
-
const skillEntries = await
|
|
78698
|
+
const categoryPath = join79(skillsDir2, category.name);
|
|
78699
|
+
const skillEntries = await readdir21(categoryPath, { withFileTypes: true });
|
|
77898
78700
|
for (const skillEntry of skillEntries) {
|
|
77899
78701
|
if (skillEntry.isDirectory() && !skillEntry.name.startsWith(".")) {
|
|
77900
|
-
const skillPath =
|
|
78702
|
+
const skillPath = join79(categoryPath, skillEntry.name);
|
|
77901
78703
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
77902
78704
|
skills.push({
|
|
77903
78705
|
name: skillEntry.name,
|
|
@@ -77925,9 +78727,9 @@ class SkillsManifestManager {
|
|
|
77925
78727
|
}
|
|
77926
78728
|
static async getAllFiles(dirPath) {
|
|
77927
78729
|
const files = [];
|
|
77928
|
-
const entries = await
|
|
78730
|
+
const entries = await readdir21(dirPath, { withFileTypes: true });
|
|
77929
78731
|
for (const entry of entries) {
|
|
77930
|
-
const fullPath =
|
|
78732
|
+
const fullPath = join79(dirPath, entry.name);
|
|
77931
78733
|
if (entry.name.startsWith(".") || BUILD_ARTIFACT_DIRS.includes(entry.name)) {
|
|
77932
78734
|
continue;
|
|
77933
78735
|
}
|
|
@@ -78048,13 +78850,13 @@ function getPathMapping(skillName, oldBasePath, newBasePath) {
|
|
|
78048
78850
|
|
|
78049
78851
|
// src/domains/skills/detection/script-detector.ts
|
|
78050
78852
|
var import_fs_extra22 = __toESM(require_lib3(), 1);
|
|
78051
|
-
import { readdir as
|
|
78052
|
-
import { join as
|
|
78853
|
+
import { readdir as readdir22 } from "node:fs/promises";
|
|
78854
|
+
import { join as join80 } from "node:path";
|
|
78053
78855
|
async function scanDirectory(skillsDir2) {
|
|
78054
78856
|
if (!await import_fs_extra22.pathExists(skillsDir2)) {
|
|
78055
78857
|
return ["flat", []];
|
|
78056
78858
|
}
|
|
78057
|
-
const entries = await
|
|
78859
|
+
const entries = await readdir22(skillsDir2, { withFileTypes: true });
|
|
78058
78860
|
const dirs = entries.filter((entry) => entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith("."));
|
|
78059
78861
|
if (dirs.length === 0) {
|
|
78060
78862
|
return ["flat", []];
|
|
@@ -78062,13 +78864,13 @@ async function scanDirectory(skillsDir2) {
|
|
|
78062
78864
|
let totalSkillLikeCount = 0;
|
|
78063
78865
|
const allSkills = [];
|
|
78064
78866
|
for (const dir of dirs) {
|
|
78065
|
-
const dirPath =
|
|
78066
|
-
const subEntries = await
|
|
78867
|
+
const dirPath = join80(skillsDir2, dir.name);
|
|
78868
|
+
const subEntries = await readdir22(dirPath, { withFileTypes: true });
|
|
78067
78869
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
78068
78870
|
if (subdirs.length > 0) {
|
|
78069
78871
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
78070
|
-
const subdirPath =
|
|
78071
|
-
const subdirFiles = await
|
|
78872
|
+
const subdirPath = join80(dirPath, subdir.name);
|
|
78873
|
+
const subdirFiles = await readdir22(subdirPath, { withFileTypes: true });
|
|
78072
78874
|
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"));
|
|
78073
78875
|
if (hasSkillMarker) {
|
|
78074
78876
|
totalSkillLikeCount++;
|
|
@@ -78224,12 +79026,12 @@ class SkillsMigrationDetector {
|
|
|
78224
79026
|
// src/domains/skills/skills-migrator.ts
|
|
78225
79027
|
init_logger();
|
|
78226
79028
|
init_types2();
|
|
78227
|
-
import { join as
|
|
79029
|
+
import { join as join85 } from "node:path";
|
|
78228
79030
|
|
|
78229
79031
|
// src/domains/skills/migrator/migration-executor.ts
|
|
78230
79032
|
init_logger();
|
|
78231
|
-
import { copyFile as copyFile5, mkdir as mkdir23, readdir as
|
|
78232
|
-
import { join as
|
|
79033
|
+
import { copyFile as copyFile5, mkdir as mkdir23, readdir as readdir23, rm as rm5 } from "node:fs/promises";
|
|
79034
|
+
import { join as join81 } from "node:path";
|
|
78233
79035
|
var import_fs_extra24 = __toESM(require_lib3(), 1);
|
|
78234
79036
|
|
|
78235
79037
|
// src/domains/skills/skills-migration-prompts.ts
|
|
@@ -78392,10 +79194,10 @@ Detected changes:`;
|
|
|
78392
79194
|
// src/domains/skills/migrator/migration-executor.ts
|
|
78393
79195
|
async function copySkillDirectory(sourceDir, destDir) {
|
|
78394
79196
|
await mkdir23(destDir, { recursive: true });
|
|
78395
|
-
const entries = await
|
|
79197
|
+
const entries = await readdir23(sourceDir, { withFileTypes: true });
|
|
78396
79198
|
for (const entry of entries) {
|
|
78397
|
-
const sourcePath =
|
|
78398
|
-
const destPath =
|
|
79199
|
+
const sourcePath = join81(sourceDir, entry.name);
|
|
79200
|
+
const destPath = join81(destDir, entry.name);
|
|
78399
79201
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
78400
79202
|
continue;
|
|
78401
79203
|
}
|
|
@@ -78410,7 +79212,7 @@ async function executeInternal(mappings, customizations, currentSkillsDir, inter
|
|
|
78410
79212
|
const migrated = [];
|
|
78411
79213
|
const preserved = [];
|
|
78412
79214
|
const errors2 = [];
|
|
78413
|
-
const tempDir =
|
|
79215
|
+
const tempDir = join81(currentSkillsDir, "..", ".skills-migration-temp");
|
|
78414
79216
|
await mkdir23(tempDir, { recursive: true });
|
|
78415
79217
|
try {
|
|
78416
79218
|
for (const mapping of mappings) {
|
|
@@ -78431,9 +79233,9 @@ async function executeInternal(mappings, customizations, currentSkillsDir, inter
|
|
|
78431
79233
|
}
|
|
78432
79234
|
}
|
|
78433
79235
|
const category = mapping.category;
|
|
78434
|
-
const targetPath = category ?
|
|
79236
|
+
const targetPath = category ? join81(tempDir, category, skillName) : join81(tempDir, skillName);
|
|
78435
79237
|
if (category) {
|
|
78436
|
-
await mkdir23(
|
|
79238
|
+
await mkdir23(join81(tempDir, category), { recursive: true });
|
|
78437
79239
|
}
|
|
78438
79240
|
await copySkillDirectory(currentSkillPath, targetPath);
|
|
78439
79241
|
migrated.push(skillName);
|
|
@@ -78499,8 +79301,8 @@ function validateMigrationPath(path12, paramName) {
|
|
|
78499
79301
|
init_logger();
|
|
78500
79302
|
init_types2();
|
|
78501
79303
|
var import_fs_extra25 = __toESM(require_lib3(), 1);
|
|
78502
|
-
import { copyFile as copyFile6, mkdir as mkdir24, readdir as
|
|
78503
|
-
import { basename as basename8, join as
|
|
79304
|
+
import { copyFile as copyFile6, mkdir as mkdir24, readdir as readdir24, rm as rm6, stat as stat16 } from "node:fs/promises";
|
|
79305
|
+
import { basename as basename8, join as join82, normalize as normalize8 } from "node:path";
|
|
78504
79306
|
function validatePath2(path12, paramName) {
|
|
78505
79307
|
if (!path12 || typeof path12 !== "string") {
|
|
78506
79308
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
@@ -78526,7 +79328,7 @@ class SkillsBackupManager {
|
|
|
78526
79328
|
const timestamp = Date.now();
|
|
78527
79329
|
const randomSuffix = Math.random().toString(36).substring(2, 8);
|
|
78528
79330
|
const backupDirName = `${SkillsBackupManager.BACKUP_PREFIX}${timestamp}-${randomSuffix}`;
|
|
78529
|
-
const backupDir = parentDir ?
|
|
79331
|
+
const backupDir = parentDir ? join82(parentDir, backupDirName) : join82(skillsDir2, "..", backupDirName);
|
|
78530
79332
|
logger.info(`Creating backup at: ${backupDir}`);
|
|
78531
79333
|
try {
|
|
78532
79334
|
await mkdir24(backupDir, { recursive: true });
|
|
@@ -78576,8 +79378,8 @@ class SkillsBackupManager {
|
|
|
78576
79378
|
return [];
|
|
78577
79379
|
}
|
|
78578
79380
|
try {
|
|
78579
|
-
const entries = await
|
|
78580
|
-
const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) =>
|
|
79381
|
+
const entries = await readdir24(parentDir, { withFileTypes: true });
|
|
79382
|
+
const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) => join82(parentDir, entry.name));
|
|
78581
79383
|
backups.sort().reverse();
|
|
78582
79384
|
return backups;
|
|
78583
79385
|
} catch (error) {
|
|
@@ -78603,10 +79405,10 @@ class SkillsBackupManager {
|
|
|
78603
79405
|
return await SkillsBackupManager.getDirectorySize(backupDir);
|
|
78604
79406
|
}
|
|
78605
79407
|
static async copyDirectory(sourceDir, destDir) {
|
|
78606
|
-
const entries = await
|
|
79408
|
+
const entries = await readdir24(sourceDir, { withFileTypes: true });
|
|
78607
79409
|
for (const entry of entries) {
|
|
78608
|
-
const sourcePath =
|
|
78609
|
-
const destPath =
|
|
79410
|
+
const sourcePath = join82(sourceDir, entry.name);
|
|
79411
|
+
const destPath = join82(destDir, entry.name);
|
|
78610
79412
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
78611
79413
|
continue;
|
|
78612
79414
|
}
|
|
@@ -78620,9 +79422,9 @@ class SkillsBackupManager {
|
|
|
78620
79422
|
}
|
|
78621
79423
|
static async getDirectorySize(dirPath) {
|
|
78622
79424
|
let size = 0;
|
|
78623
|
-
const entries = await
|
|
79425
|
+
const entries = await readdir24(dirPath, { withFileTypes: true });
|
|
78624
79426
|
for (const entry of entries) {
|
|
78625
|
-
const fullPath =
|
|
79427
|
+
const fullPath = join82(dirPath, entry.name);
|
|
78626
79428
|
if (entry.isSymbolicLink()) {
|
|
78627
79429
|
continue;
|
|
78628
79430
|
}
|
|
@@ -78657,13 +79459,13 @@ import { relative as relative14 } from "node:path";
|
|
|
78657
79459
|
init_skip_directories();
|
|
78658
79460
|
import { createHash as createHash3 } from "node:crypto";
|
|
78659
79461
|
import { createReadStream as createReadStream3 } from "node:fs";
|
|
78660
|
-
import { readFile as readFile36, readdir as
|
|
78661
|
-
import { join as
|
|
79462
|
+
import { readFile as readFile36, readdir as readdir25 } from "node:fs/promises";
|
|
79463
|
+
import { join as join83, relative as relative13 } from "node:path";
|
|
78662
79464
|
async function getAllFiles(dirPath) {
|
|
78663
79465
|
const files = [];
|
|
78664
|
-
const entries = await
|
|
79466
|
+
const entries = await readdir25(dirPath, { withFileTypes: true });
|
|
78665
79467
|
for (const entry of entries) {
|
|
78666
|
-
const fullPath =
|
|
79468
|
+
const fullPath = join83(dirPath, entry.name);
|
|
78667
79469
|
if (entry.name.startsWith(".") || BUILD_ARTIFACT_DIRS.includes(entry.name) || entry.isSymbolicLink()) {
|
|
78668
79470
|
continue;
|
|
78669
79471
|
}
|
|
@@ -78677,12 +79479,12 @@ async function getAllFiles(dirPath) {
|
|
|
78677
79479
|
return files;
|
|
78678
79480
|
}
|
|
78679
79481
|
async function hashFile(filePath) {
|
|
78680
|
-
return new Promise((
|
|
79482
|
+
return new Promise((resolve15, reject) => {
|
|
78681
79483
|
const hash = createHash3("sha256");
|
|
78682
79484
|
const stream = createReadStream3(filePath);
|
|
78683
79485
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
78684
79486
|
stream.on("end", () => {
|
|
78685
|
-
|
|
79487
|
+
resolve15(hash.digest("hex"));
|
|
78686
79488
|
});
|
|
78687
79489
|
stream.on("error", (error) => {
|
|
78688
79490
|
stream.destroy();
|
|
@@ -78789,8 +79591,8 @@ async function detectFileChanges(currentSkillPath, baselineSkillPath) {
|
|
|
78789
79591
|
// src/domains/skills/customization/scan-reporter.ts
|
|
78790
79592
|
init_types2();
|
|
78791
79593
|
var import_fs_extra27 = __toESM(require_lib3(), 1);
|
|
78792
|
-
import { readdir as
|
|
78793
|
-
import { join as
|
|
79594
|
+
import { readdir as readdir26 } from "node:fs/promises";
|
|
79595
|
+
import { join as join84, normalize as normalize9 } from "node:path";
|
|
78794
79596
|
function validatePath3(path12, paramName) {
|
|
78795
79597
|
if (!path12 || typeof path12 !== "string") {
|
|
78796
79598
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
@@ -78806,19 +79608,19 @@ async function scanSkillsDirectory(skillsDir2) {
|
|
|
78806
79608
|
if (!await import_fs_extra27.pathExists(skillsDir2)) {
|
|
78807
79609
|
return ["flat", []];
|
|
78808
79610
|
}
|
|
78809
|
-
const entries = await
|
|
79611
|
+
const entries = await readdir26(skillsDir2, { withFileTypes: true });
|
|
78810
79612
|
const dirs = entries.filter((entry) => entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith("."));
|
|
78811
79613
|
if (dirs.length === 0) {
|
|
78812
79614
|
return ["flat", []];
|
|
78813
79615
|
}
|
|
78814
|
-
const firstDirPath =
|
|
78815
|
-
const subEntries = await
|
|
79616
|
+
const firstDirPath = join84(skillsDir2, dirs[0].name);
|
|
79617
|
+
const subEntries = await readdir26(firstDirPath, { withFileTypes: true });
|
|
78816
79618
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
78817
79619
|
if (subdirs.length > 0) {
|
|
78818
79620
|
let skillLikeCount = 0;
|
|
78819
79621
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
78820
|
-
const subdirPath =
|
|
78821
|
-
const subdirFiles = await
|
|
79622
|
+
const subdirPath = join84(firstDirPath, subdir.name);
|
|
79623
|
+
const subdirFiles = await readdir26(subdirPath, { withFileTypes: true });
|
|
78822
79624
|
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"));
|
|
78823
79625
|
if (hasSkillMarker) {
|
|
78824
79626
|
skillLikeCount++;
|
|
@@ -78827,8 +79629,8 @@ async function scanSkillsDirectory(skillsDir2) {
|
|
|
78827
79629
|
if (skillLikeCount > 0) {
|
|
78828
79630
|
const skills = [];
|
|
78829
79631
|
for (const dir of dirs) {
|
|
78830
|
-
const categoryPath =
|
|
78831
|
-
const skillDirs = await
|
|
79632
|
+
const categoryPath = join84(skillsDir2, dir.name);
|
|
79633
|
+
const skillDirs = await readdir26(categoryPath, { withFileTypes: true });
|
|
78832
79634
|
skills.push(...skillDirs.filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name));
|
|
78833
79635
|
}
|
|
78834
79636
|
return ["categorized", skills];
|
|
@@ -78837,17 +79639,17 @@ async function scanSkillsDirectory(skillsDir2) {
|
|
|
78837
79639
|
return ["flat", dirs.map((dir) => dir.name)];
|
|
78838
79640
|
}
|
|
78839
79641
|
async function findSkillPath(skillsDir2, skillName) {
|
|
78840
|
-
const flatPath =
|
|
79642
|
+
const flatPath = join84(skillsDir2, skillName);
|
|
78841
79643
|
if (await import_fs_extra27.pathExists(flatPath)) {
|
|
78842
79644
|
return { path: flatPath, category: undefined };
|
|
78843
79645
|
}
|
|
78844
|
-
const entries = await
|
|
79646
|
+
const entries = await readdir26(skillsDir2, { withFileTypes: true });
|
|
78845
79647
|
for (const entry of entries) {
|
|
78846
79648
|
if (!entry.isDirectory() || entry.name.startsWith(".") || entry.name === "node_modules") {
|
|
78847
79649
|
continue;
|
|
78848
79650
|
}
|
|
78849
|
-
const categoryPath =
|
|
78850
|
-
const skillPath =
|
|
79651
|
+
const categoryPath = join84(skillsDir2, entry.name);
|
|
79652
|
+
const skillPath = join84(categoryPath, skillName);
|
|
78851
79653
|
if (await import_fs_extra27.pathExists(skillPath)) {
|
|
78852
79654
|
return { path: skillPath, category: entry.name };
|
|
78853
79655
|
}
|
|
@@ -78941,7 +79743,7 @@ class SkillsMigrator {
|
|
|
78941
79743
|
}
|
|
78942
79744
|
}
|
|
78943
79745
|
if (options2.backup && !options2.dryRun) {
|
|
78944
|
-
const claudeDir2 =
|
|
79746
|
+
const claudeDir2 = join85(currentSkillsDir, "..");
|
|
78945
79747
|
result.backupPath = await SkillsBackupManager.createBackup(currentSkillsDir, claudeDir2);
|
|
78946
79748
|
logger.success(`Backup created at: ${result.backupPath}`);
|
|
78947
79749
|
}
|
|
@@ -79002,7 +79804,7 @@ async function handleMigration(ctx) {
|
|
|
79002
79804
|
logger.debug("Skipping skills migration (fresh installation)");
|
|
79003
79805
|
return ctx;
|
|
79004
79806
|
}
|
|
79005
|
-
const newSkillsDir =
|
|
79807
|
+
const newSkillsDir = join86(ctx.extractDir, ".claude", "skills");
|
|
79006
79808
|
const currentSkillsDir = PathResolver.buildSkillsPath(ctx.resolvedDir, ctx.options.global);
|
|
79007
79809
|
if (!await import_fs_extra28.pathExists(newSkillsDir) || !await import_fs_extra28.pathExists(currentSkillsDir)) {
|
|
79008
79810
|
return ctx;
|
|
@@ -79025,14 +79827,14 @@ async function handleMigration(ctx) {
|
|
|
79025
79827
|
return ctx;
|
|
79026
79828
|
}
|
|
79027
79829
|
// src/commands/init/phases/opencode-handler.ts
|
|
79028
|
-
import { cp as cp2, readdir as
|
|
79029
|
-
import { join as
|
|
79830
|
+
import { cp as cp2, readdir as readdir28, rm as rm7 } from "node:fs/promises";
|
|
79831
|
+
import { join as join88 } from "node:path";
|
|
79030
79832
|
|
|
79031
79833
|
// src/services/transformers/opencode-path-transformer.ts
|
|
79032
79834
|
init_logger();
|
|
79033
|
-
import { readFile as readFile37, readdir as
|
|
79835
|
+
import { readFile as readFile37, readdir as readdir27, writeFile as writeFile23 } from "node:fs/promises";
|
|
79034
79836
|
import { platform as platform12 } from "node:os";
|
|
79035
|
-
import { extname as extname3, join as
|
|
79837
|
+
import { extname as extname3, join as join87 } from "node:path";
|
|
79036
79838
|
var IS_WINDOWS3 = platform12() === "win32";
|
|
79037
79839
|
function getOpenCodeGlobalPath() {
|
|
79038
79840
|
return "$HOME/.config/opencode/";
|
|
@@ -79091,9 +79893,9 @@ async function transformPathsForGlobalOpenCode(directory, options2 = {}) {
|
|
|
79091
79893
|
let totalChanges = 0;
|
|
79092
79894
|
let filesSkipped = 0;
|
|
79093
79895
|
async function processDirectory2(dir) {
|
|
79094
|
-
const entries = await
|
|
79896
|
+
const entries = await readdir27(dir, { withFileTypes: true });
|
|
79095
79897
|
for (const entry of entries) {
|
|
79096
|
-
const fullPath =
|
|
79898
|
+
const fullPath = join87(dir, entry.name);
|
|
79097
79899
|
if (entry.isDirectory()) {
|
|
79098
79900
|
if (entry.name === "node_modules" || entry.name.startsWith(".")) {
|
|
79099
79901
|
continue;
|
|
@@ -79132,7 +79934,7 @@ async function handleOpenCode(ctx) {
|
|
|
79132
79934
|
if (ctx.cancelled || !ctx.extractDir || !ctx.resolvedDir) {
|
|
79133
79935
|
return ctx;
|
|
79134
79936
|
}
|
|
79135
|
-
const openCodeSource =
|
|
79937
|
+
const openCodeSource = join88(ctx.extractDir, ".opencode");
|
|
79136
79938
|
if (!await import_fs_extra29.pathExists(openCodeSource)) {
|
|
79137
79939
|
logger.debug("No .opencode directory in archive, skipping");
|
|
79138
79940
|
return ctx;
|
|
@@ -79148,10 +79950,10 @@ async function handleOpenCode(ctx) {
|
|
|
79148
79950
|
logger.success(`Transformed ${transformResult.totalChanges} OpenCode path(s) in ${transformResult.filesTransformed} file(s)`);
|
|
79149
79951
|
}
|
|
79150
79952
|
await import_fs_extra29.ensureDir(targetDir);
|
|
79151
|
-
const entries = await
|
|
79953
|
+
const entries = await readdir28(openCodeSource, { withFileTypes: true });
|
|
79152
79954
|
for (const entry of entries) {
|
|
79153
|
-
const sourcePath =
|
|
79154
|
-
const targetPath =
|
|
79955
|
+
const sourcePath = join88(openCodeSource, entry.name);
|
|
79956
|
+
const targetPath = join88(targetDir, entry.name);
|
|
79155
79957
|
if (await import_fs_extra29.pathExists(targetPath)) {
|
|
79156
79958
|
if (!ctx.options.forceOverwrite) {
|
|
79157
79959
|
logger.verbose(`Skipping existing: ${entry.name}`);
|
|
@@ -79244,7 +80046,7 @@ Please use only one download method.`);
|
|
|
79244
80046
|
}
|
|
79245
80047
|
// src/commands/init/phases/post-install-handler.ts
|
|
79246
80048
|
init_projects_registry();
|
|
79247
|
-
import { join as
|
|
80049
|
+
import { join as join89 } from "node:path";
|
|
79248
80050
|
init_logger();
|
|
79249
80051
|
init_path_resolver();
|
|
79250
80052
|
var import_fs_extra30 = __toESM(require_lib3(), 1);
|
|
@@ -79253,8 +80055,8 @@ async function handlePostInstall(ctx) {
|
|
|
79253
80055
|
return ctx;
|
|
79254
80056
|
}
|
|
79255
80057
|
if (ctx.options.global) {
|
|
79256
|
-
const claudeMdSource =
|
|
79257
|
-
const claudeMdDest =
|
|
80058
|
+
const claudeMdSource = join89(ctx.extractDir, "CLAUDE.md");
|
|
80059
|
+
const claudeMdDest = join89(ctx.resolvedDir, "CLAUDE.md");
|
|
79258
80060
|
if (await import_fs_extra30.pathExists(claudeMdSource)) {
|
|
79259
80061
|
if (!await import_fs_extra30.pathExists(claudeMdDest)) {
|
|
79260
80062
|
await import_fs_extra30.copy(claudeMdSource, claudeMdDest);
|
|
@@ -79302,7 +80104,7 @@ async function handlePostInstall(ctx) {
|
|
|
79302
80104
|
}
|
|
79303
80105
|
if (!ctx.options.skipSetup) {
|
|
79304
80106
|
await promptSetupWizardIfNeeded({
|
|
79305
|
-
envPath:
|
|
80107
|
+
envPath: join89(ctx.claudeDir, ".env"),
|
|
79306
80108
|
claudeDir: ctx.claudeDir,
|
|
79307
80109
|
isGlobal: ctx.options.global,
|
|
79308
80110
|
isNonInteractive: ctx.isNonInteractive,
|
|
@@ -79326,7 +80128,7 @@ async function handlePostInstall(ctx) {
|
|
|
79326
80128
|
init_config_manager();
|
|
79327
80129
|
init_github_client();
|
|
79328
80130
|
import { mkdir as mkdir25 } from "node:fs/promises";
|
|
79329
|
-
import { join as
|
|
80131
|
+
import { join as join91, resolve as resolve16 } from "node:path";
|
|
79330
80132
|
|
|
79331
80133
|
// src/domains/github/kit-access-checker.ts
|
|
79332
80134
|
init_logger();
|
|
@@ -79456,8 +80258,8 @@ async function runPreflightChecks() {
|
|
|
79456
80258
|
|
|
79457
80259
|
// src/domains/installation/fresh-installer.ts
|
|
79458
80260
|
init_metadata_migration();
|
|
79459
|
-
import { existsSync as
|
|
79460
|
-
import { dirname as dirname17, join as
|
|
80261
|
+
import { existsSync as existsSync38, readdirSync as readdirSync3, rmSync as rmSync3, rmdirSync as rmdirSync2, unlinkSync as unlinkSync4 } from "node:fs";
|
|
80262
|
+
import { dirname as dirname17, join as join90, resolve as resolve15 } from "node:path";
|
|
79461
80263
|
init_logger();
|
|
79462
80264
|
init_safe_spinner();
|
|
79463
80265
|
var import_fs_extra31 = __toESM(require_lib3(), 1);
|
|
@@ -79505,15 +80307,15 @@ async function analyzeFreshInstallation(claudeDir2) {
|
|
|
79505
80307
|
};
|
|
79506
80308
|
}
|
|
79507
80309
|
function cleanupEmptyDirectories2(filePath, claudeDir2) {
|
|
79508
|
-
const normalizedClaudeDir =
|
|
79509
|
-
let currentDir =
|
|
80310
|
+
const normalizedClaudeDir = resolve15(claudeDir2);
|
|
80311
|
+
let currentDir = resolve15(dirname17(filePath));
|
|
79510
80312
|
while (currentDir !== normalizedClaudeDir && currentDir.startsWith(normalizedClaudeDir)) {
|
|
79511
80313
|
try {
|
|
79512
80314
|
const entries = readdirSync3(currentDir);
|
|
79513
80315
|
if (entries.length === 0) {
|
|
79514
80316
|
rmdirSync2(currentDir);
|
|
79515
80317
|
logger.debug(`Removed empty directory: ${currentDir}`);
|
|
79516
|
-
currentDir =
|
|
80318
|
+
currentDir = resolve15(dirname17(currentDir));
|
|
79517
80319
|
} else {
|
|
79518
80320
|
break;
|
|
79519
80321
|
}
|
|
@@ -79530,9 +80332,9 @@ async function removeFilesByOwnership(claudeDir2, analysis, includeModified) {
|
|
|
79530
80332
|
const filesToRemove = includeModified ? [...analysis.ckFiles, ...analysis.ckModifiedFiles] : analysis.ckFiles;
|
|
79531
80333
|
const filesToPreserve = includeModified ? analysis.userFiles : [...analysis.ckModifiedFiles, ...analysis.userFiles];
|
|
79532
80334
|
for (const file of filesToRemove) {
|
|
79533
|
-
const fullPath =
|
|
80335
|
+
const fullPath = join90(claudeDir2, file.path);
|
|
79534
80336
|
try {
|
|
79535
|
-
if (
|
|
80337
|
+
if (existsSync38(fullPath)) {
|
|
79536
80338
|
unlinkSync4(fullPath);
|
|
79537
80339
|
removedFiles.push(file.path);
|
|
79538
80340
|
logger.debug(`Removed: ${file.path}`);
|
|
@@ -79555,7 +80357,7 @@ async function removeFilesByOwnership(claudeDir2, analysis, includeModified) {
|
|
|
79555
80357
|
};
|
|
79556
80358
|
}
|
|
79557
80359
|
async function updateMetadataAfterFresh(claudeDir2, removedFiles) {
|
|
79558
|
-
const metadataPath =
|
|
80360
|
+
const metadataPath = join90(claudeDir2, "metadata.json");
|
|
79559
80361
|
if (!await import_fs_extra31.pathExists(metadataPath)) {
|
|
79560
80362
|
return;
|
|
79561
80363
|
}
|
|
@@ -79598,7 +80400,7 @@ async function removeSubdirectoriesFallback(claudeDir2) {
|
|
|
79598
80400
|
const removedFiles = [];
|
|
79599
80401
|
let removedDirCount = 0;
|
|
79600
80402
|
for (const subdir of CLAUDEKIT_SUBDIRECTORIES) {
|
|
79601
|
-
const subdirPath =
|
|
80403
|
+
const subdirPath = join90(claudeDir2, subdir);
|
|
79602
80404
|
if (await import_fs_extra31.pathExists(subdirPath)) {
|
|
79603
80405
|
rmSync3(subdirPath, { recursive: true, force: true });
|
|
79604
80406
|
removedDirCount++;
|
|
@@ -79606,7 +80408,7 @@ async function removeSubdirectoriesFallback(claudeDir2) {
|
|
|
79606
80408
|
logger.debug(`Removed subdirectory: ${subdir}/`);
|
|
79607
80409
|
}
|
|
79608
80410
|
}
|
|
79609
|
-
const metadataPath =
|
|
80411
|
+
const metadataPath = join90(claudeDir2, "metadata.json");
|
|
79610
80412
|
if (await import_fs_extra31.pathExists(metadataPath)) {
|
|
79611
80413
|
unlinkSync4(metadataPath);
|
|
79612
80414
|
removedFiles.push("metadata.json");
|
|
@@ -79824,7 +80626,7 @@ async function handleSelection(ctx) {
|
|
|
79824
80626
|
}
|
|
79825
80627
|
}
|
|
79826
80628
|
}
|
|
79827
|
-
const resolvedDir =
|
|
80629
|
+
const resolvedDir = resolve16(targetDir);
|
|
79828
80630
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
79829
80631
|
if (!ctx.options.global && PathResolver.isLocalSameAsGlobal(resolvedDir)) {
|
|
79830
80632
|
logger.warning("You're at HOME directory. Installing here modifies your GLOBAL ClaudeKit.");
|
|
@@ -79858,7 +80660,7 @@ async function handleSelection(ctx) {
|
|
|
79858
80660
|
}
|
|
79859
80661
|
if (!ctx.options.fresh) {
|
|
79860
80662
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
79861
|
-
const claudeDir2 = prefix ?
|
|
80663
|
+
const claudeDir2 = prefix ? join91(resolvedDir, prefix) : resolvedDir;
|
|
79862
80664
|
try {
|
|
79863
80665
|
const existingMetadata = await readManifest(claudeDir2);
|
|
79864
80666
|
if (existingMetadata?.kits) {
|
|
@@ -79890,7 +80692,7 @@ async function handleSelection(ctx) {
|
|
|
79890
80692
|
}
|
|
79891
80693
|
if (ctx.options.fresh) {
|
|
79892
80694
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
79893
|
-
const claudeDir2 = prefix ?
|
|
80695
|
+
const claudeDir2 = prefix ? join91(resolvedDir, prefix) : resolvedDir;
|
|
79894
80696
|
const canProceed = await handleFreshInstallation(claudeDir2, ctx.prompts);
|
|
79895
80697
|
if (!canProceed) {
|
|
79896
80698
|
return { ...ctx, cancelled: true };
|
|
@@ -79909,7 +80711,7 @@ async function handleSelection(ctx) {
|
|
|
79909
80711
|
logger.info("Fetching available versions...");
|
|
79910
80712
|
let currentVersion = null;
|
|
79911
80713
|
try {
|
|
79912
|
-
const metadataPath = ctx.options.global ?
|
|
80714
|
+
const metadataPath = ctx.options.global ? join91(PathResolver.getGlobalKitDir(), "metadata.json") : join91(resolvedDir, ".claude", "metadata.json");
|
|
79913
80715
|
const metadata = await readClaudeKitMetadata(metadataPath);
|
|
79914
80716
|
currentVersion = metadata?.version || null;
|
|
79915
80717
|
if (currentVersion) {
|
|
@@ -79984,7 +80786,7 @@ async function handleSelection(ctx) {
|
|
|
79984
80786
|
}
|
|
79985
80787
|
// src/commands/init/phases/sync-handler.ts
|
|
79986
80788
|
import { copyFile as copyFile7, mkdir as mkdir26, open as open4, readFile as readFile39, rename as rename3, stat as stat17, unlink as unlink8, writeFile as writeFile25 } from "node:fs/promises";
|
|
79987
|
-
import { dirname as dirname18, join as
|
|
80789
|
+
import { dirname as dirname18, join as join92, resolve as resolve17 } from "node:path";
|
|
79988
80790
|
init_logger();
|
|
79989
80791
|
init_path_resolver();
|
|
79990
80792
|
var import_fs_extra33 = __toESM(require_lib3(), 1);
|
|
@@ -79993,14 +80795,14 @@ async function handleSync(ctx) {
|
|
|
79993
80795
|
if (!ctx.options.sync) {
|
|
79994
80796
|
return ctx;
|
|
79995
80797
|
}
|
|
79996
|
-
const resolvedDir = ctx.options.global ? PathResolver.getGlobalKitDir() :
|
|
79997
|
-
const claudeDir2 = ctx.options.global ? resolvedDir :
|
|
80798
|
+
const resolvedDir = ctx.options.global ? PathResolver.getGlobalKitDir() : resolve17(ctx.options.dir || ".");
|
|
80799
|
+
const claudeDir2 = ctx.options.global ? resolvedDir : join92(resolvedDir, ".claude");
|
|
79998
80800
|
if (!await import_fs_extra33.pathExists(claudeDir2)) {
|
|
79999
80801
|
logger.error("Cannot sync: no .claude directory found");
|
|
80000
80802
|
ctx.prompts.note("Run 'ck init' without --sync to install first.", "No Installation Found");
|
|
80001
80803
|
return { ...ctx, cancelled: true };
|
|
80002
80804
|
}
|
|
80003
|
-
const metadataPath =
|
|
80805
|
+
const metadataPath = join92(claudeDir2, "metadata.json");
|
|
80004
80806
|
if (!await import_fs_extra33.pathExists(metadataPath)) {
|
|
80005
80807
|
logger.error("Cannot sync: no metadata.json found");
|
|
80006
80808
|
ctx.prompts.note(`Your installation may be from an older version.
|
|
@@ -80100,7 +80902,7 @@ function getLockTimeout() {
|
|
|
80100
80902
|
var STALE_LOCK_THRESHOLD_MS = 5 * 60 * 1000;
|
|
80101
80903
|
async function acquireSyncLock(global3) {
|
|
80102
80904
|
const cacheDir = PathResolver.getCacheDir(global3);
|
|
80103
|
-
const lockPath =
|
|
80905
|
+
const lockPath = join92(cacheDir, ".sync-lock");
|
|
80104
80906
|
const startTime = Date.now();
|
|
80105
80907
|
const lockTimeout = getLockTimeout();
|
|
80106
80908
|
await mkdir26(dirname18(lockPath), { recursive: true });
|
|
@@ -80127,7 +80929,7 @@ async function acquireSyncLock(global3) {
|
|
|
80127
80929
|
}
|
|
80128
80930
|
logger.debug(`Lock stat failed: ${statError}`);
|
|
80129
80931
|
}
|
|
80130
|
-
await new Promise((
|
|
80932
|
+
await new Promise((resolve18) => setTimeout(resolve18, 100));
|
|
80131
80933
|
continue;
|
|
80132
80934
|
}
|
|
80133
80935
|
throw err;
|
|
@@ -80146,10 +80948,10 @@ async function executeSyncMerge(ctx) {
|
|
|
80146
80948
|
const releaseLock = await acquireSyncLock(ctx.options.global);
|
|
80147
80949
|
try {
|
|
80148
80950
|
const trackedFiles = ctx.syncTrackedFiles;
|
|
80149
|
-
const upstreamDir = ctx.options.global ?
|
|
80951
|
+
const upstreamDir = ctx.options.global ? join92(ctx.extractDir, ".claude") : ctx.extractDir;
|
|
80150
80952
|
let deletions = [];
|
|
80151
80953
|
try {
|
|
80152
|
-
const sourceMetadataPath =
|
|
80954
|
+
const sourceMetadataPath = join92(upstreamDir, "metadata.json");
|
|
80153
80955
|
if (await import_fs_extra33.pathExists(sourceMetadataPath)) {
|
|
80154
80956
|
const content = await readFile39(sourceMetadataPath, "utf-8");
|
|
80155
80957
|
const sourceMetadata = JSON.parse(content);
|
|
@@ -80181,7 +80983,7 @@ async function executeSyncMerge(ctx) {
|
|
|
80181
80983
|
try {
|
|
80182
80984
|
const sourcePath = await validateSyncPath(upstreamDir, file.path);
|
|
80183
80985
|
const targetPath = await validateSyncPath(ctx.claudeDir, file.path);
|
|
80184
|
-
const targetDir =
|
|
80986
|
+
const targetDir = join92(targetPath, "..");
|
|
80185
80987
|
try {
|
|
80186
80988
|
await mkdir26(targetDir, { recursive: true });
|
|
80187
80989
|
} catch (mkdirError) {
|
|
@@ -80352,7 +81154,7 @@ async function createBackup(claudeDir2, files, backupDir) {
|
|
|
80352
81154
|
const sourcePath = await validateSyncPath(claudeDir2, file.path);
|
|
80353
81155
|
if (await import_fs_extra33.pathExists(sourcePath)) {
|
|
80354
81156
|
const targetPath = await validateSyncPath(backupDir, file.path);
|
|
80355
|
-
const targetDir =
|
|
81157
|
+
const targetDir = join92(targetPath, "..");
|
|
80356
81158
|
await mkdir26(targetDir, { recursive: true });
|
|
80357
81159
|
await copyFile7(sourcePath, targetPath);
|
|
80358
81160
|
}
|
|
@@ -80367,7 +81169,7 @@ async function createBackup(claudeDir2, files, backupDir) {
|
|
|
80367
81169
|
}
|
|
80368
81170
|
// src/commands/init/phases/transform-handler.ts
|
|
80369
81171
|
init_config_manager();
|
|
80370
|
-
import { join as
|
|
81172
|
+
import { join as join96 } from "node:path";
|
|
80371
81173
|
|
|
80372
81174
|
// src/services/transformers/folder-path-transformer.ts
|
|
80373
81175
|
init_logger();
|
|
@@ -80378,38 +81180,38 @@ init_logger();
|
|
|
80378
81180
|
init_types2();
|
|
80379
81181
|
var import_fs_extra34 = __toESM(require_lib3(), 1);
|
|
80380
81182
|
import { rename as rename4, rm as rm8 } from "node:fs/promises";
|
|
80381
|
-
import { join as
|
|
81183
|
+
import { join as join93, relative as relative15 } from "node:path";
|
|
80382
81184
|
async function collectDirsToRename(extractDir, folders) {
|
|
80383
81185
|
const dirsToRename = [];
|
|
80384
81186
|
if (folders.docs !== DEFAULT_FOLDERS.docs) {
|
|
80385
|
-
const docsPath =
|
|
81187
|
+
const docsPath = join93(extractDir, DEFAULT_FOLDERS.docs);
|
|
80386
81188
|
if (await import_fs_extra34.pathExists(docsPath)) {
|
|
80387
81189
|
dirsToRename.push({
|
|
80388
81190
|
from: docsPath,
|
|
80389
|
-
to:
|
|
81191
|
+
to: join93(extractDir, folders.docs)
|
|
80390
81192
|
});
|
|
80391
81193
|
}
|
|
80392
|
-
const claudeDocsPath =
|
|
81194
|
+
const claudeDocsPath = join93(extractDir, ".claude", DEFAULT_FOLDERS.docs);
|
|
80393
81195
|
if (await import_fs_extra34.pathExists(claudeDocsPath)) {
|
|
80394
81196
|
dirsToRename.push({
|
|
80395
81197
|
from: claudeDocsPath,
|
|
80396
|
-
to:
|
|
81198
|
+
to: join93(extractDir, ".claude", folders.docs)
|
|
80397
81199
|
});
|
|
80398
81200
|
}
|
|
80399
81201
|
}
|
|
80400
81202
|
if (folders.plans !== DEFAULT_FOLDERS.plans) {
|
|
80401
|
-
const plansPath =
|
|
81203
|
+
const plansPath = join93(extractDir, DEFAULT_FOLDERS.plans);
|
|
80402
81204
|
if (await import_fs_extra34.pathExists(plansPath)) {
|
|
80403
81205
|
dirsToRename.push({
|
|
80404
81206
|
from: plansPath,
|
|
80405
|
-
to:
|
|
81207
|
+
to: join93(extractDir, folders.plans)
|
|
80406
81208
|
});
|
|
80407
81209
|
}
|
|
80408
|
-
const claudePlansPath =
|
|
81210
|
+
const claudePlansPath = join93(extractDir, ".claude", DEFAULT_FOLDERS.plans);
|
|
80409
81211
|
if (await import_fs_extra34.pathExists(claudePlansPath)) {
|
|
80410
81212
|
dirsToRename.push({
|
|
80411
81213
|
from: claudePlansPath,
|
|
80412
|
-
to:
|
|
81214
|
+
to: join93(extractDir, ".claude", folders.plans)
|
|
80413
81215
|
});
|
|
80414
81216
|
}
|
|
80415
81217
|
}
|
|
@@ -80449,8 +81251,8 @@ async function renameFolders(dirsToRename, extractDir, options2) {
|
|
|
80449
81251
|
// src/services/transformers/folder-transform/path-replacer.ts
|
|
80450
81252
|
init_logger();
|
|
80451
81253
|
init_types2();
|
|
80452
|
-
import { readFile as readFile40, readdir as
|
|
80453
|
-
import { join as
|
|
81254
|
+
import { readFile as readFile40, readdir as readdir29, writeFile as writeFile26 } from "node:fs/promises";
|
|
81255
|
+
import { join as join94, relative as relative16 } from "node:path";
|
|
80454
81256
|
var TRANSFORMABLE_FILE_PATTERNS = [
|
|
80455
81257
|
".md",
|
|
80456
81258
|
".txt",
|
|
@@ -80501,9 +81303,9 @@ function compileReplacements(replacements) {
|
|
|
80501
81303
|
async function transformFileContents(dir, compiledReplacements, options2) {
|
|
80502
81304
|
let filesChanged = 0;
|
|
80503
81305
|
let replacementsCount = 0;
|
|
80504
|
-
const entries = await
|
|
81306
|
+
const entries = await readdir29(dir, { withFileTypes: true });
|
|
80505
81307
|
for (const entry of entries) {
|
|
80506
|
-
const fullPath =
|
|
81308
|
+
const fullPath = join94(dir, entry.name);
|
|
80507
81309
|
if (entry.isDirectory()) {
|
|
80508
81310
|
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
80509
81311
|
continue;
|
|
@@ -80638,9 +81440,9 @@ async function transformFolderPaths(extractDir, folders, options2 = {}) {
|
|
|
80638
81440
|
|
|
80639
81441
|
// src/services/transformers/global-path-transformer.ts
|
|
80640
81442
|
init_logger();
|
|
80641
|
-
import { readFile as readFile41, readdir as
|
|
81443
|
+
import { readFile as readFile41, readdir as readdir30, writeFile as writeFile27 } from "node:fs/promises";
|
|
80642
81444
|
import { platform as platform13 } from "node:os";
|
|
80643
|
-
import { extname as extname4, join as
|
|
81445
|
+
import { extname as extname4, join as join95 } from "node:path";
|
|
80644
81446
|
var IS_WINDOWS4 = platform13() === "win32";
|
|
80645
81447
|
var HOME_PREFIX = IS_WINDOWS4 ? "%USERPROFILE%" : "$HOME";
|
|
80646
81448
|
function getHomeDirPrefix() {
|
|
@@ -80748,9 +81550,9 @@ async function transformPathsForGlobalInstall(directory, options2 = {}) {
|
|
|
80748
81550
|
let filesSkipped = 0;
|
|
80749
81551
|
const skippedFiles = [];
|
|
80750
81552
|
async function processDirectory2(dir) {
|
|
80751
|
-
const entries = await
|
|
81553
|
+
const entries = await readdir30(dir, { withFileTypes: true });
|
|
80752
81554
|
for (const entry of entries) {
|
|
80753
|
-
const fullPath =
|
|
81555
|
+
const fullPath = join95(dir, entry.name);
|
|
80754
81556
|
if (entry.isDirectory()) {
|
|
80755
81557
|
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
80756
81558
|
continue;
|
|
@@ -80826,7 +81628,7 @@ async function handleTransforms(ctx) {
|
|
|
80826
81628
|
logger.debug(ctx.options.global ? "Saved folder configuration to ~/.claude/.ck.json" : "Saved folder configuration to .claude/.ck.json");
|
|
80827
81629
|
}
|
|
80828
81630
|
}
|
|
80829
|
-
const claudeDir2 = ctx.options.global ? ctx.resolvedDir :
|
|
81631
|
+
const claudeDir2 = ctx.options.global ? ctx.resolvedDir : join96(ctx.resolvedDir, ".claude");
|
|
80830
81632
|
return {
|
|
80831
81633
|
...ctx,
|
|
80832
81634
|
foldersConfig,
|
|
@@ -81019,7 +81821,7 @@ var import_picocolors22 = __toESM(require_picocolors(), 1);
|
|
|
81019
81821
|
|
|
81020
81822
|
// src/commands/new/phases/directory-setup.ts
|
|
81021
81823
|
init_config_manager();
|
|
81022
|
-
import { resolve as
|
|
81824
|
+
import { resolve as resolve18 } from "node:path";
|
|
81023
81825
|
init_logger();
|
|
81024
81826
|
init_path_resolver();
|
|
81025
81827
|
init_types2();
|
|
@@ -81104,7 +81906,7 @@ async function directorySetup(validOptions, prompts) {
|
|
|
81104
81906
|
targetDir = await prompts.getDirectory(targetDir);
|
|
81105
81907
|
}
|
|
81106
81908
|
}
|
|
81107
|
-
const resolvedDir =
|
|
81909
|
+
const resolvedDir = resolve18(targetDir);
|
|
81108
81910
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
81109
81911
|
if (PathResolver.isLocalSameAsGlobal(resolvedDir)) {
|
|
81110
81912
|
logger.warning("You're creating a project at HOME directory.");
|
|
@@ -81161,7 +81963,7 @@ async function handleDirectorySetup(ctx) {
|
|
|
81161
81963
|
// src/commands/new/phases/project-creation.ts
|
|
81162
81964
|
init_config_manager();
|
|
81163
81965
|
init_github_client();
|
|
81164
|
-
import { join as
|
|
81966
|
+
import { join as join97 } from "node:path";
|
|
81165
81967
|
init_logger();
|
|
81166
81968
|
init_output_manager();
|
|
81167
81969
|
init_types2();
|
|
@@ -81287,7 +82089,7 @@ async function projectCreation(kit, resolvedDir, validOptions, isNonInteractive2
|
|
|
81287
82089
|
output.section("Installing");
|
|
81288
82090
|
logger.verbose("Installation target", { directory: resolvedDir });
|
|
81289
82091
|
const merger = new FileMerger;
|
|
81290
|
-
const claudeDir2 =
|
|
82092
|
+
const claudeDir2 = join97(resolvedDir, ".claude");
|
|
81291
82093
|
merger.setMultiKitContext(claudeDir2, kit);
|
|
81292
82094
|
if (validOptions.exclude && validOptions.exclude.length > 0) {
|
|
81293
82095
|
merger.addIgnorePatterns(validOptions.exclude);
|
|
@@ -81334,7 +82136,7 @@ async function handleProjectCreation(ctx) {
|
|
|
81334
82136
|
}
|
|
81335
82137
|
// src/commands/new/phases/post-setup.ts
|
|
81336
82138
|
init_projects_registry();
|
|
81337
|
-
import { join as
|
|
82139
|
+
import { join as join98 } from "node:path";
|
|
81338
82140
|
init_package_installer();
|
|
81339
82141
|
init_logger();
|
|
81340
82142
|
init_path_resolver();
|
|
@@ -81366,9 +82168,9 @@ async function postSetup(resolvedDir, validOptions, isNonInteractive2, prompts)
|
|
|
81366
82168
|
withSudo: validOptions.withSudo
|
|
81367
82169
|
});
|
|
81368
82170
|
}
|
|
81369
|
-
const claudeDir2 =
|
|
82171
|
+
const claudeDir2 = join98(resolvedDir, ".claude");
|
|
81370
82172
|
await promptSetupWizardIfNeeded({
|
|
81371
|
-
envPath:
|
|
82173
|
+
envPath: join98(claudeDir2, ".env"),
|
|
81372
82174
|
claudeDir: claudeDir2,
|
|
81373
82175
|
isGlobal: false,
|
|
81374
82176
|
isNonInteractive: isNonInteractive2,
|
|
@@ -81440,13 +82242,13 @@ init_claudekit_data2();
|
|
|
81440
82242
|
init_logger();
|
|
81441
82243
|
init_safe_prompts();
|
|
81442
82244
|
var import_picocolors23 = __toESM(require_picocolors(), 1);
|
|
81443
|
-
import { existsSync as
|
|
81444
|
-
import { resolve as
|
|
82245
|
+
import { existsSync as existsSync39 } from "node:fs";
|
|
82246
|
+
import { resolve as resolve19 } from "node:path";
|
|
81445
82247
|
async function handleAdd(projectPath, options2) {
|
|
81446
82248
|
logger.debug(`Adding project: ${projectPath}, options: ${JSON.stringify(options2)}`);
|
|
81447
82249
|
intro("Add Project");
|
|
81448
|
-
const absolutePath =
|
|
81449
|
-
if (!
|
|
82250
|
+
const absolutePath = resolve19(projectPath);
|
|
82251
|
+
if (!existsSync39(absolutePath)) {
|
|
81450
82252
|
log.error(`Path does not exist: ${absolutePath}`);
|
|
81451
82253
|
process.exitCode = 1;
|
|
81452
82254
|
return;
|
|
@@ -82374,7 +83176,7 @@ async function detectInstallations() {
|
|
|
82374
83176
|
|
|
82375
83177
|
// src/commands/uninstall/removal-handler.ts
|
|
82376
83178
|
import { readdirSync as readdirSync5, rmSync as rmSync5 } from "node:fs";
|
|
82377
|
-
import { join as
|
|
83179
|
+
import { join as join100, resolve as resolve20, sep as sep4 } from "node:path";
|
|
82378
83180
|
init_logger();
|
|
82379
83181
|
init_safe_prompts();
|
|
82380
83182
|
init_safe_spinner();
|
|
@@ -82383,7 +83185,7 @@ var import_fs_extra37 = __toESM(require_lib3(), 1);
|
|
|
82383
83185
|
// src/commands/uninstall/analysis-handler.ts
|
|
82384
83186
|
init_metadata_migration();
|
|
82385
83187
|
import { readdirSync as readdirSync4, rmSync as rmSync4 } from "node:fs";
|
|
82386
|
-
import { dirname as dirname19, join as
|
|
83188
|
+
import { dirname as dirname19, join as join99 } from "node:path";
|
|
82387
83189
|
init_logger();
|
|
82388
83190
|
init_safe_prompts();
|
|
82389
83191
|
var import_picocolors27 = __toESM(require_picocolors(), 1);
|
|
@@ -82431,7 +83233,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
82431
83233
|
if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
|
|
82432
83234
|
const kitFiles = metadata.kits[kit].files || [];
|
|
82433
83235
|
for (const trackedFile of kitFiles) {
|
|
82434
|
-
const filePath =
|
|
83236
|
+
const filePath = join99(installation.path, trackedFile.path);
|
|
82435
83237
|
if (uninstallManifest.filesToPreserve.includes(trackedFile.path)) {
|
|
82436
83238
|
result.toPreserve.push({ path: trackedFile.path, reason: "shared with other kit" });
|
|
82437
83239
|
continue;
|
|
@@ -82461,7 +83263,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
82461
83263
|
return result;
|
|
82462
83264
|
}
|
|
82463
83265
|
for (const trackedFile of allTrackedFiles) {
|
|
82464
|
-
const filePath =
|
|
83266
|
+
const filePath = join99(installation.path, trackedFile.path);
|
|
82465
83267
|
const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
|
|
82466
83268
|
if (!ownershipResult.exists)
|
|
82467
83269
|
continue;
|
|
@@ -82515,8 +83317,8 @@ async function isDirectory(filePath) {
|
|
|
82515
83317
|
}
|
|
82516
83318
|
async function isPathSafeToRemove(filePath, baseDir) {
|
|
82517
83319
|
try {
|
|
82518
|
-
const resolvedPath =
|
|
82519
|
-
const resolvedBase =
|
|
83320
|
+
const resolvedPath = resolve20(filePath);
|
|
83321
|
+
const resolvedBase = resolve20(baseDir);
|
|
82520
83322
|
if (!resolvedPath.startsWith(resolvedBase + sep4) && resolvedPath !== resolvedBase) {
|
|
82521
83323
|
logger.debug(`Path outside installation directory: ${filePath}`);
|
|
82522
83324
|
return false;
|
|
@@ -82524,7 +83326,7 @@ async function isPathSafeToRemove(filePath, baseDir) {
|
|
|
82524
83326
|
const stats = await import_fs_extra37.lstat(filePath);
|
|
82525
83327
|
if (stats.isSymbolicLink()) {
|
|
82526
83328
|
const realPath = await import_fs_extra37.realpath(filePath);
|
|
82527
|
-
const resolvedReal =
|
|
83329
|
+
const resolvedReal = resolve20(realPath);
|
|
82528
83330
|
if (!resolvedReal.startsWith(resolvedBase + sep4) && resolvedReal !== resolvedBase) {
|
|
82529
83331
|
logger.debug(`Symlink points outside installation directory: ${filePath} -> ${realPath}`);
|
|
82530
83332
|
return false;
|
|
@@ -82558,7 +83360,7 @@ async function removeInstallations(installations, options2) {
|
|
|
82558
83360
|
let removedCount = 0;
|
|
82559
83361
|
let cleanedDirs = 0;
|
|
82560
83362
|
for (const item of analysis.toDelete) {
|
|
82561
|
-
const filePath =
|
|
83363
|
+
const filePath = join100(installation.path, item.path);
|
|
82562
83364
|
if (!await import_fs_extra37.pathExists(filePath))
|
|
82563
83365
|
continue;
|
|
82564
83366
|
if (!await isPathSafeToRemove(filePath, installation.path)) {
|
|
@@ -82932,8 +83734,8 @@ init_version_checker();
|
|
|
82932
83734
|
init_logger();
|
|
82933
83735
|
init_path_resolver();
|
|
82934
83736
|
init_types2();
|
|
82935
|
-
import { existsSync as
|
|
82936
|
-
import { join as
|
|
83737
|
+
import { existsSync as existsSync40, readFileSync as readFileSync9 } from "node:fs";
|
|
83738
|
+
import { join as join101 } from "node:path";
|
|
82937
83739
|
var packageVersion = package_default.version;
|
|
82938
83740
|
function formatInstalledKits(metadata) {
|
|
82939
83741
|
if (!metadata.kits || Object.keys(metadata.kits).length === 0) {
|
|
@@ -82965,13 +83767,13 @@ async function displayVersion() {
|
|
|
82965
83767
|
let localKitVersion = null;
|
|
82966
83768
|
let isGlobalOnlyKit = false;
|
|
82967
83769
|
const globalKitDir = PathResolver.getGlobalKitDir();
|
|
82968
|
-
const globalMetadataPath =
|
|
83770
|
+
const globalMetadataPath = join101(globalKitDir, "metadata.json");
|
|
82969
83771
|
const prefix = PathResolver.getPathPrefix(false);
|
|
82970
|
-
const localMetadataPath = prefix ?
|
|
83772
|
+
const localMetadataPath = prefix ? join101(process.cwd(), prefix, "metadata.json") : join101(process.cwd(), "metadata.json");
|
|
82971
83773
|
const isLocalSameAsGlobal = localMetadataPath === globalMetadataPath;
|
|
82972
|
-
if (!isLocalSameAsGlobal &&
|
|
83774
|
+
if (!isLocalSameAsGlobal && existsSync40(localMetadataPath)) {
|
|
82973
83775
|
try {
|
|
82974
|
-
const rawMetadata = JSON.parse(
|
|
83776
|
+
const rawMetadata = JSON.parse(readFileSync9(localMetadataPath, "utf-8"));
|
|
82975
83777
|
const metadata = MetadataSchema.parse(rawMetadata);
|
|
82976
83778
|
const kitsDisplay = formatInstalledKits(metadata);
|
|
82977
83779
|
if (kitsDisplay) {
|
|
@@ -82983,9 +83785,9 @@ async function displayVersion() {
|
|
|
82983
83785
|
logger.verbose("Failed to parse local metadata.json", { error });
|
|
82984
83786
|
}
|
|
82985
83787
|
}
|
|
82986
|
-
if (
|
|
83788
|
+
if (existsSync40(globalMetadataPath)) {
|
|
82987
83789
|
try {
|
|
82988
|
-
const rawMetadata = JSON.parse(
|
|
83790
|
+
const rawMetadata = JSON.parse(readFileSync9(globalMetadataPath, "utf-8"));
|
|
82989
83791
|
const metadata = MetadataSchema.parse(rawMetadata);
|
|
82990
83792
|
const kitsDisplay = formatInstalledKits(metadata);
|
|
82991
83793
|
if (kitsDisplay) {
|