@juho0719/cckit 0.2.0 → 0.2.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/assets/claudemd/CLAUDE.md +69 -0
- package/dist/{chunk-6B46AIFM.js → chunk-OLLOS3GG.js} +16 -0
- package/dist/chunk-SW3OJLHC.js +35 -0
- package/dist/claudemd-KKQ2DL7P.js +7 -0
- package/dist/{cli-H6IDWH7Q.js → cli-D2Q5QUO7.js} +27 -4
- package/dist/index.js +21 -13
- package/dist/{registry-EGXWYWWK.js → registry-BU55RMHU.js} +3 -1
- package/dist/{uninstall-cli-KYQTJCKO.js → uninstall-cli-VCOZGDBM.js} +115 -8
- package/package.json +1 -1
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Claude Behavioral Guidelines
|
|
3
|
+
description: LLM coding best practices - think before coding, simplicity, surgical changes, goal-driven execution
|
|
4
|
+
---
|
|
5
|
+
# Claude Behavioral Guidelines
|
|
6
|
+
|
|
7
|
+
Behavioral guidelines to reduce common LLM coding mistakes. Merge with project-specific instructions as needed.
|
|
8
|
+
|
|
9
|
+
**Tradeoff:** These guidelines bias toward caution over speed. For trivial tasks, use judgment.
|
|
10
|
+
|
|
11
|
+
## 1. Think Before Coding
|
|
12
|
+
|
|
13
|
+
**Don't assume. Don't hide confusion. Surface tradeoffs.**
|
|
14
|
+
|
|
15
|
+
Before implementing:
|
|
16
|
+
- State your assumptions explicitly. If uncertain, ask.
|
|
17
|
+
- If multiple interpretations exist, present them - don't pick silently.
|
|
18
|
+
- If a simpler approach exists, say so. Push back when warranted.
|
|
19
|
+
- If something is unclear, stop. Name what's confusing. Ask.
|
|
20
|
+
|
|
21
|
+
## 2. Simplicity First
|
|
22
|
+
|
|
23
|
+
**Minimum code that solves the problem. Nothing speculative.**
|
|
24
|
+
|
|
25
|
+
- No features beyond what was asked.
|
|
26
|
+
- No abstractions for single-use code.
|
|
27
|
+
- No "flexibility" or "configurability" that wasn't requested.
|
|
28
|
+
- No error handling for impossible scenarios.
|
|
29
|
+
- If you write 200 lines and it could be 50, rewrite it.
|
|
30
|
+
|
|
31
|
+
Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify.
|
|
32
|
+
|
|
33
|
+
## 3. Surgical Changes
|
|
34
|
+
|
|
35
|
+
**Touch only what you must. Clean up only your own mess.**
|
|
36
|
+
|
|
37
|
+
When editing existing code:
|
|
38
|
+
- Don't "improve" adjacent code, comments, or formatting.
|
|
39
|
+
- Don't refactor things that aren't broken.
|
|
40
|
+
- Match existing style, even if you'd do it differently.
|
|
41
|
+
- If you notice unrelated dead code, mention it - don't delete it.
|
|
42
|
+
|
|
43
|
+
When your changes create orphans:
|
|
44
|
+
- Remove imports/variables/functions that YOUR changes made unused.
|
|
45
|
+
- Don't remove pre-existing dead code unless asked.
|
|
46
|
+
|
|
47
|
+
The test: Every changed line should trace directly to the user's request.
|
|
48
|
+
|
|
49
|
+
## 4. Goal-Driven Execution
|
|
50
|
+
|
|
51
|
+
**Define success criteria. Loop until verified.**
|
|
52
|
+
|
|
53
|
+
Transform tasks into verifiable goals:
|
|
54
|
+
- "Add validation" → "Write tests for invalid inputs, then make them pass"
|
|
55
|
+
- "Fix the bug" → "Write a test that reproduces it, then make it pass"
|
|
56
|
+
- "Refactor X" → "Ensure tests pass before and after"
|
|
57
|
+
|
|
58
|
+
For multi-step tasks, state a brief plan:
|
|
59
|
+
```
|
|
60
|
+
1. [Step] → verify: [check]
|
|
61
|
+
2. [Step] → verify: [check]
|
|
62
|
+
3. [Step] → verify: [check]
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
**These guidelines are working if:** fewer unnecessary changes in diffs, fewer rewrites due to overcomplication, and clarifying questions come before implementation rather than after mistakes.
|
|
@@ -98,6 +98,21 @@ async function getRuleCategories() {
|
|
|
98
98
|
}
|
|
99
99
|
return categories;
|
|
100
100
|
}
|
|
101
|
+
async function getClaudemdItems() {
|
|
102
|
+
const dir = join(getAssetsDir(), "claudemd");
|
|
103
|
+
const files = (await readdir(dir)).filter((f) => f.endsWith(".md"));
|
|
104
|
+
const items = [];
|
|
105
|
+
for (const file of files) {
|
|
106
|
+
const content = await readFile(join(dir, file), "utf-8");
|
|
107
|
+
const fm = parseFrontmatter(content);
|
|
108
|
+
items.push({
|
|
109
|
+
name: fm["name"] || basename(file, ".md"),
|
|
110
|
+
description: fm["description"] || "",
|
|
111
|
+
file
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
return items;
|
|
115
|
+
}
|
|
101
116
|
async function getMcpServers() {
|
|
102
117
|
const filePath = join(getAssetsDir(), "mcps", "mcp-servers.json");
|
|
103
118
|
const content = await readFile(filePath, "utf-8");
|
|
@@ -132,5 +147,6 @@ export {
|
|
|
132
147
|
getCommands,
|
|
133
148
|
getHooks,
|
|
134
149
|
getRuleCategories,
|
|
150
|
+
getClaudemdItems,
|
|
135
151
|
getMcpServers
|
|
136
152
|
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getAssetsDir
|
|
3
|
+
} from "./chunk-5XOKKPAA.js";
|
|
4
|
+
|
|
5
|
+
// src/installers/claudemd.ts
|
|
6
|
+
import { join } from "path";
|
|
7
|
+
import { readFile, writeFile, access } from "fs/promises";
|
|
8
|
+
import { constants } from "fs";
|
|
9
|
+
async function installClaudemd(items, targetDir) {
|
|
10
|
+
const claudemdDir = join(getAssetsDir(), "claudemd");
|
|
11
|
+
const targetClaudeMd = join(targetDir, "CLAUDE.md");
|
|
12
|
+
let existing = "";
|
|
13
|
+
try {
|
|
14
|
+
await access(targetClaudeMd, constants.F_OK);
|
|
15
|
+
existing = await readFile(targetClaudeMd, "utf-8");
|
|
16
|
+
} catch {
|
|
17
|
+
}
|
|
18
|
+
const toAppend = [];
|
|
19
|
+
for (const item of items) {
|
|
20
|
+
const raw = await readFile(join(claudemdDir, item.file), "utf-8");
|
|
21
|
+
const content = raw.replace(/^---\s*\n[\s\S]*?\n---\s*\n/, "").trim();
|
|
22
|
+
const headerMatch = content.match(/^#{1,2}\s+.+/m);
|
|
23
|
+
if (headerMatch) {
|
|
24
|
+
if (existing.includes(headerMatch[0])) continue;
|
|
25
|
+
}
|
|
26
|
+
toAppend.push(content);
|
|
27
|
+
}
|
|
28
|
+
if (toAppend.length === 0) return;
|
|
29
|
+
const appendContent = (existing.endsWith("\n") ? "" : "\n") + toAppend.join("\n\n") + "\n";
|
|
30
|
+
await writeFile(targetClaudeMd, existing + appendContent, "utf-8");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export {
|
|
34
|
+
installClaudemd
|
|
35
|
+
};
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
installMcps
|
|
3
3
|
} from "./chunk-W63UKEIT.js";
|
|
4
|
+
import {
|
|
5
|
+
installClaudemd
|
|
6
|
+
} from "./chunk-SW3OJLHC.js";
|
|
4
7
|
import {
|
|
5
8
|
getAgents,
|
|
9
|
+
getClaudemdItems,
|
|
6
10
|
getCommands,
|
|
7
11
|
getHooks,
|
|
8
12
|
getMcpServers,
|
|
9
13
|
getRuleCategories,
|
|
10
14
|
getSkills
|
|
11
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-OLLOS3GG.js";
|
|
12
16
|
import {
|
|
13
17
|
installAgents
|
|
14
18
|
} from "./chunk-EYY2IZ7N.js";
|
|
@@ -74,7 +78,8 @@ async function runCli() {
|
|
|
74
78
|
{ name: "Commands - Slash commands", value: "commands" },
|
|
75
79
|
{ name: "Hooks - Post-tool hooks", value: "hooks" },
|
|
76
80
|
{ name: "Rules - CLAUDE.md rules", value: "rules" },
|
|
77
|
-
{ name: "MCPs - MCP server configs", value: "mcps" }
|
|
81
|
+
{ name: "MCPs - MCP server configs", value: "mcps" },
|
|
82
|
+
{ name: "ClaudeMd - Behavioral guidelines", value: "claudemd" }
|
|
78
83
|
]
|
|
79
84
|
});
|
|
80
85
|
if (selectedCategories.length === 0) {
|
|
@@ -89,7 +94,8 @@ async function runCli() {
|
|
|
89
94
|
hooks: [],
|
|
90
95
|
ruleCategories: [],
|
|
91
96
|
mcps: [],
|
|
92
|
-
mcpEnvValues: /* @__PURE__ */ new Map()
|
|
97
|
+
mcpEnvValues: /* @__PURE__ */ new Map(),
|
|
98
|
+
claudemds: []
|
|
93
99
|
};
|
|
94
100
|
const skippedMcps = /* @__PURE__ */ new Map();
|
|
95
101
|
if (selectedCategories.includes("agents")) {
|
|
@@ -147,6 +153,17 @@ async function runCli() {
|
|
|
147
153
|
}))
|
|
148
154
|
});
|
|
149
155
|
}
|
|
156
|
+
if (selectedCategories.includes("claudemd")) {
|
|
157
|
+
const allClaudemds = await getClaudemdItems();
|
|
158
|
+
plan.claudemds = await checkbox({
|
|
159
|
+
message: "Select claudemd items:",
|
|
160
|
+
choices: allClaudemds.map((c) => ({
|
|
161
|
+
name: `${chalk.bold(c.name.padEnd(35))} ${chalk.gray(c.description.slice(0, 55))}`,
|
|
162
|
+
value: c,
|
|
163
|
+
checked: false
|
|
164
|
+
}))
|
|
165
|
+
});
|
|
166
|
+
}
|
|
150
167
|
if (selectedCategories.includes("mcps")) {
|
|
151
168
|
const allMcps = await getMcpServers();
|
|
152
169
|
plan.mcps = await checkbox({
|
|
@@ -196,8 +213,9 @@ async function runCli() {
|
|
|
196
213
|
if (plan.hooks.length) console.log(` Hooks : ${plan.hooks.map((h) => h.name).join(", ")}`);
|
|
197
214
|
if (plan.ruleCategories.length) console.log(` Rules : ${plan.ruleCategories.join(", ")}`);
|
|
198
215
|
if (plan.mcps.length) console.log(` MCPs : ${plan.mcps.map((m) => m.name).join(", ")}`);
|
|
216
|
+
if (plan.claudemds.length) console.log(` ClaudeMd: ${plan.claudemds.map((c) => c.name).join(", ")}`);
|
|
199
217
|
console.log("");
|
|
200
|
-
const totalItems = plan.agents.length + plan.skills.length + plan.commands.length + plan.hooks.length + plan.ruleCategories.length + plan.mcps.length;
|
|
218
|
+
const totalItems = plan.agents.length + plan.skills.length + plan.commands.length + plan.hooks.length + plan.ruleCategories.length + plan.mcps.length + plan.claudemds.length;
|
|
201
219
|
if (totalItems === 0) {
|
|
202
220
|
console.log(chalk.yellow(" Nothing selected. Exiting."));
|
|
203
221
|
return;
|
|
@@ -235,6 +253,10 @@ async function runCli() {
|
|
|
235
253
|
spinner.text = "Installing MCP servers...";
|
|
236
254
|
await installMcps(plan.mcps, plan.scope, plan.mcpEnvValues);
|
|
237
255
|
}
|
|
256
|
+
if (plan.claudemds.length) {
|
|
257
|
+
spinner.text = "Installing claudemd...";
|
|
258
|
+
await installClaudemd(plan.claudemds, targetDir);
|
|
259
|
+
}
|
|
238
260
|
spinner.succeed(chalk.green("Installation complete!"));
|
|
239
261
|
console.log("");
|
|
240
262
|
if (plan.agents.length) console.log(` ${chalk.green("\u2713")} ${plan.agents.length} agent(s) \u2192 ${join(targetDir, "agents")}`);
|
|
@@ -243,6 +265,7 @@ async function runCli() {
|
|
|
243
265
|
if (plan.hooks.length) console.log(` ${chalk.green("\u2713")} ${plan.hooks.length} hook(s) \u2192 ${join(targetDir, "hooks")}`);
|
|
244
266
|
if (plan.ruleCategories.length) console.log(` ${chalk.green("\u2713")} Rules appended \u2192 ${join(targetDir, "CLAUDE.md")}`);
|
|
245
267
|
if (plan.mcps.length) console.log(` ${chalk.green("\u2713")} ${plan.mcps.length} MCP server(s) \u2192 ${scope === "global" ? "~/.claude.json" : "./.claude.json"}`);
|
|
268
|
+
if (plan.claudemds.length) console.log(` ${chalk.green("\u2713")} ClaudeMd appended \u2192 ${join(targetDir, "CLAUDE.md")}`);
|
|
246
269
|
console.log("");
|
|
247
270
|
if (skippedMcps.size > 0) {
|
|
248
271
|
console.log(chalk.yellow(" \u26A0 The following MCP servers have placeholder env vars:"));
|
package/dist/index.js
CHANGED
|
@@ -51,33 +51,38 @@ Installing all to ${targetDir}...
|
|
|
51
51
|
{ getHooks },
|
|
52
52
|
{ getRuleCategories },
|
|
53
53
|
{ getMcpServers },
|
|
54
|
+
{ getClaudemdItems },
|
|
54
55
|
{ installAgents },
|
|
55
56
|
{ installSkills },
|
|
56
57
|
{ installCommands },
|
|
57
58
|
{ installHooks },
|
|
58
59
|
{ installRules },
|
|
59
|
-
{ installMcps }
|
|
60
|
+
{ installMcps },
|
|
61
|
+
{ installClaudemd }
|
|
60
62
|
] = await Promise.all([
|
|
61
|
-
import("./registry-
|
|
62
|
-
import("./registry-
|
|
63
|
-
import("./registry-
|
|
64
|
-
import("./registry-
|
|
65
|
-
import("./registry-
|
|
66
|
-
import("./registry-
|
|
63
|
+
import("./registry-BU55RMHU.js"),
|
|
64
|
+
import("./registry-BU55RMHU.js"),
|
|
65
|
+
import("./registry-BU55RMHU.js"),
|
|
66
|
+
import("./registry-BU55RMHU.js"),
|
|
67
|
+
import("./registry-BU55RMHU.js"),
|
|
68
|
+
import("./registry-BU55RMHU.js"),
|
|
69
|
+
import("./registry-BU55RMHU.js"),
|
|
67
70
|
import("./agents-AEKT67A6.js"),
|
|
68
71
|
import("./skills-ULMW3UCM.js"),
|
|
69
72
|
import("./commands-P5LILVZ5.js"),
|
|
70
73
|
import("./hooks-IIG2XK4I.js"),
|
|
71
74
|
import("./rules-2CPBVNNJ.js"),
|
|
72
|
-
import("./mcps-67Q7TBGW.js")
|
|
75
|
+
import("./mcps-67Q7TBGW.js"),
|
|
76
|
+
import("./claudemd-KKQ2DL7P.js")
|
|
73
77
|
]);
|
|
74
|
-
const [agents, skills, commands, hooks, ruleCategories, mcps] = await Promise.all([
|
|
78
|
+
const [agents, skills, commands, hooks, ruleCategories, mcps, claudemds] = await Promise.all([
|
|
75
79
|
getAgents(),
|
|
76
80
|
getSkills(),
|
|
77
81
|
getCommands(),
|
|
78
82
|
getHooks(),
|
|
79
83
|
getRuleCategories(),
|
|
80
|
-
getMcpServers()
|
|
84
|
+
getMcpServers(),
|
|
85
|
+
getClaudemdItems()
|
|
81
86
|
]);
|
|
82
87
|
spinner.text = "Installing agents...";
|
|
83
88
|
await installAgents(agents, targetDir);
|
|
@@ -92,6 +97,8 @@ Installing all to ${targetDir}...
|
|
|
92
97
|
await installRules(ruleCategories.map((rc) => rc.category), claudeMd);
|
|
93
98
|
spinner.text = "Installing MCP servers...";
|
|
94
99
|
await installMcps(mcps, scope, /* @__PURE__ */ new Map());
|
|
100
|
+
spinner.text = "Installing claudemd...";
|
|
101
|
+
await installClaudemd(claudemds, targetDir);
|
|
95
102
|
spinner.succeed(chalk.green("All items installed successfully!"));
|
|
96
103
|
console.log(`
|
|
97
104
|
${chalk.green("\u2713")} ${agents.length} agents`);
|
|
@@ -99,7 +106,8 @@ Installing all to ${targetDir}...
|
|
|
99
106
|
console.log(` ${chalk.green("\u2713")} ${commands.length} commands`);
|
|
100
107
|
console.log(` ${chalk.green("\u2713")} ${hooks.length} hooks`);
|
|
101
108
|
console.log(` ${chalk.green("\u2713")} Rules (${ruleCategories.length} categories)`);
|
|
102
|
-
console.log(` ${chalk.green("\u2713")} ${mcps.length} MCP servers
|
|
109
|
+
console.log(` ${chalk.green("\u2713")} ${mcps.length} MCP servers`);
|
|
110
|
+
console.log(` ${chalk.green("\u2713")} ${claudemds.length} claudemd item(s)
|
|
103
111
|
`);
|
|
104
112
|
} catch (err) {
|
|
105
113
|
spinner.fail("Installation failed");
|
|
@@ -117,7 +125,7 @@ async function main() {
|
|
|
117
125
|
return;
|
|
118
126
|
}
|
|
119
127
|
if (args.includes("--uninstall") || args.includes("-u")) {
|
|
120
|
-
const { runUninstallCli } = await import("./uninstall-cli-
|
|
128
|
+
const { runUninstallCli } = await import("./uninstall-cli-VCOZGDBM.js");
|
|
121
129
|
await runUninstallCli();
|
|
122
130
|
return;
|
|
123
131
|
}
|
|
@@ -127,7 +135,7 @@ async function main() {
|
|
|
127
135
|
await installAll(scope);
|
|
128
136
|
return;
|
|
129
137
|
}
|
|
130
|
-
const { runCli } = await import("./cli-
|
|
138
|
+
const { runCli } = await import("./cli-D2Q5QUO7.js");
|
|
131
139
|
await runCli();
|
|
132
140
|
}
|
|
133
141
|
main().catch((err) => {
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getAgents,
|
|
3
|
+
getClaudemdItems,
|
|
3
4
|
getCommands,
|
|
4
5
|
getHooks,
|
|
5
6
|
getMcpServers,
|
|
6
7
|
getRuleCategories,
|
|
7
8
|
getSkills
|
|
8
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-OLLOS3GG.js";
|
|
9
10
|
import "./chunk-5XOKKPAA.js";
|
|
10
11
|
export {
|
|
11
12
|
getAgents,
|
|
13
|
+
getClaudemdItems,
|
|
12
14
|
getCommands,
|
|
13
15
|
getHooks,
|
|
14
16
|
getMcpServers,
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getAgents,
|
|
3
|
+
getClaudemdItems,
|
|
3
4
|
getCommands,
|
|
4
5
|
getHooks,
|
|
5
6
|
getMcpServers,
|
|
6
7
|
getRuleCategories,
|
|
7
8
|
getSkills
|
|
8
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-OLLOS3GG.js";
|
|
9
10
|
import {
|
|
10
11
|
getAssetsDir,
|
|
11
12
|
getGlobalDir,
|
|
@@ -16,7 +17,7 @@ import {
|
|
|
16
17
|
import { checkbox, select, confirm } from "@inquirer/prompts";
|
|
17
18
|
import chalk from "chalk";
|
|
18
19
|
import ora from "ora";
|
|
19
|
-
import { join as
|
|
20
|
+
import { join as join9 } from "path";
|
|
20
21
|
|
|
21
22
|
// src/scanner.ts
|
|
22
23
|
import { readdir, readFile, access } from "fs/promises";
|
|
@@ -108,6 +109,35 @@ async function getInstalledRuleCategories(targetDir) {
|
|
|
108
109
|
}
|
|
109
110
|
return installedCategories;
|
|
110
111
|
}
|
|
112
|
+
async function getInstalledClaudemd(targetDir) {
|
|
113
|
+
const claudeMdPath = join(targetDir, "CLAUDE.md");
|
|
114
|
+
let content = "";
|
|
115
|
+
try {
|
|
116
|
+
await access(claudeMdPath, constants.F_OK);
|
|
117
|
+
content = await readFile(claudeMdPath, "utf-8");
|
|
118
|
+
} catch {
|
|
119
|
+
return [];
|
|
120
|
+
}
|
|
121
|
+
const installedHeaders = /* @__PURE__ */ new Set();
|
|
122
|
+
for (const line of content.split("\n")) {
|
|
123
|
+
const match = line.match(/^(#{1,2}\s+.+)/);
|
|
124
|
+
if (match) installedHeaders.add(match[1].trim());
|
|
125
|
+
}
|
|
126
|
+
const allItems = await getClaudemdItems();
|
|
127
|
+
const result = [];
|
|
128
|
+
for (const item of allItems) {
|
|
129
|
+
try {
|
|
130
|
+
const raw = await readFile(join(getAssetsDir(), "claudemd", item.file), "utf-8");
|
|
131
|
+
const itemContent = raw.replace(/^---\s*\n[\s\S]*?\n---\s*\n/, "");
|
|
132
|
+
const headerMatch = itemContent.match(/^(#{1,2}\s+.+)/m);
|
|
133
|
+
if (headerMatch && installedHeaders.has(headerMatch[1].trim())) {
|
|
134
|
+
result.push(item);
|
|
135
|
+
}
|
|
136
|
+
} catch {
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
111
141
|
async function getInstalledMcps(scope) {
|
|
112
142
|
const filePath = getClaudeJsonPath(scope);
|
|
113
143
|
let claudeJson = {};
|
|
@@ -307,6 +337,58 @@ async function uninstallMcps(serverNames, scope) {
|
|
|
307
337
|
await writeFile3(filePath, JSON.stringify(claudeJson, null, 2) + "\n", "utf-8");
|
|
308
338
|
}
|
|
309
339
|
|
|
340
|
+
// src/uninstallers/claudemd.ts
|
|
341
|
+
import { readFile as readFile5, writeFile as writeFile4, access as access8 } from "fs/promises";
|
|
342
|
+
import { constants as constants8 } from "fs";
|
|
343
|
+
import { join as join8 } from "path";
|
|
344
|
+
async function uninstallClaudemd(items, targetDir) {
|
|
345
|
+
const claudeMdPath = join8(targetDir, "CLAUDE.md");
|
|
346
|
+
let existing = "";
|
|
347
|
+
try {
|
|
348
|
+
await access8(claudeMdPath, constants8.F_OK);
|
|
349
|
+
existing = await readFile5(claudeMdPath, "utf-8");
|
|
350
|
+
} catch {
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
const headersToRemove = /* @__PURE__ */ new Set();
|
|
354
|
+
for (const item of items) {
|
|
355
|
+
try {
|
|
356
|
+
const raw = await readFile5(join8(getAssetsDir(), "claudemd", item.file), "utf-8");
|
|
357
|
+
const content = raw.replace(/^---\s*\n[\s\S]*?\n---\s*\n/, "");
|
|
358
|
+
const headerMatch = content.match(/^(#{1,2}\s+.+)/m);
|
|
359
|
+
if (headerMatch) {
|
|
360
|
+
headersToRemove.add(headerMatch[1].trim());
|
|
361
|
+
}
|
|
362
|
+
} catch {
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
if (headersToRemove.size === 0) return;
|
|
366
|
+
const lines = existing.split("\n");
|
|
367
|
+
const result = [];
|
|
368
|
+
let inRemovedSection = false;
|
|
369
|
+
let currentDepth = 0;
|
|
370
|
+
for (const line of lines) {
|
|
371
|
+
const headerMatch = line.match(/^(#{1,2})\s+/);
|
|
372
|
+
if (headerMatch) {
|
|
373
|
+
const depth = headerMatch[1].length;
|
|
374
|
+
const trimmed = line.trim();
|
|
375
|
+
if (headersToRemove.has(trimmed)) {
|
|
376
|
+
inRemovedSection = true;
|
|
377
|
+
currentDepth = depth;
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
if (inRemovedSection && depth <= currentDepth) {
|
|
381
|
+
inRemovedSection = false;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
if (!inRemovedSection) {
|
|
385
|
+
result.push(line);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
const cleaned = result.join("\n").replace(/\n{3,}/g, "\n\n");
|
|
389
|
+
await writeFile4(claudeMdPath, cleaned, "utf-8");
|
|
390
|
+
}
|
|
391
|
+
|
|
310
392
|
// src/uninstall-cli.ts
|
|
311
393
|
function printBanner() {
|
|
312
394
|
console.log(
|
|
@@ -344,16 +426,18 @@ async function runUninstallCli() {
|
|
|
344
426
|
installedCommands,
|
|
345
427
|
installedHooks,
|
|
346
428
|
installedRuleCategories,
|
|
347
|
-
installedMcpNames
|
|
429
|
+
installedMcpNames,
|
|
430
|
+
installedClaudemds
|
|
348
431
|
] = await Promise.all([
|
|
349
432
|
getInstalledAgents(targetDir),
|
|
350
433
|
getInstalledSkills(targetDir),
|
|
351
434
|
getInstalledCommands(targetDir),
|
|
352
435
|
getInstalledHooks(targetDir),
|
|
353
436
|
getInstalledRuleCategories(targetDir),
|
|
354
|
-
getInstalledMcps(scope)
|
|
437
|
+
getInstalledMcps(scope),
|
|
438
|
+
getInstalledClaudemd(targetDir)
|
|
355
439
|
]);
|
|
356
|
-
const totalInstalled = installedAgents.length + installedSkills.length + installedCommands.length + installedHooks.length + installedRuleCategories.length + installedMcpNames.length;
|
|
440
|
+
const totalInstalled = installedAgents.length + installedSkills.length + installedCommands.length + installedHooks.length + installedRuleCategories.length + installedMcpNames.length + installedClaudemds.length;
|
|
357
441
|
if (totalInstalled === 0) {
|
|
358
442
|
console.log(chalk.yellow(" Nothing installed. Exiting."));
|
|
359
443
|
return;
|
|
@@ -389,6 +473,11 @@ async function runUninstallCli() {
|
|
|
389
473
|
name: `MCPs ${chalk.gray(`(${installedMcpNames.length} installed)`)}`,
|
|
390
474
|
value: "mcps"
|
|
391
475
|
});
|
|
476
|
+
if (installedClaudemds.length > 0)
|
|
477
|
+
availableCategories.push({
|
|
478
|
+
name: `ClaudeMd ${chalk.gray(`(${installedClaudemds.length} installed)`)}`,
|
|
479
|
+
value: "claudemd"
|
|
480
|
+
});
|
|
392
481
|
const selectedCategories = await checkbox({
|
|
393
482
|
message: "Select categories to uninstall:",
|
|
394
483
|
choices: availableCategories
|
|
@@ -404,7 +493,8 @@ async function runUninstallCli() {
|
|
|
404
493
|
commands: [],
|
|
405
494
|
hooks: [],
|
|
406
495
|
ruleCategories: [],
|
|
407
|
-
mcpNames: []
|
|
496
|
+
mcpNames: [],
|
|
497
|
+
claudemds: []
|
|
408
498
|
};
|
|
409
499
|
if (selectedCategories.includes("agents") && installedAgents.length > 0) {
|
|
410
500
|
plan.agents = await checkbox({
|
|
@@ -466,7 +556,17 @@ async function runUninstallCli() {
|
|
|
466
556
|
}))
|
|
467
557
|
});
|
|
468
558
|
}
|
|
469
|
-
|
|
559
|
+
if (selectedCategories.includes("claudemd") && installedClaudemds.length > 0) {
|
|
560
|
+
plan.claudemds = await checkbox({
|
|
561
|
+
message: "Select claudemd items to uninstall:",
|
|
562
|
+
choices: installedClaudemds.map((c) => ({
|
|
563
|
+
name: `${chalk.bold(c.name.padEnd(35))} ${chalk.gray(c.description.slice(0, 55))}`,
|
|
564
|
+
value: c,
|
|
565
|
+
checked: false
|
|
566
|
+
}))
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
const totalToRemove = plan.agents.length + plan.skills.length + plan.commands.length + plan.hooks.length + plan.ruleCategories.length + plan.mcpNames.length + plan.claudemds.length;
|
|
470
570
|
if (totalToRemove === 0) {
|
|
471
571
|
console.log(chalk.yellow("\n Nothing selected. Exiting."));
|
|
472
572
|
return;
|
|
@@ -482,6 +582,7 @@ async function runUninstallCli() {
|
|
|
482
582
|
if (plan.ruleCategories.length)
|
|
483
583
|
console.log(` Rules : ${plan.ruleCategories.join(", ")}`);
|
|
484
584
|
if (plan.mcpNames.length) console.log(` MCPs : ${plan.mcpNames.join(", ")}`);
|
|
585
|
+
if (plan.claudemds.length) console.log(` ClaudeMd: ${plan.claudemds.map((c) => c.name).join(", ")}`);
|
|
485
586
|
console.log("");
|
|
486
587
|
const ok = await confirm({
|
|
487
588
|
message: chalk.red("Proceed with uninstallation? This cannot be undone."),
|
|
@@ -512,13 +613,17 @@ async function runUninstallCli() {
|
|
|
512
613
|
}
|
|
513
614
|
if (plan.ruleCategories.length) {
|
|
514
615
|
spinner.text = "Removing rules...";
|
|
515
|
-
const claudeMd =
|
|
616
|
+
const claudeMd = join9(targetDir, "CLAUDE.md");
|
|
516
617
|
await uninstallRules(plan.ruleCategories, claudeMd);
|
|
517
618
|
}
|
|
518
619
|
if (plan.mcpNames.length) {
|
|
519
620
|
spinner.text = "Removing MCP servers...";
|
|
520
621
|
await uninstallMcps(plan.mcpNames, scope);
|
|
521
622
|
}
|
|
623
|
+
if (plan.claudemds.length) {
|
|
624
|
+
spinner.text = "Removing claudemd...";
|
|
625
|
+
await uninstallClaudemd(plan.claudemds, targetDir);
|
|
626
|
+
}
|
|
522
627
|
spinner.succeed(chalk.green("Uninstallation complete!"));
|
|
523
628
|
console.log("");
|
|
524
629
|
if (plan.agents.length)
|
|
@@ -533,6 +638,8 @@ async function runUninstallCli() {
|
|
|
533
638
|
console.log(` ${chalk.red("\u2717")} Rules removed (${plan.ruleCategories.join(", ")})`);
|
|
534
639
|
if (plan.mcpNames.length)
|
|
535
640
|
console.log(` ${chalk.red("\u2717")} ${plan.mcpNames.length} MCP server(s) removed`);
|
|
641
|
+
if (plan.claudemds.length)
|
|
642
|
+
console.log(` ${chalk.red("\u2717")} ClaudeMd removed (${plan.claudemds.map((c) => c.name).join(", ")})`);
|
|
536
643
|
console.log("");
|
|
537
644
|
} catch (err) {
|
|
538
645
|
spinner.fail(chalk.red("Uninstallation failed"));
|
package/package.json
CHANGED