agentic-skill-mill 1.0.10 → 1.0.11
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 +8 -12
- package/compiled/claude/agentic-skill-mill/SKILL.md +21 -24
- package/compiled/codex/agentic-skill-mill/SKILL.md +21 -24
- package/compiled/cursor/skills/agentic-skill-mill/SKILL.md +21 -24
- package/compiled/opencode/agentic-skill-mill.md +21 -24
- package/compiled/windsurf/skills/agentic-skill-mill/SKILL.md +21 -24
- package/dist/core/scaffold.js +0 -1
- package/dist/core/scaffold.js.map +1 -1
- package/install.js +555 -0
- package/package.json +10 -13
- package/skill/build/manifest.json +0 -2
- package/skill/fragments/meta/architecture-overview.md +5 -5
- package/skill/fragments/meta/distribution-and-ci.md +12 -14
- package/skill/fragments/meta/rename-workflow.md +2 -2
- package/skill/skills/agentic-skill-mill/agentic-skill-mill.md +2 -3
- package/compiled/cursor/rules/agentic-skill-mill.mdc +0 -555
- package/compiled/windsurf/rules/agentic-skill-mill.md +0 -555
- package/install-local.ps1 +0 -385
- package/install-local.sh +0 -265
- package/install.ps1 +0 -48
- package/install.sh +0 -44
package/install.js
ADDED
|
@@ -0,0 +1,555 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Unified install script for agentic-skill-mill.
|
|
4
|
+
*
|
|
5
|
+
* Cross-platform Node.js implementation that replaces:
|
|
6
|
+
* - install.sh / install.ps1
|
|
7
|
+
* - install-local.sh / install-local.ps1
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* node install.js [options]
|
|
11
|
+
*
|
|
12
|
+
* Options:
|
|
13
|
+
* --claude Install skills for Claude Code
|
|
14
|
+
* --cursor Install skills for Cursor
|
|
15
|
+
* --windsurf Install skills for Windsurf
|
|
16
|
+
* --opencode Install skills for OpenCode
|
|
17
|
+
* --codex Install skills for Codex
|
|
18
|
+
* --all Install for all five tools
|
|
19
|
+
* --skills-only Skip npm install/build/link (just copy skills)
|
|
20
|
+
* --uninstall Remove installed skills from target tools
|
|
21
|
+
* --compile-only Generate compiled/ output directory (no install)
|
|
22
|
+
* -h, --help Show this help
|
|
23
|
+
*
|
|
24
|
+
* If no flags are provided, the script auto-detects installed tools.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import fs from 'node:fs';
|
|
28
|
+
import path from 'node:path';
|
|
29
|
+
import os from 'node:os';
|
|
30
|
+
import { spawnSync } from 'node:child_process';
|
|
31
|
+
import { fileURLToPath } from 'node:url';
|
|
32
|
+
|
|
33
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
34
|
+
const repoDir = path.dirname(path.resolve(__filename));
|
|
35
|
+
|
|
36
|
+
// --- Constants -------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
const MANAGED_MARKER = 'managed_by: agentic-skill-mill';
|
|
39
|
+
const PROJECT_NAME = 'agentic-skill-mill';
|
|
40
|
+
const CLI_BIN_NAME = 'skillmill';
|
|
41
|
+
const SKILL_NAME = 'agentic-skill-mill';
|
|
42
|
+
|
|
43
|
+
const HOME = os.homedir();
|
|
44
|
+
const APPDATA = process.env.APPDATA;
|
|
45
|
+
|
|
46
|
+
// --- Source dirs (compiled output) -------------------------------------
|
|
47
|
+
|
|
48
|
+
const COMPILED_DIR = path.join(repoDir, 'compiled');
|
|
49
|
+
|
|
50
|
+
const SRC = {
|
|
51
|
+
claude: path.join(COMPILED_DIR, 'claude', SKILL_NAME),
|
|
52
|
+
cursorSkills: path.join(COMPILED_DIR, 'cursor', 'skills'),
|
|
53
|
+
windsurfSkills: path.join(COMPILED_DIR, 'windsurf', 'skills'),
|
|
54
|
+
opencode: path.join(COMPILED_DIR, 'opencode'),
|
|
55
|
+
codex: path.join(COMPILED_DIR, 'codex', SKILL_NAME),
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// --- Target directories -----------------------------------------------------
|
|
59
|
+
|
|
60
|
+
const DEST = {
|
|
61
|
+
claude: path.join(HOME, '.claude', 'skills', SKILL_NAME),
|
|
62
|
+
cursorSkills: path.join(HOME, '.cursor', 'skills', SKILL_NAME),
|
|
63
|
+
windsurfSkills: path.join(HOME, '.codeium', 'windsurf', 'skills', SKILL_NAME),
|
|
64
|
+
opencode: path.join(APPDATA || path.join(HOME, '.config', 'opencode'), 'agents'),
|
|
65
|
+
codex: path.join(process.env.CODEX_HOME || path.join(HOME, '.codex'), 'skills', SKILL_NAME),
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// --- Filesystem helpers ----------------------------------------------------
|
|
69
|
+
|
|
70
|
+
function ensureDir(dir) {
|
|
71
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function listFiles(dir, ext) {
|
|
75
|
+
if (!fs.existsSync(dir)) return [];
|
|
76
|
+
return fs.readdirSync(dir)
|
|
77
|
+
.filter((name) => name.endsWith(ext))
|
|
78
|
+
.map((name) => path.join(dir, name));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function readText(file) {
|
|
82
|
+
return fs.readFileSync(file, 'utf8');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function writeText(file, content) {
|
|
86
|
+
ensureDir(path.dirname(file));
|
|
87
|
+
fs.writeFileSync(file, content);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function fileExists(file) {
|
|
91
|
+
try {
|
|
92
|
+
return fs.statSync(file).isFile();
|
|
93
|
+
} catch {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function dirExists(dir) {
|
|
99
|
+
try {
|
|
100
|
+
return fs.statSync(dir).isDirectory();
|
|
101
|
+
} catch {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function fileContains(file, marker) {
|
|
107
|
+
if (!fileExists(file)) return false;
|
|
108
|
+
return readText(file).includes(marker);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function cleanupManagedFiles(destDir) {
|
|
112
|
+
if (!dirExists(destDir)) return;
|
|
113
|
+
const walk = (d) => {
|
|
114
|
+
for (const entry of fs.readdirSync(d, { withFileTypes: true })) {
|
|
115
|
+
const full = path.join(d, entry.name);
|
|
116
|
+
if (entry.isDirectory()) {
|
|
117
|
+
walk(full);
|
|
118
|
+
} else if (entry.isFile() && fileContains(full, MANAGED_MARKER)) {
|
|
119
|
+
fs.unlinkSync(full);
|
|
120
|
+
console.log(` Removed stale: ${full}`);
|
|
121
|
+
// Try to remove empty parent dirs
|
|
122
|
+
const parent = path.dirname(full);
|
|
123
|
+
try {
|
|
124
|
+
if (dirExists(parent) && fs.readdirSync(parent).length === 0) {
|
|
125
|
+
fs.rmdirSync(parent);
|
|
126
|
+
}
|
|
127
|
+
} catch {
|
|
128
|
+
// Ignore errors
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
walk(destDir);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function copyFile(src, dest) {
|
|
137
|
+
ensureDir(path.dirname(dest));
|
|
138
|
+
fs.copyFileSync(src, dest);
|
|
139
|
+
console.log(` ${dest}`);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// --- Shell helpers --------------------------------------------------------
|
|
143
|
+
|
|
144
|
+
function runNode(args, options = {}) {
|
|
145
|
+
const result = spawnSync('node', args, {
|
|
146
|
+
stdio: 'inherit',
|
|
147
|
+
cwd: repoDir,
|
|
148
|
+
...options,
|
|
149
|
+
});
|
|
150
|
+
if (result.status !== 0) {
|
|
151
|
+
process.exit(result.status ?? 1);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function runNpm(args, options = {}) {
|
|
156
|
+
const result = spawnSync('npm', args, {
|
|
157
|
+
stdio: 'inherit',
|
|
158
|
+
cwd: repoDir,
|
|
159
|
+
...options,
|
|
160
|
+
});
|
|
161
|
+
if (result.status !== 0) {
|
|
162
|
+
process.exit(result.status ?? 1);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// --- Install functions ------------------------------------------------------
|
|
167
|
+
|
|
168
|
+
function installClaude() {
|
|
169
|
+
const src = SRC.claude;
|
|
170
|
+
const dest = DEST.claude;
|
|
171
|
+
if (!dirExists(src)) {
|
|
172
|
+
console.log(` Warning: source missing ${src}`);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
ensureDir(dest);
|
|
176
|
+
const srcFile = path.join(src, 'SKILL.md');
|
|
177
|
+
if (fileExists(srcFile)) {
|
|
178
|
+
copyFile(srcFile, path.join(dest, 'SKILL.md'));
|
|
179
|
+
}
|
|
180
|
+
console.log(` Claude: ${dest}`);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function installCursor() {
|
|
184
|
+
// Skills directory only (not rules)
|
|
185
|
+
const srcSkills = SRC.cursorSkills;
|
|
186
|
+
const destSkills = DEST.cursorSkills;
|
|
187
|
+
if (dirExists(srcSkills)) {
|
|
188
|
+
ensureDir(destSkills);
|
|
189
|
+
const srcFile = path.join(srcSkills, 'SKILL.md');
|
|
190
|
+
if (fileExists(srcFile)) {
|
|
191
|
+
copyFile(srcFile, path.join(destSkills, 'SKILL.md'));
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
console.log(` Cursor: skills -> ${destSkills}`);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function installWindsurf() {
|
|
198
|
+
// Skills directory only (not rules)
|
|
199
|
+
const srcSkills = SRC.windsurfSkills;
|
|
200
|
+
const destSkills = DEST.windsurfSkills;
|
|
201
|
+
if (dirExists(srcSkills)) {
|
|
202
|
+
ensureDir(destSkills);
|
|
203
|
+
const srcFile = path.join(srcSkills, 'SKILL.md');
|
|
204
|
+
if (fileExists(srcFile)) {
|
|
205
|
+
copyFile(srcFile, path.join(destSkills, 'SKILL.md'));
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
console.log(` Windsurf: skills -> ${destSkills}`);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function installOpenCode() {
|
|
212
|
+
const src = SRC.opencode;
|
|
213
|
+
const dest = DEST.opencode;
|
|
214
|
+
if (!dirExists(src)) {
|
|
215
|
+
console.log(` Warning: source missing ${src}`);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
ensureDir(dest);
|
|
219
|
+
// opencode uses .md files directly in agents directory
|
|
220
|
+
for (const srcFile of listFiles(src, '.md')) {
|
|
221
|
+
const destFile = path.join(dest, path.basename(srcFile));
|
|
222
|
+
copyFile(srcFile, destFile);
|
|
223
|
+
}
|
|
224
|
+
console.log(` OpenCode: ${dest}`);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function installCodex() {
|
|
228
|
+
const src = SRC.codex;
|
|
229
|
+
const dest = DEST.codex;
|
|
230
|
+
if (!dirExists(src)) {
|
|
231
|
+
console.log(` Warning: source missing ${src}`);
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
ensureDir(dest);
|
|
235
|
+
const srcFile = path.join(src, 'SKILL.md');
|
|
236
|
+
if (fileExists(srcFile)) {
|
|
237
|
+
copyFile(srcFile, path.join(dest, 'SKILL.md'));
|
|
238
|
+
}
|
|
239
|
+
console.log(` Codex: ${dest}`);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// --- Uninstall functions ---------------------------------------------------
|
|
243
|
+
|
|
244
|
+
function uninstallClaude() {
|
|
245
|
+
const dest = DEST.claude;
|
|
246
|
+
if (dirExists(dest)) {
|
|
247
|
+
fs.rmSync(dest, { recursive: true, force: true });
|
|
248
|
+
}
|
|
249
|
+
console.log(` Claude: removed`);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function uninstallCursor() {
|
|
253
|
+
const destSkills = DEST.cursorSkills;
|
|
254
|
+
if (dirExists(destSkills)) {
|
|
255
|
+
fs.rmSync(destSkills, { recursive: true, force: true });
|
|
256
|
+
}
|
|
257
|
+
console.log(` Cursor: removed`);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function uninstallWindsurf() {
|
|
261
|
+
const destSkills = DEST.windsurfSkills;
|
|
262
|
+
if (dirExists(destSkills)) {
|
|
263
|
+
fs.rmSync(destSkills, { recursive: true, force: true });
|
|
264
|
+
}
|
|
265
|
+
console.log(` Windsurf: removed`);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function uninstallOpenCode() {
|
|
269
|
+
const dest = DEST.opencode;
|
|
270
|
+
if (dirExists(dest)) {
|
|
271
|
+
for (const f of listFiles(dest, '.md')) {
|
|
272
|
+
if (fileContains(f, MANAGED_MARKER)) {
|
|
273
|
+
fs.unlinkSync(f);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
console.log(` OpenCode: removed`);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function uninstallCodex() {
|
|
281
|
+
const dest = DEST.codex;
|
|
282
|
+
if (dirExists(dest)) {
|
|
283
|
+
fs.rmSync(dest, { recursive: true, force: true });
|
|
284
|
+
}
|
|
285
|
+
console.log(` Codex: removed`);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// --- Auto-detection -------------------------------------------------------
|
|
289
|
+
|
|
290
|
+
function detectEditors() {
|
|
291
|
+
const detected = [];
|
|
292
|
+
if (dirExists(path.join(HOME, '.claude'))) detected.push('claude');
|
|
293
|
+
if (dirExists(path.join(HOME, '.cursor'))) detected.push('cursor');
|
|
294
|
+
if (
|
|
295
|
+
dirExists(path.join(HOME, '.windsurf')) ||
|
|
296
|
+
dirExists(path.join(HOME, '.codeium', 'windsurf'))
|
|
297
|
+
) {
|
|
298
|
+
detected.push('windsurf');
|
|
299
|
+
}
|
|
300
|
+
if (
|
|
301
|
+
dirExists(path.join(APPDATA || path.join(HOME, '.config', 'opencode'))) ||
|
|
302
|
+
dirExists(path.join(HOME, '.config', 'opencode'))
|
|
303
|
+
) {
|
|
304
|
+
detected.push('opencode');
|
|
305
|
+
}
|
|
306
|
+
if (
|
|
307
|
+
process.env.CODEX_HOME ||
|
|
308
|
+
dirExists(path.join(HOME, '.codex'))
|
|
309
|
+
) {
|
|
310
|
+
detected.push('codex');
|
|
311
|
+
}
|
|
312
|
+
return detected;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// --- CLI parsing ---------------------------------------------------------
|
|
316
|
+
|
|
317
|
+
function printHelp() {
|
|
318
|
+
process.stdout.write(`Usage: node install.js [options]
|
|
319
|
+
|
|
320
|
+
Options:
|
|
321
|
+
--claude Install skills for Claude Code
|
|
322
|
+
--cursor Install skills for Cursor
|
|
323
|
+
--windsurf Install skills for Windsurf
|
|
324
|
+
--opencode Install skills for OpenCode
|
|
325
|
+
--codex Install skills for Codex
|
|
326
|
+
--all Install for all five tools
|
|
327
|
+
--skills-only Skip npm install/build/link (just copy skills)
|
|
328
|
+
--uninstall Remove installed skills from target tools
|
|
329
|
+
--compile-only Generate compiled/ output directory (no install)
|
|
330
|
+
-h, --help Show this help
|
|
331
|
+
|
|
332
|
+
No flags = auto-detect installed tools.
|
|
333
|
+
|
|
334
|
+
Environment overrides:
|
|
335
|
+
CODEX_HOME Codex home directory (default: ~/.codex)
|
|
336
|
+
`);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function parseArgs(argv) {
|
|
340
|
+
const targets = [];
|
|
341
|
+
const flags = {
|
|
342
|
+
help: false,
|
|
343
|
+
skillsOnly: false,
|
|
344
|
+
uninstall: false,
|
|
345
|
+
compileOnly: false,
|
|
346
|
+
all: false,
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
for (const arg of argv) {
|
|
350
|
+
switch (arg) {
|
|
351
|
+
case '--claude':
|
|
352
|
+
targets.push('claude');
|
|
353
|
+
break;
|
|
354
|
+
case '--cursor':
|
|
355
|
+
targets.push('cursor');
|
|
356
|
+
break;
|
|
357
|
+
case '--windsurf':
|
|
358
|
+
targets.push('windsurf');
|
|
359
|
+
break;
|
|
360
|
+
case '--opencode':
|
|
361
|
+
targets.push('opencode');
|
|
362
|
+
break;
|
|
363
|
+
case '--codex':
|
|
364
|
+
targets.push('codex');
|
|
365
|
+
break;
|
|
366
|
+
case '--all':
|
|
367
|
+
flags.all = true;
|
|
368
|
+
break;
|
|
369
|
+
case '--skills-only':
|
|
370
|
+
flags.skillsOnly = true;
|
|
371
|
+
break;
|
|
372
|
+
case '--uninstall':
|
|
373
|
+
flags.uninstall = true;
|
|
374
|
+
break;
|
|
375
|
+
case '--compile-only':
|
|
376
|
+
flags.compileOnly = true;
|
|
377
|
+
break;
|
|
378
|
+
case '-h':
|
|
379
|
+
case '--help':
|
|
380
|
+
flags.help = true;
|
|
381
|
+
break;
|
|
382
|
+
default:
|
|
383
|
+
console.error(`Unknown option: ${arg}`);
|
|
384
|
+
console.error('Run: node install.js --help');
|
|
385
|
+
process.exit(1);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
if (flags.all) {
|
|
390
|
+
targets.length = 0;
|
|
391
|
+
targets.push('claude', 'cursor', 'windsurf', 'opencode', 'codex');
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
return { targets, flags };
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// --- Build orchestration -------------------------------------------------
|
|
398
|
+
|
|
399
|
+
function buildProject() {
|
|
400
|
+
console.log('--> Installing dependencies...');
|
|
401
|
+
runNpm(['install']);
|
|
402
|
+
|
|
403
|
+
console.log('--> Cleaning previous build...');
|
|
404
|
+
const distDir = path.join(repoDir, 'dist');
|
|
405
|
+
if (dirExists(distDir)) {
|
|
406
|
+
fs.rmSync(distDir, { recursive: true });
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
console.log('--> Building TypeScript...');
|
|
410
|
+
runNpm(['run', 'build']);
|
|
411
|
+
|
|
412
|
+
const distCli = path.join(distDir, 'cli', 'index.js');
|
|
413
|
+
if (fileExists(distCli)) {
|
|
414
|
+
fs.chmodSync(distCli, 0o755);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
console.log('--> Compiling skills...');
|
|
418
|
+
runNpm(['run', 'compile']);
|
|
419
|
+
|
|
420
|
+
console.log('--> Linking CLI globally...');
|
|
421
|
+
runNpm(['link']);
|
|
422
|
+
|
|
423
|
+
// Verify CLI is available
|
|
424
|
+
const npmPrefix = spawnSync('npm', ['prefix', '-g'], { encoding: 'utf8' }).stdout.trim();
|
|
425
|
+
const cliPath = path.join(npmPrefix, 'bin', CLI_BIN_NAME);
|
|
426
|
+
const cliPathAlt = path.join(npmPrefix, 'bin', `${CLI_BIN_NAME}.cmd`);
|
|
427
|
+
|
|
428
|
+
if (fileExists(cliPath) || fileExists(cliPathAlt)) {
|
|
429
|
+
console.log(` ${CLI_BIN_NAME}: ${cliPath}`);
|
|
430
|
+
} else {
|
|
431
|
+
console.log(` Warning: ${CLI_BIN_NAME} not found after npm link. Try: npm link`);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// --- Main -----------------------------------------------------------------
|
|
436
|
+
|
|
437
|
+
function main(argv) {
|
|
438
|
+
const { targets, flags } = parseArgs(argv);
|
|
439
|
+
|
|
440
|
+
if (flags.help) {
|
|
441
|
+
printHelp();
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// Compile-only path
|
|
446
|
+
if (flags.compileOnly) {
|
|
447
|
+
console.log('==> Compiling skills...');
|
|
448
|
+
runNode([path.join(repoDir, 'skill', 'build', 'compile.mjs')]);
|
|
449
|
+
console.log('==> Done.');
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// Resolve targets
|
|
454
|
+
let resolvedTargets = targets.length > 0 ? targets : detectEditors();
|
|
455
|
+
|
|
456
|
+
if (resolvedTargets.length === 0) {
|
|
457
|
+
console.error(
|
|
458
|
+
'ERROR: No supported tools detected. Use --claude, --cursor, --windsurf, --opencode, or --codex.'
|
|
459
|
+
);
|
|
460
|
+
process.exit(1);
|
|
461
|
+
}
|
|
462
|
+
// Dedupe
|
|
463
|
+
resolvedTargets = [...new Set(resolvedTargets)];
|
|
464
|
+
|
|
465
|
+
console.log(`==> ${PROJECT_NAME} setup`);
|
|
466
|
+
console.log(` Project: ${repoDir}`);
|
|
467
|
+
console.log(` Targets: ${resolvedTargets.join(' ')}`);
|
|
468
|
+
console.log('');
|
|
469
|
+
|
|
470
|
+
// Uninstall path
|
|
471
|
+
if (flags.uninstall) {
|
|
472
|
+
console.log('==> Uninstalling...');
|
|
473
|
+
for (const t of resolvedTargets) {
|
|
474
|
+
switch (t) {
|
|
475
|
+
case 'claude':
|
|
476
|
+
uninstallClaude();
|
|
477
|
+
break;
|
|
478
|
+
case 'cursor':
|
|
479
|
+
uninstallCursor();
|
|
480
|
+
break;
|
|
481
|
+
case 'windsurf':
|
|
482
|
+
uninstallWindsurf();
|
|
483
|
+
break;
|
|
484
|
+
case 'opencode':
|
|
485
|
+
uninstallOpenCode();
|
|
486
|
+
break;
|
|
487
|
+
case 'codex':
|
|
488
|
+
uninstallCodex();
|
|
489
|
+
break;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
console.log('--> Removing CLI link...');
|
|
494
|
+
runNpm(['unlink', PROJECT_NAME]);
|
|
495
|
+
|
|
496
|
+
console.log('');
|
|
497
|
+
console.log('==> Done. Skills and CLI removed.');
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// Install path
|
|
502
|
+
if (!flags.skillsOnly) {
|
|
503
|
+
buildProject();
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
console.log('--> Cleaning stale files...');
|
|
507
|
+
for (const t of resolvedTargets) {
|
|
508
|
+
switch (t) {
|
|
509
|
+
case 'claude':
|
|
510
|
+
cleanupManagedFiles(DEST.claude);
|
|
511
|
+
break;
|
|
512
|
+
case 'cursor':
|
|
513
|
+
cleanupManagedFiles(DEST.cursorSkills);
|
|
514
|
+
break;
|
|
515
|
+
case 'windsurf':
|
|
516
|
+
cleanupManagedFiles(DEST.windsurfSkills);
|
|
517
|
+
break;
|
|
518
|
+
case 'opencode':
|
|
519
|
+
cleanupManagedFiles(DEST.opencode);
|
|
520
|
+
break;
|
|
521
|
+
case 'codex':
|
|
522
|
+
cleanupManagedFiles(DEST.codex);
|
|
523
|
+
break;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
console.log('--> Installing skills...');
|
|
528
|
+
for (const t of resolvedTargets) {
|
|
529
|
+
switch (t) {
|
|
530
|
+
case 'claude':
|
|
531
|
+
installClaude();
|
|
532
|
+
break;
|
|
533
|
+
case 'cursor':
|
|
534
|
+
installCursor();
|
|
535
|
+
break;
|
|
536
|
+
case 'windsurf':
|
|
537
|
+
installWindsurf();
|
|
538
|
+
break;
|
|
539
|
+
case 'opencode':
|
|
540
|
+
installOpenCode();
|
|
541
|
+
break;
|
|
542
|
+
case 'codex':
|
|
543
|
+
installCodex();
|
|
544
|
+
break;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
console.log('');
|
|
549
|
+
console.log('==> Done.');
|
|
550
|
+
console.log('');
|
|
551
|
+
console.log(`Skills installed for: ${resolvedTargets.join(' ')}`);
|
|
552
|
+
console.log(`CLI available as: ${CLI_BIN_NAME}`);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
main(process.argv.slice(2));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentic-skill-mill",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.11",
|
|
4
4
|
"description": "Forge and refine agent skill projects -- fragment-composed skills compiled to 7 IDE targets with a companion CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -19,10 +19,7 @@
|
|
|
19
19
|
"compiled",
|
|
20
20
|
"skill",
|
|
21
21
|
"README.md",
|
|
22
|
-
"install.
|
|
23
|
-
"install-local.sh",
|
|
24
|
-
"install.ps1",
|
|
25
|
-
"install-local.ps1"
|
|
22
|
+
"install.js"
|
|
26
23
|
],
|
|
27
24
|
"scripts": {
|
|
28
25
|
"build": "tsc -p tsconfig.build.json",
|
|
@@ -31,14 +28,14 @@
|
|
|
31
28
|
"test:coverage": "vitest run --coverage",
|
|
32
29
|
"lint": "eslint src",
|
|
33
30
|
"typecheck": "tsc --noEmit",
|
|
34
|
-
"setup": "
|
|
35
|
-
"setup:all": "
|
|
36
|
-
"setup:windows": "
|
|
37
|
-
"setup:windows:all": "
|
|
38
|
-
"install-skills": "
|
|
39
|
-
"install-skills:windows": "
|
|
40
|
-
"uninstall-skills": "
|
|
41
|
-
"uninstall-skills:windows": "
|
|
31
|
+
"setup": "node install.js",
|
|
32
|
+
"setup:all": "node install.js --all",
|
|
33
|
+
"setup:windows": "node install.js",
|
|
34
|
+
"setup:windows:all": "node install.js --all",
|
|
35
|
+
"install-skills": "node install.js --skills-only",
|
|
36
|
+
"install-skills:windows": "node install.js --skills-only",
|
|
37
|
+
"uninstall-skills": "node install.js --uninstall",
|
|
38
|
+
"uninstall-skills:windows": "node install.js --uninstall",
|
|
42
39
|
"compile": "node skill/build/compile.mjs",
|
|
43
40
|
"compile:validate": "node skill/build/compile.mjs --validate",
|
|
44
41
|
"compile:watch": "node skill/build/compile.mjs --watch"
|
|
@@ -6,7 +6,7 @@ Skills (what to do) CLI Companion (tools to do it with)
|
|
|
6
6
|
skill/fragments/*.md src/core/*.ts
|
|
7
7
|
| |
|
|
8
8
|
v v
|
|
9
|
-
compiled/ (
|
|
9
|
+
compiled/ (5 IDE formats) dist/ (npm -> npx or global CLI)
|
|
10
10
|
| |
|
|
11
11
|
+---------> Agent <----------+
|
|
12
12
|
^
|
|
@@ -31,9 +31,9 @@ Skills (what to do) CLI Companion (tools to do it with)
|
|
|
31
31
|
- `src/errors/types.ts` — Typed error hierarchy (AppError, NotFoundError, etc.)
|
|
32
32
|
- `src/cache/cache-manager.ts` — Two-tier cache (memory + disk) with TTL
|
|
33
33
|
|
|
34
|
-
**Local installers:** Every project ships
|
|
34
|
+
**Local installers:** Every project ships a single cross-platform `install.js` (Node.js).
|
|
35
35
|
|
|
36
|
-
**The
|
|
36
|
+
**The installer** (`install.js`) builds the CLI, compiles skills, and copies compiled outputs to IDE-specific directories (~/.claude/skills, ~/.cursor/rules, etc.) with marker-based stale file cleanup. The bootstrap installer is hosted at `https://agenticskillmill.com/install.sh` and bundled in the npm package. It installs the npm utility first, then delegates to `node install.js --skills-only`.
|
|
37
37
|
|
|
38
38
|
### Key files to modify when augmenting a project
|
|
39
39
|
|
|
@@ -41,8 +41,8 @@ Skills (what to do) CLI Companion (tools to do it with)
|
|
|
41
41
|
|------|---------|
|
|
42
42
|
| Add a CLI command | `src/core/<name>.ts`, `src/cli/commands/<name>.ts`, `src/cli/index.ts`, `src/index.ts` |
|
|
43
43
|
| Add a fragment | `skill/fragments/<category>/<name>.md`, `skill/build/manifest.json`, skill source |
|
|
44
|
-
| Add a skill | `skill/skills/<name>/<name>.md`, `skill/build/manifest.json
|
|
45
|
-
| Change installer behavior | `install.sh` and `install.ps1`
|
|
44
|
+
| Add a skill | `skill/skills/<name>/<name>.md`, `skill/build/manifest.json` |
|
|
45
|
+
| Change installer behavior | `install.js`, then copy to `site/install.sh` and `site/install.ps1` |
|
|
46
46
|
| Update the landing page | `site/index.html`, `site/style.css` |
|
|
47
47
|
| Change CI secrets or workflow | `.github/workflows/release.yml` or `deploy-pages.yml`, repo settings |
|
|
48
48
|
| Rename the project | See the rename workflow |
|
|
@@ -11,21 +11,20 @@ There are multiple ways users consume it:
|
|
|
11
11
|
| Remote install (bash) | `bash <(curl -fsSL https://<domain>/install.sh)` | End users on Linux/macOS |
|
|
12
12
|
| Remote install (PowerShell) | `irm https://<domain>/install.ps1 \| iex` | End users on Windows |
|
|
13
13
|
| npx (no install) | `npx --yes agentic-skill-mill@latest <command>` | Users running CLI commands without global install |
|
|
14
|
-
| Local development | `git clone` then `
|
|
14
|
+
| Local development | `git clone` then `node install.js --all` | Contributors working on the project itself |
|
|
15
15
|
|
|
16
|
-
###
|
|
16
|
+
### One unified installer
|
|
17
17
|
|
|
18
|
-
**`install
|
|
19
|
-
- `npm install` + `npm run build` + `npm run compile`
|
|
20
|
-
- `npm link` to make `skillmill` available globally
|
|
18
|
+
**`install.js`** is a single cross-platform Node.js installer that replaces the old shell/PowerShell split:
|
|
19
|
+
- Runs `npm install` + `npm run build` + `npm run compile` + `npm link`
|
|
21
20
|
- Copies compiled skill outputs to IDE-specific directories (~/.claude/skills, ~/.cursor/rules, etc.)
|
|
22
21
|
- Supports `--skills-only` (skip build, just copy), `--uninstall`, `--compile-only`, and per-tool flags (`--cursor`, `--claude`, etc.)
|
|
23
22
|
- Auto-detects installed tools when no flags are provided
|
|
24
23
|
|
|
25
|
-
**`install.sh`** is the remote bootstrap installer. It is hosted at `https://agenticskillmill.com/install.sh` (source: `site/install.sh`) and bundled in the npm package. It:
|
|
24
|
+
**`site/install.sh`** is the remote bootstrap installer. It is hosted at `https://agenticskillmill.com/install.sh` (source: `site/install.sh`) and bundled in the npm package. It:
|
|
26
25
|
1. Runs `npm install -g agentic-skill-mill@latest`
|
|
27
|
-
2. Locates `install
|
|
28
|
-
3. Delegates to `install
|
|
26
|
+
2. Locates `install.js` inside the globally installed package
|
|
27
|
+
3. Delegates to `node install.js --skills-only` with the user's flags
|
|
29
28
|
|
|
30
29
|
Both scripts respect environment overrides `SKILLMILL_PACKAGE_NAME` and `SKILLMILL_PACKAGE_VERSION`.
|
|
31
30
|
|
|
@@ -36,11 +35,10 @@ The `files` array in `package.json` controls what ships to npm:
|
|
|
36
35
|
| Entry | Purpose |
|
|
37
36
|
|-------|---------|
|
|
38
37
|
| `dist` | Compiled TypeScript CLI and library |
|
|
39
|
-
| `compiled` | Pre-compiled skill outputs for all
|
|
38
|
+
| `compiled` | Pre-compiled skill outputs for all 5 IDE targets |
|
|
40
39
|
| `skill` | Skill sources, fragments, compiler, and manifest |
|
|
41
40
|
| `README.md` | Package documentation |
|
|
42
|
-
| `install.
|
|
43
|
-
| `install-local.sh` | Full local installer (used by bootstrap in --skills-only mode) |
|
|
41
|
+
| `install.js` | Unified cross-platform installer |
|
|
44
42
|
|
|
45
43
|
The `bin` field maps `skillmill` to `dist/cli/index.js`, so `npx agentic-skill-mill` and global install both expose the `skillmill` command.
|
|
46
44
|
|
|
@@ -76,8 +74,8 @@ When updating the bootstrap installer logic, edit `install.sh` and `install.ps1`
|
|
|
76
74
|
|
|
77
75
|
| Change | Files to update |
|
|
78
76
|
|--------|----------------|
|
|
79
|
-
| Add a new skill | `
|
|
80
|
-
| Change package name | `package.json` name + bin, `
|
|
81
|
-
| Change bootstrap behavior | `install.
|
|
77
|
+
| Add a new skill | `skill/build/manifest.json` |
|
|
78
|
+
| Change package name | `package.json` name + bin, `site/install.sh` default, `install.js` PROJECT_NAME + CLI_BIN_NAME, `site/index.html`, README |
|
|
79
|
+
| Change bootstrap behavior | `install.js`, then copy to `site/install.sh` and `site/install.ps1` |
|
|
82
80
|
| Add a GitHub Actions secret | Repo settings, document in README |
|
|
83
81
|
| Update domain | `site/CNAME`, README, skill source, architecture fragment |
|