claudekit-cli 3.26.0 → 3.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +331 -99
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -16194,7 +16194,7 @@ var init_init_command_help = __esm(() => {
|
|
|
16194
16194
|
},
|
|
16195
16195
|
{
|
|
16196
16196
|
flags: "--fresh",
|
|
16197
|
-
description: "
|
|
16197
|
+
description: "Remove ClaudeKit directories (commands/, agents/, skills/, rules/, hooks/) and reinstall"
|
|
16198
16198
|
}
|
|
16199
16199
|
]
|
|
16200
16200
|
},
|
|
@@ -16442,7 +16442,7 @@ var init_update_command_help = __esm(() => {
|
|
|
16442
16442
|
sections: [
|
|
16443
16443
|
{
|
|
16444
16444
|
title: "Note",
|
|
16445
|
-
content: "'ck update' updates the CLI tool only. To update kit content (skills, commands,
|
|
16445
|
+
content: "'ck update' updates the CLI tool only. To update kit content (skills, commands, rules), use 'ck init' for local or 'ck init -g' for global."
|
|
16446
16446
|
}
|
|
16447
16447
|
]
|
|
16448
16448
|
};
|
|
@@ -16592,7 +16592,7 @@ function getPagerArgs(pagerCmd) {
|
|
|
16592
16592
|
return [];
|
|
16593
16593
|
}
|
|
16594
16594
|
async function trySystemPager(content) {
|
|
16595
|
-
return new Promise((
|
|
16595
|
+
return new Promise((resolve11) => {
|
|
16596
16596
|
const pagerCmd = process.env.PAGER || "less";
|
|
16597
16597
|
const pagerArgs = getPagerArgs(pagerCmd);
|
|
16598
16598
|
try {
|
|
@@ -16602,20 +16602,20 @@ async function trySystemPager(content) {
|
|
|
16602
16602
|
});
|
|
16603
16603
|
const timeout = setTimeout(() => {
|
|
16604
16604
|
pager.kill();
|
|
16605
|
-
|
|
16605
|
+
resolve11(false);
|
|
16606
16606
|
}, 30000);
|
|
16607
16607
|
pager.stdin.write(content);
|
|
16608
16608
|
pager.stdin.end();
|
|
16609
16609
|
pager.on("close", (code2) => {
|
|
16610
16610
|
clearTimeout(timeout);
|
|
16611
|
-
|
|
16611
|
+
resolve11(code2 === 0);
|
|
16612
16612
|
});
|
|
16613
16613
|
pager.on("error", () => {
|
|
16614
16614
|
clearTimeout(timeout);
|
|
16615
|
-
|
|
16615
|
+
resolve11(false);
|
|
16616
16616
|
});
|
|
16617
16617
|
} catch {
|
|
16618
|
-
|
|
16618
|
+
resolve11(false);
|
|
16619
16619
|
}
|
|
16620
16620
|
});
|
|
16621
16621
|
}
|
|
@@ -16642,16 +16642,16 @@ async function basicPager(content) {
|
|
|
16642
16642
|
break;
|
|
16643
16643
|
}
|
|
16644
16644
|
const remaining = lines.length - currentLine;
|
|
16645
|
-
await new Promise((
|
|
16645
|
+
await new Promise((resolve11) => {
|
|
16646
16646
|
rl.question(`-- More (${remaining} lines) [Enter/q] --`, (answer) => {
|
|
16647
16647
|
if (answer.toLowerCase() === "q") {
|
|
16648
16648
|
rl.close();
|
|
16649
16649
|
process.exitCode = 0;
|
|
16650
|
-
|
|
16650
|
+
resolve11();
|
|
16651
16651
|
return;
|
|
16652
16652
|
}
|
|
16653
16653
|
process.stdout.write("\x1B[1A\x1B[2K");
|
|
16654
|
-
|
|
16654
|
+
resolve11();
|
|
16655
16655
|
});
|
|
16656
16656
|
});
|
|
16657
16657
|
}
|
|
@@ -18542,7 +18542,7 @@ class PathResolver {
|
|
|
18542
18542
|
}
|
|
18543
18543
|
static buildComponentPath(baseDir, component, global2) {
|
|
18544
18544
|
if (!PathResolver.isValidComponentName(component)) {
|
|
18545
|
-
throw new Error(`Invalid component name: "${component}" contains path traversal patterns. Valid names are simple directory names like "agents", "commands", "
|
|
18545
|
+
throw new Error(`Invalid component name: "${component}" contains path traversal patterns. Valid names are simple directory names like "agents", "commands", "rules", "skills", or "hooks".`);
|
|
18546
18546
|
}
|
|
18547
18547
|
const prefix = PathResolver.getPathPrefix(global2);
|
|
18548
18548
|
if (prefix) {
|
|
@@ -18620,7 +18620,7 @@ async function scanClaudeKitDirectory(directoryPath) {
|
|
|
18620
18620
|
const counts = {
|
|
18621
18621
|
agents: 0,
|
|
18622
18622
|
commands: 0,
|
|
18623
|
-
|
|
18623
|
+
rules: 0,
|
|
18624
18624
|
skills: 0
|
|
18625
18625
|
};
|
|
18626
18626
|
try {
|
|
@@ -18638,10 +18638,14 @@ async function scanClaudeKitDirectory(directoryPath) {
|
|
|
18638
18638
|
const commandFiles = await import_fs_extra.readdir(commandsPath);
|
|
18639
18639
|
counts.commands = commandFiles.filter((file) => file.endsWith(".md")).length;
|
|
18640
18640
|
}
|
|
18641
|
-
if (items.includes("
|
|
18641
|
+
if (items.includes("rules")) {
|
|
18642
|
+
const rulesPath = join2(directoryPath, "rules");
|
|
18643
|
+
const ruleFiles = await import_fs_extra.readdir(rulesPath);
|
|
18644
|
+
counts.rules = ruleFiles.filter((file) => file.endsWith(".md")).length;
|
|
18645
|
+
} else if (items.includes("workflows")) {
|
|
18642
18646
|
const workflowsPath = join2(directoryPath, "workflows");
|
|
18643
18647
|
const workflowFiles = await import_fs_extra.readdir(workflowsPath);
|
|
18644
|
-
counts.
|
|
18648
|
+
counts.rules = workflowFiles.filter((file) => file.endsWith(".md")).length;
|
|
18645
18649
|
}
|
|
18646
18650
|
if (items.includes("skills")) {
|
|
18647
18651
|
const skillsPath = join2(directoryPath, "skills");
|
|
@@ -18682,12 +18686,12 @@ async function getClaudeKitSetup(projectDir = process.cwd()) {
|
|
|
18682
18686
|
global: {
|
|
18683
18687
|
path: "",
|
|
18684
18688
|
metadata: null,
|
|
18685
|
-
components: { agents: 0, commands: 0,
|
|
18689
|
+
components: { agents: 0, commands: 0, rules: 0, skills: 0 }
|
|
18686
18690
|
},
|
|
18687
18691
|
project: {
|
|
18688
18692
|
path: "",
|
|
18689
18693
|
metadata: null,
|
|
18690
|
-
components: { agents: 0, commands: 0,
|
|
18694
|
+
components: { agents: 0, commands: 0, rules: 0, skills: 0 }
|
|
18691
18695
|
}
|
|
18692
18696
|
};
|
|
18693
18697
|
const globalDir = getGlobalInstallDir();
|
|
@@ -19310,16 +19314,16 @@ function checkComponentCounts(setup) {
|
|
|
19310
19314
|
const project = setup.project.components;
|
|
19311
19315
|
const totalAgents = global2.agents + project.agents;
|
|
19312
19316
|
const totalCommands = global2.commands + project.commands;
|
|
19313
|
-
const
|
|
19317
|
+
const totalRules = global2.rules + project.rules;
|
|
19314
19318
|
const totalSkills = global2.skills + project.skills;
|
|
19315
|
-
const totalComponents = totalAgents + totalCommands +
|
|
19319
|
+
const totalComponents = totalAgents + totalCommands + totalRules + totalSkills;
|
|
19316
19320
|
return {
|
|
19317
19321
|
id: "ck-component-counts",
|
|
19318
19322
|
name: "ClaudeKit Components",
|
|
19319
19323
|
group: "claudekit",
|
|
19320
19324
|
priority: "standard",
|
|
19321
19325
|
status: totalComponents > 0 ? "info" : "warn",
|
|
19322
|
-
message: totalComponents > 0 ? `${totalAgents} agents, ${totalCommands} commands, ${
|
|
19326
|
+
message: totalComponents > 0 ? `${totalAgents} agents, ${totalCommands} commands, ${totalRules} rules, ${totalSkills} skills` : "No components found",
|
|
19323
19327
|
suggestion: totalComponents === 0 ? "Install ClaudeKit: ck new --kit engineer" : undefined,
|
|
19324
19328
|
autoFixable: false
|
|
19325
19329
|
};
|
|
@@ -19680,7 +19684,7 @@ async function checkProjectConfigCompleteness(setup, projectDir) {
|
|
|
19680
19684
|
};
|
|
19681
19685
|
}
|
|
19682
19686
|
const projectClaudeDir = join11(projectDir, ".claude");
|
|
19683
|
-
const requiredDirs = ["agents", "commands", "
|
|
19687
|
+
const requiredDirs = ["agents", "commands", "skills"];
|
|
19684
19688
|
const missingDirs = [];
|
|
19685
19689
|
for (const dir of requiredDirs) {
|
|
19686
19690
|
const dirPath = join11(projectClaudeDir, dir);
|
|
@@ -19688,9 +19692,14 @@ async function checkProjectConfigCompleteness(setup, projectDir) {
|
|
|
19688
19692
|
missingDirs.push(dir);
|
|
19689
19693
|
}
|
|
19690
19694
|
}
|
|
19695
|
+
const hasRulesOrWorkflows = existsSync10(join11(projectClaudeDir, "rules")) || existsSync10(join11(projectClaudeDir, "workflows"));
|
|
19696
|
+
if (!hasRulesOrWorkflows) {
|
|
19697
|
+
missingDirs.push("rules");
|
|
19698
|
+
}
|
|
19691
19699
|
const files = await readdir3(projectClaudeDir).catch(() => []);
|
|
19692
19700
|
const hasOnlyClaudeMd = files.length === 1 && files.includes("CLAUDE.md");
|
|
19693
|
-
|
|
19701
|
+
const totalRequired = requiredDirs.length + 1;
|
|
19702
|
+
if (hasOnlyClaudeMd || missingDirs.length === totalRequired) {
|
|
19694
19703
|
return {
|
|
19695
19704
|
id: "ck-project-config-complete",
|
|
19696
19705
|
name: "Project Config Completeness",
|
|
@@ -19698,7 +19707,7 @@ async function checkProjectConfigCompleteness(setup, projectDir) {
|
|
|
19698
19707
|
priority: "standard",
|
|
19699
19708
|
status: "fail",
|
|
19700
19709
|
message: "Incomplete configuration",
|
|
19701
|
-
details: "Only CLAUDE.md found - missing agents, commands,
|
|
19710
|
+
details: "Only CLAUDE.md found - missing agents, commands, rules, skills",
|
|
19702
19711
|
suggestion: "Run 'ck init' to install complete ClaudeKit in project",
|
|
19703
19712
|
autoFixable: false
|
|
19704
19713
|
};
|
|
@@ -24657,9 +24666,9 @@ async function promptDirectorySelection(global2 = false) {
|
|
|
24657
24666
|
{ key: "agents", label: "Agents", pattern: prefix ? `${prefix}/agents` : "agents" },
|
|
24658
24667
|
{ key: "commands", label: "Commands", pattern: prefix ? `${prefix}/commands` : "commands" },
|
|
24659
24668
|
{
|
|
24660
|
-
key: "
|
|
24661
|
-
label: "
|
|
24662
|
-
pattern: prefix ? `${prefix}/
|
|
24669
|
+
key: "rules",
|
|
24670
|
+
label: "Rules",
|
|
24671
|
+
pattern: prefix ? `${prefix}/rules` : "rules"
|
|
24663
24672
|
},
|
|
24664
24673
|
{ key: "skills", label: "Skills", pattern: prefix ? `${prefix}/skills` : "skills" },
|
|
24665
24674
|
{ key: "hooks", label: "Hooks", pattern: prefix ? `${prefix}/hooks` : "hooks" }
|
|
@@ -24681,12 +24690,25 @@ async function promptDirectorySelection(global2 = false) {
|
|
|
24681
24690
|
}
|
|
24682
24691
|
return selectedCategories;
|
|
24683
24692
|
}
|
|
24684
|
-
async function promptFreshConfirmation(targetPath) {
|
|
24685
|
-
logger.warning("[!]
|
|
24693
|
+
async function promptFreshConfirmation(targetPath, analysis) {
|
|
24694
|
+
logger.warning("[!] Fresh installation will remove ClaudeKit files:");
|
|
24686
24695
|
logger.info(`Path: ${targetPath}`);
|
|
24687
|
-
|
|
24696
|
+
if (analysis?.hasMetadata) {
|
|
24697
|
+
const ckCount = analysis.ckFiles.length + analysis.ckModifiedFiles.length;
|
|
24698
|
+
const userCount = analysis.userFiles.length;
|
|
24699
|
+
logger.info(` Remove: ${ckCount} CK-owned files`);
|
|
24700
|
+
logger.info(` Preserve: ${userCount} user-created files`);
|
|
24701
|
+
if (userCount > 0) {
|
|
24702
|
+
const samples = analysis.userFiles.slice(0, 3).map((f3) => f3.path);
|
|
24703
|
+
const remaining = userCount - samples.length;
|
|
24704
|
+
logger.info(` Examples preserved: ${samples.join(", ")}${remaining > 0 ? ` (+${remaining} more)` : ""}`);
|
|
24705
|
+
}
|
|
24706
|
+
} else {
|
|
24707
|
+
logger.info(" Remove: commands/, agents/, skills/, rules/, hooks/");
|
|
24708
|
+
logger.info(" Preserve: settings.json, Claude Code data");
|
|
24709
|
+
}
|
|
24688
24710
|
const confirmation = await te({
|
|
24689
|
-
message: "Type 'yes' to confirm
|
|
24711
|
+
message: "Type 'yes' to confirm:",
|
|
24690
24712
|
placeholder: "yes",
|
|
24691
24713
|
validate: (value) => {
|
|
24692
24714
|
if (value.toLowerCase() !== "yes") {
|
|
@@ -24884,8 +24906,8 @@ class PromptsManager {
|
|
|
24884
24906
|
logger.info("You can install these manually later using npm install -g <package>");
|
|
24885
24907
|
}
|
|
24886
24908
|
}
|
|
24887
|
-
async promptFreshConfirmation(targetPath) {
|
|
24888
|
-
return promptFreshConfirmation(targetPath);
|
|
24909
|
+
async promptFreshConfirmation(targetPath, analysis) {
|
|
24910
|
+
return promptFreshConfirmation(targetPath, analysis);
|
|
24889
24911
|
}
|
|
24890
24912
|
async promptUpdateMode() {
|
|
24891
24913
|
return promptUpdateMode();
|
|
@@ -26440,7 +26462,7 @@ var import_ignore = __toESM(require_ignore(), 1);
|
|
|
26440
26462
|
// src/domains/installation/download/file-downloader.ts
|
|
26441
26463
|
init_logger();
|
|
26442
26464
|
init_output_manager();
|
|
26443
|
-
import { createWriteStream as createWriteStream2 } from "node:fs";
|
|
26465
|
+
import { createWriteStream as createWriteStream2, rmSync } from "node:fs";
|
|
26444
26466
|
import { mkdir as mkdir9 } from "node:fs/promises";
|
|
26445
26467
|
import { join as join28 } from "node:path";
|
|
26446
26468
|
|
|
@@ -26688,11 +26710,29 @@ class FileDownloader {
|
|
|
26688
26710
|
downloadedSize += value.length;
|
|
26689
26711
|
progressBar.update(downloadedSize);
|
|
26690
26712
|
}
|
|
26713
|
+
if (downloadedSize !== totalSize) {
|
|
26714
|
+
fileStream.end();
|
|
26715
|
+
await new Promise((resolve5) => fileStream.once("close", resolve5));
|
|
26716
|
+
try {
|
|
26717
|
+
rmSync(destPath, { force: true });
|
|
26718
|
+
} catch (cleanupError) {
|
|
26719
|
+
const errorMsg = cleanupError instanceof Error ? cleanupError.message : String(cleanupError);
|
|
26720
|
+
logger.debug(`Failed to clean up partial download ${destPath}: ${errorMsg}`);
|
|
26721
|
+
}
|
|
26722
|
+
throw new DownloadError(`Incomplete download: received ${formatBytes(downloadedSize)} of ${formatBytes(totalSize)}`);
|
|
26723
|
+
}
|
|
26691
26724
|
fileStream.end();
|
|
26692
26725
|
progressBar.complete(`Downloaded ${asset.name}`);
|
|
26693
26726
|
return destPath;
|
|
26694
26727
|
} catch (error) {
|
|
26695
|
-
fileStream.
|
|
26728
|
+
fileStream.end();
|
|
26729
|
+
await new Promise((resolve5) => fileStream.once("close", resolve5));
|
|
26730
|
+
try {
|
|
26731
|
+
rmSync(destPath, { force: true });
|
|
26732
|
+
} catch (cleanupError) {
|
|
26733
|
+
const errorMsg = cleanupError instanceof Error ? cleanupError.message : String(cleanupError);
|
|
26734
|
+
logger.debug(`Failed to clean up partial download ${destPath}: ${errorMsg}`);
|
|
26735
|
+
}
|
|
26696
26736
|
throw error;
|
|
26697
26737
|
}
|
|
26698
26738
|
} catch (error) {
|
|
@@ -26742,11 +26782,19 @@ class FileDownloader {
|
|
|
26742
26782
|
progressBar.update(downloadedSize);
|
|
26743
26783
|
}
|
|
26744
26784
|
}
|
|
26745
|
-
fileStream.end();
|
|
26746
26785
|
const expectedSize = Number(response.headers.get("content-length"));
|
|
26747
26786
|
if (expectedSize > 0 && downloadedSize !== expectedSize) {
|
|
26787
|
+
fileStream.end();
|
|
26788
|
+
await new Promise((resolve5) => fileStream.once("close", resolve5));
|
|
26789
|
+
try {
|
|
26790
|
+
rmSync(destPath, { force: true });
|
|
26791
|
+
} catch (cleanupError) {
|
|
26792
|
+
const errorMsg = cleanupError instanceof Error ? cleanupError.message : String(cleanupError);
|
|
26793
|
+
logger.debug(`Failed to clean up partial download ${destPath}: ${errorMsg}`);
|
|
26794
|
+
}
|
|
26748
26795
|
throw new DownloadError(`Incomplete download: received ${formatBytes(downloadedSize)} of ${formatBytes(expectedSize)}`);
|
|
26749
26796
|
}
|
|
26797
|
+
fileStream.end();
|
|
26750
26798
|
if (progressBar) {
|
|
26751
26799
|
progressBar.complete(`Downloaded ${name}`);
|
|
26752
26800
|
} else {
|
|
@@ -26754,7 +26802,14 @@ class FileDownloader {
|
|
|
26754
26802
|
}
|
|
26755
26803
|
return destPath;
|
|
26756
26804
|
} catch (error) {
|
|
26757
|
-
fileStream.
|
|
26805
|
+
fileStream.end();
|
|
26806
|
+
await new Promise((resolve5) => fileStream.once("close", resolve5));
|
|
26807
|
+
try {
|
|
26808
|
+
rmSync(destPath, { force: true });
|
|
26809
|
+
} catch (cleanupError) {
|
|
26810
|
+
const errorMsg = cleanupError instanceof Error ? cleanupError.message : String(cleanupError);
|
|
26811
|
+
logger.debug(`Failed to clean up partial download ${destPath}: ${errorMsg}`);
|
|
26812
|
+
}
|
|
26758
26813
|
throw error;
|
|
26759
26814
|
}
|
|
26760
26815
|
}
|
|
@@ -34468,7 +34523,7 @@ async function getUninstallManifest(claudeDir, kit) {
|
|
|
34468
34523
|
const installedFiles = detection.metadata.installedFiles || [];
|
|
34469
34524
|
const hasFiles = legacyFiles2.length > 0 || installedFiles.length > 0;
|
|
34470
34525
|
if (!hasFiles) {
|
|
34471
|
-
const legacyDirs2 = ["commands", "agents", "skills", "workflows", "hooks", "scripts"];
|
|
34526
|
+
const legacyDirs2 = ["commands", "agents", "skills", "rules", "workflows", "hooks", "scripts"];
|
|
34472
34527
|
const legacyFileList = ["metadata.json"];
|
|
34473
34528
|
return {
|
|
34474
34529
|
filesToRemove: [...legacyDirs2, ...legacyFileList],
|
|
@@ -34486,7 +34541,7 @@ async function getUninstallManifest(claudeDir, kit) {
|
|
|
34486
34541
|
remainingKits: []
|
|
34487
34542
|
};
|
|
34488
34543
|
}
|
|
34489
|
-
const legacyDirs = ["commands", "agents", "skills", "workflows", "hooks", "scripts"];
|
|
34544
|
+
const legacyDirs = ["commands", "agents", "skills", "rules", "workflows", "hooks", "scripts"];
|
|
34490
34545
|
const legacyFiles = ["metadata.json"];
|
|
34491
34546
|
return {
|
|
34492
34547
|
filesToRemove: [...legacyDirs, ...legacyFiles],
|
|
@@ -40330,7 +40385,7 @@ Optional: DISCORD_WEBHOOK_URL, TELEGRAM_BOT_TOKEN`, "Configuration skipped");
|
|
|
40330
40385
|
}
|
|
40331
40386
|
// src/commands/init/phases/selection-handler.ts
|
|
40332
40387
|
import { mkdir as mkdir20 } from "node:fs/promises";
|
|
40333
|
-
import { join as join66, resolve as
|
|
40388
|
+
import { join as join66, resolve as resolve8 } from "node:path";
|
|
40334
40389
|
|
|
40335
40390
|
// src/domains/github/kit-access-checker.ts
|
|
40336
40391
|
init_logger();
|
|
@@ -40457,38 +40512,196 @@ async function runPreflightChecks() {
|
|
|
40457
40512
|
}
|
|
40458
40513
|
|
|
40459
40514
|
// src/domains/installation/fresh-installer.ts
|
|
40515
|
+
import { existsSync as existsSync19, readdirSync, rmSync as rmSync2, rmdirSync, unlinkSync as unlinkSync3 } from "node:fs";
|
|
40516
|
+
import { dirname as dirname9, join as join65, resolve as resolve7 } from "node:path";
|
|
40460
40517
|
init_logger();
|
|
40461
|
-
import { join as join65 } from "node:path";
|
|
40462
40518
|
var import_fs_extra29 = __toESM(require_lib(), 1);
|
|
40463
|
-
var CLAUDEKIT_SUBDIRECTORIES = ["commands", "agents", "skills", "
|
|
40519
|
+
var CLAUDEKIT_SUBDIRECTORIES = ["commands", "agents", "skills", "rules", "hooks"];
|
|
40520
|
+
async function analyzeFreshInstallation(claudeDir) {
|
|
40521
|
+
const metadata = await readManifest(claudeDir);
|
|
40522
|
+
if (!metadata) {
|
|
40523
|
+
return {
|
|
40524
|
+
ckFiles: [],
|
|
40525
|
+
ckModifiedFiles: [],
|
|
40526
|
+
userFiles: [],
|
|
40527
|
+
hasMetadata: false
|
|
40528
|
+
};
|
|
40529
|
+
}
|
|
40530
|
+
const allFiles = getAllTrackedFiles(metadata);
|
|
40531
|
+
if (allFiles.length === 0) {
|
|
40532
|
+
return {
|
|
40533
|
+
ckFiles: [],
|
|
40534
|
+
ckModifiedFiles: [],
|
|
40535
|
+
userFiles: [],
|
|
40536
|
+
hasMetadata: false
|
|
40537
|
+
};
|
|
40538
|
+
}
|
|
40539
|
+
const ckFiles = [];
|
|
40540
|
+
const ckModifiedFiles = [];
|
|
40541
|
+
const userFiles = [];
|
|
40542
|
+
for (const file of allFiles) {
|
|
40543
|
+
switch (file.ownership) {
|
|
40544
|
+
case "ck":
|
|
40545
|
+
ckFiles.push(file);
|
|
40546
|
+
break;
|
|
40547
|
+
case "ck-modified":
|
|
40548
|
+
ckModifiedFiles.push(file);
|
|
40549
|
+
break;
|
|
40550
|
+
case "user":
|
|
40551
|
+
userFiles.push(file);
|
|
40552
|
+
break;
|
|
40553
|
+
}
|
|
40554
|
+
}
|
|
40555
|
+
return {
|
|
40556
|
+
ckFiles,
|
|
40557
|
+
ckModifiedFiles,
|
|
40558
|
+
userFiles,
|
|
40559
|
+
hasMetadata: true
|
|
40560
|
+
};
|
|
40561
|
+
}
|
|
40562
|
+
function cleanupEmptyDirectories(filePath, claudeDir) {
|
|
40563
|
+
const normalizedClaudeDir = resolve7(claudeDir);
|
|
40564
|
+
let currentDir = resolve7(dirname9(filePath));
|
|
40565
|
+
while (currentDir !== normalizedClaudeDir && currentDir.startsWith(normalizedClaudeDir)) {
|
|
40566
|
+
try {
|
|
40567
|
+
const entries = readdirSync(currentDir);
|
|
40568
|
+
if (entries.length === 0) {
|
|
40569
|
+
rmdirSync(currentDir);
|
|
40570
|
+
logger.debug(`Removed empty directory: ${currentDir}`);
|
|
40571
|
+
currentDir = resolve7(dirname9(currentDir));
|
|
40572
|
+
} else {
|
|
40573
|
+
break;
|
|
40574
|
+
}
|
|
40575
|
+
} catch (error) {
|
|
40576
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
40577
|
+
logger.debug(`Could not remove directory ${currentDir}: ${errorMsg}`);
|
|
40578
|
+
break;
|
|
40579
|
+
}
|
|
40580
|
+
}
|
|
40581
|
+
}
|
|
40582
|
+
async function removeFilesByOwnership(claudeDir, analysis, includeModified) {
|
|
40583
|
+
const removedFiles = [];
|
|
40584
|
+
const preservedFiles = [];
|
|
40585
|
+
const filesToRemove = includeModified ? [...analysis.ckFiles, ...analysis.ckModifiedFiles] : analysis.ckFiles;
|
|
40586
|
+
const filesToPreserve = includeModified ? analysis.userFiles : [...analysis.ckModifiedFiles, ...analysis.userFiles];
|
|
40587
|
+
for (const file of filesToRemove) {
|
|
40588
|
+
const fullPath = join65(claudeDir, file.path);
|
|
40589
|
+
try {
|
|
40590
|
+
if (existsSync19(fullPath)) {
|
|
40591
|
+
unlinkSync3(fullPath);
|
|
40592
|
+
removedFiles.push(file.path);
|
|
40593
|
+
logger.debug(`Removed: ${file.path}`);
|
|
40594
|
+
cleanupEmptyDirectories(fullPath, claudeDir);
|
|
40595
|
+
}
|
|
40596
|
+
} catch (error) {
|
|
40597
|
+
logger.debug(`Failed to remove ${file.path}: ${error}`);
|
|
40598
|
+
}
|
|
40599
|
+
}
|
|
40600
|
+
for (const file of filesToPreserve) {
|
|
40601
|
+
preservedFiles.push(file.path);
|
|
40602
|
+
}
|
|
40603
|
+
await updateMetadataAfterFresh(claudeDir, removedFiles);
|
|
40604
|
+
return {
|
|
40605
|
+
success: true,
|
|
40606
|
+
removedCount: removedFiles.length,
|
|
40607
|
+
preservedCount: preservedFiles.length,
|
|
40608
|
+
removedFiles,
|
|
40609
|
+
preservedFiles
|
|
40610
|
+
};
|
|
40611
|
+
}
|
|
40612
|
+
async function updateMetadataAfterFresh(claudeDir, removedFiles) {
|
|
40613
|
+
const metadataPath = join65(claudeDir, "metadata.json");
|
|
40614
|
+
if (!await import_fs_extra29.pathExists(metadataPath)) {
|
|
40615
|
+
return;
|
|
40616
|
+
}
|
|
40617
|
+
let content;
|
|
40618
|
+
try {
|
|
40619
|
+
content = await import_fs_extra29.readFile(metadataPath, "utf-8");
|
|
40620
|
+
} catch (readError) {
|
|
40621
|
+
logger.warning(`Failed to read metadata.json: ${readError instanceof Error ? readError.message : String(readError)}`);
|
|
40622
|
+
return;
|
|
40623
|
+
}
|
|
40624
|
+
let metadata;
|
|
40625
|
+
try {
|
|
40626
|
+
metadata = JSON.parse(content);
|
|
40627
|
+
} catch (parseError) {
|
|
40628
|
+
logger.warning(`Failed to parse metadata.json: ${parseError instanceof Error ? parseError.message : String(parseError)}`);
|
|
40629
|
+
logger.info("Recommendation: Run 'ck init' to rebuild metadata");
|
|
40630
|
+
return;
|
|
40631
|
+
}
|
|
40632
|
+
const removedSet = new Set(removedFiles);
|
|
40633
|
+
if (metadata.kits) {
|
|
40634
|
+
for (const kitName of Object.keys(metadata.kits)) {
|
|
40635
|
+
const kit = metadata.kits[kitName];
|
|
40636
|
+
if (kit?.files) {
|
|
40637
|
+
kit.files = kit.files.filter((f3) => !removedSet.has(f3.path));
|
|
40638
|
+
}
|
|
40639
|
+
}
|
|
40640
|
+
}
|
|
40641
|
+
if (metadata.files) {
|
|
40642
|
+
metadata.files = metadata.files.filter((f3) => !removedSet.has(f3.path));
|
|
40643
|
+
}
|
|
40644
|
+
try {
|
|
40645
|
+
await import_fs_extra29.writeFile(metadataPath, JSON.stringify(metadata, null, 2));
|
|
40646
|
+
logger.debug(`Updated metadata.json, removed ${removedFiles.length} file entries`);
|
|
40647
|
+
} catch (writeError) {
|
|
40648
|
+
logger.warning(`Failed to write metadata.json: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
40649
|
+
logger.info("Recommendation: Check file permissions and run 'ck init' to rebuild metadata");
|
|
40650
|
+
}
|
|
40651
|
+
}
|
|
40652
|
+
async function removeSubdirectoriesFallback(claudeDir) {
|
|
40653
|
+
const removedFiles = [];
|
|
40654
|
+
let removedDirCount = 0;
|
|
40655
|
+
for (const subdir of CLAUDEKIT_SUBDIRECTORIES) {
|
|
40656
|
+
const subdirPath = join65(claudeDir, subdir);
|
|
40657
|
+
if (await import_fs_extra29.pathExists(subdirPath)) {
|
|
40658
|
+
rmSync2(subdirPath, { recursive: true, force: true });
|
|
40659
|
+
removedDirCount++;
|
|
40660
|
+
removedFiles.push(`${subdir}/ (entire directory)`);
|
|
40661
|
+
logger.debug(`Removed subdirectory: ${subdir}/`);
|
|
40662
|
+
}
|
|
40663
|
+
}
|
|
40664
|
+
const metadataPath = join65(claudeDir, "metadata.json");
|
|
40665
|
+
if (await import_fs_extra29.pathExists(metadataPath)) {
|
|
40666
|
+
unlinkSync3(metadataPath);
|
|
40667
|
+
removedFiles.push("metadata.json");
|
|
40668
|
+
}
|
|
40669
|
+
return {
|
|
40670
|
+
success: true,
|
|
40671
|
+
removedCount: removedDirCount,
|
|
40672
|
+
preservedCount: 0,
|
|
40673
|
+
removedFiles,
|
|
40674
|
+
preservedFiles: []
|
|
40675
|
+
};
|
|
40676
|
+
}
|
|
40464
40677
|
async function handleFreshInstallation(claudeDir, prompts) {
|
|
40465
40678
|
if (!await import_fs_extra29.pathExists(claudeDir)) {
|
|
40466
40679
|
logger.info(".claude directory does not exist, proceeding with fresh installation");
|
|
40467
40680
|
return true;
|
|
40468
40681
|
}
|
|
40469
|
-
const
|
|
40682
|
+
const analysis = await analyzeFreshInstallation(claudeDir);
|
|
40683
|
+
const confirmed = await prompts.promptFreshConfirmation(claudeDir, analysis);
|
|
40470
40684
|
if (!confirmed) {
|
|
40471
40685
|
logger.info("Fresh installation cancelled");
|
|
40472
40686
|
return false;
|
|
40473
40687
|
}
|
|
40474
|
-
|
|
40475
|
-
const spinner = createSpinner("Removing ClaudeKit subdirectories...").start();
|
|
40688
|
+
const spinner = createSpinner("Removing ClaudeKit files...").start();
|
|
40476
40689
|
try {
|
|
40477
|
-
|
|
40478
|
-
|
|
40479
|
-
|
|
40480
|
-
|
|
40481
|
-
|
|
40482
|
-
|
|
40483
|
-
|
|
40484
|
-
|
|
40485
|
-
|
|
40690
|
+
let result;
|
|
40691
|
+
if (analysis.hasMetadata && (analysis.ckFiles.length > 0 || analysis.ckModifiedFiles.length > 0)) {
|
|
40692
|
+
result = await removeFilesByOwnership(claudeDir, analysis, true);
|
|
40693
|
+
spinner.succeed(`Removed ${result.removedCount} CK files, preserved ${result.preservedCount} user files`);
|
|
40694
|
+
} else {
|
|
40695
|
+
result = await removeSubdirectoriesFallback(claudeDir);
|
|
40696
|
+
spinner.succeed(`Removed ${result.removedCount} ClaudeKit directories`);
|
|
40697
|
+
}
|
|
40698
|
+
if (result.preservedCount > 0) {
|
|
40699
|
+
logger.verbose(`Preserved user files: ${result.preservedFiles.slice(0, 5).join(", ")}${result.preservedFiles.length > 5 ? ` and ${result.preservedFiles.length - 5} more` : ""}`);
|
|
40486
40700
|
}
|
|
40487
|
-
spinner.succeed(`Successfully removed ${removedCount} ClaudeKit subdirectories (preserving user configs)`);
|
|
40488
40701
|
return true;
|
|
40489
40702
|
} catch (error) {
|
|
40490
|
-
spinner.fail("Failed to remove ClaudeKit
|
|
40491
|
-
throw new Error(`Failed to remove
|
|
40703
|
+
spinner.fail("Failed to remove ClaudeKit files");
|
|
40704
|
+
throw new Error(`Failed to remove files: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
40492
40705
|
}
|
|
40493
40706
|
}
|
|
40494
40707
|
|
|
@@ -40517,6 +40730,18 @@ async function handleSelection(ctx) {
|
|
|
40517
40730
|
release: release2
|
|
40518
40731
|
};
|
|
40519
40732
|
}
|
|
40733
|
+
const downloadMethods = [];
|
|
40734
|
+
if (ctx.options.useGit)
|
|
40735
|
+
downloadMethods.push("--use-git");
|
|
40736
|
+
if (ctx.options.archive)
|
|
40737
|
+
downloadMethods.push("--archive");
|
|
40738
|
+
if (ctx.options.kitPath)
|
|
40739
|
+
downloadMethods.push("--kit-path");
|
|
40740
|
+
if (downloadMethods.length > 1) {
|
|
40741
|
+
logger.error(`Mutually exclusive download methods: ${downloadMethods.join(", ")}`);
|
|
40742
|
+
logger.info("Use only one of: --use-git, --archive, or --kit-path");
|
|
40743
|
+
return { ...ctx, cancelled: true };
|
|
40744
|
+
}
|
|
40520
40745
|
const config = await ConfigManager.get();
|
|
40521
40746
|
let accessibleKits;
|
|
40522
40747
|
if (!ctx.options.useGit && !ctx.options.kitPath && !ctx.options.archive) {
|
|
@@ -40652,7 +40877,7 @@ async function handleSelection(ctx) {
|
|
|
40652
40877
|
}
|
|
40653
40878
|
}
|
|
40654
40879
|
}
|
|
40655
|
-
const resolvedDir =
|
|
40880
|
+
const resolvedDir = resolve8(targetDir);
|
|
40656
40881
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
40657
40882
|
if (!ctx.options.global && PathResolver.isLocalSameAsGlobal(resolvedDir)) {
|
|
40658
40883
|
logger.warning("You're at HOME directory. Installing here modifies your GLOBAL ClaudeKit.");
|
|
@@ -40724,15 +40949,16 @@ async function handleSelection(ctx) {
|
|
|
40724
40949
|
return { ...ctx, cancelled: true };
|
|
40725
40950
|
}
|
|
40726
40951
|
}
|
|
40727
|
-
const
|
|
40952
|
+
const isOfflineMode = !!(ctx.options.kitPath || ctx.options.archive);
|
|
40953
|
+
const github = isOfflineMode ? null : new GitHubClient;
|
|
40728
40954
|
let selectedVersion = ctx.options.release;
|
|
40729
|
-
if (!selectedVersion && ctx.isNonInteractive && !ctx.options.yes) {
|
|
40955
|
+
if (!selectedVersion && ctx.isNonInteractive && !ctx.options.yes && !isOfflineMode) {
|
|
40730
40956
|
throw new Error("Non-interactive mode requires either: --release <tag> OR --yes (uses latest)");
|
|
40731
40957
|
}
|
|
40732
|
-
if (!selectedVersion && ctx.options.yes) {
|
|
40958
|
+
if (!selectedVersion && ctx.options.yes && !isOfflineMode) {
|
|
40733
40959
|
logger.info("Using latest stable version (--yes flag)");
|
|
40734
40960
|
}
|
|
40735
|
-
if (!selectedVersion && !ctx.isNonInteractive) {
|
|
40961
|
+
if (!selectedVersion && !ctx.isNonInteractive && !isOfflineMode) {
|
|
40736
40962
|
logger.info("Fetching available versions...");
|
|
40737
40963
|
let currentVersion = null;
|
|
40738
40964
|
try {
|
|
@@ -40765,7 +40991,13 @@ async function handleSelection(ctx) {
|
|
|
40765
40991
|
}
|
|
40766
40992
|
}
|
|
40767
40993
|
let release;
|
|
40768
|
-
if (
|
|
40994
|
+
if (isOfflineMode) {
|
|
40995
|
+
release = undefined;
|
|
40996
|
+
logger.verbose("Offline mode - skipping release fetch", {
|
|
40997
|
+
kitPath: ctx.options.kitPath,
|
|
40998
|
+
archive: ctx.options.archive
|
|
40999
|
+
});
|
|
41000
|
+
} else if (ctx.options.useGit && selectedVersion) {
|
|
40769
41001
|
release = {
|
|
40770
41002
|
id: 0,
|
|
40771
41003
|
tag_name: selectedVersion,
|
|
@@ -40777,9 +41009,9 @@ async function handleSelection(ctx) {
|
|
|
40777
41009
|
assets: []
|
|
40778
41010
|
};
|
|
40779
41011
|
logger.verbose("Using git clone mode with tag", { tag: selectedVersion });
|
|
40780
|
-
} else if (selectedVersion) {
|
|
41012
|
+
} else if (selectedVersion && github) {
|
|
40781
41013
|
release = await github.getReleaseByTag(kit, selectedVersion);
|
|
40782
|
-
} else {
|
|
41014
|
+
} else if (github) {
|
|
40783
41015
|
if (ctx.options.beta) {
|
|
40784
41016
|
logger.info("Fetching latest beta release...");
|
|
40785
41017
|
} else {
|
|
@@ -40804,8 +41036,8 @@ async function handleSelection(ctx) {
|
|
|
40804
41036
|
};
|
|
40805
41037
|
}
|
|
40806
41038
|
// src/commands/init/phases/sync-handler.ts
|
|
40807
|
-
import { copyFile as copyFile6, mkdir as mkdir21, open, rename as rename3, stat as stat10, unlink as unlink7, writeFile as
|
|
40808
|
-
import { dirname as
|
|
41039
|
+
import { copyFile as copyFile6, mkdir as mkdir21, open, rename as rename3, stat as stat10, unlink as unlink7, writeFile as writeFile20 } from "node:fs/promises";
|
|
41040
|
+
import { dirname as dirname10, join as join67, resolve as resolve9 } from "node:path";
|
|
40809
41041
|
init_logger();
|
|
40810
41042
|
var import_fs_extra31 = __toESM(require_lib(), 1);
|
|
40811
41043
|
var import_picocolors19 = __toESM(require_picocolors(), 1);
|
|
@@ -40813,7 +41045,7 @@ async function handleSync(ctx) {
|
|
|
40813
41045
|
if (!ctx.options.sync) {
|
|
40814
41046
|
return ctx;
|
|
40815
41047
|
}
|
|
40816
|
-
const resolvedDir = ctx.options.global ? PathResolver.getGlobalKitDir() :
|
|
41048
|
+
const resolvedDir = ctx.options.global ? PathResolver.getGlobalKitDir() : resolve9(ctx.options.dir || ".");
|
|
40817
41049
|
const claudeDir = ctx.options.global ? resolvedDir : join67(resolvedDir, ".claude");
|
|
40818
41050
|
if (!await import_fs_extra31.pathExists(claudeDir)) {
|
|
40819
41051
|
logger.error("Cannot sync: no .claude directory found");
|
|
@@ -40923,7 +41155,7 @@ async function acquireSyncLock(global3) {
|
|
|
40923
41155
|
const lockPath = join67(cacheDir, ".sync-lock");
|
|
40924
41156
|
const startTime = Date.now();
|
|
40925
41157
|
const lockTimeout = getLockTimeout();
|
|
40926
|
-
await mkdir21(
|
|
41158
|
+
await mkdir21(dirname10(lockPath), { recursive: true });
|
|
40927
41159
|
while (Date.now() - startTime < lockTimeout) {
|
|
40928
41160
|
try {
|
|
40929
41161
|
const handle = await open(lockPath, "wx");
|
|
@@ -40947,7 +41179,7 @@ async function acquireSyncLock(global3) {
|
|
|
40947
41179
|
}
|
|
40948
41180
|
logger.debug(`Lock stat failed: ${statError}`);
|
|
40949
41181
|
}
|
|
40950
|
-
await new Promise((
|
|
41182
|
+
await new Promise((resolve10) => setTimeout(resolve10, 100));
|
|
40951
41183
|
continue;
|
|
40952
41184
|
}
|
|
40953
41185
|
throw err;
|
|
@@ -41066,7 +41298,7 @@ async function executeSyncMerge(ctx) {
|
|
|
41066
41298
|
try {
|
|
41067
41299
|
const tempPath = `${currentPath}.tmp.${Date.now()}`;
|
|
41068
41300
|
try {
|
|
41069
|
-
await
|
|
41301
|
+
await writeFile20(tempPath, result.result, "utf-8");
|
|
41070
41302
|
await rename3(tempPath, currentPath);
|
|
41071
41303
|
} catch (atomicError) {
|
|
41072
41304
|
await unlink7(tempPath).catch(() => {});
|
|
@@ -41252,7 +41484,7 @@ async function renameFolders(dirsToRename, extractDir, options) {
|
|
|
41252
41484
|
// src/services/transformers/folder-transform/path-replacer.ts
|
|
41253
41485
|
init_logger();
|
|
41254
41486
|
init_types2();
|
|
41255
|
-
import { readFile as
|
|
41487
|
+
import { readFile as readFile24, readdir as readdir23, writeFile as writeFile21 } from "node:fs/promises";
|
|
41256
41488
|
import { join as join69, relative as relative13 } from "node:path";
|
|
41257
41489
|
var TRANSFORMABLE_FILE_PATTERNS = [
|
|
41258
41490
|
".md",
|
|
@@ -41319,7 +41551,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
41319
41551
|
if (!shouldTransform)
|
|
41320
41552
|
continue;
|
|
41321
41553
|
try {
|
|
41322
|
-
const content = await
|
|
41554
|
+
const content = await readFile24(fullPath, "utf-8");
|
|
41323
41555
|
let newContent = content;
|
|
41324
41556
|
let changeCount = 0;
|
|
41325
41557
|
for (const { regex: regex2, replacement } of compiledReplacements) {
|
|
@@ -41335,7 +41567,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
41335
41567
|
if (options.dryRun) {
|
|
41336
41568
|
logger.debug(`[dry-run] Would update ${relative13(dir, fullPath)}: ${changeCount} replacement(s)`);
|
|
41337
41569
|
} else {
|
|
41338
|
-
await
|
|
41570
|
+
await writeFile21(fullPath, newContent, "utf-8");
|
|
41339
41571
|
logger.debug(`Updated ${relative13(dir, fullPath)}: ${changeCount} replacement(s)`);
|
|
41340
41572
|
}
|
|
41341
41573
|
filesChanged++;
|
|
@@ -41441,7 +41673,7 @@ async function transformFolderPaths(extractDir, folders, options = {}) {
|
|
|
41441
41673
|
|
|
41442
41674
|
// src/services/transformers/global-path-transformer.ts
|
|
41443
41675
|
init_logger();
|
|
41444
|
-
import { readFile as
|
|
41676
|
+
import { readFile as readFile25, readdir as readdir24, writeFile as writeFile22 } from "node:fs/promises";
|
|
41445
41677
|
import { platform as platform12 } from "node:os";
|
|
41446
41678
|
import { extname as extname3, join as join70 } from "node:path";
|
|
41447
41679
|
var IS_WINDOWS4 = platform12() === "win32";
|
|
@@ -41561,10 +41793,10 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
|
41561
41793
|
await processDirectory2(fullPath);
|
|
41562
41794
|
} else if (entry.isFile() && shouldTransformFile3(entry.name)) {
|
|
41563
41795
|
try {
|
|
41564
|
-
const content = await
|
|
41796
|
+
const content = await readFile25(fullPath, "utf-8");
|
|
41565
41797
|
const { transformed, changes } = transformContent(content);
|
|
41566
41798
|
if (changes > 0) {
|
|
41567
|
-
await
|
|
41799
|
+
await writeFile22(fullPath, transformed, "utf-8");
|
|
41568
41800
|
filesTransformed++;
|
|
41569
41801
|
totalChanges += changes;
|
|
41570
41802
|
if (options.verbose) {
|
|
@@ -41819,7 +42051,7 @@ init_types2();
|
|
|
41819
42051
|
var import_picocolors20 = __toESM(require_picocolors(), 1);
|
|
41820
42052
|
|
|
41821
42053
|
// src/commands/new/phases/directory-setup.ts
|
|
41822
|
-
import { resolve as
|
|
42054
|
+
import { resolve as resolve10 } from "node:path";
|
|
41823
42055
|
init_logger();
|
|
41824
42056
|
init_types2();
|
|
41825
42057
|
var import_fs_extra33 = __toESM(require_lib(), 1);
|
|
@@ -41903,7 +42135,7 @@ async function directorySetup(validOptions, prompts) {
|
|
|
41903
42135
|
targetDir = await prompts.getDirectory(targetDir);
|
|
41904
42136
|
}
|
|
41905
42137
|
}
|
|
41906
|
-
const resolvedDir =
|
|
42138
|
+
const resolvedDir = resolve10(targetDir);
|
|
41907
42139
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
41908
42140
|
if (PathResolver.isLocalSameAsGlobal(resolvedDir)) {
|
|
41909
42141
|
logger.warning("You're creating a project at HOME directory.");
|
|
@@ -42244,14 +42476,14 @@ async function detectInstallations() {
|
|
|
42244
42476
|
}
|
|
42245
42477
|
|
|
42246
42478
|
// src/commands/uninstall/removal-handler.ts
|
|
42247
|
-
import { readdirSync as
|
|
42479
|
+
import { readdirSync as readdirSync3, rmSync as rmSync4 } from "node:fs";
|
|
42248
42480
|
import { join as join74 } from "node:path";
|
|
42249
42481
|
init_logger();
|
|
42250
42482
|
var import_fs_extra35 = __toESM(require_lib(), 1);
|
|
42251
42483
|
|
|
42252
42484
|
// src/commands/uninstall/analysis-handler.ts
|
|
42253
|
-
import { readdirSync, rmSync } from "node:fs";
|
|
42254
|
-
import { dirname as
|
|
42485
|
+
import { readdirSync as readdirSync2, rmSync as rmSync3 } from "node:fs";
|
|
42486
|
+
import { dirname as dirname11, join as join73 } from "node:path";
|
|
42255
42487
|
init_logger();
|
|
42256
42488
|
var import_picocolors21 = __toESM(require_picocolors(), 1);
|
|
42257
42489
|
function classifyFileByOwnership(ownership, forceOverwrite, deleteReason) {
|
|
@@ -42266,17 +42498,17 @@ function classifyFileByOwnership(ownership, forceOverwrite, deleteReason) {
|
|
|
42266
42498
|
}
|
|
42267
42499
|
return { action: "preserve", reason: "user-created" };
|
|
42268
42500
|
}
|
|
42269
|
-
async function
|
|
42501
|
+
async function cleanupEmptyDirectories2(filePath, installationRoot) {
|
|
42270
42502
|
let cleaned = 0;
|
|
42271
|
-
let currentDir =
|
|
42503
|
+
let currentDir = dirname11(filePath);
|
|
42272
42504
|
while (currentDir !== installationRoot && currentDir.startsWith(installationRoot)) {
|
|
42273
42505
|
try {
|
|
42274
|
-
const entries =
|
|
42506
|
+
const entries = readdirSync2(currentDir);
|
|
42275
42507
|
if (entries.length === 0) {
|
|
42276
|
-
|
|
42508
|
+
rmSync3(currentDir, { recursive: true });
|
|
42277
42509
|
cleaned++;
|
|
42278
42510
|
logger.debug(`Removed empty directory: ${currentDir}`);
|
|
42279
|
-
currentDir =
|
|
42511
|
+
currentDir = dirname11(currentDir);
|
|
42280
42512
|
} else {
|
|
42281
42513
|
break;
|
|
42282
42514
|
}
|
|
@@ -42393,16 +42625,16 @@ async function removeInstallations(installations, options) {
|
|
|
42393
42625
|
await import_fs_extra35.remove(filePath);
|
|
42394
42626
|
removedCount++;
|
|
42395
42627
|
logger.debug(`Removed: ${item.path}`);
|
|
42396
|
-
cleanedDirs += await
|
|
42628
|
+
cleanedDirs += await cleanupEmptyDirectories2(filePath, installation.path);
|
|
42397
42629
|
}
|
|
42398
42630
|
}
|
|
42399
42631
|
if (options.kit && analysis.remainingKits.length > 0) {
|
|
42400
42632
|
await ManifestWriter.removeKitFromManifest(installation.path, options.kit);
|
|
42401
42633
|
}
|
|
42402
42634
|
try {
|
|
42403
|
-
const remaining =
|
|
42635
|
+
const remaining = readdirSync3(installation.path);
|
|
42404
42636
|
if (remaining.length === 0) {
|
|
42405
|
-
|
|
42637
|
+
rmSync4(installation.path, { recursive: true });
|
|
42406
42638
|
logger.debug(`Removed empty installation directory: ${installation.path}`);
|
|
42407
42639
|
}
|
|
42408
42640
|
} catch {}
|
|
@@ -42706,7 +42938,7 @@ var import_fs_extra36 = __toESM(require_lib(), 1);
|
|
|
42706
42938
|
// package.json
|
|
42707
42939
|
var package_default = {
|
|
42708
42940
|
name: "claudekit-cli",
|
|
42709
|
-
version: "3.
|
|
42941
|
+
version: "3.27.0",
|
|
42710
42942
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
42711
42943
|
type: "module",
|
|
42712
42944
|
repository: {
|
|
@@ -43184,7 +43416,7 @@ function registerCommands(cli) {
|
|
|
43184
43416
|
}
|
|
43185
43417
|
|
|
43186
43418
|
// src/cli/version-display.ts
|
|
43187
|
-
import { existsSync as
|
|
43419
|
+
import { existsSync as existsSync21, readFileSync as readFileSync7 } from "node:fs";
|
|
43188
43420
|
import { join as join77 } from "node:path";
|
|
43189
43421
|
|
|
43190
43422
|
// src/domains/versioning/checking/version-utils.ts
|
|
@@ -43210,8 +43442,8 @@ init_types2();
|
|
|
43210
43442
|
|
|
43211
43443
|
// src/domains/versioning/version-cache.ts
|
|
43212
43444
|
init_logger();
|
|
43213
|
-
import { existsSync as
|
|
43214
|
-
import { mkdir as mkdir22, readFile as
|
|
43445
|
+
import { existsSync as existsSync20 } from "node:fs";
|
|
43446
|
+
import { mkdir as mkdir22, readFile as readFile27, writeFile as writeFile23 } from "node:fs/promises";
|
|
43215
43447
|
import { join as join76 } from "node:path";
|
|
43216
43448
|
class VersionCacheManager {
|
|
43217
43449
|
static CACHE_FILENAME = "version-check.json";
|
|
@@ -43223,11 +43455,11 @@ class VersionCacheManager {
|
|
|
43223
43455
|
static async load() {
|
|
43224
43456
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
43225
43457
|
try {
|
|
43226
|
-
if (!
|
|
43458
|
+
if (!existsSync20(cacheFile)) {
|
|
43227
43459
|
logger.debug("Version check cache not found");
|
|
43228
43460
|
return null;
|
|
43229
43461
|
}
|
|
43230
|
-
const content = await
|
|
43462
|
+
const content = await readFile27(cacheFile, "utf-8");
|
|
43231
43463
|
const cache2 = JSON.parse(content);
|
|
43232
43464
|
if (!cache2.lastCheck || !cache2.currentVersion || !cache2.latestVersion) {
|
|
43233
43465
|
logger.debug("Invalid cache structure, ignoring");
|
|
@@ -43244,10 +43476,10 @@ class VersionCacheManager {
|
|
|
43244
43476
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
43245
43477
|
const cacheDir = PathResolver.getCacheDir(false);
|
|
43246
43478
|
try {
|
|
43247
|
-
if (!
|
|
43479
|
+
if (!existsSync20(cacheDir)) {
|
|
43248
43480
|
await mkdir22(cacheDir, { recursive: true, mode: 448 });
|
|
43249
43481
|
}
|
|
43250
|
-
await
|
|
43482
|
+
await writeFile23(cacheFile, JSON.stringify(cache2, null, 2), "utf-8");
|
|
43251
43483
|
logger.debug(`Version check cache saved to ${cacheFile}`);
|
|
43252
43484
|
} catch (error) {
|
|
43253
43485
|
logger.debug(`Failed to save version check cache: ${error}`);
|
|
@@ -43266,7 +43498,7 @@ class VersionCacheManager {
|
|
|
43266
43498
|
static async clear() {
|
|
43267
43499
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
43268
43500
|
try {
|
|
43269
|
-
if (
|
|
43501
|
+
if (existsSync20(cacheFile)) {
|
|
43270
43502
|
const fs14 = await import("node:fs/promises");
|
|
43271
43503
|
await fs14.unlink(cacheFile);
|
|
43272
43504
|
logger.debug("Version check cache cleared");
|
|
@@ -43489,7 +43721,7 @@ async function displayVersion() {
|
|
|
43489
43721
|
const prefix = PathResolver.getPathPrefix(false);
|
|
43490
43722
|
const localMetadataPath = prefix ? join77(process.cwd(), prefix, "metadata.json") : join77(process.cwd(), "metadata.json");
|
|
43491
43723
|
const isLocalSameAsGlobal = localMetadataPath === globalMetadataPath;
|
|
43492
|
-
if (!isLocalSameAsGlobal &&
|
|
43724
|
+
if (!isLocalSameAsGlobal && existsSync21(localMetadataPath)) {
|
|
43493
43725
|
try {
|
|
43494
43726
|
const rawMetadata = JSON.parse(readFileSync7(localMetadataPath, "utf-8"));
|
|
43495
43727
|
const metadata = MetadataSchema.parse(rawMetadata);
|
|
@@ -43503,7 +43735,7 @@ async function displayVersion() {
|
|
|
43503
43735
|
logger.verbose("Failed to parse local metadata.json", { error });
|
|
43504
43736
|
}
|
|
43505
43737
|
}
|
|
43506
|
-
if (
|
|
43738
|
+
if (existsSync21(globalMetadataPath)) {
|
|
43507
43739
|
try {
|
|
43508
43740
|
const rawMetadata = JSON.parse(readFileSync7(globalMetadataPath, "utf-8"));
|
|
43509
43741
|
const metadata = MetadataSchema.parse(rawMetadata);
|