claudekit-cli 4.3.1-dev.11 → 4.3.1-dev.12
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/bin/postinstall-self-heal.cjs +143 -0
- package/cli-manifest.json +2 -2
- package/dist/index.js +37 -23
- package/package.json +3 -1
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const fs = require("node:fs");
|
|
5
|
+
const os = require("node:os");
|
|
6
|
+
const path = require("node:path");
|
|
7
|
+
|
|
8
|
+
const MAX_SETTINGS_BYTES = 5 * 1024 * 1024;
|
|
9
|
+
|
|
10
|
+
function isLegacyDescriptiveNamePrompt(entry) {
|
|
11
|
+
if (!entry || entry.type !== "prompt" || typeof entry.prompt !== "string") return false;
|
|
12
|
+
|
|
13
|
+
const prompt = entry.prompt;
|
|
14
|
+
const lowerPrompt = prompt.toLowerCase();
|
|
15
|
+
const isOriginalLegacyPrompt =
|
|
16
|
+
prompt.includes("Use kebab-case file naming") &&
|
|
17
|
+
prompt.includes("self-documenting") &&
|
|
18
|
+
prompt.includes("Grep, Glob, Search");
|
|
19
|
+
const isDescriptiveNameKebabPrompt =
|
|
20
|
+
lowerPrompt.includes("descriptive-name") &&
|
|
21
|
+
lowerPrompt.includes("kebab-case") &&
|
|
22
|
+
(lowerPrompt.includes("file") || lowerPrompt.includes("filename"));
|
|
23
|
+
|
|
24
|
+
return isOriginalLegacyPrompt || isDescriptiveNameKebabPrompt;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function pruneHooks(settings) {
|
|
28
|
+
if (!settings || typeof settings !== "object" || !settings.hooks) return 0;
|
|
29
|
+
|
|
30
|
+
let pruned = 0;
|
|
31
|
+
for (const [eventName, entries] of Object.entries(settings.hooks)) {
|
|
32
|
+
if (!Array.isArray(entries)) continue;
|
|
33
|
+
|
|
34
|
+
const keptEntries = [];
|
|
35
|
+
for (const entry of entries) {
|
|
36
|
+
if (isLegacyDescriptiveNamePrompt(entry)) {
|
|
37
|
+
pruned++;
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (Array.isArray(entry?.hooks)) {
|
|
42
|
+
const keptHooks = entry.hooks.filter((hook) => {
|
|
43
|
+
if (isLegacyDescriptiveNamePrompt(hook)) {
|
|
44
|
+
pruned++;
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
return true;
|
|
48
|
+
});
|
|
49
|
+
if (keptHooks.length > 0) keptEntries.push({ ...entry, hooks: keptHooks });
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
keptEntries.push(entry);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (keptEntries.length === 0) {
|
|
57
|
+
delete settings.hooks[eventName];
|
|
58
|
+
} else {
|
|
59
|
+
settings.hooks[eventName] = keptEntries;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (Object.keys(settings.hooks).length === 0) settings.hooks = undefined;
|
|
64
|
+
return pruned;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function pruneSettingsFile(filePath) {
|
|
68
|
+
try {
|
|
69
|
+
if (!filePath || !fs.existsSync(filePath)) return 0;
|
|
70
|
+
const stat = fs.statSync(filePath);
|
|
71
|
+
if (!stat.isFile() || stat.size > MAX_SETTINGS_BYTES) return 0;
|
|
72
|
+
|
|
73
|
+
const settings = JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
74
|
+
const pruned = pruneHooks(settings);
|
|
75
|
+
if (pruned > 0) {
|
|
76
|
+
fs.writeFileSync(filePath, `${JSON.stringify(settings, null, 2)}\n`);
|
|
77
|
+
}
|
|
78
|
+
return pruned;
|
|
79
|
+
} catch {
|
|
80
|
+
return 0;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function getHomeDir() {
|
|
85
|
+
return process.env.CK_TEST_HOME || os.homedir();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function addIfSettingsFile(files, filePath) {
|
|
89
|
+
if (!filePath) return;
|
|
90
|
+
const base = path.basename(filePath);
|
|
91
|
+
if (
|
|
92
|
+
base === "settings.json" ||
|
|
93
|
+
base === "settings.local.json" ||
|
|
94
|
+
base.endsWith(".settings.json")
|
|
95
|
+
) {
|
|
96
|
+
files.add(path.resolve(filePath));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function collectCandidateSettingsFiles() {
|
|
101
|
+
const files = new Set();
|
|
102
|
+
const initCwd = process.env.INIT_CWD;
|
|
103
|
+
if (initCwd && path.isAbsolute(initCwd)) {
|
|
104
|
+
addIfSettingsFile(files, path.join(initCwd, ".claude", "settings.json"));
|
|
105
|
+
addIfSettingsFile(files, path.join(initCwd, ".claude", "settings.local.json"));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const homeDir = getHomeDir();
|
|
109
|
+
const globalClaudeDir = process.env.CLAUDE_CONFIG_DIR || path.join(homeDir, ".claude");
|
|
110
|
+
addIfSettingsFile(files, path.join(globalClaudeDir, "settings.json"));
|
|
111
|
+
addIfSettingsFile(files, path.join(globalClaudeDir, "settings.local.json"));
|
|
112
|
+
|
|
113
|
+
const ccsDir = process.env.CK_TEST_CCS_DIR || path.join(homeDir, ".ccs");
|
|
114
|
+
try {
|
|
115
|
+
for (const dirent of fs.readdirSync(ccsDir, { withFileTypes: true })) {
|
|
116
|
+
if (dirent.isFile()) addIfSettingsFile(files, path.join(ccsDir, dirent.name));
|
|
117
|
+
}
|
|
118
|
+
} catch {
|
|
119
|
+
// Optional compatibility directory; skip when absent or unreadable.
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return [...files];
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function main() {
|
|
126
|
+
let pruned = 0;
|
|
127
|
+
for (const filePath of collectCandidateSettingsFiles()) {
|
|
128
|
+
pruned += pruneSettingsFile(filePath);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (pruned > 0 && process.env.CK_POSTINSTALL_DEBUG === "1") {
|
|
132
|
+
console.warn(`[claudekit-cli] Pruned ${pruned} legacy hook prompt(s)`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
main();
|
|
137
|
+
|
|
138
|
+
module.exports = {
|
|
139
|
+
collectCandidateSettingsFiles,
|
|
140
|
+
isLegacyDescriptiveNamePrompt,
|
|
141
|
+
pruneHooks,
|
|
142
|
+
pruneSettingsFile,
|
|
143
|
+
};
|
package/cli-manifest.json
CHANGED
package/dist/index.js
CHANGED
|
@@ -63357,7 +63357,7 @@ var package_default;
|
|
|
63357
63357
|
var init_package = __esm(() => {
|
|
63358
63358
|
package_default = {
|
|
63359
63359
|
name: "claudekit-cli",
|
|
63360
|
-
version: "4.3.1-dev.
|
|
63360
|
+
version: "4.3.1-dev.12",
|
|
63361
63361
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
63362
63362
|
type: "module",
|
|
63363
63363
|
repository: {
|
|
@@ -63373,6 +63373,7 @@ var init_package = __esm(() => {
|
|
|
63373
63373
|
},
|
|
63374
63374
|
files: [
|
|
63375
63375
|
"bin/ck.js",
|
|
63376
|
+
"bin/postinstall-self-heal.cjs",
|
|
63376
63377
|
"dist/index.js",
|
|
63377
63378
|
"dist/ui/",
|
|
63378
63379
|
"cli-manifest.json"
|
|
@@ -63404,6 +63405,7 @@ var init_package = __esm(() => {
|
|
|
63404
63405
|
"ci:local": "bash scripts/ci-local.sh",
|
|
63405
63406
|
"install:hooks": "./.githooks/install.sh",
|
|
63406
63407
|
prepare: `node -e "try{require('child_process').execSync('git rev-parse --git-dir',{stdio:'ignore'});require('child_process').execSync('bash .githooks/install.sh',{stdio:'inherit'})}catch(e){console.warn('[i] Hook install skipped:',e.message)}"`,
|
|
63408
|
+
postinstall: "node bin/postinstall-self-heal.cjs",
|
|
63407
63409
|
"help:check-parity": "bun run scripts/check-help-parity.ts",
|
|
63408
63410
|
"manifest:generate": "bun run scripts/generate-cli-manifest.ts",
|
|
63409
63411
|
"docs:generate": "bun run scripts/generate-cli-reference.ts",
|
|
@@ -63989,7 +63991,7 @@ var init_shared2 = __esm(() => {
|
|
|
63989
63991
|
|
|
63990
63992
|
// src/domains/health-checks/checkers/hook-health-checker.ts
|
|
63991
63993
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
63992
|
-
import { existsSync as existsSync45, readFileSync as readFileSync12, statSync as statSync9, writeFileSync as writeFileSync5 } from "node:fs";
|
|
63994
|
+
import { existsSync as existsSync45, readFileSync as readFileSync12, readdirSync as readdirSync8, statSync as statSync9, writeFileSync as writeFileSync5 } from "node:fs";
|
|
63993
63995
|
import { readdir as readdir17 } from "node:fs/promises";
|
|
63994
63996
|
import { homedir as homedir41, tmpdir } from "node:os";
|
|
63995
63997
|
import { join as join64, resolve as resolve33 } from "node:path";
|
|
@@ -64026,6 +64028,7 @@ function getCanonicalGlobalCommandRoot() {
|
|
|
64026
64028
|
}
|
|
64027
64029
|
function getClaudeSettingsFiles(projectDir) {
|
|
64028
64030
|
const globalClaudeDir = PathResolver.getGlobalKitDir();
|
|
64031
|
+
const ccsSettingsDir = join64(process.env.CK_TEST_HOME ?? homedir41(), ".ccs");
|
|
64029
64032
|
const candidates = [
|
|
64030
64033
|
{
|
|
64031
64034
|
path: resolve33(projectDir, ".claude", "settings.json"),
|
|
@@ -64048,6 +64051,17 @@ function getClaudeSettingsFiles(projectDir) {
|
|
|
64048
64051
|
root: getCanonicalGlobalCommandRoot()
|
|
64049
64052
|
}
|
|
64050
64053
|
];
|
|
64054
|
+
try {
|
|
64055
|
+
for (const dirent of readdirSync8(ccsSettingsDir, { withFileTypes: true })) {
|
|
64056
|
+
if (!dirent.isFile() || !dirent.name.endsWith(".settings.json"))
|
|
64057
|
+
continue;
|
|
64058
|
+
candidates.push({
|
|
64059
|
+
path: resolve33(ccsSettingsDir, dirent.name),
|
|
64060
|
+
label: `.ccs/${dirent.name}`,
|
|
64061
|
+
root: "$HOME"
|
|
64062
|
+
});
|
|
64063
|
+
}
|
|
64064
|
+
} catch {}
|
|
64051
64065
|
return candidates.filter((candidate) => existsSync45(candidate.path));
|
|
64052
64066
|
}
|
|
64053
64067
|
function isAlreadyCanonical(cmd) {
|
|
@@ -76419,7 +76433,7 @@ var init_content_validator = __esm(() => {
|
|
|
76419
76433
|
|
|
76420
76434
|
// src/commands/content/phases/context-cache-manager.ts
|
|
76421
76435
|
import { createHash as createHash9 } from "node:crypto";
|
|
76422
|
-
import { existsSync as existsSync79, mkdirSync as mkdirSync5, readFileSync as readFileSync18, readdirSync as
|
|
76436
|
+
import { existsSync as existsSync79, mkdirSync as mkdirSync5, readFileSync as readFileSync18, readdirSync as readdirSync13, statSync as statSync14 } from "node:fs";
|
|
76423
76437
|
import { rename as rename16, writeFile as writeFile40 } from "node:fs/promises";
|
|
76424
76438
|
import { homedir as homedir55 } from "node:os";
|
|
76425
76439
|
import { basename as basename34, join as join160 } from "node:path";
|
|
@@ -76468,7 +76482,7 @@ function getDocSourcePaths(repoPath) {
|
|
|
76468
76482
|
const docsDir = join160(repoPath, "docs");
|
|
76469
76483
|
if (existsSync79(docsDir)) {
|
|
76470
76484
|
try {
|
|
76471
|
-
const files =
|
|
76485
|
+
const files = readdirSync13(docsDir);
|
|
76472
76486
|
for (const f3 of files) {
|
|
76473
76487
|
if (f3.endsWith(".md"))
|
|
76474
76488
|
paths.push(join160(docsDir, f3));
|
|
@@ -76481,7 +76495,7 @@ function getDocSourcePaths(repoPath) {
|
|
|
76481
76495
|
const stylesDir = join160(repoPath, "assets", "writing-styles");
|
|
76482
76496
|
if (existsSync79(stylesDir)) {
|
|
76483
76497
|
try {
|
|
76484
|
-
const files =
|
|
76498
|
+
const files = readdirSync13(stylesDir);
|
|
76485
76499
|
for (const f3 of files) {
|
|
76486
76500
|
paths.push(join160(stylesDir, f3));
|
|
76487
76501
|
}
|
|
@@ -76676,7 +76690,7 @@ function extractContentFromResponse(response) {
|
|
|
76676
76690
|
|
|
76677
76691
|
// src/commands/content/phases/docs-summarizer.ts
|
|
76678
76692
|
import { execSync as execSync7 } from "node:child_process";
|
|
76679
|
-
import { existsSync as existsSync80, readFileSync as readFileSync19, readdirSync as
|
|
76693
|
+
import { existsSync as existsSync80, readFileSync as readFileSync19, readdirSync as readdirSync14 } from "node:fs";
|
|
76680
76694
|
import { join as join161 } from "node:path";
|
|
76681
76695
|
async function summarizeProjectDocs(repoPath, contentLogger) {
|
|
76682
76696
|
const rawContent = collectRawDocs(repoPath);
|
|
@@ -76734,7 +76748,7 @@ function collectRawDocs(repoPath) {
|
|
|
76734
76748
|
const docsDir = join161(repoPath, "docs");
|
|
76735
76749
|
if (existsSync80(docsDir)) {
|
|
76736
76750
|
try {
|
|
76737
|
-
const files =
|
|
76751
|
+
const files = readdirSync14(docsDir).filter((f3) => f3.endsWith(".md")).sort();
|
|
76738
76752
|
for (const f3 of files) {
|
|
76739
76753
|
const content = readCapped(join161(docsDir, f3), 5000);
|
|
76740
76754
|
if (content) {
|
|
@@ -76758,7 +76772,7 @@ ${content}`);
|
|
|
76758
76772
|
const stylesDir = join161(repoPath, "assets", "writing-styles");
|
|
76759
76773
|
if (existsSync80(stylesDir)) {
|
|
76760
76774
|
try {
|
|
76761
|
-
const files =
|
|
76775
|
+
const files = readdirSync14(stylesDir).slice(0, 3);
|
|
76762
76776
|
styles3 = files.map((f3) => readCapped(join161(stylesDir, f3), 1000)).filter(Boolean).join(`
|
|
76763
76777
|
|
|
76764
76778
|
`);
|
|
@@ -76949,7 +76963,7 @@ IMPORTANT: Generate the image and output the path as JSON: {"imagePath": "/path/
|
|
|
76949
76963
|
|
|
76950
76964
|
// src/commands/content/phases/photo-generator.ts
|
|
76951
76965
|
import { execSync as execSync8 } from "node:child_process";
|
|
76952
|
-
import { existsSync as existsSync81, mkdirSync as mkdirSync6, readdirSync as
|
|
76966
|
+
import { existsSync as existsSync81, mkdirSync as mkdirSync6, readdirSync as readdirSync15 } from "node:fs";
|
|
76953
76967
|
import { homedir as homedir56 } from "node:os";
|
|
76954
76968
|
import { join as join162 } from "node:path";
|
|
76955
76969
|
async function generatePhoto(_content, context, config, platform18, contentId, contentLogger) {
|
|
@@ -76974,7 +76988,7 @@ async function generatePhoto(_content, context, config, platform18, contentId, c
|
|
|
76974
76988
|
return { path: imagePath, ...dimensions, format: "png" };
|
|
76975
76989
|
}
|
|
76976
76990
|
}
|
|
76977
|
-
const files =
|
|
76991
|
+
const files = readdirSync15(mediaDir);
|
|
76978
76992
|
const imageFile = files.find((f3) => /\.(png|jpg|jpeg|webp)$/i.test(f3));
|
|
76979
76993
|
if (imageFile) {
|
|
76980
76994
|
const ext2 = imageFile.split(".").pop() ?? "png";
|
|
@@ -77361,7 +77375,7 @@ function isNoiseCommit(title, author) {
|
|
|
77361
77375
|
|
|
77362
77376
|
// src/commands/content/phases/change-detector.ts
|
|
77363
77377
|
import { execSync as execSync10, spawnSync as spawnSync9 } from "node:child_process";
|
|
77364
|
-
import { existsSync as existsSync84, readFileSync as readFileSync20, readdirSync as
|
|
77378
|
+
import { existsSync as existsSync84, readFileSync as readFileSync20, readdirSync as readdirSync16, statSync as statSync16 } from "node:fs";
|
|
77365
77379
|
import { join as join164 } from "node:path";
|
|
77366
77380
|
function detectCommits(repo, since) {
|
|
77367
77381
|
try {
|
|
@@ -77477,7 +77491,7 @@ function detectCompletedPlans(repo, since) {
|
|
|
77477
77491
|
const sinceMs = new Date(since).getTime();
|
|
77478
77492
|
const events = [];
|
|
77479
77493
|
try {
|
|
77480
|
-
const entries =
|
|
77494
|
+
const entries = readdirSync16(plansDir, { withFileTypes: true });
|
|
77481
77495
|
for (const entry of entries) {
|
|
77482
77496
|
if (!entry.isDirectory())
|
|
77483
77497
|
continue;
|
|
@@ -77558,7 +77572,7 @@ function classifyCommit(event) {
|
|
|
77558
77572
|
|
|
77559
77573
|
// src/commands/content/phases/repo-discoverer.ts
|
|
77560
77574
|
import { execSync as execSync11 } from "node:child_process";
|
|
77561
|
-
import { readdirSync as
|
|
77575
|
+
import { readdirSync as readdirSync17 } from "node:fs";
|
|
77562
77576
|
import { join as join165 } from "node:path";
|
|
77563
77577
|
function discoverRepos2(cwd2) {
|
|
77564
77578
|
const repos = [];
|
|
@@ -77568,7 +77582,7 @@ function discoverRepos2(cwd2) {
|
|
|
77568
77582
|
repos.push(info);
|
|
77569
77583
|
}
|
|
77570
77584
|
try {
|
|
77571
|
-
const entries =
|
|
77585
|
+
const entries = readdirSync17(cwd2, { withFileTypes: true });
|
|
77572
77586
|
for (const entry of entries) {
|
|
77573
77587
|
if (!entry.isDirectory() || entry.name.startsWith("."))
|
|
77574
77588
|
continue;
|
|
@@ -100782,7 +100796,7 @@ async function handleDownload(ctx) {
|
|
|
100782
100796
|
import { join as join120 } from "node:path";
|
|
100783
100797
|
|
|
100784
100798
|
// src/domains/installation/deletion-handler.ts
|
|
100785
|
-
import { existsSync as existsSync65, lstatSync as lstatSync3, readdirSync as
|
|
100799
|
+
import { existsSync as existsSync65, lstatSync as lstatSync3, readdirSync as readdirSync9, rmSync as rmSync2, rmdirSync, unlinkSync as unlinkSync4 } from "node:fs";
|
|
100786
100800
|
import { dirname as dirname35, join as join106, relative as relative21, resolve as resolve41, sep as sep12 } from "node:path";
|
|
100787
100801
|
|
|
100788
100802
|
// src/services/file-operations/manifest/manifest-reader.ts
|
|
@@ -100976,7 +100990,7 @@ function collectFilesRecursively(dir, baseDir) {
|
|
|
100976
100990
|
if (!existsSync65(dir))
|
|
100977
100991
|
return results;
|
|
100978
100992
|
try {
|
|
100979
|
-
const entries =
|
|
100993
|
+
const entries = readdirSync9(dir, { withFileTypes: true });
|
|
100980
100994
|
for (const entry of entries) {
|
|
100981
100995
|
const fullPath = join106(dir, entry.name);
|
|
100982
100996
|
const relativePath = relative21(baseDir, fullPath);
|
|
@@ -101014,7 +101028,7 @@ function cleanupEmptyDirectories(filePath, claudeDir3) {
|
|
|
101014
101028
|
while (currentDir !== normalizedClaudeDir && currentDir.startsWith(normalizedClaudeDir) && iterations < MAX_CLEANUP_ITERATIONS) {
|
|
101015
101029
|
iterations++;
|
|
101016
101030
|
try {
|
|
101017
|
-
const entries =
|
|
101031
|
+
const entries = readdirSync9(currentDir);
|
|
101018
101032
|
if (entries.length === 0) {
|
|
101019
101033
|
rmdirSync(currentDir);
|
|
101020
101034
|
logger.debug(`Removed empty directory: ${currentDir}`);
|
|
@@ -106750,7 +106764,7 @@ async function runPreflightChecks() {
|
|
|
106750
106764
|
|
|
106751
106765
|
// src/domains/installation/fresh-installer.ts
|
|
106752
106766
|
init_metadata_migration();
|
|
106753
|
-
import { existsSync as existsSync67, readdirSync as
|
|
106767
|
+
import { existsSync as existsSync67, readdirSync as readdirSync10, rmSync as rmSync3, rmdirSync as rmdirSync2, unlinkSync as unlinkSync5 } from "node:fs";
|
|
106754
106768
|
import { basename as basename28, dirname as dirname39, join as join132, resolve as resolve45 } from "node:path";
|
|
106755
106769
|
init_logger();
|
|
106756
106770
|
init_safe_spinner();
|
|
@@ -106807,7 +106821,7 @@ function cleanupEmptyDirectories2(filePath, claudeDir3) {
|
|
|
106807
106821
|
let currentDir = resolve45(dirname39(filePath));
|
|
106808
106822
|
while (currentDir !== normalizedClaudeDir && currentDir.startsWith(normalizedClaudeDir)) {
|
|
106809
106823
|
try {
|
|
106810
|
-
const entries =
|
|
106824
|
+
const entries = readdirSync10(currentDir);
|
|
106811
106825
|
if (entries.length === 0) {
|
|
106812
106826
|
rmdirSync2(currentDir);
|
|
106813
106827
|
logger.debug(`Removed empty directory: ${currentDir}`);
|
|
@@ -113365,7 +113379,7 @@ async function detectInstallations() {
|
|
|
113365
113379
|
}
|
|
113366
113380
|
|
|
113367
113381
|
// src/commands/uninstall/removal-handler.ts
|
|
113368
|
-
import { readdirSync as
|
|
113382
|
+
import { readdirSync as readdirSync12, rmSync as rmSync5 } from "node:fs";
|
|
113369
113383
|
import { basename as basename33, join as join152, resolve as resolve58, sep as sep14 } from "node:path";
|
|
113370
113384
|
init_logger();
|
|
113371
113385
|
init_safe_prompts();
|
|
@@ -113374,7 +113388,7 @@ var import_fs_extra42 = __toESM(require_lib(), 1);
|
|
|
113374
113388
|
|
|
113375
113389
|
// src/commands/uninstall/analysis-handler.ts
|
|
113376
113390
|
init_metadata_migration();
|
|
113377
|
-
import { readdirSync as
|
|
113391
|
+
import { readdirSync as readdirSync11, rmSync as rmSync4 } from "node:fs";
|
|
113378
113392
|
import { dirname as dirname48, join as join151 } from "node:path";
|
|
113379
113393
|
init_logger();
|
|
113380
113394
|
init_safe_prompts();
|
|
@@ -113400,7 +113414,7 @@ async function cleanupEmptyDirectories3(filePath, installationRoot) {
|
|
|
113400
113414
|
let currentDir = dirname48(filePath);
|
|
113401
113415
|
while (currentDir !== installationRoot && currentDir.startsWith(installationRoot)) {
|
|
113402
113416
|
try {
|
|
113403
|
-
const entries =
|
|
113417
|
+
const entries = readdirSync11(currentDir);
|
|
113404
113418
|
if (entries.length === 0) {
|
|
113405
113419
|
rmSync4(currentDir, { recursive: true });
|
|
113406
113420
|
cleaned++;
|
|
@@ -113644,7 +113658,7 @@ async function removeInstallations(installations, options2) {
|
|
|
113644
113658
|
}
|
|
113645
113659
|
}
|
|
113646
113660
|
try {
|
|
113647
|
-
const remaining =
|
|
113661
|
+
const remaining = readdirSync12(installation.path);
|
|
113648
113662
|
if (remaining.length === 0) {
|
|
113649
113663
|
rmSync5(installation.path, { recursive: true });
|
|
113650
113664
|
logger.debug(`Removed empty installation directory: ${installation.path}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claudekit-cli",
|
|
3
|
-
"version": "4.3.1-dev.
|
|
3
|
+
"version": "4.3.1-dev.12",
|
|
4
4
|
"description": "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"files": [
|
|
18
18
|
"bin/ck.js",
|
|
19
|
+
"bin/postinstall-self-heal.cjs",
|
|
19
20
|
"dist/index.js",
|
|
20
21
|
"dist/ui/",
|
|
21
22
|
"cli-manifest.json"
|
|
@@ -47,6 +48,7 @@
|
|
|
47
48
|
"ci:local": "bash scripts/ci-local.sh",
|
|
48
49
|
"install:hooks": "./.githooks/install.sh",
|
|
49
50
|
"prepare": "node -e \"try{require('child_process').execSync('git rev-parse --git-dir',{stdio:'ignore'});require('child_process').execSync('bash .githooks/install.sh',{stdio:'inherit'})}catch(e){console.warn('[i] Hook install skipped:',e.message)}\"",
|
|
51
|
+
"postinstall": "node bin/postinstall-self-heal.cjs",
|
|
50
52
|
"help:check-parity": "bun run scripts/check-help-parity.ts",
|
|
51
53
|
"manifest:generate": "bun run scripts/generate-cli-manifest.ts",
|
|
52
54
|
"docs:generate": "bun run scripts/generate-cli-reference.ts",
|