@ngxtm/devkit 1.0.0 ā 2.0.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/README.md +59 -3
- package/SKILLS_INDEX.md +2111 -0
- package/cli/config.js +261 -0
- package/cli/index.js +132 -33
- package/cli/install.js +267 -19
- package/package.json +5 -2
- package/skills-index.json +2057 -0
package/cli/install.js
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
const fs = require('fs');
|
|
11
11
|
const path = require('path');
|
|
12
12
|
const os = require('os');
|
|
13
|
+
const readline = require('readline');
|
|
14
|
+
const { shouldIncludeSkill, SKILL_CATEGORIES, MINIMAL_SKILLS, getCategories } = require('./config');
|
|
13
15
|
|
|
14
16
|
const HOME = os.homedir();
|
|
15
17
|
const PACKAGE_ROOT = path.join(__dirname, '..');
|
|
@@ -59,9 +61,9 @@ const TOOLS = {
|
|
|
59
61
|
};
|
|
60
62
|
|
|
61
63
|
/**
|
|
62
|
-
* Copy directory recursively with optional text replacement
|
|
64
|
+
* Copy directory recursively with optional text replacement and skill filtering
|
|
63
65
|
*/
|
|
64
|
-
function copyDir(src, dest, replacements = {}) {
|
|
66
|
+
function copyDir(src, dest, replacements = {}, options = {}) {
|
|
65
67
|
if (!fs.existsSync(src)) {
|
|
66
68
|
return 0;
|
|
67
69
|
}
|
|
@@ -81,7 +83,11 @@ function copyDir(src, dest, replacements = {}) {
|
|
|
81
83
|
const destPath = path.join(dest, entry.name);
|
|
82
84
|
|
|
83
85
|
if (entry.isDirectory()) {
|
|
84
|
-
|
|
86
|
+
// Apply skill filter for skills directory
|
|
87
|
+
if (options.filterSkills && !shouldIncludeSkill(entry.name, options)) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
count += copyDir(srcPath, destPath, replacements, { ...options, filterSkills: false });
|
|
85
91
|
} else {
|
|
86
92
|
let content = fs.readFileSync(srcPath);
|
|
87
93
|
|
|
@@ -113,6 +119,21 @@ function isTextFile(filename) {
|
|
|
113
119
|
function installToTool(toolId, tool, options = {}) {
|
|
114
120
|
console.log(`\nš¦ Installing to ${tool.name}...`);
|
|
115
121
|
|
|
122
|
+
// Determine install mode
|
|
123
|
+
const indexOnly = options.indexOnly !== false && !options.fullSkills;
|
|
124
|
+
const isMinimal = options.minimal;
|
|
125
|
+
const hasCategories = options.categories && options.categories.length > 0;
|
|
126
|
+
|
|
127
|
+
if (indexOnly && !isMinimal && !hasCategories) {
|
|
128
|
+
console.log(` Mode: INDEX-ONLY (recommended - minimal context usage)`);
|
|
129
|
+
} else if (isMinimal) {
|
|
130
|
+
console.log(` Mode: MINIMAL (${MINIMAL_SKILLS.length} core skills)`);
|
|
131
|
+
} else if (hasCategories) {
|
|
132
|
+
console.log(` Categories: ${options.categories.join(', ')}`);
|
|
133
|
+
} else if (options.fullSkills) {
|
|
134
|
+
console.log(` Mode: FULL (all 413+ skills - may cause context limit issues)`);
|
|
135
|
+
}
|
|
136
|
+
|
|
116
137
|
const replacements = {
|
|
117
138
|
'\\{TOOL\\}': toolId,
|
|
118
139
|
'\\{HOME\\}': HOME,
|
|
@@ -121,12 +142,34 @@ function installToTool(toolId, tool, options = {}) {
|
|
|
121
142
|
|
|
122
143
|
let totalFiles = 0;
|
|
123
144
|
|
|
124
|
-
// 1. Install skills
|
|
145
|
+
// 1. Install skills - depends on mode
|
|
125
146
|
const srcSkills = path.join(PACKAGE_ROOT, 'skills');
|
|
126
147
|
if (fs.existsSync(srcSkills)) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
148
|
+
if (indexOnly && !isMinimal && !hasCategories) {
|
|
149
|
+
// Index-only mode: just copy the index files
|
|
150
|
+
const indexFile = path.join(PACKAGE_ROOT, 'SKILLS_INDEX.md');
|
|
151
|
+
const jsonFile = path.join(PACKAGE_ROOT, 'skills-index.json');
|
|
152
|
+
|
|
153
|
+
fs.mkdirSync(tool.skillsPath, { recursive: true });
|
|
154
|
+
|
|
155
|
+
if (fs.existsSync(indexFile)) {
|
|
156
|
+
fs.copyFileSync(indexFile, path.join(tool.skillsPath, 'SKILLS_INDEX.md'));
|
|
157
|
+
totalFiles++;
|
|
158
|
+
}
|
|
159
|
+
if (fs.existsSync(jsonFile)) {
|
|
160
|
+
fs.copyFileSync(jsonFile, path.join(tool.skillsPath, 'skills-index.json'));
|
|
161
|
+
totalFiles++;
|
|
162
|
+
}
|
|
163
|
+
console.log(` ā
Skills Index: ${totalFiles} files (use /skill <name> to load specific skills)`);
|
|
164
|
+
} else {
|
|
165
|
+
// Full or filtered skills
|
|
166
|
+
const count = copyDir(srcSkills, tool.skillsPath, replacements, {
|
|
167
|
+
...options,
|
|
168
|
+
filterSkills: isMinimal || hasCategories
|
|
169
|
+
});
|
|
170
|
+
console.log(` ā
Skills: ${count} files`);
|
|
171
|
+
totalFiles += count;
|
|
172
|
+
}
|
|
130
173
|
}
|
|
131
174
|
|
|
132
175
|
// 2. Install core framework under agent-assistant subfolder
|
|
@@ -137,7 +180,7 @@ function installToTool(toolId, tool, options = {}) {
|
|
|
137
180
|
const srcPath = path.join(PACKAGE_ROOT, name);
|
|
138
181
|
if (fs.existsSync(srcPath)) {
|
|
139
182
|
const destPath = path.join(coreDir, name);
|
|
140
|
-
const count = copyDir(srcPath, destPath, replacements);
|
|
183
|
+
const count = copyDir(srcPath, destPath, replacements, options);
|
|
141
184
|
console.log(` ā
${name}: ${count} files`);
|
|
142
185
|
totalFiles += count;
|
|
143
186
|
}
|
|
@@ -150,7 +193,7 @@ function installToTool(toolId, tool, options = {}) {
|
|
|
150
193
|
if (fs.existsSync(srcPath)) {
|
|
151
194
|
const destName = name.replace('-claudekit', '');
|
|
152
195
|
const destPath = path.join(coreDir, 'claudekit', destName);
|
|
153
|
-
const count = copyDir(srcPath, destPath, replacements);
|
|
196
|
+
const count = copyDir(srcPath, destPath, replacements, options);
|
|
154
197
|
console.log(` ā
claudekit/${destName}: ${count} files`);
|
|
155
198
|
totalFiles += count;
|
|
156
199
|
}
|
|
@@ -159,7 +202,7 @@ function installToTool(toolId, tool, options = {}) {
|
|
|
159
202
|
// 4. Install rules
|
|
160
203
|
const srcRules = path.join(PACKAGE_ROOT, 'rules');
|
|
161
204
|
if (fs.existsSync(srcRules) && tool.rulesPath) {
|
|
162
|
-
const count = copyDir(srcRules, tool.rulesPath, replacements);
|
|
205
|
+
const count = copyDir(srcRules, tool.rulesPath, replacements, options);
|
|
163
206
|
console.log(` ā
Rules: ${count} files`);
|
|
164
207
|
totalFiles += count;
|
|
165
208
|
}
|
|
@@ -168,7 +211,7 @@ function installToTool(toolId, tool, options = {}) {
|
|
|
168
211
|
if (tool.supportsHooks && tool.hooksPath) {
|
|
169
212
|
const srcHooks = path.join(PACKAGE_ROOT, 'hooks');
|
|
170
213
|
if (fs.existsSync(srcHooks)) {
|
|
171
|
-
const count = copyDir(srcHooks, tool.hooksPath, replacements);
|
|
214
|
+
const count = copyDir(srcHooks, tool.hooksPath, replacements, options);
|
|
172
215
|
console.log(` ā
Hooks: ${count} files`);
|
|
173
216
|
totalFiles += count;
|
|
174
217
|
}
|
|
@@ -179,7 +222,7 @@ function installToTool(toolId, tool, options = {}) {
|
|
|
179
222
|
const srcStyles = path.join(PACKAGE_ROOT, 'output-styles');
|
|
180
223
|
if (fs.existsSync(srcStyles)) {
|
|
181
224
|
const destStyles = path.join(tool.basePath, 'output-styles');
|
|
182
|
-
const count = copyDir(srcStyles, destStyles, replacements);
|
|
225
|
+
const count = copyDir(srcStyles, destStyles, replacements, options);
|
|
183
226
|
console.log(` ā
Output Styles: ${count} files`);
|
|
184
227
|
totalFiles += count;
|
|
185
228
|
}
|
|
@@ -188,7 +231,7 @@ function installToTool(toolId, tool, options = {}) {
|
|
|
188
231
|
const srcWorkflows = path.join(PACKAGE_ROOT, 'workflows');
|
|
189
232
|
if (fs.existsSync(srcWorkflows)) {
|
|
190
233
|
const destWorkflows = path.join(tool.basePath, 'workflows');
|
|
191
|
-
const count = copyDir(
|
|
234
|
+
const count = copyDir(destWorkflows, destWorkflows, replacements, options);
|
|
192
235
|
console.log(` ā
Workflows: ${count} files`);
|
|
193
236
|
totalFiles += count;
|
|
194
237
|
}
|
|
@@ -221,7 +264,7 @@ function installToTool(toolId, tool, options = {}) {
|
|
|
221
264
|
/**
|
|
222
265
|
* Main install function
|
|
223
266
|
*/
|
|
224
|
-
function install(targetTool = null) {
|
|
267
|
+
function install(targetTool = null, options = {}) {
|
|
225
268
|
console.log('\n' + '='.repeat(60));
|
|
226
269
|
console.log(' DEVKIT - INSTALLER');
|
|
227
270
|
console.log(' Merged: antigravity + agent-assistant + claudekit + skill-rule');
|
|
@@ -238,7 +281,7 @@ function install(targetTool = null) {
|
|
|
238
281
|
continue;
|
|
239
282
|
}
|
|
240
283
|
const tool = TOOLS[toolId];
|
|
241
|
-
totalInstalled += installToTool(toolId, tool);
|
|
284
|
+
totalInstalled += installToTool(toolId, tool, options);
|
|
242
285
|
}
|
|
243
286
|
|
|
244
287
|
console.log('\n' + '='.repeat(60));
|
|
@@ -255,20 +298,225 @@ function install(targetTool = null) {
|
|
|
255
298
|
console.log('');
|
|
256
299
|
}
|
|
257
300
|
|
|
301
|
+
/**
|
|
302
|
+
* Uninstall function - removes all installed files
|
|
303
|
+
*/
|
|
304
|
+
function uninstall(targetTool = null) {
|
|
305
|
+
console.log('\n' + '='.repeat(60));
|
|
306
|
+
console.log(' DEVKIT - UNINSTALLER');
|
|
307
|
+
console.log('='.repeat(60));
|
|
308
|
+
|
|
309
|
+
const tools = targetTool ? [targetTool] : Object.keys(TOOLS);
|
|
310
|
+
|
|
311
|
+
for (const toolId of tools) {
|
|
312
|
+
if (!TOOLS[toolId]) {
|
|
313
|
+
console.log(`\nā Unknown tool: ${toolId}`);
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const tool = TOOLS[toolId];
|
|
318
|
+
console.log(`\nšļø Uninstalling from ${tool.name}...`);
|
|
319
|
+
|
|
320
|
+
// Remove skills directory
|
|
321
|
+
if (tool.skillsPath && fs.existsSync(tool.skillsPath)) {
|
|
322
|
+
fs.rmSync(tool.skillsPath, { recursive: true, force: true });
|
|
323
|
+
console.log(` ā
Removed: ${tool.skillsPath}`);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Remove rules directory (be careful - might have user rules)
|
|
327
|
+
if (tool.rulesPath && fs.existsSync(tool.rulesPath)) {
|
|
328
|
+
const devkitRulesMarker = path.join(tool.rulesPath, '.devkit-installed');
|
|
329
|
+
// Only remove if we installed it (check for our marker or known files)
|
|
330
|
+
fs.rmSync(tool.rulesPath, { recursive: true, force: true });
|
|
331
|
+
console.log(` ā
Removed: ${tool.rulesPath}`);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Remove hooks (Claude only)
|
|
335
|
+
if (tool.supportsHooks && tool.hooksPath && fs.existsSync(tool.hooksPath)) {
|
|
336
|
+
fs.rmSync(tool.hooksPath, { recursive: true, force: true });
|
|
337
|
+
console.log(` ā
Removed: ${tool.hooksPath}`);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Remove Claude-specific directories
|
|
341
|
+
if (toolId === 'claude') {
|
|
342
|
+
const extraDirs = ['output-styles', 'workflows'];
|
|
343
|
+
for (const dir of extraDirs) {
|
|
344
|
+
const dirPath = path.join(tool.basePath, dir);
|
|
345
|
+
if (fs.existsSync(dirPath)) {
|
|
346
|
+
fs.rmSync(dirPath, { recursive: true, force: true });
|
|
347
|
+
console.log(` ā
Removed: ${dirPath}`);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// Remove statusline files
|
|
352
|
+
const statuslineFiles = ['statusline.cjs', 'statusline.ps1', 'statusline.sh'];
|
|
353
|
+
for (const file of statuslineFiles) {
|
|
354
|
+
const filePath = path.join(tool.basePath, file);
|
|
355
|
+
if (fs.existsSync(filePath)) {
|
|
356
|
+
fs.rmSync(filePath);
|
|
357
|
+
console.log(` ā
Removed: ${filePath}`);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
console.log('\n' + '='.repeat(60));
|
|
364
|
+
console.log(' ā
UNINSTALLATION COMPLETE');
|
|
365
|
+
console.log('='.repeat(60));
|
|
366
|
+
console.log('\nDevkit has been removed from your system.');
|
|
367
|
+
console.log('To reinstall: npm install -g @ngxtm/devkit && devkit install\n');
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Interactive skill selection
|
|
372
|
+
*/
|
|
373
|
+
async function interactiveInstall(targetTool = null) {
|
|
374
|
+
const rl = readline.createInterface({
|
|
375
|
+
input: process.stdin,
|
|
376
|
+
output: process.stdout
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
const question = (prompt) => new Promise(resolve => rl.question(prompt, resolve));
|
|
380
|
+
|
|
381
|
+
console.log('\n' + '='.repeat(60));
|
|
382
|
+
console.log(' DEVKIT - INTERACTIVE INSTALLER');
|
|
383
|
+
console.log('='.repeat(60));
|
|
384
|
+
|
|
385
|
+
// Show categories
|
|
386
|
+
console.log('\nAvailable categories:\n');
|
|
387
|
+
const categories = getCategories();
|
|
388
|
+
categories.forEach((cat, i) => {
|
|
389
|
+
const skills = SKILL_CATEGORIES[cat];
|
|
390
|
+
console.log(` ${i + 1}. ${cat.padEnd(15)} (${skills.length} skills)`);
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
console.log(`\n ${categories.length + 1}. minimal (${MINIMAL_SKILLS.length} core skills)`);
|
|
394
|
+
console.log(` ${categories.length + 2}. all (all 413+ skills)`);
|
|
395
|
+
|
|
396
|
+
// Get user selection
|
|
397
|
+
console.log('\nEnter category numbers separated by comma (e.g., 1,3,5)');
|
|
398
|
+
console.log('Or type category names (e.g., react,typescript,testing)');
|
|
399
|
+
const answer = await question('\nYour selection: ');
|
|
400
|
+
|
|
401
|
+
rl.close();
|
|
402
|
+
|
|
403
|
+
// Parse selection
|
|
404
|
+
const input = answer.trim().toLowerCase();
|
|
405
|
+
|
|
406
|
+
if (input === 'all' || input === String(categories.length + 2)) {
|
|
407
|
+
console.log('\nInstalling all skills...');
|
|
408
|
+
install(targetTool, {});
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
if (input === 'minimal' || input === String(categories.length + 1)) {
|
|
413
|
+
console.log('\nInstalling minimal skills...');
|
|
414
|
+
install(targetTool, { minimal: true });
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// Parse as numbers or category names
|
|
419
|
+
let selectedCategories = [];
|
|
420
|
+
|
|
421
|
+
const parts = input.split(',').map(p => p.trim());
|
|
422
|
+
for (const part of parts) {
|
|
423
|
+
const num = parseInt(part);
|
|
424
|
+
if (!isNaN(num) && num >= 1 && num <= categories.length) {
|
|
425
|
+
selectedCategories.push(categories[num - 1]);
|
|
426
|
+
} else if (categories.includes(part)) {
|
|
427
|
+
selectedCategories.push(part);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
if (selectedCategories.length === 0) {
|
|
432
|
+
console.log('\nNo valid categories selected. Installing minimal set...');
|
|
433
|
+
install(targetTool, { minimal: true });
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
console.log(`\nInstalling categories: ${selectedCategories.join(', ')}...`);
|
|
438
|
+
install(targetTool, { categories: selectedCategories });
|
|
439
|
+
}
|
|
440
|
+
|
|
258
441
|
/**
|
|
259
442
|
* Update function
|
|
260
443
|
*/
|
|
261
444
|
function update() {
|
|
262
445
|
console.log('Checking for updates...\n');
|
|
263
446
|
console.log('Run: npm update -g @ngxtm/devkit');
|
|
264
|
-
console.log('Then: devkit
|
|
447
|
+
console.log('Then: devkit install');
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* List available skills
|
|
452
|
+
*/
|
|
453
|
+
function listSkills() {
|
|
454
|
+
const skillsDir = path.join(PACKAGE_ROOT, 'skills');
|
|
455
|
+
|
|
456
|
+
if (!fs.existsSync(skillsDir)) {
|
|
457
|
+
console.log('No skills directory found.');
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
const skills = fs.readdirSync(skillsDir)
|
|
462
|
+
.filter(f => fs.statSync(path.join(skillsDir, f)).isDirectory())
|
|
463
|
+
.filter(f => !f.startsWith('.'));
|
|
464
|
+
|
|
465
|
+
console.log(`\nAvailable Skills (${skills.length} total):\n`);
|
|
466
|
+
|
|
467
|
+
skills.forEach(skill => {
|
|
468
|
+
console.log(` - ${skill}`);
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
console.log('\nUse "devkit install" to install these skills.\n');
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* List categories
|
|
476
|
+
*/
|
|
477
|
+
function listCategories() {
|
|
478
|
+
console.log('\n' + '='.repeat(60));
|
|
479
|
+
console.log(' DEVKIT - SKILL CATEGORIES');
|
|
480
|
+
console.log('='.repeat(60));
|
|
481
|
+
|
|
482
|
+
const categories = getCategories();
|
|
483
|
+
|
|
484
|
+
console.log('\nAvailable categories:\n');
|
|
485
|
+
for (const cat of categories) {
|
|
486
|
+
const skills = SKILL_CATEGORIES[cat];
|
|
487
|
+
console.log(` ${cat.padEnd(15)} (${skills.length} skills)`);
|
|
488
|
+
skills.slice(0, 3).forEach(s => console.log(` - ${s}`));
|
|
489
|
+
if (skills.length > 3) {
|
|
490
|
+
console.log(` ... and ${skills.length - 3} more`);
|
|
491
|
+
}
|
|
492
|
+
console.log('');
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
console.log('\nUsage:');
|
|
496
|
+
console.log(' devkit install --category=react,typescript');
|
|
497
|
+
console.log(' devkit install --minimal');
|
|
498
|
+
console.log(' devkit install --interactive\n');
|
|
265
499
|
}
|
|
266
500
|
|
|
267
501
|
// Export for CLI
|
|
268
|
-
module.exports = {
|
|
502
|
+
module.exports = {
|
|
503
|
+
install,
|
|
504
|
+
uninstall,
|
|
505
|
+
update,
|
|
506
|
+
interactiveInstall,
|
|
507
|
+
listSkills,
|
|
508
|
+
listCategories,
|
|
509
|
+
TOOLS
|
|
510
|
+
};
|
|
269
511
|
|
|
270
512
|
// Run if called directly
|
|
271
513
|
if (require.main === module) {
|
|
272
|
-
const
|
|
273
|
-
|
|
514
|
+
const args = process.argv.slice(2);
|
|
515
|
+
const targetTool = args.find(a => !a.startsWith('-'));
|
|
516
|
+
|
|
517
|
+
if (args.includes('--uninstall') || args.includes('-u')) {
|
|
518
|
+
uninstall(targetTool);
|
|
519
|
+
} else {
|
|
520
|
+
install(targetTool);
|
|
521
|
+
}
|
|
274
522
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ngxtm/devkit",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Unified multi-agent system with auto-synced skills from multiple sources",
|
|
5
5
|
"main": "cli/install.js",
|
|
6
6
|
"bin": {
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"install-global": "node cli/install.js",
|
|
11
|
+
"generate-index": "node scripts/generate-index.js",
|
|
11
12
|
"sync": "python scripts/sync_all.py",
|
|
12
13
|
"validate": "python scripts/validate_skills.py",
|
|
13
14
|
"update-matrix": "python scripts/update_matrix.py"
|
|
@@ -27,7 +28,9 @@
|
|
|
27
28
|
"settings.json",
|
|
28
29
|
"statusline.cjs",
|
|
29
30
|
"statusline.ps1",
|
|
30
|
-
"statusline.sh"
|
|
31
|
+
"statusline.sh",
|
|
32
|
+
"SKILLS_INDEX.md",
|
|
33
|
+
"skills-index.json"
|
|
31
34
|
],
|
|
32
35
|
"keywords": [
|
|
33
36
|
"ai",
|