@rokkit/cli 1.4.0 → 1.4.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/dist/src/agents.d.ts +2 -2
- package/dist/src/init.d.ts +402 -17
- package/dist/src/skills.d.ts +1 -1
- package/dist/src/validate.d.ts +8 -27
- package/package.json +6 -5
- package/src/agents.js +73 -40
- package/src/contrast.js +141 -82
- package/src/convert.js +4 -2
- package/src/doctor.js +29 -36
- package/src/init.js +126 -87
- package/src/skills.js +51 -25
- package/src/validate.js +59 -41
package/dist/src/agents.d.ts
CHANGED
|
@@ -46,13 +46,13 @@ export function fetchAgents(names: string[], { cwd, force, baseUrl, fetchImpl }?
|
|
|
46
46
|
export function runAgentsList({ agentsDir, cwd }?: {
|
|
47
47
|
agentsDir?: string;
|
|
48
48
|
cwd?: string;
|
|
49
|
-
}):
|
|
49
|
+
}): void;
|
|
50
50
|
/**
|
|
51
51
|
* Resolve which agents to install, then copy (or fetch with --remote) and report.
|
|
52
52
|
* @param {string[]} names
|
|
53
53
|
* @param {{ all?: boolean, force?: boolean, remote?: boolean, agentsDir?: string, cwd?: string, fetchImpl?: typeof fetch }} [opts]
|
|
54
54
|
*/
|
|
55
|
-
export function runAgentsAdd(names: string[],
|
|
55
|
+
export function runAgentsAdd(names: string[], opts?: {
|
|
56
56
|
all?: boolean;
|
|
57
57
|
force?: boolean;
|
|
58
58
|
remote?: boolean;
|
package/dist/src/init.d.ts
CHANGED
|
@@ -37,22 +37,407 @@ export function generateChartConfig({ chartColors, chartShades }: {
|
|
|
37
37
|
chartColors: string;
|
|
38
38
|
chartShades: string;
|
|
39
39
|
}): Record<string, unknown>;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
40
|
+
export function generateZenSumiConfig(opts?: {}): {
|
|
41
|
+
chart: Record<string, unknown>;
|
|
42
|
+
storageKey: any;
|
|
43
|
+
themes: any;
|
|
44
|
+
defaultTheme: any;
|
|
45
|
+
switcher: any;
|
|
46
|
+
palettes: {
|
|
47
|
+
kami: {
|
|
48
|
+
50: string;
|
|
49
|
+
100: string;
|
|
50
|
+
200: string;
|
|
51
|
+
300: string;
|
|
52
|
+
400: string;
|
|
53
|
+
500: string;
|
|
54
|
+
600: string;
|
|
55
|
+
700: string;
|
|
56
|
+
800: string;
|
|
57
|
+
900: string;
|
|
58
|
+
950: string;
|
|
59
|
+
};
|
|
60
|
+
sumi: {
|
|
61
|
+
50: string;
|
|
62
|
+
100: string;
|
|
63
|
+
200: string;
|
|
64
|
+
300: string;
|
|
65
|
+
400: string;
|
|
66
|
+
500: string;
|
|
67
|
+
600: string;
|
|
68
|
+
700: string;
|
|
69
|
+
800: string;
|
|
70
|
+
900: string;
|
|
71
|
+
950: string;
|
|
72
|
+
};
|
|
73
|
+
shu: {
|
|
74
|
+
50: string;
|
|
75
|
+
100: string;
|
|
76
|
+
200: string;
|
|
77
|
+
300: string;
|
|
78
|
+
400: string;
|
|
79
|
+
500: string;
|
|
80
|
+
600: string;
|
|
81
|
+
700: string;
|
|
82
|
+
800: string;
|
|
83
|
+
900: string;
|
|
84
|
+
950: string;
|
|
85
|
+
};
|
|
86
|
+
hisui: {
|
|
87
|
+
50: string;
|
|
88
|
+
100: string;
|
|
89
|
+
200: string;
|
|
90
|
+
300: string;
|
|
91
|
+
400: string;
|
|
92
|
+
500: string;
|
|
93
|
+
600: string;
|
|
94
|
+
700: string;
|
|
95
|
+
800: string;
|
|
96
|
+
900: string;
|
|
97
|
+
950: string;
|
|
98
|
+
};
|
|
99
|
+
kohaku: {
|
|
100
|
+
50: string;
|
|
101
|
+
100: string;
|
|
102
|
+
200: string;
|
|
103
|
+
300: string;
|
|
104
|
+
400: string;
|
|
105
|
+
500: string;
|
|
106
|
+
600: string;
|
|
107
|
+
700: string;
|
|
108
|
+
800: string;
|
|
109
|
+
900: string;
|
|
110
|
+
950: string;
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
colorSpace: string;
|
|
114
|
+
tokens: string;
|
|
115
|
+
skin: {
|
|
116
|
+
surface: {
|
|
117
|
+
light: string;
|
|
118
|
+
dark: string;
|
|
119
|
+
};
|
|
120
|
+
ink: {
|
|
121
|
+
light: string;
|
|
122
|
+
dark: string;
|
|
123
|
+
};
|
|
124
|
+
primary: string;
|
|
125
|
+
accent: string;
|
|
126
|
+
success: string;
|
|
127
|
+
warning: string;
|
|
128
|
+
danger: string;
|
|
129
|
+
error: string;
|
|
130
|
+
info: string;
|
|
131
|
+
};
|
|
132
|
+
shape: {
|
|
133
|
+
radius: string;
|
|
134
|
+
};
|
|
135
|
+
typography: {
|
|
136
|
+
display: string;
|
|
137
|
+
sans: string;
|
|
138
|
+
mono: string;
|
|
139
|
+
};
|
|
140
|
+
} | {
|
|
141
|
+
chart?: undefined;
|
|
142
|
+
storageKey: any;
|
|
143
|
+
themes: any;
|
|
144
|
+
defaultTheme: any;
|
|
145
|
+
switcher: any;
|
|
146
|
+
palettes: {
|
|
147
|
+
kami: {
|
|
148
|
+
50: string;
|
|
149
|
+
100: string;
|
|
150
|
+
200: string;
|
|
151
|
+
300: string;
|
|
152
|
+
400: string;
|
|
153
|
+
500: string;
|
|
154
|
+
600: string;
|
|
155
|
+
700: string;
|
|
156
|
+
800: string;
|
|
157
|
+
900: string;
|
|
158
|
+
950: string;
|
|
159
|
+
};
|
|
160
|
+
sumi: {
|
|
161
|
+
50: string;
|
|
162
|
+
100: string;
|
|
163
|
+
200: string;
|
|
164
|
+
300: string;
|
|
165
|
+
400: string;
|
|
166
|
+
500: string;
|
|
167
|
+
600: string;
|
|
168
|
+
700: string;
|
|
169
|
+
800: string;
|
|
170
|
+
900: string;
|
|
171
|
+
950: string;
|
|
172
|
+
};
|
|
173
|
+
shu: {
|
|
174
|
+
50: string;
|
|
175
|
+
100: string;
|
|
176
|
+
200: string;
|
|
177
|
+
300: string;
|
|
178
|
+
400: string;
|
|
179
|
+
500: string;
|
|
180
|
+
600: string;
|
|
181
|
+
700: string;
|
|
182
|
+
800: string;
|
|
183
|
+
900: string;
|
|
184
|
+
950: string;
|
|
185
|
+
};
|
|
186
|
+
hisui: {
|
|
187
|
+
50: string;
|
|
188
|
+
100: string;
|
|
189
|
+
200: string;
|
|
190
|
+
300: string;
|
|
191
|
+
400: string;
|
|
192
|
+
500: string;
|
|
193
|
+
600: string;
|
|
194
|
+
700: string;
|
|
195
|
+
800: string;
|
|
196
|
+
900: string;
|
|
197
|
+
950: string;
|
|
198
|
+
};
|
|
199
|
+
kohaku: {
|
|
200
|
+
50: string;
|
|
201
|
+
100: string;
|
|
202
|
+
200: string;
|
|
203
|
+
300: string;
|
|
204
|
+
400: string;
|
|
205
|
+
500: string;
|
|
206
|
+
600: string;
|
|
207
|
+
700: string;
|
|
208
|
+
800: string;
|
|
209
|
+
900: string;
|
|
210
|
+
950: string;
|
|
211
|
+
};
|
|
212
|
+
};
|
|
213
|
+
colorSpace: string;
|
|
214
|
+
tokens: string;
|
|
215
|
+
skin: {
|
|
216
|
+
surface: {
|
|
217
|
+
light: string;
|
|
218
|
+
dark: string;
|
|
219
|
+
};
|
|
220
|
+
ink: {
|
|
221
|
+
light: string;
|
|
222
|
+
dark: string;
|
|
223
|
+
};
|
|
224
|
+
primary: string;
|
|
225
|
+
accent: string;
|
|
226
|
+
success: string;
|
|
227
|
+
warning: string;
|
|
228
|
+
danger: string;
|
|
229
|
+
error: string;
|
|
230
|
+
info: string;
|
|
231
|
+
};
|
|
232
|
+
shape: {
|
|
233
|
+
radius: string;
|
|
234
|
+
};
|
|
235
|
+
typography: {
|
|
236
|
+
display: string;
|
|
237
|
+
sans: string;
|
|
238
|
+
mono: string;
|
|
239
|
+
};
|
|
240
|
+
} | {
|
|
241
|
+
chart: Record<string, unknown>;
|
|
242
|
+
storageKey?: undefined;
|
|
243
|
+
themes: any;
|
|
244
|
+
defaultTheme: any;
|
|
245
|
+
switcher: any;
|
|
246
|
+
palettes: {
|
|
247
|
+
kami: {
|
|
248
|
+
50: string;
|
|
249
|
+
100: string;
|
|
250
|
+
200: string;
|
|
251
|
+
300: string;
|
|
252
|
+
400: string;
|
|
253
|
+
500: string;
|
|
254
|
+
600: string;
|
|
255
|
+
700: string;
|
|
256
|
+
800: string;
|
|
257
|
+
900: string;
|
|
258
|
+
950: string;
|
|
259
|
+
};
|
|
260
|
+
sumi: {
|
|
261
|
+
50: string;
|
|
262
|
+
100: string;
|
|
263
|
+
200: string;
|
|
264
|
+
300: string;
|
|
265
|
+
400: string;
|
|
266
|
+
500: string;
|
|
267
|
+
600: string;
|
|
268
|
+
700: string;
|
|
269
|
+
800: string;
|
|
270
|
+
900: string;
|
|
271
|
+
950: string;
|
|
272
|
+
};
|
|
273
|
+
shu: {
|
|
274
|
+
50: string;
|
|
275
|
+
100: string;
|
|
276
|
+
200: string;
|
|
277
|
+
300: string;
|
|
278
|
+
400: string;
|
|
279
|
+
500: string;
|
|
280
|
+
600: string;
|
|
281
|
+
700: string;
|
|
282
|
+
800: string;
|
|
283
|
+
900: string;
|
|
284
|
+
950: string;
|
|
285
|
+
};
|
|
286
|
+
hisui: {
|
|
287
|
+
50: string;
|
|
288
|
+
100: string;
|
|
289
|
+
200: string;
|
|
290
|
+
300: string;
|
|
291
|
+
400: string;
|
|
292
|
+
500: string;
|
|
293
|
+
600: string;
|
|
294
|
+
700: string;
|
|
295
|
+
800: string;
|
|
296
|
+
900: string;
|
|
297
|
+
950: string;
|
|
298
|
+
};
|
|
299
|
+
kohaku: {
|
|
300
|
+
50: string;
|
|
301
|
+
100: string;
|
|
302
|
+
200: string;
|
|
303
|
+
300: string;
|
|
304
|
+
400: string;
|
|
305
|
+
500: string;
|
|
306
|
+
600: string;
|
|
307
|
+
700: string;
|
|
308
|
+
800: string;
|
|
309
|
+
900: string;
|
|
310
|
+
950: string;
|
|
311
|
+
};
|
|
312
|
+
};
|
|
313
|
+
colorSpace: string;
|
|
314
|
+
tokens: string;
|
|
315
|
+
skin: {
|
|
316
|
+
surface: {
|
|
317
|
+
light: string;
|
|
318
|
+
dark: string;
|
|
319
|
+
};
|
|
320
|
+
ink: {
|
|
321
|
+
light: string;
|
|
322
|
+
dark: string;
|
|
323
|
+
};
|
|
324
|
+
primary: string;
|
|
325
|
+
accent: string;
|
|
326
|
+
success: string;
|
|
327
|
+
warning: string;
|
|
328
|
+
danger: string;
|
|
329
|
+
error: string;
|
|
330
|
+
info: string;
|
|
331
|
+
};
|
|
332
|
+
shape: {
|
|
333
|
+
radius: string;
|
|
334
|
+
};
|
|
335
|
+
typography: {
|
|
336
|
+
display: string;
|
|
337
|
+
sans: string;
|
|
338
|
+
mono: string;
|
|
339
|
+
};
|
|
340
|
+
} | {
|
|
341
|
+
chart?: undefined;
|
|
342
|
+
storageKey?: undefined;
|
|
343
|
+
themes: any;
|
|
344
|
+
defaultTheme: any;
|
|
345
|
+
switcher: any;
|
|
346
|
+
palettes: {
|
|
347
|
+
kami: {
|
|
348
|
+
50: string;
|
|
349
|
+
100: string;
|
|
350
|
+
200: string;
|
|
351
|
+
300: string;
|
|
352
|
+
400: string;
|
|
353
|
+
500: string;
|
|
354
|
+
600: string;
|
|
355
|
+
700: string;
|
|
356
|
+
800: string;
|
|
357
|
+
900: string;
|
|
358
|
+
950: string;
|
|
359
|
+
};
|
|
360
|
+
sumi: {
|
|
361
|
+
50: string;
|
|
362
|
+
100: string;
|
|
363
|
+
200: string;
|
|
364
|
+
300: string;
|
|
365
|
+
400: string;
|
|
366
|
+
500: string;
|
|
367
|
+
600: string;
|
|
368
|
+
700: string;
|
|
369
|
+
800: string;
|
|
370
|
+
900: string;
|
|
371
|
+
950: string;
|
|
372
|
+
};
|
|
373
|
+
shu: {
|
|
374
|
+
50: string;
|
|
375
|
+
100: string;
|
|
376
|
+
200: string;
|
|
377
|
+
300: string;
|
|
378
|
+
400: string;
|
|
379
|
+
500: string;
|
|
380
|
+
600: string;
|
|
381
|
+
700: string;
|
|
382
|
+
800: string;
|
|
383
|
+
900: string;
|
|
384
|
+
950: string;
|
|
385
|
+
};
|
|
386
|
+
hisui: {
|
|
387
|
+
50: string;
|
|
388
|
+
100: string;
|
|
389
|
+
200: string;
|
|
390
|
+
300: string;
|
|
391
|
+
400: string;
|
|
392
|
+
500: string;
|
|
393
|
+
600: string;
|
|
394
|
+
700: string;
|
|
395
|
+
800: string;
|
|
396
|
+
900: string;
|
|
397
|
+
950: string;
|
|
398
|
+
};
|
|
399
|
+
kohaku: {
|
|
400
|
+
50: string;
|
|
401
|
+
100: string;
|
|
402
|
+
200: string;
|
|
403
|
+
300: string;
|
|
404
|
+
400: string;
|
|
405
|
+
500: string;
|
|
406
|
+
600: string;
|
|
407
|
+
700: string;
|
|
408
|
+
800: string;
|
|
409
|
+
900: string;
|
|
410
|
+
950: string;
|
|
411
|
+
};
|
|
412
|
+
};
|
|
413
|
+
colorSpace: string;
|
|
414
|
+
tokens: string;
|
|
415
|
+
skin: {
|
|
416
|
+
surface: {
|
|
417
|
+
light: string;
|
|
418
|
+
dark: string;
|
|
419
|
+
};
|
|
420
|
+
ink: {
|
|
421
|
+
light: string;
|
|
422
|
+
dark: string;
|
|
423
|
+
};
|
|
424
|
+
primary: string;
|
|
425
|
+
accent: string;
|
|
426
|
+
success: string;
|
|
427
|
+
warning: string;
|
|
428
|
+
danger: string;
|
|
429
|
+
error: string;
|
|
430
|
+
info: string;
|
|
431
|
+
};
|
|
432
|
+
shape: {
|
|
433
|
+
radius: string;
|
|
434
|
+
};
|
|
435
|
+
typography: {
|
|
436
|
+
display: string;
|
|
437
|
+
sans: string;
|
|
438
|
+
mono: string;
|
|
439
|
+
};
|
|
440
|
+
};
|
|
56
441
|
/**
|
|
57
442
|
* Build a Rokkit config object from the user's init choices.
|
|
58
443
|
* Emits the named-token `skin` shape (skin + colorSpace + tokens), plus
|
|
@@ -63,7 +448,7 @@ export function generateZenSumiConfig(opts?: {
|
|
|
63
448
|
* storageKey?: string }} opts
|
|
64
449
|
* @returns {Record<string, unknown>}
|
|
65
450
|
*/
|
|
66
|
-
export function generateConfig(
|
|
451
|
+
export function generateConfig(opts: {
|
|
67
452
|
palette: string;
|
|
68
453
|
customColors?: Record<string, string>;
|
|
69
454
|
icons?: string;
|
package/dist/src/skills.d.ts
CHANGED
|
@@ -39,7 +39,7 @@ export function installSkills(names: string[], { cwd, force, skillsDir }?: {
|
|
|
39
39
|
export function runSkillsList({ skillsDir, cwd }?: {
|
|
40
40
|
skillsDir?: string;
|
|
41
41
|
cwd?: string;
|
|
42
|
-
}):
|
|
42
|
+
}): void;
|
|
43
43
|
/**
|
|
44
44
|
* Resolve which skills to install, then copy and report.
|
|
45
45
|
* @param {string[]} names
|
package/dist/src/validate.d.ts
CHANGED
|
@@ -1,33 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
* Advisory validation run by `doctor`: config shape rules for the named-token
|
|
3
|
-
* system, and a scan for surface/border tokens misused as text colour.
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* Validate a parsed rokkit config for the named-token system. All advisory (warn).
|
|
7
|
-
* @param {Record<string, unknown> | null} config
|
|
8
|
-
* @returns {Array<{ id: string, label: string, status: 'warn', fixable: false, fix: string }>}
|
|
9
|
-
*/
|
|
10
|
-
export function validateConfigShape(config: Record<string, unknown> | null): Array<{
|
|
1
|
+
export function validateConfigShape(config: any): {
|
|
11
2
|
id: string;
|
|
12
3
|
label: string;
|
|
13
|
-
status:
|
|
14
|
-
fixable:
|
|
4
|
+
status: string;
|
|
5
|
+
fixable: boolean;
|
|
15
6
|
fix: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
* Advisory lint: scan src/ for surface/border tokens used as text colour.
|
|
19
|
-
* @param {{ list?: (dir: string) => string[], exists: (p: string) => boolean, read: (p: string) => string, resolve: (p: string) => string }} fs
|
|
20
|
-
* @returns {Array<{ id: string, label: string, status: 'warn', fixable: false, fix: string }>}
|
|
21
|
-
*/
|
|
22
|
-
export function checkTextTokenUsage(fs: {
|
|
23
|
-
list?: (dir: string) => string[];
|
|
24
|
-
exists: (p: string) => boolean;
|
|
25
|
-
read: (p: string) => string;
|
|
26
|
-
resolve: (p: string) => string;
|
|
27
|
-
}): Array<{
|
|
7
|
+
}[];
|
|
8
|
+
export function checkTextTokenUsage(fs: any): {
|
|
28
9
|
id: string;
|
|
29
10
|
label: string;
|
|
30
|
-
status:
|
|
31
|
-
fixable:
|
|
11
|
+
status: string;
|
|
12
|
+
fixable: boolean;
|
|
32
13
|
fix: string;
|
|
33
|
-
}
|
|
14
|
+
}[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rokkit/cli",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.2",
|
|
4
4
|
"description": "Command line utilities for icon bundling and conversion.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -16,20 +16,21 @@
|
|
|
16
16
|
"prepublishOnly": "cp ../../LICENSE . && bun clean && bun tsc --project tsconfig.build.json",
|
|
17
17
|
"postpublish": "rm -f LICENSE",
|
|
18
18
|
"clean": "rm -rf dist",
|
|
19
|
-
"build": "bun prepublishOnly"
|
|
19
|
+
"build": "bun prepublishOnly",
|
|
20
|
+
"check:build": "bun run clean && tsc --project tsconfig.build.json"
|
|
20
21
|
},
|
|
21
22
|
"publishConfig": {
|
|
22
23
|
"access": "public"
|
|
23
24
|
},
|
|
24
25
|
"devDependencies": {
|
|
25
26
|
"iconify": "^1.4.0",
|
|
26
|
-
"vitest": "^4.
|
|
27
|
+
"vitest": "^4.1.11"
|
|
27
28
|
},
|
|
28
29
|
"dependencies": {
|
|
29
30
|
"@mdi/svg": "^7.4.47",
|
|
30
|
-
"@rokkit/unocss": "1.4.
|
|
31
|
+
"@rokkit/unocss": "1.4.2",
|
|
31
32
|
"sade": "^1.8.1",
|
|
32
|
-
"@iconify/tools": "5.0.
|
|
33
|
+
"@iconify/tools": "^5.0.14",
|
|
33
34
|
"@iconify/types": "^2.0.0",
|
|
34
35
|
"prompts": "^2.4.2",
|
|
35
36
|
"ramda": "^0.32.0"
|
package/src/agents.js
CHANGED
|
@@ -77,29 +77,36 @@ export async function fetchAgents(
|
|
|
77
77
|
) {
|
|
78
78
|
const targetRoot = resolve(cwd, '.claude', 'agents')
|
|
79
79
|
const results = []
|
|
80
|
+
// Sequential on purpose: the outcomes should print in the order the user
|
|
81
|
+
// listed the agents, and every write targets the same directory anyway.
|
|
80
82
|
for (const name of names) {
|
|
81
|
-
|
|
82
|
-
if (existsSync(dest) && !force) {
|
|
83
|
-
results.push({ name, status: 'skipped' })
|
|
84
|
-
continue
|
|
85
|
-
}
|
|
86
|
-
const res = await fetchImpl(`${baseUrl}/${name}.md`)
|
|
87
|
-
if (!res.ok) {
|
|
88
|
-
results.push({ name, status: 'unknown' })
|
|
89
|
-
continue
|
|
90
|
-
}
|
|
91
|
-
mkdirSync(targetRoot, { recursive: true })
|
|
92
|
-
writeFileSync(dest, await res.text())
|
|
93
|
-
results.push({ name, status: 'added' })
|
|
83
|
+
results.push(await fetchAgent(name, { targetRoot, force, baseUrl, fetchImpl }))
|
|
94
84
|
}
|
|
95
85
|
return results
|
|
96
86
|
}
|
|
97
87
|
|
|
88
|
+
/**
|
|
89
|
+
* Fetch and write one agent. Reports its outcome rather than throwing, so one
|
|
90
|
+
* missing name doesn't abandon the rest of the batch.
|
|
91
|
+
* @param {string} name
|
|
92
|
+
* @param {{ targetRoot: string, force: boolean, baseUrl: string, fetchImpl: typeof fetch }} ctx
|
|
93
|
+
* @returns {Promise<{ name: string, status: 'added' | 'skipped' | 'unknown' }>}
|
|
94
|
+
*/
|
|
95
|
+
async function fetchAgent(name, { targetRoot, force, baseUrl, fetchImpl }) {
|
|
96
|
+
const dest = join(targetRoot, `${name}.md`)
|
|
97
|
+
if (existsSync(dest) && !force) return { name, status: 'skipped' }
|
|
98
|
+
const res = await fetchImpl(`${baseUrl}/${name}.md`)
|
|
99
|
+
if (!res.ok) return { name, status: 'unknown' }
|
|
100
|
+
mkdirSync(targetRoot, { recursive: true })
|
|
101
|
+
writeFileSync(dest, await res.text())
|
|
102
|
+
return { name, status: 'added' }
|
|
103
|
+
}
|
|
104
|
+
|
|
98
105
|
/**
|
|
99
106
|
* Print the catalog, marking already-installed agents.
|
|
100
107
|
* @param {{ agentsDir?: string, cwd?: string }} [opts]
|
|
101
108
|
*/
|
|
102
|
-
export
|
|
109
|
+
export function runAgentsList({ agentsDir, cwd = process.cwd() } = {}) {
|
|
103
110
|
const catalog = listAgents({ agentsDir })
|
|
104
111
|
if (catalog.length === 0) {
|
|
105
112
|
console.info('No agents available.')
|
|
@@ -120,40 +127,66 @@ export async function runAgentsList({ agentsDir, cwd = process.cwd() } = {}) {
|
|
|
120
127
|
* @param {string[]} names
|
|
121
128
|
* @param {{ all?: boolean, force?: boolean, remote?: boolean, agentsDir?: string, cwd?: string, fetchImpl?: typeof fetch }} [opts]
|
|
122
129
|
*/
|
|
123
|
-
export async function runAgentsAdd(
|
|
124
|
-
|
|
125
|
-
{ all = false, force = false, remote = false, agentsDir, cwd = process.cwd(), fetchImpl } = {}
|
|
126
|
-
) {
|
|
130
|
+
export async function runAgentsAdd(names, opts = {}) {
|
|
131
|
+
const { all = false, agentsDir } = opts
|
|
127
132
|
const catalog = listAgents({ agentsDir })
|
|
128
|
-
|
|
129
|
-
if (all) {
|
|
130
|
-
selected = catalog.map((a) => a.name)
|
|
131
|
-
} else if (selected.length === 0) {
|
|
132
|
-
const res = await prompts({
|
|
133
|
-
type: 'multiselect',
|
|
134
|
-
name: 'picked',
|
|
135
|
-
message: 'Select agents to add',
|
|
136
|
-
choices: catalog.map((a) => ({ title: a.name, value: a.name, description: a.description }))
|
|
137
|
-
})
|
|
138
|
-
selected = res.picked ?? []
|
|
139
|
-
}
|
|
133
|
+
const selected = await resolveAgentSelection(names, catalog, all)
|
|
140
134
|
if (selected.length === 0) {
|
|
141
135
|
console.info('No agents selected.')
|
|
142
136
|
return
|
|
143
137
|
}
|
|
138
|
+
await installAndReport(selected, catalog, opts)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Install the selection — locally, or from the site with `--remote` — and report
|
|
143
|
+
* each outcome.
|
|
144
|
+
*
|
|
145
|
+
* @param {string[]} selected
|
|
146
|
+
* @param {Array<{ name: string, description: string }>} catalog
|
|
147
|
+
* @param {{ force?: boolean, remote?: boolean, agentsDir?: string, cwd?: string, fetchImpl?: typeof fetch }} opts
|
|
148
|
+
*/
|
|
149
|
+
async function installAndReport(
|
|
150
|
+
selected,
|
|
151
|
+
catalog,
|
|
152
|
+
{ force = false, remote = false, agentsDir, cwd = process.cwd(), fetchImpl }
|
|
153
|
+
) {
|
|
144
154
|
const results = remote
|
|
145
155
|
? await fetchAgents(selected, { cwd, force, fetchImpl })
|
|
146
156
|
: installAgents(selected, { cwd, force, agentsDir })
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
+
results.forEach(reportAgentResult)
|
|
158
|
+
if (!results.some((r) => r.status === 'unknown')) return
|
|
159
|
+
// A remote fetch has no catalog to enumerate, so there are no valid names to suggest.
|
|
160
|
+
if (!remote) console.error(`\nValid agents: ${catalog.map((a) => a.name).join(', ')}`)
|
|
161
|
+
process.exitCode = 1
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Which agents to install: everything with `--all`, the named ones, or an
|
|
166
|
+
* interactive pick when neither was given.
|
|
167
|
+
* @param {string[]} names
|
|
168
|
+
* @param {Array<{ name: string, description: string }>} catalog
|
|
169
|
+
* @param {boolean} all
|
|
170
|
+
* @returns {Promise<string[]>}
|
|
171
|
+
*/
|
|
172
|
+
async function resolveAgentSelection(names, catalog, all) {
|
|
173
|
+
if (all) return catalog.map((a) => a.name)
|
|
174
|
+
if (names.length > 0) return names
|
|
175
|
+
const res = await prompts({
|
|
176
|
+
type: 'multiselect',
|
|
177
|
+
name: 'picked',
|
|
178
|
+
message: 'Select agents to add',
|
|
179
|
+
choices: catalog.map((a) => ({ title: a.name, value: a.name, description: a.description }))
|
|
180
|
+
})
|
|
181
|
+
return res.picked ?? []
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/** Report one install outcome. Unknown names go to stderr — they're a user error. */
|
|
185
|
+
function reportAgentResult(r) {
|
|
186
|
+
if (r.status === 'added') console.info(` added .claude/agents/${r.name}.md`)
|
|
187
|
+
else if (r.status === 'skipped')
|
|
188
|
+
console.info(` skipped ${r.name} (exists — use --force to overwrite)`)
|
|
189
|
+
else console.error(` unknown agent: ${r.name}`)
|
|
157
190
|
}
|
|
158
191
|
|
|
159
192
|
/**
|