td-ai-tools 1.0.7 → 1.0.8
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 +5 -0
- package/bin/cli.js +130 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,6 +36,9 @@ npx td-ai-tools install pr-solver horizon-component-library
|
|
|
36
36
|
npx td-ai-tools update
|
|
37
37
|
npx td-ai-tools update --all
|
|
38
38
|
npx td-ai-tools update pr-solver
|
|
39
|
+
npx td-ai-tools delete
|
|
40
|
+
npx td-ai-tools delete --all
|
|
41
|
+
npx td-ai-tools delete pr-solver
|
|
39
42
|
```
|
|
40
43
|
|
|
41
44
|
The installer copies requested items into both agent layouts:
|
|
@@ -46,6 +49,8 @@ This keeps the installed assets available to both Claude-style and `.agents`-sty
|
|
|
46
49
|
|
|
47
50
|
`install` now errors when the target item already exists. Use `update` to replace an existing installed skill or agent pack.
|
|
48
51
|
|
|
52
|
+
`delete` removes installed items from both `.claude/` and `.agents/` target directories, and works on any installed skill or agent pack regardless of whether it is in the catalogue.
|
|
53
|
+
|
|
49
54
|
## Local Verification
|
|
50
55
|
Run the local smoke test to package the repo and verify installation into a throwaway project:
|
|
51
56
|
|
package/bin/cli.js
CHANGED
|
@@ -66,6 +66,23 @@ function installSkill(name, { replaceExisting = false } = {}) {
|
|
|
66
66
|
return true;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
function deleteSkill(name) {
|
|
70
|
+
let deletedAny = false;
|
|
71
|
+
for (const target of INSTALL_TARGETS) {
|
|
72
|
+
const dest = path.join(TARGET_ROOT, target.root, 'skills', name);
|
|
73
|
+
if (fs.existsSync(dest)) {
|
|
74
|
+
fs.rmSync(dest, { recursive: true, force: true });
|
|
75
|
+
console.log(` [skill] ${name} deleted from ${target.root}/skills/${name}/`);
|
|
76
|
+
deletedAny = true;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (!deletedAny) {
|
|
80
|
+
console.error(` [error] Skill "${name}" is not installed.`);
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
|
|
69
86
|
function installAgent(name, { replaceExisting = false } = {}) {
|
|
70
87
|
const src = path.join(AGENTS_DIR, name);
|
|
71
88
|
if (!fs.existsSync(src)) {
|
|
@@ -88,6 +105,38 @@ function installAgent(name, { replaceExisting = false } = {}) {
|
|
|
88
105
|
return true;
|
|
89
106
|
}
|
|
90
107
|
|
|
108
|
+
function deleteAgent(name) {
|
|
109
|
+
let deletedAny = false;
|
|
110
|
+
for (const target of INSTALL_TARGETS) {
|
|
111
|
+
const dest = path.join(TARGET_ROOT, target.root, 'agents', name);
|
|
112
|
+
if (fs.existsSync(dest)) {
|
|
113
|
+
fs.rmSync(dest, { recursive: true, force: true });
|
|
114
|
+
console.log(` [agent] ${name} deleted from ${target.root}/agents/${name}/`);
|
|
115
|
+
deletedAny = true;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (!deletedAny) {
|
|
119
|
+
console.error(` [error] Agent pack "${name}" is not installed.`);
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function getInstalled(type) {
|
|
126
|
+
const installed = new Set();
|
|
127
|
+
for (const target of INSTALL_TARGETS) {
|
|
128
|
+
const dir = path.join(TARGET_ROOT, target.root, type);
|
|
129
|
+
if (fs.existsSync(dir)) {
|
|
130
|
+
for (const entry of fs.readdirSync(dir)) {
|
|
131
|
+
if (fs.statSync(path.join(dir, entry)).isDirectory()) {
|
|
132
|
+
installed.add(entry);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return [...installed].sort();
|
|
138
|
+
}
|
|
139
|
+
|
|
91
140
|
function printList() {
|
|
92
141
|
const skills = getAvailable(SKILLS_DIR);
|
|
93
142
|
const agents = getAvailable(AGENTS_DIR);
|
|
@@ -113,6 +162,12 @@ function buildMenu() {
|
|
|
113
162
|
return [...skills, ...agents];
|
|
114
163
|
}
|
|
115
164
|
|
|
165
|
+
function buildDeleteMenu() {
|
|
166
|
+
const skills = getInstalled('skills').map(name => ({ type: 'skill', name }));
|
|
167
|
+
const agents = getInstalled('agents').map(name => ({ type: 'agent', name }));
|
|
168
|
+
return [...skills, ...agents];
|
|
169
|
+
}
|
|
170
|
+
|
|
116
171
|
function installItems(items, options = {}) {
|
|
117
172
|
for (const item of items) {
|
|
118
173
|
if (item.type === 'skill') installSkill(item.name, options);
|
|
@@ -120,6 +175,13 @@ function installItems(items, options = {}) {
|
|
|
120
175
|
}
|
|
121
176
|
}
|
|
122
177
|
|
|
178
|
+
function deleteItems(items) {
|
|
179
|
+
for (const item of items) {
|
|
180
|
+
if (item.type === 'skill') deleteSkill(item.name);
|
|
181
|
+
else deleteAgent(item.name);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
123
185
|
async function interactiveInstall(mode = 'install') {
|
|
124
186
|
const menu = buildMenu();
|
|
125
187
|
if (menu.length === 0) {
|
|
@@ -153,6 +215,39 @@ async function interactiveInstall(mode = 'install') {
|
|
|
153
215
|
});
|
|
154
216
|
}
|
|
155
217
|
|
|
218
|
+
async function interactiveDelete() {
|
|
219
|
+
const menu = buildDeleteMenu();
|
|
220
|
+
if (menu.length === 0) {
|
|
221
|
+
console.log('No installed skills or agent packs to delete.');
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
console.log('\nInstalled (enter numbers separated by spaces, or "all"):\n');
|
|
226
|
+
menu.forEach((item, i) => {
|
|
227
|
+
const label = item.type === 'skill' ? 'skill' : 'agent';
|
|
228
|
+
console.log(` [${i + 1}] ${label}: ${item.name}`);
|
|
229
|
+
});
|
|
230
|
+
console.log('');
|
|
231
|
+
|
|
232
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
233
|
+
return new Promise(resolve => {
|
|
234
|
+
rl.question('Select items to delete: ', answer => {
|
|
235
|
+
rl.close();
|
|
236
|
+
const trimmed = answer.trim().toLowerCase();
|
|
237
|
+
let selected;
|
|
238
|
+
if (trimmed === 'all') {
|
|
239
|
+
selected = menu;
|
|
240
|
+
} else {
|
|
241
|
+
const indices = trimmed.split(/\s+/).map(n => parseInt(n, 10) - 1);
|
|
242
|
+
selected = indices.filter(i => i >= 0 && i < menu.length).map(i => menu[i]);
|
|
243
|
+
}
|
|
244
|
+
console.log('');
|
|
245
|
+
deleteItems(selected);
|
|
246
|
+
resolve();
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
|
|
156
251
|
function resolveNames(names) {
|
|
157
252
|
const skills = getAvailable(SKILLS_DIR);
|
|
158
253
|
const agents = getAvailable(AGENTS_DIR);
|
|
@@ -169,6 +264,22 @@ function resolveNames(names) {
|
|
|
169
264
|
return items;
|
|
170
265
|
}
|
|
171
266
|
|
|
267
|
+
function resolveDeleteNames(names) {
|
|
268
|
+
const installedSkills = getInstalled('skills');
|
|
269
|
+
const installedAgents = getInstalled('agents');
|
|
270
|
+
const items = [];
|
|
271
|
+
for (const name of names) {
|
|
272
|
+
if (installedSkills.includes(name)) {
|
|
273
|
+
items.push({ type: 'skill', name });
|
|
274
|
+
} else if (installedAgents.includes(name)) {
|
|
275
|
+
items.push({ type: 'agent', name });
|
|
276
|
+
} else {
|
|
277
|
+
console.error(` [error] "${name}" is not installed.`);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return items;
|
|
281
|
+
}
|
|
282
|
+
|
|
172
283
|
async function main() {
|
|
173
284
|
const args = process.argv.slice(2);
|
|
174
285
|
|
|
@@ -183,6 +294,9 @@ Usage:
|
|
|
183
294
|
npx td-ai-tools update Interactive update (replaces existing items)
|
|
184
295
|
npx td-ai-tools update --all Update everything
|
|
185
296
|
npx td-ai-tools update <name...> Update specific skills or agent packs
|
|
297
|
+
npx td-ai-tools delete Interactive delete
|
|
298
|
+
npx td-ai-tools delete --all Delete everything
|
|
299
|
+
npx td-ai-tools delete <name...> Delete specific skills or agent packs
|
|
186
300
|
|
|
187
301
|
Skills are installed to: .claude/skills/<name>/
|
|
188
302
|
.agents/skills/<name>/
|
|
@@ -234,6 +348,22 @@ Agent packs installed to: .claude/agents/<name>/
|
|
|
234
348
|
return;
|
|
235
349
|
}
|
|
236
350
|
|
|
351
|
+
if (cmd === 'delete') {
|
|
352
|
+
const rest = args.slice(1);
|
|
353
|
+
if (rest.length === 0) {
|
|
354
|
+
await interactiveDelete();
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
if (rest[0] === '--all') {
|
|
358
|
+
console.log('');
|
|
359
|
+
deleteItems(buildDeleteMenu());
|
|
360
|
+
} else {
|
|
361
|
+
console.log('');
|
|
362
|
+
deleteItems(resolveDeleteNames(rest));
|
|
363
|
+
}
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
|
|
237
367
|
console.error(`Unknown command: "${cmd}". Run with --help for usage.`);
|
|
238
368
|
process.exit(1);
|
|
239
369
|
}
|