add-skill-kit 1.5.6 → 2.3.2
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/README.md +1 -1
- package/bin/lib/commands/help.js +149 -32
- package/bin/lib/commands/install.js +21 -1
- package/bin/lib/commands/uninstall.js +268 -9
- package/bin/lib/config.js +3 -0
- package/bin/lib/helpers.js +25 -5
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -109,7 +109,7 @@ add-skill-kit doctor
|
|
|
109
109
|
### 🎯 Intelligent Installation
|
|
110
110
|
|
|
111
111
|
- **Interactive selection** - Chọn skills cần cài
|
|
112
|
-
- **Auto-Install CLI** - Tự động cài
|
|
112
|
+
- **Auto-Install CLI** - Tự động cài `agentskillskit-cli`
|
|
113
113
|
- **Symlink mode** - Tiết kiệm disk space
|
|
114
114
|
- **Copy mode** - Offline support
|
|
115
115
|
- **Merkle verification** - Đảm bảo integrity
|
package/bin/lib/commands/help.js
CHANGED
|
@@ -2,41 +2,158 @@
|
|
|
2
2
|
* @fileoverview Help command
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import { c } from "../ui.js";
|
|
5
|
+
import { step, stepLine, S, c, select, isCancel, cancel } from "../ui.js";
|
|
6
6
|
import { VERSION } from "../config.js";
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
* Show help
|
|
9
|
+
* Show interactive help menu
|
|
10
10
|
*/
|
|
11
11
|
export async function run() {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
12
|
+
let running = true;
|
|
13
|
+
|
|
14
|
+
while (running) {
|
|
15
|
+
stepLine();
|
|
16
|
+
step(c.bold("kit") + c.dim(` v${VERSION}`));
|
|
17
|
+
step(c.dim("What would you like to know?"));
|
|
18
|
+
stepLine();
|
|
19
|
+
|
|
20
|
+
const choice = await select({
|
|
21
|
+
message: "Select a topic",
|
|
22
|
+
options: [
|
|
23
|
+
{ value: "commands", label: "Commands", hint: "View all available commands" },
|
|
24
|
+
{ value: "options", label: "Options", hint: "View all flags and options" },
|
|
25
|
+
{ value: "quickstart", label: "Quick Start", hint: "Get started quickly" },
|
|
26
|
+
{ value: "exit", label: "Exit", hint: "Close help" }
|
|
27
|
+
]
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
if (isCancel(choice) || choice === "exit") {
|
|
31
|
+
stepLine();
|
|
32
|
+
step("Goodbye!");
|
|
33
|
+
stepLine();
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
stepLine();
|
|
38
|
+
|
|
39
|
+
switch (choice) {
|
|
40
|
+
case "commands":
|
|
41
|
+
await showCommands();
|
|
42
|
+
break;
|
|
43
|
+
case "options":
|
|
44
|
+
showOptions();
|
|
45
|
+
break;
|
|
46
|
+
case "quickstart":
|
|
47
|
+
showQuickStart();
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
stepLine();
|
|
52
|
+
|
|
53
|
+
// Ask what to do next
|
|
54
|
+
const next = await select({
|
|
55
|
+
message: "What's next?",
|
|
56
|
+
options: [
|
|
57
|
+
{ value: "back", label: "Back to menu", hint: "See other topics" },
|
|
58
|
+
{ value: "exit", label: "Exit", hint: "Close help" }
|
|
59
|
+
]
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
if (isCancel(next) || next === "exit") {
|
|
63
|
+
stepLine();
|
|
64
|
+
step("Goodbye!");
|
|
65
|
+
stepLine();
|
|
66
|
+
running = false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function showCommands() {
|
|
72
|
+
step(c.bold("Available Commands"), S.diamondFilled, "cyan");
|
|
73
|
+
stepLine();
|
|
74
|
+
|
|
75
|
+
step(c.cyan("<org/repo>") + c.dim(" Install all skills from repository"));
|
|
76
|
+
step(c.dim("Example: kit agentskillkit/agent-skills"));
|
|
77
|
+
stepLine();
|
|
78
|
+
|
|
79
|
+
step(c.cyan("<org/repo#skill>") + c.dim(" Install specific skill"));
|
|
80
|
+
step(c.dim("Example: kit agentskillkit/agent-skills#react-patterns"));
|
|
81
|
+
stepLine();
|
|
82
|
+
|
|
83
|
+
step(c.cyan("list") + c.dim(" List installed skills"));
|
|
84
|
+
step(c.cyan("uninstall") + c.dim(" Remove skill(s) (interactive)"));
|
|
85
|
+
step(c.cyan("uninstall all") + c.dim(" Remove everything (automatic)"));
|
|
86
|
+
step(c.cyan("update <skill>") + c.dim(" Update a skill"));
|
|
87
|
+
step(c.cyan("verify") + c.dim(" Verify checksums"));
|
|
88
|
+
step(c.cyan("doctor") + c.dim(" Check health"));
|
|
89
|
+
step(c.cyan("lock") + c.dim(" Generate skill-lock.json"));
|
|
90
|
+
step(c.cyan("init") + c.dim(" Initialize skills directory"));
|
|
91
|
+
step(c.cyan("validate [skill]") + c.dim(" Validate against Antigravity spec"));
|
|
92
|
+
step(c.cyan("analyze <skill>") + c.dim(" Analyze skill structure"));
|
|
93
|
+
step(c.cyan("cache [info|clear]") + c.dim(" Manage cache"));
|
|
94
|
+
step(c.cyan("info <skill>") + c.dim(" Show skill info"));
|
|
95
|
+
|
|
96
|
+
stepLine();
|
|
97
|
+
|
|
98
|
+
// Interactive command selection
|
|
99
|
+
const executeCmd = await select({
|
|
100
|
+
message: "Execute a command?",
|
|
101
|
+
options: [
|
|
102
|
+
{ value: "list", label: "list", hint: "List installed skills" },
|
|
103
|
+
{ value: "doctor", label: "doctor", hint: "Check health" },
|
|
104
|
+
{ value: "verify", label: "verify", hint: "Verify checksums" },
|
|
105
|
+
{ value: "uninstall", label: "uninstall", hint: "Interactive removal" },
|
|
106
|
+
{ value: "lock", label: "lock", hint: "Generate lockfile" },
|
|
107
|
+
{ value: "init", label: "init", hint: "Initialize directory" },
|
|
108
|
+
{ value: "none", label: "← Back", hint: "Return to topics" }
|
|
109
|
+
]
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
if (!isCancel(executeCmd) && executeCmd !== "none") {
|
|
113
|
+
stepLine();
|
|
114
|
+
step(c.cyan(`Running: kit ${executeCmd}`));
|
|
115
|
+
stepLine();
|
|
116
|
+
|
|
117
|
+
// Dynamic import and execute command
|
|
118
|
+
try {
|
|
119
|
+
const commandModule = await import(`./${executeCmd}.js`);
|
|
120
|
+
await commandModule.run();
|
|
121
|
+
} catch (err) {
|
|
122
|
+
step(c.red(`Command not yet implemented: ${executeCmd}`));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function showOptions() {
|
|
128
|
+
step(c.bold("Available Options"), S.diamondFilled, "cyan");
|
|
129
|
+
stepLine();
|
|
130
|
+
|
|
131
|
+
step(c.cyan("--global, -g") + c.dim(" Use global scope (~/.gemini)"));
|
|
132
|
+
step(c.cyan("--force, -f") + c.dim(" Force operation without confirmation"));
|
|
133
|
+
step(c.cyan("--strict") + c.dim(" Fail on any violations"));
|
|
134
|
+
step(c.cyan("--fix") + c.dim(" Auto-fix issues (e.g., checksums)"));
|
|
135
|
+
step(c.cyan("--dry-run") + c.dim(" Preview changes without executing"));
|
|
136
|
+
step(c.cyan("--verbose, -v") + c.dim(" Show detailed output"));
|
|
137
|
+
step(c.cyan("--json") + c.dim(" Output in JSON format"));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function showQuickStart() {
|
|
141
|
+
step(c.bold("Quick Start Guide"), S.diamondFilled, "cyan");
|
|
142
|
+
stepLine();
|
|
143
|
+
|
|
144
|
+
step(c.bold("1. Install skills"));
|
|
145
|
+
step(" " + c.cyan("kit agentskillkit/agent-skills"));
|
|
146
|
+
stepLine();
|
|
147
|
+
|
|
148
|
+
step(c.bold("2. Choose scope"));
|
|
149
|
+
step(" " + c.dim("→ Current Project (local .agent/)"));
|
|
150
|
+
step(" " + c.dim("→ Global System (available everywhere)"));
|
|
151
|
+
stepLine();
|
|
152
|
+
|
|
153
|
+
step(c.bold("3. Check installation"));
|
|
154
|
+
step(" " + c.cyan("kit doctor"));
|
|
155
|
+
stepLine();
|
|
156
|
+
|
|
157
|
+
step(c.bold("4. Use in your AI"));
|
|
158
|
+
step(" " + c.dim("Skills are now available in .agent/skills/"));
|
|
42
159
|
}
|
|
@@ -597,7 +597,27 @@ export async function run(spec) {
|
|
|
597
597
|
try {
|
|
598
598
|
await execAsync(`npm install -D ${cliPackage}`, { timeout: 120000 });
|
|
599
599
|
cliSpinner.stop("Agent CLI installed locally");
|
|
600
|
-
|
|
600
|
+
|
|
601
|
+
// Add npm scripts to package.json
|
|
602
|
+
try {
|
|
603
|
+
const pkgPath = path.join(process.cwd(), "package.json");
|
|
604
|
+
if (fs.existsSync(pkgPath)) {
|
|
605
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
606
|
+
pkg.scripts = pkg.scripts || {};
|
|
607
|
+
|
|
608
|
+
// Add agent script if not exists
|
|
609
|
+
if (!pkg.scripts.agent) {
|
|
610
|
+
pkg.scripts.agent = "agent";
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
614
|
+
step(c.green("✓ Added npm script: 'agent'"));
|
|
615
|
+
}
|
|
616
|
+
} catch (scriptErr) {
|
|
617
|
+
step(c.yellow("⚠ Could not add npm scripts automatically"));
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
step(c.dim("Run: npm run agent"));
|
|
601
621
|
} catch (e) {
|
|
602
622
|
cliSpinner.stop(c.yellow("Local CLI installation skipped"));
|
|
603
623
|
step(c.dim(`Run manually: npm i -D ${cliPackage}`));
|
|
@@ -4,29 +4,287 @@
|
|
|
4
4
|
|
|
5
5
|
import fs from "fs";
|
|
6
6
|
import path from "path";
|
|
7
|
+
import os from "os";
|
|
7
8
|
import prompts from "prompts";
|
|
8
9
|
import { resolveScope, createBackup } from "../helpers.js";
|
|
9
|
-
import { step, stepLine, success, fatal, c } from "../ui.js";
|
|
10
|
+
import { step, stepLine, success, fatal, c, select, isCancel, cancel } from "../ui.js";
|
|
10
11
|
import { DRY } from "../config.js";
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
|
-
* Remove a skill
|
|
14
|
-
* @param {string} skillName
|
|
14
|
+
* Remove a skill or all skills
|
|
15
|
+
* @param {string} skillName - Skill name or "all" to remove everything
|
|
15
16
|
*/
|
|
16
17
|
export async function run(skillName) {
|
|
17
|
-
if (!skillName) fatal("Missing skill name");
|
|
18
|
-
|
|
19
18
|
const scope = resolveScope();
|
|
19
|
+
|
|
20
|
+
// Check if skills directory exists
|
|
21
|
+
if (!fs.existsSync(scope)) {
|
|
22
|
+
fatal("No skills directory found");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Get list of installed skills
|
|
26
|
+
const skills = fs.readdirSync(scope)
|
|
27
|
+
.filter(item => {
|
|
28
|
+
const itemPath = path.join(scope, item);
|
|
29
|
+
return fs.statSync(itemPath).isDirectory() && fs.existsSync(path.join(itemPath, "SKILL.md"));
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
if (skills.length === 0) {
|
|
33
|
+
step("No skills installed");
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// CASE 1: kit uninstall all → Auto-remove everything
|
|
38
|
+
if (skillName === "all") {
|
|
39
|
+
await removeAllAutomatic(scope, skills);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// CASE 2: kit uninstall (no params) → Interactive menu
|
|
44
|
+
if (!skillName) {
|
|
45
|
+
await interactiveRemove(scope, skills);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// CASE 3: kit uninstall <skill> → Remove specific skill
|
|
50
|
+
await removeSingleSkill(scope, skillName);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Interactive menu for skill removal
|
|
55
|
+
*/
|
|
56
|
+
async function interactiveRemove(scope, skills) {
|
|
57
|
+
stepLine();
|
|
58
|
+
step(`Found ${skills.length} installed skill(s)`);
|
|
59
|
+
stepLine();
|
|
60
|
+
|
|
61
|
+
const choice = await select({
|
|
62
|
+
message: "What would you like to do?",
|
|
63
|
+
options: [
|
|
64
|
+
{ value: "select", label: "Select specific skill", hint: "Choose one skill to remove" },
|
|
65
|
+
{ value: "all", label: "Remove all skills", hint: "Remove everything (with confirmations)" },
|
|
66
|
+
{ value: "cancel", label: "Cancel", hint: "Go back" }
|
|
67
|
+
]
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
if (isCancel(choice) || choice === "cancel") {
|
|
71
|
+
cancel("Cancelled");
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (choice === "all") {
|
|
76
|
+
await removeAllWithConfirmation(scope, skills);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Select specific skill
|
|
81
|
+
const skillChoice = await select({
|
|
82
|
+
message: "Select skill to remove",
|
|
83
|
+
options: skills.map(s => ({ value: s, label: s }))
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
if (isCancel(skillChoice)) {
|
|
87
|
+
cancel("Cancelled");
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
await removeSingleSkill(scope, skillChoice);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Remove all skills automatically (kit uninstall all)
|
|
96
|
+
*/
|
|
97
|
+
async function removeAllAutomatic(scope, skills) {
|
|
98
|
+
stepLine();
|
|
99
|
+
step(c.yellow("AUTOMATIC COMPLETE REMOVAL"));
|
|
100
|
+
step(c.dim(`Removing ${skills.length} skill(s) + .agent folder + npm dependencies`));
|
|
101
|
+
stepLine();
|
|
102
|
+
|
|
103
|
+
if (DRY) {
|
|
104
|
+
step(`Would remove ${skills.length} skill(s) from: ${scope}`);
|
|
105
|
+
step("Would remove .agent folder");
|
|
106
|
+
step("Would remove npm dependencies");
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// 1. Remove all skills with backup
|
|
111
|
+
for (const skill of skills) {
|
|
112
|
+
const targetDir = path.join(scope, skill);
|
|
113
|
+
createBackup(targetDir, skill);
|
|
114
|
+
fs.rmSync(targetDir, { recursive: true, force: true });
|
|
115
|
+
step(`✓ Removed: ${skill}`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// 2. Remove .agent folder
|
|
119
|
+
const agentDir = path.dirname(scope);
|
|
120
|
+
if (fs.existsSync(agentDir) && path.basename(agentDir) === ".agent") {
|
|
121
|
+
fs.rmSync(agentDir, { recursive: true, force: true });
|
|
122
|
+
step("✓ Removed: .agent folder");
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// 3. Remove npm dependencies
|
|
126
|
+
const cwd = process.cwd();
|
|
127
|
+
const nodeModules = path.join(cwd, "node_modules");
|
|
128
|
+
const packageJson = path.join(cwd, "package.json");
|
|
129
|
+
const packageLock = path.join(cwd, "package-lock.json");
|
|
130
|
+
|
|
131
|
+
if (fs.existsSync(nodeModules)) {
|
|
132
|
+
fs.rmSync(nodeModules, { recursive: true, force: true });
|
|
133
|
+
step("✓ Removed: node_modules/");
|
|
134
|
+
}
|
|
135
|
+
if (fs.existsSync(packageJson)) {
|
|
136
|
+
fs.rmSync(packageJson);
|
|
137
|
+
step("✓ Removed: package.json");
|
|
138
|
+
}
|
|
139
|
+
if (fs.existsSync(packageLock)) {
|
|
140
|
+
fs.rmSync(packageLock);
|
|
141
|
+
step("✓ Removed: package-lock.json");
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// 4. For global installs, ask about ~/.gemini/ cleanup
|
|
145
|
+
if (scope.includes(".gemini")) {
|
|
146
|
+
stepLine();
|
|
147
|
+
step(c.yellow("Global Configuration Cleanup"));
|
|
148
|
+
step(c.dim("The entire ~/.gemini/ folder can be removed:"));
|
|
149
|
+
step(c.dim(" • GEMINI.md (global rules)"));
|
|
150
|
+
step(c.dim(" • All Antigravity configs"));
|
|
151
|
+
step(c.dim(" • Cache and backups"));
|
|
152
|
+
stepLine();
|
|
153
|
+
|
|
154
|
+
const geminiRoot = path.join(require("os").homedir(), ".gemini");
|
|
155
|
+
if (fs.existsSync(geminiRoot)) {
|
|
156
|
+
// Just remove it automatically in "all" mode
|
|
157
|
+
fs.rmSync(geminiRoot, { recursive: true, force: true });
|
|
158
|
+
step("✓ Removed: ~/.gemini/ (complete cleanup)");
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
stepLine();
|
|
163
|
+
success("Complete cleanup done - everything removed");
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Remove all skills with step-by-step confirmations (kit uninstall → all)
|
|
168
|
+
*/
|
|
169
|
+
async function removeAllWithConfirmation(scope, skills) {
|
|
170
|
+
stepLine();
|
|
171
|
+
step(`Found ${skills.length} skill(s) to remove:`);
|
|
172
|
+
skills.forEach(s => step(` • ${s}`, "", "dim"));
|
|
173
|
+
stepLine();
|
|
174
|
+
|
|
175
|
+
const confirmSkills = await prompts({
|
|
176
|
+
type: "confirm",
|
|
177
|
+
name: "value",
|
|
178
|
+
message: `Remove all ${skills.length} skill(s)?`,
|
|
179
|
+
initial: false
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
if (!confirmSkills.value) {
|
|
183
|
+
step("Cancelled");
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Remove each skill with backup
|
|
188
|
+
for (const skill of skills) {
|
|
189
|
+
const targetDir = path.join(scope, skill);
|
|
190
|
+
createBackup(targetDir, skill);
|
|
191
|
+
fs.rmSync(targetDir, { recursive: true, force: true });
|
|
192
|
+
step(`Removed: ${skill}`);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
success(`All ${skills.length} skill(s) removed successfully`);
|
|
196
|
+
stepLine();
|
|
197
|
+
|
|
198
|
+
// Ask about .agent folder
|
|
199
|
+
const agentDir = path.dirname(scope);
|
|
200
|
+
if (fs.existsSync(agentDir) && path.basename(agentDir) === ".agent") {
|
|
201
|
+
stepLine();
|
|
202
|
+
step(c.yellow("Complete Cleanup"));
|
|
203
|
+
step(c.dim("The following will also be removed:"));
|
|
204
|
+
step(c.dim(" • Agents"));
|
|
205
|
+
step(c.dim(" • Workflows"));
|
|
206
|
+
step(c.dim(" • Knowledge & Lessons"));
|
|
207
|
+
step(c.dim(" • All configuration files"));
|
|
208
|
+
stepLine();
|
|
209
|
+
|
|
210
|
+
const confirmAgent = await prompts({
|
|
211
|
+
type: "confirm",
|
|
212
|
+
name: "value",
|
|
213
|
+
message: "Remove entire .agent folder?",
|
|
214
|
+
initial: false
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
if (confirmAgent.value) {
|
|
218
|
+
fs.rmSync(agentDir, { recursive: true, force: true });
|
|
219
|
+
success("Complete cleanup done - .agent folder removed");
|
|
220
|
+
|
|
221
|
+
// Ask about npm dependencies
|
|
222
|
+
stepLine();
|
|
223
|
+
step(c.yellow("npm Dependencies Cleanup"));
|
|
224
|
+
step(c.dim("The following npm files will also be removed:"));
|
|
225
|
+
step(c.dim(" • node_modules/"));
|
|
226
|
+
step(c.dim(" • package.json"));
|
|
227
|
+
step(c.dim(" • package-lock.json"));
|
|
228
|
+
stepLine();
|
|
229
|
+
|
|
230
|
+
const confirmNpm = await prompts({
|
|
231
|
+
type: "confirm",
|
|
232
|
+
name: "value",
|
|
233
|
+
message: "Remove npm dependencies?",
|
|
234
|
+
initial: false
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
if (confirmNpm.value) {
|
|
238
|
+
const cwd = process.cwd();
|
|
239
|
+
const nodeModules = path.join(cwd, "node_modules");
|
|
240
|
+
const packageJson = path.join(cwd, "package.json");
|
|
241
|
+
const packageLock = path.join(cwd, "package-lock.json");
|
|
242
|
+
|
|
243
|
+
if (fs.existsSync(nodeModules)) {
|
|
244
|
+
fs.rmSync(nodeModules, { recursive: true, force: true });
|
|
245
|
+
step("Removed: node_modules/");
|
|
246
|
+
}
|
|
247
|
+
if (fs.existsSync(packageJson)) {
|
|
248
|
+
fs.rmSync(packageJson);
|
|
249
|
+
step("Removed: package.json");
|
|
250
|
+
}
|
|
251
|
+
if (fs.existsSync(packageLock)) {
|
|
252
|
+
fs.rmSync(packageLock);
|
|
253
|
+
step("Removed: package-lock.json");
|
|
254
|
+
}
|
|
255
|
+
success("npm dependencies removed");
|
|
256
|
+
} else {
|
|
257
|
+
step(c.dim("Kept npm dependencies"));
|
|
258
|
+
}
|
|
259
|
+
} else {
|
|
260
|
+
step(c.dim("Kept .agent folder (agents, workflows, etc.)"));
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
stepLine();
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Remove a single skill
|
|
269
|
+
*/
|
|
270
|
+
async function removeSingleSkill(scope, skillName) {
|
|
20
271
|
const targetDir = path.join(scope, skillName);
|
|
21
272
|
|
|
22
|
-
if (!fs.existsSync(targetDir))
|
|
273
|
+
if (!fs.existsSync(targetDir)) {
|
|
274
|
+
fatal(`Skill not found: ${skillName}`);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (!fs.existsSync(path.join(targetDir, "SKILL.md"))) {
|
|
278
|
+
fatal(`Not a valid skill: ${skillName}`);
|
|
279
|
+
}
|
|
23
280
|
|
|
24
281
|
stepLine();
|
|
282
|
+
step(`Removing skill: ${c.cyan(skillName)}`);
|
|
25
283
|
|
|
26
284
|
const confirm = await prompts({
|
|
27
285
|
type: "confirm",
|
|
28
286
|
name: "value",
|
|
29
|
-
message:
|
|
287
|
+
message: "Confirm removal?",
|
|
30
288
|
initial: false
|
|
31
289
|
});
|
|
32
290
|
|
|
@@ -40,9 +298,10 @@ export async function run(skillName) {
|
|
|
40
298
|
return;
|
|
41
299
|
}
|
|
42
300
|
|
|
43
|
-
createBackup(targetDir, skillName);
|
|
44
|
-
|
|
301
|
+
const backup = createBackup(targetDir, skillName);
|
|
302
|
+
if (backup) step(`Backup created: ${backup}`);
|
|
45
303
|
|
|
304
|
+
fs.rmSync(targetDir, { recursive: true, force: true });
|
|
46
305
|
success(`Removed: ${skillName}`);
|
|
47
306
|
stepLine();
|
|
48
307
|
}
|
package/bin/lib/config.js
CHANGED
|
@@ -56,6 +56,9 @@ export const FORCE = flags.has("--force") || flags.has("-f");
|
|
|
56
56
|
/** @type {boolean} Dry run mode */
|
|
57
57
|
export const DRY = flags.has("--dry-run");
|
|
58
58
|
|
|
59
|
+
/** @type {boolean} Auto-fix mode */
|
|
60
|
+
export const FIX = flags.has("--fix");
|
|
61
|
+
|
|
59
62
|
/** @type {boolean} Strict mode */
|
|
60
63
|
export const STRICT = flags.has("--strict");
|
|
61
64
|
|
package/bin/lib/helpers.js
CHANGED
|
@@ -119,11 +119,31 @@ export function resolveScope() {
|
|
|
119
119
|
*/
|
|
120
120
|
export function createBackup(skillDir, skillName) {
|
|
121
121
|
if (DRY) return null;
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
122
|
+
|
|
123
|
+
try {
|
|
124
|
+
const ts = new Date().toISOString().replace(/[:.]/g, "-");
|
|
125
|
+
const bp = path.join(BACKUP_DIR, `${skillName}_${ts}`);
|
|
126
|
+
fs.mkdirSync(BACKUP_DIR, { recursive: true });
|
|
127
|
+
|
|
128
|
+
// Resolve symlink to real path (Windows compatibility)
|
|
129
|
+
const realPath = fs.realpathSync(skillDir);
|
|
130
|
+
|
|
131
|
+
fs.cpSync(realPath, bp, { recursive: true });
|
|
132
|
+
return bp;
|
|
133
|
+
} catch (err) {
|
|
134
|
+
// Fallback: try direct copy if realpath fails
|
|
135
|
+
try {
|
|
136
|
+
const ts = new Date().toISOString().replace(/[:.]/g, "-");
|
|
137
|
+
const bp = path.join(BACKUP_DIR, `${skillName}_${ts}`);
|
|
138
|
+
fs.cpSync(skillDir, bp, { recursive: true });
|
|
139
|
+
return bp;
|
|
140
|
+
} catch (fallbackErr) {
|
|
141
|
+
if (process.env.DEBUG) {
|
|
142
|
+
console.error(`Backup failed for ${skillName}:`, fallbackErr.message);
|
|
143
|
+
}
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
127
147
|
}
|
|
128
148
|
|
|
129
149
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "add-skill-kit",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.3.2",
|
|
4
4
|
"description": "Enterprise-grade Agent Skill Manager with Antigravity Skills support, Progressive Disclosure detection, and semantic routing validation",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "agentskillkit <agentskillkit@gmail.com>",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
},
|
|
15
15
|
"type": "module",
|
|
16
16
|
"bin": {
|
|
17
|
-
"
|
|
17
|
+
"kit": "./bin/cli.js"
|
|
18
18
|
},
|
|
19
19
|
"files": [
|
|
20
20
|
"bin/",
|