skild 0.4.2 → 0.4.4

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.
Files changed (2) hide show
  1. package/dist/index.js +539 -220
  2. package/package.json +3 -2
package/dist/index.js CHANGED
@@ -2,14 +2,14 @@
2
2
 
3
3
  // src/index.ts
4
4
  import { Command } from "commander";
5
- import chalk15 from "chalk";
5
+ import chalk16 from "chalk";
6
6
  import { createRequire } from "module";
7
7
 
8
8
  // src/commands/install.ts
9
9
  import fs2 from "fs";
10
10
  import path2 from "path";
11
- import chalk2 from "chalk";
12
- import { deriveChildSource, fetchWithTimeout, installRegistrySkill, installSkill, isValidAlias, loadRegistryAuth, materializeSourceToTemp, resolveRegistryAlias, resolveRegistryUrl, SkildError, PLATFORMS } from "@skild/core";
11
+ import chalk3 from "chalk";
12
+ import { deriveChildSource, fetchWithTimeout, installRegistrySkill, installSkill, isValidAlias, loadRegistryAuth, materializeSourceToTemp, resolveRegistryAlias, resolveRegistryUrl, SkildError, PLATFORMS as PLATFORMS2 } from "@skild/core";
13
13
 
14
14
  // src/utils/logger.ts
15
15
  import chalk from "chalk";
@@ -71,72 +71,280 @@ var logger = {
71
71
  }
72
72
  };
73
73
 
74
- // src/utils/prompt.ts
74
+ // src/utils/interactive-select.ts
75
75
  import readline from "readline";
76
- async function promptLine(question, defaultValue) {
77
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout, terminal: true });
78
- try {
79
- const suffix = defaultValue ? ` (${defaultValue})` : "";
80
- const answer = await new Promise((resolve) => rl.question(`${question}${suffix}: `, resolve));
81
- const trimmed = answer.trim();
82
- return trimmed || defaultValue || "";
83
- } finally {
84
- rl.close();
76
+ import chalk2 from "chalk";
77
+ import { PLATFORMS } from "@skild/core";
78
+ var PLATFORM_DISPLAY = {
79
+ claude: { name: "Claude" },
80
+ codex: { name: "Codex" },
81
+ copilot: { name: "Copilot" },
82
+ antigravity: { name: "Antigravity" }
83
+ };
84
+ function buildSkillTree(skills) {
85
+ const allNode = {
86
+ id: "all",
87
+ name: "All Skills",
88
+ depth: 1,
89
+ children: [],
90
+ leafIndices: [],
91
+ isLeaf: false
92
+ };
93
+ for (let i = 0; i < skills.length; i++) {
94
+ const relPath = skills[i].relPath;
95
+ const parts = relPath === "." ? ["."] : relPath.split("/").filter(Boolean);
96
+ allNode.leafIndices.push(i);
97
+ let current = allNode;
98
+ for (let d = 0; d < parts.length; d++) {
99
+ const part = parts[d];
100
+ const nodeId = parts.slice(0, d + 1).join("/");
101
+ let child = current.children.find((c2) => c2.name === part);
102
+ if (!child) {
103
+ child = {
104
+ id: nodeId,
105
+ name: part,
106
+ depth: d + 2,
107
+ // +2 because allNode is depth 1
108
+ children: [],
109
+ leafIndices: [],
110
+ isLeaf: d === parts.length - 1
111
+ };
112
+ current.children.push(child);
113
+ }
114
+ child.leafIndices.push(i);
115
+ current = child;
116
+ }
85
117
  }
118
+ const root = { id: "", name: ".", depth: 0, children: [allNode], leafIndices: allNode.leafIndices.slice(), isLeaf: false };
119
+ return root;
86
120
  }
87
- async function promptPassword(question) {
88
- if (!process.stdin.isTTY || !process.stdout.isTTY) {
89
- return promptLine(question);
121
+ function flattenTree(root) {
122
+ const result = [];
123
+ function walk(node) {
124
+ if (node.id !== "") {
125
+ result.push(node);
126
+ }
127
+ for (const child of node.children) {
128
+ walk(child);
129
+ }
130
+ }
131
+ for (const child of root.children) {
132
+ walk(child);
133
+ }
134
+ return result;
135
+ }
136
+ function getNodeState(node, selected) {
137
+ const total = node.leafIndices.length;
138
+ if (total === 0) return "none";
139
+ let count = 0;
140
+ for (const idx of node.leafIndices) {
141
+ if (selected.has(idx)) count++;
90
142
  }
143
+ if (count === 0) return "none";
144
+ if (count === total) return "all";
145
+ return "partial";
146
+ }
147
+ async function interactiveTreeSelect(items, options) {
148
+ const { title, subtitle, buildTree, formatNode, defaultAll } = options;
149
+ const root = buildTree(items);
150
+ const flatNodes = flattenTree(root);
151
+ if (flatNodes.length === 0) return null;
152
+ const selected = /* @__PURE__ */ new Set();
153
+ if (defaultAll) {
154
+ for (let i = 0; i < items.length; i++) selected.add(i);
155
+ }
156
+ let cursor = 0;
91
157
  const stdin = process.stdin;
92
158
  const stdout = process.stdout;
93
- stdout.write(`${question}: `);
159
+ if (!stdin.isTTY || !stdout.isTTY) {
160
+ return defaultAll ? Array.from(selected) : null;
161
+ }
94
162
  const wasRaw = Boolean(stdin.isRaw);
95
163
  stdin.setRawMode(true);
96
164
  stdin.resume();
97
165
  readline.emitKeypressEvents(stdin);
98
- const buf = [];
99
- return await new Promise((resolve, reject) => {
166
+ function render() {
167
+ stdout.write("\x1B[?25l");
168
+ const totalLines = flatNodes.length + 4;
169
+ stdout.write(`\x1B[${totalLines}A`);
170
+ stdout.write("\x1B[0J");
171
+ stdout.write(`
172
+ ${chalk2.bold.cyan(title)}
173
+ `);
174
+ stdout.write(`${chalk2.dim(subtitle)}
175
+
176
+ `);
177
+ for (let i = 0; i < flatNodes.length; i++) {
178
+ const node = flatNodes[i];
179
+ const state = getNodeState(node, selected);
180
+ const isCursor = i === cursor;
181
+ stdout.write(formatNode(node, state, isCursor) + "\n");
182
+ }
183
+ stdout.write("\n");
184
+ }
185
+ function initialRender() {
186
+ stdout.write(`
187
+ ${chalk2.bold.cyan(title)}
188
+ `);
189
+ stdout.write(`${chalk2.dim(subtitle)}
190
+
191
+ `);
192
+ for (let i = 0; i < flatNodes.length; i++) {
193
+ const node = flatNodes[i];
194
+ const state = getNodeState(node, selected);
195
+ const isCursor = i === cursor;
196
+ stdout.write(formatNode(node, state, isCursor) + "\n");
197
+ }
198
+ stdout.write("\n");
199
+ }
200
+ initialRender();
201
+ return new Promise((resolve) => {
100
202
  function cleanup() {
101
- stdin.off("keypress", onKeypress);
102
203
  stdin.setRawMode(wasRaw);
103
204
  stdin.pause();
205
+ stdin.removeListener("keypress", onKeypress);
206
+ stdout.write("\x1B[?25h");
104
207
  }
105
- function onKeypress(str, key) {
106
- if (key?.ctrl && key?.name === "c") {
107
- stdout.write("\n");
208
+ function onKeypress(_str, key) {
209
+ if (key.ctrl && key.name === "c") {
108
210
  cleanup();
109
- const err = new Error("Prompt cancelled");
110
- err.code = "PROMPT_CANCELLED";
111
- reject(err);
211
+ resolve(null);
112
212
  return;
113
213
  }
114
- if (key?.name === "return" || key?.name === "enter") {
115
- stdout.write("\n");
214
+ if (key.name === "return" || key.name === "enter") {
116
215
  cleanup();
117
- resolve(buf.join(""));
216
+ const result = Array.from(selected);
217
+ if (result.length === 0) {
218
+ resolve(null);
219
+ } else {
220
+ resolve(result);
221
+ }
118
222
  return;
119
223
  }
120
- if (key?.name === "backspace" || key?.name === "delete") {
121
- if (buf.length) buf.pop();
224
+ if (key.name === "up") {
225
+ cursor = (cursor - 1 + flatNodes.length) % flatNodes.length;
226
+ render();
227
+ return;
228
+ }
229
+ if (key.name === "down") {
230
+ cursor = (cursor + 1) % flatNodes.length;
231
+ render();
232
+ return;
233
+ }
234
+ if (key.name === "space") {
235
+ const node = flatNodes[cursor];
236
+ const state = getNodeState(node, selected);
237
+ if (state === "all") {
238
+ for (const idx of node.leafIndices) {
239
+ selected.delete(idx);
240
+ }
241
+ } else {
242
+ for (const idx of node.leafIndices) {
243
+ selected.add(idx);
244
+ }
245
+ }
246
+ render();
247
+ return;
248
+ }
249
+ if (key.name === "a") {
250
+ const allSelected = selected.size === items.length;
251
+ if (allSelected) {
252
+ selected.clear();
253
+ } else {
254
+ for (let i = 0; i < items.length; i++) selected.add(i);
255
+ }
256
+ render();
122
257
  return;
123
258
  }
124
- if (!str) return;
125
- if (key?.ctrl || key?.meta) return;
126
- buf.push(str);
127
259
  }
128
260
  stdin.on("keypress", onKeypress);
129
261
  });
130
262
  }
131
- async function promptConfirm(question, options = {}) {
132
- const defaultValue = options.defaultValue ?? false;
133
- const suffix = defaultValue ? " (Y/n)" : " (y/N)";
134
- const answer = await promptLine(`${question}${suffix}`);
135
- const v = answer.trim().toLowerCase();
136
- if (!v) return defaultValue;
137
- if (v === "y" || v === "yes") return true;
138
- if (v === "n" || v === "no") return false;
139
- return defaultValue;
263
+ async function promptSkillsInteractive(skills, options = {}) {
264
+ if (skills.length === 0) return null;
265
+ const selectedIndices = await interactiveTreeSelect(skills, {
266
+ title: "Select skills to install",
267
+ subtitle: "\u2191\u2193 navigate \u2022 Space toggle \u2022 Enter confirm",
268
+ buildTree: buildSkillTree,
269
+ formatNode: (node, state, isCursor) => {
270
+ const indent = " ".repeat(node.depth - 1);
271
+ const checkbox = state === "all" ? chalk2.green("\u25CF") : state === "partial" ? chalk2.yellow("\u25D0") : chalk2.dim("\u25CB");
272
+ const name = isCursor ? chalk2.cyan.underline(node.name) : node.name;
273
+ const cursor = isCursor ? chalk2.cyan("\u203A ") : " ";
274
+ const count = node.leafIndices.length > 1 ? chalk2.dim(` (${node.leafIndices.length})`) : "";
275
+ let hint = "";
276
+ if (isCursor && node.leafIndices.length > 0) {
277
+ hint = state === "all" ? chalk2.dim(" \u2190 Space to deselect") : chalk2.dim(" \u2190 Space to select");
278
+ }
279
+ return `${cursor}${indent}${checkbox} ${name}${count}${hint}`;
280
+ },
281
+ defaultAll: options.defaultAll !== false
282
+ });
283
+ if (!selectedIndices || selectedIndices.length === 0) {
284
+ return null;
285
+ }
286
+ console.log(chalk2.green(`
287
+ \u2713 ${selectedIndices.length} skill${selectedIndices.length > 1 ? "s" : ""} selected
288
+ `));
289
+ return selectedIndices.map((i) => skills[i]);
290
+ }
291
+ async function promptPlatformsInteractive(options = {}) {
292
+ const platformItems = PLATFORMS.map((p) => ({ platform: p }));
293
+ const selectedIndices = await interactiveTreeSelect(platformItems, {
294
+ title: "Select target platforms",
295
+ subtitle: "\u2191\u2193 navigate \u2022 Space toggle \u2022 Enter confirm",
296
+ buildTree: (items) => {
297
+ const allNode = {
298
+ id: "all",
299
+ name: "All Platforms",
300
+ depth: 1,
301
+ children: [],
302
+ leafIndices: [],
303
+ isLeaf: false
304
+ };
305
+ for (let i = 0; i < items.length; i++) {
306
+ const p = items[i].platform;
307
+ allNode.children.push({
308
+ id: p,
309
+ name: p,
310
+ depth: 2,
311
+ children: [],
312
+ leafIndices: [i],
313
+ isLeaf: true
314
+ });
315
+ allNode.leafIndices.push(i);
316
+ }
317
+ const root = { id: "", name: ".", depth: 0, children: [allNode], leafIndices: allNode.leafIndices.slice(), isLeaf: false };
318
+ return root;
319
+ },
320
+ formatNode: (node, state, isCursor) => {
321
+ const indent = " ".repeat(node.depth - 1);
322
+ const checkbox = state === "all" ? chalk2.green("\u25CF") : state === "partial" ? chalk2.yellow("\u25D0") : chalk2.dim("\u25CB");
323
+ let displayName = node.name;
324
+ if (node.name !== "All Platforms") {
325
+ const platform = node.name;
326
+ const display = PLATFORM_DISPLAY[platform];
327
+ if (display) displayName = display.name;
328
+ }
329
+ const name = isCursor ? chalk2.cyan.underline(displayName) : displayName;
330
+ const cursor = isCursor ? chalk2.cyan("\u203A ") : " ";
331
+ const count = node.leafIndices.length > 1 ? chalk2.dim(` (${node.leafIndices.length})`) : "";
332
+ let hint = "";
333
+ if (isCursor && node.leafIndices.length > 0) {
334
+ hint = state === "all" ? chalk2.dim(" \u2190 Space to deselect") : chalk2.dim(" \u2190 Space to select");
335
+ }
336
+ return `${cursor}${indent}${checkbox} ${name}${count}${hint}`;
337
+ },
338
+ defaultAll: options.defaultAll !== false
339
+ });
340
+ if (!selectedIndices || selectedIndices.length === 0) {
341
+ return null;
342
+ }
343
+ const selected = selectedIndices.map((i) => PLATFORMS[i]);
344
+ console.log(chalk2.green(`
345
+ \u2713 Installing to ${selected.length} platform${selected.length > 1 ? "s" : ""}
346
+ `));
347
+ return selected;
140
348
  }
141
349
 
142
350
  // src/commands/install-discovery.ts
@@ -233,10 +441,6 @@ function printJson(value) {
233
441
  process.stdout.write(`${JSON.stringify(value, null, 2)}
234
442
  `);
235
443
  }
236
- function previewDiscovered(found, limit = 12) {
237
- const preview = found.slice(0, limit).map((s) => ` - ${s.relPath}`).join("\n");
238
- return `${preview}${found.length > limit ? "\n ..." : ""}`;
239
- }
240
444
  function asDiscoveredSkills(discovered, toSuggestedSource, toMaterializedDir) {
241
445
  return discovered.map((d) => ({
242
446
  relPath: d.relPath,
@@ -248,41 +452,55 @@ async function install(source, options = {}) {
248
452
  const scope = options.local ? "project" : "global";
249
453
  const auth = loadRegistryAuth();
250
454
  const registryUrlForDeps = options.registry || auth?.registryUrl;
251
- const all = Boolean(options.all);
252
455
  const jsonOnly = Boolean(options.json);
253
456
  const recursive = Boolean(options.recursive);
254
457
  const yes = Boolean(options.yes);
255
458
  const maxDepth = parsePositiveInt(options.depth, 6);
256
459
  const maxSkills = parsePositiveInt(options.maxSkills, 200);
257
- const platform = options.target || "claude";
258
- if (all && options.target) {
460
+ const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY) && !jsonOnly;
461
+ const requestedAll = Boolean(options.all);
462
+ const requestedTarget = options.target;
463
+ if (requestedAll && options.target) {
259
464
  const message = "Invalid options: use either --all or --target, not both.";
260
465
  if (jsonOnly) printJson({ ok: false, error: message });
261
- else console.error(chalk2.red(message));
466
+ else console.error(chalk3.red(message));
262
467
  process.exitCode = 1;
263
468
  return;
264
469
  }
470
+ let targets = [];
471
+ let deferPlatformSelection = false;
472
+ if (requestedAll) {
473
+ targets = [...PLATFORMS2];
474
+ } else if (requestedTarget) {
475
+ targets = [requestedTarget];
476
+ } else if (yes) {
477
+ targets = [...PLATFORMS2];
478
+ } else if (interactive) {
479
+ deferPlatformSelection = true;
480
+ targets = [...PLATFORMS2];
481
+ } else {
482
+ targets = ["claude"];
483
+ }
484
+ const allPlatformsSelected = targets.length === PLATFORMS2.length;
265
485
  let resolvedSource = source.trim();
266
486
  try {
267
487
  if (looksLikeAlias(resolvedSource)) {
268
488
  const registryUrl = resolveRegistryUrl(registryUrlForDeps);
269
489
  const resolved = await resolveRegistryAlias(registryUrl, resolvedSource);
270
- if (!jsonOnly) logger.info(`Resolved ${chalk2.cyan(resolvedSource)} \u2192 ${chalk2.cyan(resolved.spec)} (${resolved.type})`);
490
+ if (!jsonOnly) logger.info(`Resolved ${chalk3.cyan(resolvedSource)} \u2192 ${chalk3.cyan(resolved.spec)} (${resolved.type})`);
271
491
  resolvedSource = resolved.spec;
272
492
  }
273
493
  } catch (error) {
274
494
  const message = error instanceof SkildError ? error.message : error instanceof Error ? error.message : String(error);
275
495
  if (jsonOnly) printJson({ ok: false, error: message });
276
- else console.error(chalk2.red(message));
496
+ else console.error(chalk3.red(message));
277
497
  process.exitCode = 1;
278
498
  return;
279
499
  }
280
- const targets = all ? [...PLATFORMS] : [platform];
281
500
  const results = [];
282
501
  const errors = [];
283
502
  let effectiveRecursive = recursive;
284
503
  let recursiveSkillCount = null;
285
- const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY) && !jsonOnly;
286
504
  async function installOne(inputSource, materializedDir) {
287
505
  for (const targetPlatform of targets) {
288
506
  try {
@@ -301,14 +519,14 @@ async function install(source, options = {}) {
301
519
  }
302
520
  }
303
521
  }
304
- async function maybeEnableRecursiveAndInstall(found, spinner) {
305
- if (found.length === 0) return false;
522
+ async function resolveDiscoveredSelection(found, spinner) {
523
+ if (found.length === 0) return null;
306
524
  if (found.length > maxSkills) {
307
525
  const message = `Found more than ${maxSkills} skills. Increase --max-skills to proceed.`;
308
526
  if (jsonOnly) printJson({ ok: false, error: "TOO_MANY_SKILLS", message, source, resolvedSource, maxSkills });
309
- else console.error(chalk2.red(message));
527
+ else console.error(chalk3.red(message));
310
528
  process.exitCode = 1;
311
- return true;
529
+ return null;
312
530
  }
313
531
  if (!effectiveRecursive) {
314
532
  if (jsonOnly) {
@@ -322,36 +540,66 @@ async function install(source, options = {}) {
322
540
  found: foundOutput
323
541
  });
324
542
  process.exitCode = 1;
325
- return true;
543
+ return null;
326
544
  }
327
545
  if (spinner) spinner.stop();
328
- const headline = found.length === 1 ? `No SKILL.md found at root. Found 1 skill:
329
- ${previewDiscovered(found)}
330
- ` : `No SKILL.md found at root. Found ${found.length} skills:
331
- ${previewDiscovered(found)}
546
+ const headline = found.length === 1 ? `No SKILL.md found at root. Found 1 skill.
547
+ ` : `No SKILL.md found at root. Found ${found.length} skills.
332
548
  `;
333
- console.log(chalk2.yellow(headline));
334
- const question = found.length === 1 ? "Install the discovered skill?" : "Install all discovered skills?";
335
- const confirm = yes || interactive && await promptConfirm(question, { defaultValue: found.length === 1 });
336
- if (!confirm) {
337
- console.log(chalk2.dim(`Tip: rerun with ${chalk2.cyan("skild install <source> --recursive")} to install all.`));
549
+ console.log(chalk3.yellow(headline));
550
+ if (!interactive && !yes) {
551
+ console.log(chalk3.dim(`Tip: rerun with ${chalk3.cyan("skild install <source> --recursive")} to install all.`));
338
552
  process.exitCode = 1;
339
- return true;
553
+ return null;
554
+ }
555
+ if (!yes) {
556
+ const selected = await promptSkillsInteractive(found, { defaultAll: true });
557
+ if (!selected) {
558
+ console.log(chalk3.red("No skills selected."));
559
+ process.exitCode = 1;
560
+ return null;
561
+ }
562
+ if (deferPlatformSelection) {
563
+ const selectedPlatforms = await promptPlatformsInteractive({ defaultAll: true });
564
+ if (!selectedPlatforms) {
565
+ console.log(chalk3.red("No platforms selected."));
566
+ process.exitCode = 1;
567
+ return null;
568
+ }
569
+ targets = selectedPlatforms;
570
+ deferPlatformSelection = false;
571
+ }
572
+ effectiveRecursive = true;
573
+ if (spinner) spinner.start();
574
+ recursiveSkillCount = selected.length;
575
+ return selected;
340
576
  }
341
577
  effectiveRecursive = true;
342
- if (spinner) spinner.start();
343
578
  }
344
579
  recursiveSkillCount = found.length;
345
- return false;
580
+ return found;
346
581
  }
347
582
  try {
348
583
  const spinner = jsonOnly ? null : createSpinner(
349
- all ? `Installing ${chalk2.cyan(source)} to ${chalk2.dim("all platforms")} (${scope})...` : `Installing ${chalk2.cyan(source)} to ${chalk2.dim(platform)} (${scope})...`
584
+ allPlatformsSelected ? `Installing ${chalk3.cyan(source)} to ${chalk3.dim("all platforms")} (${scope})...` : targets.length > 1 ? `Installing ${chalk3.cyan(source)} to ${chalk3.dim(`${targets.length} platforms`)} (${scope})...` : `Installing ${chalk3.cyan(source)} to ${chalk3.dim(targets[0])} (${scope})...`
350
585
  );
351
586
  let cleanupMaterialized = null;
352
587
  let materializedRoot = null;
353
588
  try {
589
+ async function ensurePlatformSelection() {
590
+ if (!deferPlatformSelection) return true;
591
+ const selectedPlatforms = await promptPlatformsInteractive({ defaultAll: true });
592
+ if (!selectedPlatforms) {
593
+ console.log(chalk3.red("No platforms selected."));
594
+ process.exitCode = 1;
595
+ return false;
596
+ }
597
+ targets = selectedPlatforms;
598
+ deferPlatformSelection = false;
599
+ return true;
600
+ }
354
601
  if (resolvedSource.startsWith("@") && resolvedSource.includes("/")) {
602
+ if (!await ensurePlatformSelection()) return;
355
603
  await installOne(resolvedSource);
356
604
  } else {
357
605
  const maybeLocalRoot = path2.resolve(resolvedSource);
@@ -359,6 +607,7 @@ ${previewDiscovered(found)}
359
607
  if (isLocal) {
360
608
  const hasSkillMd = fs2.existsSync(path2.join(maybeLocalRoot, "SKILL.md"));
361
609
  if (hasSkillMd) {
610
+ if (!await ensurePlatformSelection()) return;
362
611
  await installOne(resolvedSource);
363
612
  } else {
364
613
  const discovered = discoverSkillDirsWithHeuristics(maybeLocalRoot, { maxDepth, maxSkills });
@@ -368,17 +617,17 @@ ${previewDiscovered(found)}
368
617
  printJson({ ok: false, error: "SKILL_MD_NOT_FOUND", message, source, resolvedSource });
369
618
  } else {
370
619
  if (spinner) spinner.stop();
371
- console.error(chalk2.red(message));
620
+ console.error(chalk3.red(message));
372
621
  }
373
622
  process.exitCode = 1;
374
623
  return;
375
624
  }
376
625
  const found = asDiscoveredSkills(discovered, (d) => path2.join(maybeLocalRoot, d.relPath));
377
- const didReturn = await maybeEnableRecursiveAndInstall(found, spinner);
378
- if (didReturn) return;
379
- if (spinner) spinner.text = `Installing ${chalk2.cyan(source)} \u2014 discovered ${found.length} skills...`;
380
- for (const skill of found) {
381
- if (spinner) spinner.text = `Installing ${chalk2.cyan(skill.relPath)} (${scope})...`;
626
+ const selected = await resolveDiscoveredSelection(found, spinner);
627
+ if (!selected) return;
628
+ if (spinner) spinner.text = `Installing ${chalk3.cyan(source)} \u2014 discovered ${selected.length} skills...`;
629
+ for (const skill of selected) {
630
+ if (spinner) spinner.text = `Installing ${chalk3.cyan(skill.relPath)} (${scope})...`;
382
631
  await installOne(skill.suggestedSource, skill.materializedDir);
383
632
  }
384
633
  }
@@ -397,7 +646,7 @@ ${previewDiscovered(found)}
397
646
  printJson({ ok: false, error: "SKILL_MD_NOT_FOUND", message, source, resolvedSource });
398
647
  } else {
399
648
  if (spinner) spinner.stop();
400
- console.error(chalk2.red(message));
649
+ console.error(chalk3.red(message));
401
650
  }
402
651
  process.exitCode = 1;
403
652
  return;
@@ -407,11 +656,11 @@ ${previewDiscovered(found)}
407
656
  (d) => deriveChildSource(resolvedSource, d.relPath),
408
657
  (d) => d.absDir
409
658
  );
410
- const didReturn = await maybeEnableRecursiveAndInstall(found, spinner);
411
- if (didReturn) return;
412
- if (spinner) spinner.text = `Installing ${chalk2.cyan(source)} \u2014 discovered ${found.length} skills...`;
413
- for (const skill of found) {
414
- if (spinner) spinner.text = `Installing ${chalk2.cyan(skill.relPath)} (${scope})...`;
659
+ const selected = await resolveDiscoveredSelection(found, spinner);
660
+ if (!selected) return;
661
+ if (spinner) spinner.text = `Installing ${chalk3.cyan(source)} \u2014 discovered ${selected.length} skills...`;
662
+ for (const skill of selected) {
663
+ if (spinner) spinner.text = `Installing ${chalk3.cyan(skill.relPath)} (${scope})...`;
415
664
  await installOne(skill.suggestedSource, skill.materializedDir);
416
665
  }
417
666
  }
@@ -421,11 +670,21 @@ ${previewDiscovered(found)}
421
670
  if (cleanupMaterialized) cleanupMaterialized();
422
671
  }
423
672
  if (jsonOnly) {
424
- if (!all && !effectiveRecursive) {
673
+ if (!effectiveRecursive && targets.length === 1) {
425
674
  if (errors.length) printJson({ ok: false, error: errors[0]?.error || "Install failed." });
426
675
  else printJson(results[0] ?? null);
427
676
  } else {
428
- printJson({ ok: errors.length === 0, source, resolvedSource, scope, recursive: effectiveRecursive, all, recursiveSkillCount, results, errors });
677
+ printJson({
678
+ ok: errors.length === 0,
679
+ source,
680
+ resolvedSource,
681
+ scope,
682
+ recursive: effectiveRecursive,
683
+ all: allPlatformsSelected,
684
+ recursiveSkillCount,
685
+ results,
686
+ errors
687
+ });
429
688
  }
430
689
  process.exitCode = errors.length ? 1 : 0;
431
690
  return;
@@ -433,42 +692,42 @@ ${previewDiscovered(found)}
433
692
  if (errors.length === 0) {
434
693
  const displayName = results[0]?.canonicalName || results[0]?.name || source;
435
694
  spinner.succeed(
436
- effectiveRecursive ? `Installed ${chalk2.green(String(recursiveSkillCount ?? results.length))}${chalk2.dim(" skills")} to ${chalk2.dim(`${targets.length} platforms`)}` : all ? `Installed ${chalk2.green(displayName)} to ${chalk2.dim(`${results.length} platforms`)}` : `Installed ${chalk2.green(displayName)} to ${chalk2.dim(results[0]?.installDir || "")}`
695
+ effectiveRecursive ? `Installed ${chalk3.green(String(recursiveSkillCount ?? results.length))}${chalk3.dim(" skills")} to ${chalk3.dim(`${targets.length} platforms`)}` : targets.length > 1 ? `Installed ${chalk3.green(displayName)} to ${chalk3.dim(`${results.length} platforms`)}` : `Installed ${chalk3.green(displayName)} to ${chalk3.dim(results[0]?.installDir || "")}`
437
696
  );
438
697
  } else {
439
698
  const attempted = results.length + errors.length;
440
699
  spinner.fail(
441
- effectiveRecursive ? `Install had failures (${errors.length}/${attempted} installs failed)` : `Failed to install ${chalk2.red(source)} to ${errors.length}/${targets.length} platforms`
700
+ effectiveRecursive ? `Install had failures (${errors.length}/${attempted} installs failed)` : `Failed to install ${chalk3.red(source)} to ${errors.length}/${targets.length} platforms`
442
701
  );
443
702
  process.exitCode = 1;
444
- if (!all && errors[0]) console.error(chalk2.red(errors[0].error));
703
+ if (!effectiveRecursive && targets.length === 1 && errors[0]) console.error(chalk3.red(errors[0].error));
445
704
  }
446
- if (!effectiveRecursive && !all && results[0]) {
705
+ if (!effectiveRecursive && targets.length === 1 && results[0]) {
447
706
  const record = results[0];
448
707
  if (record.hasSkillMd) logger.installDetail("SKILL.md found \u2713");
449
708
  else logger.installDetail("Warning: No SKILL.md found", true);
450
709
  if (record.skill?.validation && !record.skill.validation.ok) {
451
- logger.installDetail(`Validation: ${chalk2.yellow("failed")} (${record.skill.validation.issues.length} issues)`, true);
710
+ logger.installDetail(`Validation: ${chalk3.yellow("failed")} (${record.skill.validation.issues.length} issues)`, true);
452
711
  } else if (record.skill?.validation?.ok) {
453
- logger.installDetail(`Validation: ${chalk2.green("ok")}`);
712
+ logger.installDetail(`Validation: ${chalk3.green("ok")}`);
454
713
  }
455
- } else if (effectiveRecursive || all) {
714
+ } else if (effectiveRecursive || targets.length > 1) {
456
715
  for (const r of results.slice(0, 60)) {
457
716
  const displayName = r.canonicalName || r.name;
458
- const suffix = r.hasSkillMd ? chalk2.green("\u2713") : chalk2.yellow("\u26A0");
459
- console.log(` ${suffix} ${chalk2.cyan(displayName)} \u2192 ${chalk2.dim(r.platform)}`);
717
+ const suffix = r.hasSkillMd ? chalk3.green("\u2713") : chalk3.yellow("\u26A0");
718
+ console.log(` ${suffix} ${chalk3.cyan(displayName)} \u2192 ${chalk3.dim(r.platform)}`);
460
719
  }
461
- if (results.length > 60) console.log(chalk2.dim(` ... and ${results.length - 60} more`));
720
+ if (results.length > 60) console.log(chalk3.dim(` ... and ${results.length - 60} more`));
462
721
  if (errors.length) {
463
- console.log(chalk2.yellow("\nFailures:"));
464
- for (const e of errors) console.log(chalk2.yellow(` - ${e.platform}: ${e.error}`));
722
+ console.log(chalk3.yellow("\nFailures:"));
723
+ for (const e of errors) console.log(chalk3.yellow(` - ${e.platform}: ${e.error}`));
465
724
  }
466
725
  process.exitCode = errors.length ? 1 : 0;
467
726
  }
468
727
  } catch (error) {
469
728
  const message = error instanceof SkildError ? error.message : error instanceof Error ? error.message : String(error);
470
729
  if (jsonOnly) printJson({ ok: false, error: message });
471
- else console.error(chalk2.red(message));
730
+ else console.error(chalk3.red(message));
472
731
  process.exitCode = 1;
473
732
  }
474
733
  }
@@ -504,8 +763,8 @@ async function reportDownload(record, registryOverride) {
504
763
  }
505
764
 
506
765
  // src/commands/list.ts
507
- import chalk3 from "chalk";
508
- import { PLATFORMS as PLATFORMS2, listAllSkills, listSkills } from "@skild/core";
766
+ import chalk4 from "chalk";
767
+ import { PLATFORMS as PLATFORMS3, listAllSkills, listSkills } from "@skild/core";
509
768
  function isSkillset(skill) {
510
769
  return Boolean(skill.record?.skillset || skill.record?.skill?.frontmatter?.skillset);
511
770
  }
@@ -520,10 +779,10 @@ function buildNameToDisplay(skills) {
520
779
  return mapping;
521
780
  }
522
781
  function statusIcon(skill) {
523
- return skill.hasSkillMd ? chalk3.green("\u2713") : chalk3.yellow("\u26A0");
782
+ return skill.hasSkillMd ? chalk4.green("\u2713") : chalk4.yellow("\u26A0");
524
783
  }
525
784
  function missingSkillMdLabel(skill) {
526
- return skill.hasSkillMd ? "" : chalk3.yellow(" (missing SKILL.md)");
785
+ return skill.hasSkillMd ? "" : chalk4.yellow(" (missing SKILL.md)");
527
786
  }
528
787
  function formatDepName(dep, nameToDisplay) {
529
788
  return dep.canonicalName || nameToDisplay.get(dep.name) || dep.name;
@@ -548,62 +807,62 @@ function summarizeDeps(record) {
548
807
  return `deps: ${byType.total}${parts.length ? ` (${parts.join(", ")})` : ""}`;
549
808
  }
550
809
  function printSkillsetSection(skills, nameToDisplay, options) {
551
- console.log(chalk3.bold(` Skillsets (${skills.length})`));
810
+ console.log(chalk4.bold(` Skillsets (${skills.length})`));
552
811
  if (skills.length === 0) {
553
- console.log(chalk3.dim(" (none)"));
812
+ console.log(chalk4.dim(" (none)"));
554
813
  return;
555
814
  }
556
815
  for (const s of skills) {
557
- const label = `${chalk3.cyan(getDisplayName(s))}${chalk3.dim(" (skillset)")}${missingSkillMdLabel(s)}`;
816
+ const label = `${chalk4.cyan(getDisplayName(s))}${chalk4.dim(" (skillset)")}${missingSkillMdLabel(s)}`;
558
817
  console.log(` ${statusIcon(s)} ${label}`);
559
818
  const summary = summarizeDeps(s.record);
560
- if (summary) console.log(chalk3.dim(` ${summary}`));
819
+ if (summary) console.log(chalk4.dim(` ${summary}`));
561
820
  if (options.verbose) {
562
821
  const deps = (s.record?.installedDependencies || []).slice().sort((a, b) => a.name.localeCompare(b.name));
563
822
  if (deps.length) {
564
- console.log(chalk3.dim(` includes (${deps.length}):`));
823
+ console.log(chalk4.dim(` includes (${deps.length}):`));
565
824
  for (const dep of deps) {
566
825
  const depName = formatDepName(dep, nameToDisplay);
567
- console.log(chalk3.dim(` - ${depName} [${dep.sourceType}]`));
826
+ console.log(chalk4.dim(` - ${depName} [${dep.sourceType}]`));
568
827
  }
569
828
  }
570
829
  }
571
- if (options.paths || !s.hasSkillMd) console.log(chalk3.dim(` path: ${s.installDir}`));
830
+ if (options.paths || !s.hasSkillMd) console.log(chalk4.dim(` path: ${s.installDir}`));
572
831
  }
573
832
  }
574
833
  function printSkillsSection(skills, options) {
575
- console.log(chalk3.bold(` Skills (${skills.length})`));
834
+ console.log(chalk4.bold(` Skills (${skills.length})`));
576
835
  if (skills.length === 0) {
577
- console.log(chalk3.dim(" (none)"));
836
+ console.log(chalk4.dim(" (none)"));
578
837
  return;
579
838
  }
580
839
  for (const s of skills) {
581
- const label = `${chalk3.cyan(getDisplayName(s))}${missingSkillMdLabel(s)}`;
840
+ const label = `${chalk4.cyan(getDisplayName(s))}${missingSkillMdLabel(s)}`;
582
841
  console.log(` ${statusIcon(s)} ${label}`);
583
- if (options.paths || !s.hasSkillMd) console.log(chalk3.dim(` path: ${s.installDir}`));
842
+ if (options.paths || !s.hasSkillMd) console.log(chalk4.dim(` path: ${s.installDir}`));
584
843
  }
585
844
  }
586
845
  function printDependenciesSection(skills, nameToDisplay, options) {
587
- console.log(chalk3.bold(` Dependencies (${skills.length})`));
846
+ console.log(chalk4.bold(` Dependencies (${skills.length})`));
588
847
  if (skills.length === 0) {
589
- console.log(chalk3.dim(" (none)"));
848
+ console.log(chalk4.dim(" (none)"));
590
849
  return;
591
850
  }
592
851
  for (const s of skills) {
593
852
  const dependedBy = (s.record?.dependedBy || []).map((name) => nameToDisplay.get(name) || name).sort((a, b) => a.localeCompare(b));
594
- const requiredBy = dependedBy.length ? chalk3.dim(` \u2190 required by: ${dependedBy.join(", ")}`) : "";
595
- const label = `${chalk3.cyan(getDisplayName(s))}${missingSkillMdLabel(s)}${requiredBy}`;
853
+ const requiredBy = dependedBy.length ? chalk4.dim(` \u2190 required by: ${dependedBy.join(", ")}`) : "";
854
+ const label = `${chalk4.cyan(getDisplayName(s))}${missingSkillMdLabel(s)}${requiredBy}`;
596
855
  console.log(` ${statusIcon(s)} ${label}`);
597
- if (options.paths || !s.hasSkillMd) console.log(chalk3.dim(` path: ${s.installDir}`));
856
+ if (options.paths || !s.hasSkillMd) console.log(chalk4.dim(` path: ${s.installDir}`));
598
857
  }
599
858
  }
600
859
  function printPlatform(skills, platform, scope, options) {
601
- console.log(chalk3.bold(`
860
+ console.log(chalk4.bold(`
602
861
  \u{1F4E6} Installed Skills \u2014 ${platform} (${scope})
603
862
  `));
604
863
  if (skills.length === 0) {
605
- console.log(chalk3.dim(" No skills installed."));
606
- console.log(chalk3.dim(` Use ${chalk3.cyan("skild install <source>")} to install a skill.`));
864
+ console.log(chalk4.dim(" No skills installed."));
865
+ console.log(chalk4.dim(` Use ${chalk4.cyan("skild install <source>")} to install a skill.`));
607
866
  return;
608
867
  }
609
868
  const nameToDisplay = buildNameToDisplay(skills);
@@ -637,11 +896,11 @@ async function list(options = {}) {
637
896
  return;
638
897
  }
639
898
  if (allSkills.length === 0) {
640
- console.log(chalk3.dim("No skills installed."));
641
- console.log(chalk3.dim(`Use ${chalk3.cyan("skild install <source>")} to install a skill.`));
899
+ console.log(chalk4.dim("No skills installed."));
900
+ console.log(chalk4.dim(`Use ${chalk4.cyan("skild install <source>")} to install a skill.`));
642
901
  return;
643
902
  }
644
- for (const p of PLATFORMS2) {
903
+ for (const p of PLATFORMS3) {
645
904
  const platformSkills = allSkills.filter((s) => s.platform === p).sort((a, b) => a.name.localeCompare(b.name));
646
905
  if (platformSkills.length === 0) continue;
647
906
  printPlatform(platformSkills, p, scope, { paths, verbose });
@@ -649,7 +908,7 @@ async function list(options = {}) {
649
908
  }
650
909
 
651
910
  // src/commands/info.ts
652
- import chalk4 from "chalk";
911
+ import chalk5 from "chalk";
653
912
  import { canonicalNameToInstallDirName, getSkillInfo, SkildError as SkildError2 } from "@skild/core";
654
913
  async function info(skill, options = {}) {
655
914
  const platform = options.target || "claude";
@@ -662,22 +921,22 @@ async function info(skill, options = {}) {
662
921
  return;
663
922
  }
664
923
  const displayName = record.canonicalName || record.name;
665
- console.log(chalk4.bold(`
666
- ${chalk4.cyan(displayName)}
924
+ console.log(chalk5.bold(`
925
+ ${chalk5.cyan(displayName)}
667
926
  `));
668
- console.log(` ${chalk4.dim("Path:")} ${record.installDir}`);
669
- console.log(` ${chalk4.dim("Source:")} ${record.source}`);
670
- console.log(` ${chalk4.dim("Target:")} ${record.platform} (${record.scope})`);
671
- console.log(` ${chalk4.dim("Installed:")} ${record.installedAt}`);
672
- if (record.updatedAt) console.log(` ${chalk4.dim("Updated:")} ${record.updatedAt}`);
673
- console.log(` ${chalk4.dim("Hash:")} ${record.contentHash}`);
674
- console.log(` ${chalk4.dim("SKILL.md:")} ${record.hasSkillMd ? chalk4.green("yes") : chalk4.yellow("no")}`);
927
+ console.log(` ${chalk5.dim("Path:")} ${record.installDir}`);
928
+ console.log(` ${chalk5.dim("Source:")} ${record.source}`);
929
+ console.log(` ${chalk5.dim("Target:")} ${record.platform} (${record.scope})`);
930
+ console.log(` ${chalk5.dim("Installed:")} ${record.installedAt}`);
931
+ if (record.updatedAt) console.log(` ${chalk5.dim("Updated:")} ${record.updatedAt}`);
932
+ console.log(` ${chalk5.dim("Hash:")} ${record.contentHash}`);
933
+ console.log(` ${chalk5.dim("SKILL.md:")} ${record.hasSkillMd ? chalk5.green("yes") : chalk5.yellow("no")}`);
675
934
  const validation = record.skill?.validation;
676
935
  if (validation) {
677
- console.log(` ${chalk4.dim("Validate:")} ${validation.ok ? chalk4.green("ok") : chalk4.red("failed")}`);
936
+ console.log(` ${chalk5.dim("Validate:")} ${validation.ok ? chalk5.green("ok") : chalk5.red("failed")}`);
678
937
  if (!validation.ok) {
679
938
  for (const issue of validation.issues) {
680
- const color = issue.level === "error" ? chalk4.red : chalk4.yellow;
939
+ const color = issue.level === "error" ? chalk5.red : chalk5.yellow;
681
940
  console.log(` - ${color(issue.level)}: ${issue.message}`);
682
941
  }
683
942
  }
@@ -685,20 +944,20 @@ ${chalk4.cyan(displayName)}
685
944
  console.log("");
686
945
  } catch (error) {
687
946
  const message = error instanceof SkildError2 ? error.message : error instanceof Error ? error.message : String(error);
688
- console.error(chalk4.red(message));
947
+ console.error(chalk5.red(message));
689
948
  process.exitCode = 1;
690
949
  }
691
950
  }
692
951
 
693
952
  // src/commands/uninstall.ts
694
- import chalk5 from "chalk";
953
+ import chalk6 from "chalk";
695
954
  import { canonicalNameToInstallDirName as canonicalNameToInstallDirName2, uninstallSkill, SkildError as SkildError3 } from "@skild/core";
696
955
  async function uninstall(skill, options = {}) {
697
956
  const platform = options.target || "claude";
698
957
  const scope = options.local ? "project" : "global";
699
958
  const canonical = skill.trim();
700
959
  const resolvedName = canonical.startsWith("@") && canonical.includes("/") ? canonicalNameToInstallDirName2(canonical) : canonical;
701
- const spinner = createSpinner(`Uninstalling ${chalk5.cyan(canonical)} from ${chalk5.dim(platform)} (${scope})...`);
960
+ const spinner = createSpinner(`Uninstalling ${chalk6.cyan(canonical)} from ${chalk6.dim(platform)} (${scope})...`);
702
961
  try {
703
962
  uninstallSkill(resolvedName, {
704
963
  platform,
@@ -706,40 +965,40 @@ async function uninstall(skill, options = {}) {
706
965
  allowMissingMetadata: Boolean(options.force),
707
966
  withDeps: Boolean(options.withDeps)
708
967
  });
709
- spinner.succeed(`Uninstalled ${chalk5.green(canonical)}`);
968
+ spinner.succeed(`Uninstalled ${chalk6.green(canonical)}`);
710
969
  } catch (error) {
711
- spinner.fail(`Failed to uninstall ${chalk5.red(canonical)}`);
970
+ spinner.fail(`Failed to uninstall ${chalk6.red(canonical)}`);
712
971
  const message = error instanceof SkildError3 ? error.message : error instanceof Error ? error.message : String(error);
713
- console.error(chalk5.red(message));
972
+ console.error(chalk6.red(message));
714
973
  process.exitCode = 1;
715
974
  }
716
975
  }
717
976
 
718
977
  // src/commands/update.ts
719
- import chalk6 from "chalk";
978
+ import chalk7 from "chalk";
720
979
  import { canonicalNameToInstallDirName as canonicalNameToInstallDirName3, updateSkill, SkildError as SkildError4 } from "@skild/core";
721
980
  async function update(skill, options = {}) {
722
981
  const platform = options.target || "claude";
723
982
  const scope = options.local ? "project" : "global";
724
983
  const label = skill ? skill : "all skills";
725
984
  const resolvedName = skill && skill.trim().startsWith("@") && skill.includes("/") ? canonicalNameToInstallDirName3(skill.trim()) : skill;
726
- const spinner = createSpinner(`Updating ${chalk6.cyan(label)} on ${chalk6.dim(platform)} (${scope})...`);
985
+ const spinner = createSpinner(`Updating ${chalk7.cyan(label)} on ${chalk7.dim(platform)} (${scope})...`);
727
986
  try {
728
987
  const results = await updateSkill(resolvedName, { platform, scope });
729
- spinner.succeed(`Updated ${chalk6.green(results.length.toString())} skill(s).`);
988
+ spinner.succeed(`Updated ${chalk7.green(results.length.toString())} skill(s).`);
730
989
  if (options.json) {
731
990
  console.log(JSON.stringify(results, null, 2));
732
991
  }
733
992
  } catch (error) {
734
- spinner.fail(`Failed to update ${chalk6.red(label)}`);
993
+ spinner.fail(`Failed to update ${chalk7.red(label)}`);
735
994
  const message = error instanceof SkildError4 ? error.message : error instanceof Error ? error.message : String(error);
736
- console.error(chalk6.red(message));
995
+ console.error(chalk7.red(message));
737
996
  process.exitCode = 1;
738
997
  }
739
998
  }
740
999
 
741
1000
  // src/commands/validate.ts
742
- import chalk7 from "chalk";
1001
+ import chalk8 from "chalk";
743
1002
  import { canonicalNameToInstallDirName as canonicalNameToInstallDirName4, validateSkill } from "@skild/core";
744
1003
  async function validate(target, options = {}) {
745
1004
  const platform = options.target || "claude";
@@ -753,42 +1012,102 @@ async function validate(target, options = {}) {
753
1012
  return;
754
1013
  }
755
1014
  if (result.ok) {
756
- console.log(chalk7.green("\u2713"), "Valid skill");
757
- if (result.frontmatter?.name) console.log(chalk7.dim(` name: ${result.frontmatter.name}`));
1015
+ console.log(chalk8.green("\u2713"), "Valid skill");
1016
+ if (result.frontmatter?.name) console.log(chalk8.dim(` name: ${result.frontmatter.name}`));
758
1017
  return;
759
1018
  }
760
- console.error(chalk7.red("\u2717"), "Invalid skill");
1019
+ console.error(chalk8.red("\u2717"), "Invalid skill");
761
1020
  for (const issue of result.issues) {
762
- const color = issue.level === "error" ? chalk7.red : chalk7.yellow;
1021
+ const color = issue.level === "error" ? chalk8.red : chalk8.yellow;
763
1022
  console.error(` - ${color(issue.level)}: ${issue.message}`);
764
1023
  }
765
1024
  process.exitCode = 1;
766
1025
  }
767
1026
 
768
1027
  // src/commands/init.ts
769
- import chalk8 from "chalk";
1028
+ import chalk9 from "chalk";
770
1029
  import { initSkill, SkildError as SkildError5 } from "@skild/core";
771
1030
  async function init(name, options = {}) {
772
- const spinner = createSpinner(`Initializing ${chalk8.cyan(name)}...`);
1031
+ const spinner = createSpinner(`Initializing ${chalk9.cyan(name)}...`);
773
1032
  try {
774
1033
  const createdDir = initSkill(name, {
775
1034
  dir: options.dir,
776
1035
  description: options.description,
777
1036
  force: Boolean(options.force)
778
1037
  });
779
- spinner.succeed(`Created ${chalk8.green(name)} at ${chalk8.dim(createdDir)}`);
780
- console.log(chalk8.dim(`Next: cd ${createdDir} && skild validate .`));
1038
+ spinner.succeed(`Created ${chalk9.green(name)} at ${chalk9.dim(createdDir)}`);
1039
+ console.log(chalk9.dim(`Next: cd ${createdDir} && skild validate .`));
781
1040
  } catch (error) {
782
- spinner.fail(`Failed to init ${chalk8.red(name)}`);
1041
+ spinner.fail(`Failed to init ${chalk9.red(name)}`);
783
1042
  const message = error instanceof SkildError5 ? error.message : error instanceof Error ? error.message : String(error);
784
- console.error(chalk8.red(message));
1043
+ console.error(chalk9.red(message));
785
1044
  process.exitCode = 1;
786
1045
  }
787
1046
  }
788
1047
 
789
1048
  // src/commands/signup.ts
790
- import chalk9 from "chalk";
1049
+ import chalk10 from "chalk";
791
1050
  import { fetchWithTimeout as fetchWithTimeout2, resolveRegistryUrl as resolveRegistryUrl2, SkildError as SkildError6 } from "@skild/core";
1051
+
1052
+ // src/utils/prompt.ts
1053
+ import readline2 from "readline";
1054
+ async function promptLine(question, defaultValue) {
1055
+ const rl = readline2.createInterface({ input: process.stdin, output: process.stdout, terminal: true });
1056
+ try {
1057
+ const suffix = defaultValue ? ` (${defaultValue})` : "";
1058
+ const answer = await new Promise((resolve) => rl.question(`${question}${suffix}: `, resolve));
1059
+ const trimmed = answer.trim();
1060
+ return trimmed || defaultValue || "";
1061
+ } finally {
1062
+ rl.close();
1063
+ }
1064
+ }
1065
+ async function promptPassword(question) {
1066
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
1067
+ return promptLine(question);
1068
+ }
1069
+ const stdin = process.stdin;
1070
+ const stdout = process.stdout;
1071
+ stdout.write(`${question}: `);
1072
+ const wasRaw = Boolean(stdin.isRaw);
1073
+ stdin.setRawMode(true);
1074
+ stdin.resume();
1075
+ readline2.emitKeypressEvents(stdin);
1076
+ const buf = [];
1077
+ return await new Promise((resolve, reject) => {
1078
+ function cleanup() {
1079
+ stdin.off("keypress", onKeypress);
1080
+ stdin.setRawMode(wasRaw);
1081
+ stdin.pause();
1082
+ }
1083
+ function onKeypress(str, key) {
1084
+ if (key?.ctrl && key?.name === "c") {
1085
+ stdout.write("\n");
1086
+ cleanup();
1087
+ const err = new Error("Prompt cancelled");
1088
+ err.code = "PROMPT_CANCELLED";
1089
+ reject(err);
1090
+ return;
1091
+ }
1092
+ if (key?.name === "return" || key?.name === "enter") {
1093
+ stdout.write("\n");
1094
+ cleanup();
1095
+ resolve(buf.join(""));
1096
+ return;
1097
+ }
1098
+ if (key?.name === "backspace" || key?.name === "delete") {
1099
+ if (buf.length) buf.pop();
1100
+ return;
1101
+ }
1102
+ if (!str) return;
1103
+ if (key?.ctrl || key?.meta) return;
1104
+ buf.push(str);
1105
+ }
1106
+ stdin.on("keypress", onKeypress);
1107
+ });
1108
+ }
1109
+
1110
+ // src/commands/signup.ts
792
1111
  async function signup(options) {
793
1112
  const registry = resolveRegistryUrl2(options.registry);
794
1113
  const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY);
@@ -796,7 +1115,7 @@ async function signup(options) {
796
1115
  const handle = options.handle?.trim() || "";
797
1116
  const password = options.password || "";
798
1117
  if ((!email || !handle || !password) && (!interactive || options.json)) {
799
- console.error(chalk9.red("Missing signup fields. Use --email/--handle/--password, or run `skild signup` interactively."));
1118
+ console.error(chalk10.red("Missing signup fields. Use --email/--handle/--password, or run `skild signup` interactively."));
800
1119
  process.exitCode = 1;
801
1120
  return;
802
1121
  }
@@ -831,13 +1150,13 @@ async function signup(options) {
831
1150
  );
832
1151
  text = await res.text();
833
1152
  if (!res.ok) {
834
- console.error(chalk9.red(`Signup failed (${res.status}): ${text}`));
1153
+ console.error(chalk10.red(`Signup failed (${res.status}): ${text}`));
835
1154
  process.exitCode = 1;
836
1155
  return;
837
1156
  }
838
1157
  } catch (error) {
839
1158
  const message = error instanceof SkildError6 ? error.message : error instanceof Error ? error.message : String(error);
840
- console.error(chalk9.red(`Signup failed: ${message}`));
1159
+ console.error(chalk10.red(`Signup failed: ${message}`));
841
1160
  process.exitCode = 1;
842
1161
  return;
843
1162
  }
@@ -845,29 +1164,29 @@ async function signup(options) {
845
1164
  console.log(text || JSON.stringify({ ok: true }, null, 2));
846
1165
  return;
847
1166
  }
848
- console.log(chalk9.green("Signup successful."));
1167
+ console.log(chalk10.green("Signup successful."));
849
1168
  try {
850
1169
  const parsed = JSON.parse(text);
851
1170
  if (parsed.verification?.requiredForPublish) {
852
1171
  if (parsed.verification.mode === "log") {
853
- console.log(chalk9.dim("Dev mode: email sending is disabled. Check the registry dev logs for the verification link."));
1172
+ console.log(chalk10.dim("Dev mode: email sending is disabled. Check the registry dev logs for the verification link."));
854
1173
  } else if (parsed.verification.sent) {
855
- console.log(chalk9.dim("Verification email sent. Check your inbox (and spam)."));
1174
+ console.log(chalk10.dim("Verification email sent. Check your inbox (and spam)."));
856
1175
  } else {
857
- console.log(chalk9.yellow("Verification email was not sent. You may need to resend from the Skild Hub."));
1176
+ console.log(chalk10.yellow("Verification email was not sent. You may need to resend from the Skild Hub."));
858
1177
  }
859
- console.log(chalk9.dim(`Verify/resend in Skild Hub: ${(parsed.verification.consoleUrl || "https://hub.skild.sh").replace(/\/+$/, "")}/verify-email/request`));
1178
+ console.log(chalk10.dim(`Verify/resend in Skild Hub: ${(parsed.verification.consoleUrl || "https://hub.skild.sh").replace(/\/+$/, "")}/verify-email/request`));
860
1179
  } else if (parsed.verification) {
861
- console.log(chalk9.dim("Email verification is recommended. Publishing may be restricted in the future."));
862
- console.log(chalk9.dim(`Verify/resend in Skild Hub: ${(parsed.verification.consoleUrl || "https://hub.skild.sh").replace(/\/+$/, "")}/verify-email/request`));
1180
+ console.log(chalk10.dim("Email verification is recommended. Publishing may be restricted in the future."));
1181
+ console.log(chalk10.dim(`Verify/resend in Skild Hub: ${(parsed.verification.consoleUrl || "https://hub.skild.sh").replace(/\/+$/, "")}/verify-email/request`));
863
1182
  }
864
1183
  } catch {
865
1184
  }
866
- console.log(chalk9.dim("Next: run `skild login`"));
1185
+ console.log(chalk10.dim("Next: run `skild login`"));
867
1186
  }
868
1187
 
869
1188
  // src/commands/login.ts
870
- import chalk10 from "chalk";
1189
+ import chalk11 from "chalk";
871
1190
  import { fetchWithTimeout as fetchWithTimeout3, resolveRegistryUrl as resolveRegistryUrl3, saveRegistryAuth, SkildError as SkildError7 } from "@skild/core";
872
1191
  async function login(options) {
873
1192
  const registry = resolveRegistryUrl3(options.registry);
@@ -875,7 +1194,7 @@ async function login(options) {
875
1194
  const handleOrEmail = options.handleOrEmail?.trim() || "";
876
1195
  const password = options.password || "";
877
1196
  if ((!handleOrEmail || !password) && (!interactive || options.json)) {
878
- console.error(chalk10.red("Missing credentials. Use --handle-or-email and --password, or run `skild login` interactively."));
1197
+ console.error(chalk11.red("Missing credentials. Use --handle-or-email and --password, or run `skild login` interactively."));
879
1198
  process.exitCode = 1;
880
1199
  return;
881
1200
  }
@@ -910,13 +1229,13 @@ async function login(options) {
910
1229
  );
911
1230
  text = await res.text();
912
1231
  if (!res.ok) {
913
- console.error(chalk10.red(`Login failed (${res.status}): ${text}`));
1232
+ console.error(chalk11.red(`Login failed (${res.status}): ${text}`));
914
1233
  process.exitCode = 1;
915
1234
  return;
916
1235
  }
917
1236
  } catch (error) {
918
1237
  const message = error instanceof SkildError7 ? error.message : error instanceof Error ? error.message : String(error);
919
- console.error(chalk10.red(`Login failed: ${message}`));
1238
+ console.error(chalk11.red(`Login failed: ${message}`));
920
1239
  process.exitCode = 1;
921
1240
  return;
922
1241
  }
@@ -932,28 +1251,28 @@ async function login(options) {
932
1251
  console.log(JSON.stringify({ ok: true, publisher: json.publisher }, null, 2));
933
1252
  return;
934
1253
  }
935
- console.log(chalk10.green(`Logged in as ${chalk10.cyan(json.publisher.handle)}.`));
1254
+ console.log(chalk11.green(`Logged in as ${chalk11.cyan(json.publisher.handle)}.`));
936
1255
  if (json.publisher.emailVerified === false) {
937
- console.log(chalk10.yellow("Email not verified. Publishing may be restricted by server policy."));
938
- console.log(chalk10.dim("Open the Skild Hub to verify: https://hub.skild.sh/verify-email/request"));
1256
+ console.log(chalk11.yellow("Email not verified. Publishing may be restricted by server policy."));
1257
+ console.log(chalk11.dim("Open the Skild Hub to verify: https://hub.skild.sh/verify-email/request"));
939
1258
  }
940
1259
  }
941
1260
 
942
1261
  // src/commands/logout.ts
943
- import chalk11 from "chalk";
1262
+ import chalk12 from "chalk";
944
1263
  import { clearRegistryAuth } from "@skild/core";
945
1264
  async function logout() {
946
1265
  clearRegistryAuth();
947
- console.log(chalk11.green("Logged out."));
1266
+ console.log(chalk12.green("Logged out."));
948
1267
  }
949
1268
 
950
1269
  // src/commands/whoami.ts
951
- import chalk12 from "chalk";
1270
+ import chalk13 from "chalk";
952
1271
  import { fetchWithTimeout as fetchWithTimeout4, loadRegistryAuth as loadRegistryAuth2, resolveRegistryUrl as resolveRegistryUrl4, SkildError as SkildError8 } from "@skild/core";
953
1272
  async function whoami() {
954
1273
  const auth = loadRegistryAuth2();
955
1274
  if (!auth) {
956
- console.error(chalk12.red("Not logged in. Run `skild login` first."));
1275
+ console.error(chalk13.red("Not logged in. Run `skild login` first."));
957
1276
  process.exitCode = 1;
958
1277
  return;
959
1278
  }
@@ -966,16 +1285,16 @@ async function whoami() {
966
1285
  );
967
1286
  const text = await res.text();
968
1287
  if (!res.ok) {
969
- console.error(chalk12.red(`whoami failed (${res.status}): ${text}`));
1288
+ console.error(chalk13.red(`whoami failed (${res.status}): ${text}`));
970
1289
  process.exitCode = 1;
971
1290
  return;
972
1291
  }
973
1292
  const json = JSON.parse(text);
974
- console.log(chalk12.cyan(json.publisher.handle));
1293
+ console.log(chalk13.cyan(json.publisher.handle));
975
1294
  } catch (error) {
976
1295
  const message = error instanceof SkildError8 ? error.message : error instanceof Error ? error.message : String(error);
977
- console.error(chalk12.red(`whoami failed: ${message}`));
978
- console.error(chalk12.dim("Tip: if you previously logged into a local registry, run `skild logout` then `skild login`."));
1296
+ console.error(chalk13.red(`whoami failed: ${message}`));
1297
+ console.error(chalk13.dim("Tip: if you previously logged into a local registry, run `skild logout` then `skild login`."));
979
1298
  process.exitCode = 1;
980
1299
  }
981
1300
  }
@@ -986,7 +1305,7 @@ import os from "os";
986
1305
  import path3 from "path";
987
1306
  import crypto from "crypto";
988
1307
  import * as tar from "tar";
989
- import chalk13 from "chalk";
1308
+ import chalk14 from "chalk";
990
1309
  import { assertValidAlias, fetchWithTimeout as fetchWithTimeout5, loadRegistryAuth as loadRegistryAuth3, normalizeAlias, resolveRegistryUrl as resolveRegistryUrl5, SkildError as SkildError9, splitCanonicalName, validateSkillDir } from "@skild/core";
991
1310
  function sha256Hex(buf) {
992
1311
  const h = crypto.createHash("sha256");
@@ -1002,15 +1321,15 @@ async function publish(options = {}) {
1002
1321
  const registry = resolveRegistryUrl5(options.registry || auth?.registryUrl);
1003
1322
  const token = auth?.token;
1004
1323
  if (!token) {
1005
- console.error(chalk13.red("Not logged in. Run `skild login` first."));
1324
+ console.error(chalk14.red("Not logged in. Run `skild login` first."));
1006
1325
  process.exitCode = 1;
1007
1326
  return;
1008
1327
  }
1009
1328
  const dir = path3.resolve(options.dir || process.cwd());
1010
1329
  const validation = validateSkillDir(dir);
1011
1330
  if (!validation.ok) {
1012
- console.error(chalk13.red("Skill validation failed:"));
1013
- for (const issue of validation.issues) console.error(chalk13.red(`- ${issue.message}`));
1331
+ console.error(chalk14.red("Skill validation failed:"));
1332
+ for (const issue of validation.issues) console.error(chalk14.red(`- ${issue.message}`));
1014
1333
  process.exitCode = 1;
1015
1334
  return;
1016
1335
  }
@@ -1024,14 +1343,14 @@ async function publish(options = {}) {
1024
1343
  const skillset = fm.skillset === true;
1025
1344
  const dependencies = Array.isArray(fm.dependencies) ? fm.dependencies : [];
1026
1345
  if (!name) {
1027
- console.error(chalk13.red("Missing name. Provide SKILL.md frontmatter.name or --name."));
1346
+ console.error(chalk14.red("Missing name. Provide SKILL.md frontmatter.name or --name."));
1028
1347
  process.exitCode = 1;
1029
1348
  return;
1030
1349
  }
1031
1350
  if (!name.startsWith("@")) {
1032
1351
  const seg = name.trim();
1033
1352
  if (!/^[a-z0-9][a-z0-9-]{1,63}$/.test(seg)) {
1034
- console.error(chalk13.red("Invalid name. Use @publisher/skill or a simple skill name (lowercase letters/digits/dashes)."));
1353
+ console.error(chalk14.red("Invalid name. Use @publisher/skill or a simple skill name (lowercase letters/digits/dashes)."));
1035
1354
  process.exitCode = 1;
1036
1355
  return;
1037
1356
  }
@@ -1042,26 +1361,26 @@ async function publish(options = {}) {
1042
1361
  );
1043
1362
  const meText = await meRes.text();
1044
1363
  if (!meRes.ok) {
1045
- console.error(chalk13.red(`Failed to infer publisher scope (${meRes.status}): ${meText}`));
1364
+ console.error(chalk14.red(`Failed to infer publisher scope (${meRes.status}): ${meText}`));
1046
1365
  process.exitCode = 1;
1047
1366
  return;
1048
1367
  }
1049
1368
  const meJson = JSON.parse(meText);
1050
1369
  const handle = String(meJson?.publisher?.handle || "").trim().toLowerCase();
1051
1370
  if (!handle) {
1052
- console.error(chalk13.red("Failed to infer publisher scope from registry response."));
1371
+ console.error(chalk14.red("Failed to infer publisher scope from registry response."));
1053
1372
  process.exitCode = 1;
1054
1373
  return;
1055
1374
  }
1056
1375
  name = `@${handle}/${seg}`;
1057
1376
  }
1058
1377
  if (!/^@[a-z0-9][a-z0-9-]{1,31}\/[a-z0-9][a-z0-9-]{1,63}$/.test(name)) {
1059
- console.error(chalk13.red("Invalid publish name. Expected @publisher/skill (lowercase letters/digits/dashes)."));
1378
+ console.error(chalk14.red("Invalid publish name. Expected @publisher/skill (lowercase letters/digits/dashes)."));
1060
1379
  process.exitCode = 1;
1061
1380
  return;
1062
1381
  }
1063
1382
  if (!version2) {
1064
- console.error(chalk13.red("Missing version. Provide semver like 1.2.3 via SKILL.md frontmatter or --skill-version."));
1383
+ console.error(chalk14.red("Missing version. Provide semver like 1.2.3 via SKILL.md frontmatter or --skill-version."));
1065
1384
  process.exitCode = 1;
1066
1385
  return;
1067
1386
  }
@@ -1070,12 +1389,12 @@ async function publish(options = {}) {
1070
1389
  assertValidAlias(alias);
1071
1390
  } catch (error) {
1072
1391
  const message = error instanceof SkildError9 ? error.message : error instanceof Error ? error.message : String(error);
1073
- console.error(chalk13.red(message));
1392
+ console.error(chalk14.red(message));
1074
1393
  process.exitCode = 1;
1075
1394
  return;
1076
1395
  }
1077
1396
  }
1078
- const spinner = createSpinner(`Publishing ${chalk13.cyan(`${name}@${version2}`)} to ${chalk13.dim(registry)}...`);
1397
+ const spinner = createSpinner(`Publishing ${chalk14.cyan(`${name}@${version2}`)} to ${chalk14.dim(registry)}...`);
1079
1398
  const tempDir = fs3.mkdtempSync(path3.join(os.tmpdir(), "skild-publish-"));
1080
1399
  const tarballPath = path3.join(tempDir, "skill.tgz");
1081
1400
  try {
@@ -1112,12 +1431,12 @@ async function publish(options = {}) {
1112
1431
  const text = await res.text();
1113
1432
  if (!res.ok) {
1114
1433
  spinner.fail(`Publish failed (${res.status})`);
1115
- console.error(chalk13.red(text));
1434
+ console.error(chalk14.red(text));
1116
1435
  process.exitCode = 1;
1117
1436
  return;
1118
1437
  }
1119
1438
  if (alias) {
1120
- spinner.text = `Publishing ${chalk13.cyan(`${name}@${version2}`)} \u2014 setting alias ${chalk13.cyan(alias)}...`;
1439
+ spinner.text = `Publishing ${chalk14.cyan(`${name}@${version2}`)} \u2014 setting alias ${chalk14.cyan(alias)}...`;
1121
1440
  const aliasRes = await fetchWithTimeout5(
1122
1441
  `${registry}/publisher/skills/${encodeURIComponent(scope)}/${encodeURIComponent(skillName)}/alias`,
1123
1442
  {
@@ -1133,7 +1452,7 @@ async function publish(options = {}) {
1133
1452
  const aliasText = await aliasRes.text();
1134
1453
  if (!aliasRes.ok) {
1135
1454
  spinner.fail(`Failed to set alias (${aliasRes.status})`);
1136
- console.error(chalk13.red(aliasText));
1455
+ console.error(chalk14.red(aliasText));
1137
1456
  process.exitCode = 1;
1138
1457
  return;
1139
1458
  }
@@ -1142,18 +1461,18 @@ async function publish(options = {}) {
1142
1461
  console.log(text);
1143
1462
  return;
1144
1463
  }
1145
- const suffix = alias ? ` (alias: ${chalk13.cyan(alias)})` : "";
1146
- spinner.succeed(`Published ${chalk13.green(`${name}@${version2}`)}${suffix} (sha256:${integrity.slice(0, 12)}\u2026)`);
1464
+ const suffix = alias ? ` (alias: ${chalk14.cyan(alias)})` : "";
1465
+ spinner.succeed(`Published ${chalk14.green(`${name}@${version2}`)}${suffix} (sha256:${integrity.slice(0, 12)}\u2026)`);
1147
1466
  try {
1148
1467
  const parsed = JSON.parse(text);
1149
1468
  const warnings = Array.isArray(parsed.warnings) ? parsed.warnings.map(String).filter(Boolean) : [];
1150
- for (const w of warnings) console.warn(chalk13.yellow(`Warning: ${w}`));
1469
+ for (const w of warnings) console.warn(chalk14.yellow(`Warning: ${w}`));
1151
1470
  } catch {
1152
1471
  }
1153
1472
  } catch (error) {
1154
1473
  spinner.fail("Publish failed");
1155
1474
  const message = error instanceof SkildError9 ? error.message : error instanceof Error ? error.message : String(error);
1156
- console.error(chalk13.red(message));
1475
+ console.error(chalk14.red(message));
1157
1476
  process.exitCode = 1;
1158
1477
  } finally {
1159
1478
  fs3.rmSync(tempDir, { recursive: true, force: true });
@@ -1161,7 +1480,7 @@ async function publish(options = {}) {
1161
1480
  }
1162
1481
 
1163
1482
  // src/commands/search.ts
1164
- import chalk14 from "chalk";
1483
+ import chalk15 from "chalk";
1165
1484
  import { resolveRegistryUrl as resolveRegistryUrl6, searchRegistrySkills, SkildError as SkildError10 } from "@skild/core";
1166
1485
  async function search(query, options = {}) {
1167
1486
  const registryUrl = resolveRegistryUrl6(options.registry);
@@ -1173,39 +1492,39 @@ async function search(query, options = {}) {
1173
1492
  return;
1174
1493
  }
1175
1494
  if (!skills.length) {
1176
- console.log(chalk14.dim("No results."));
1495
+ console.log(chalk15.dim("No results."));
1177
1496
  return;
1178
1497
  }
1179
- console.log(chalk14.bold(`
1180
- \u{1F50E} Results (${skills.length}) \u2014 ${chalk14.dim(registryUrl)}
1498
+ console.log(chalk15.bold(`
1499
+ \u{1F50E} Results (${skills.length}) \u2014 ${chalk15.dim(registryUrl)}
1181
1500
  `));
1182
1501
  for (const s of skills) {
1183
1502
  const name = String(s.name || "").trim();
1184
1503
  const desc = String(s.description || "").trim();
1185
1504
  if (!name) continue;
1186
- console.log(` ${chalk14.cyan(name)}${desc ? chalk14.dim(` \u2014 ${desc}`) : ""}`);
1505
+ console.log(` ${chalk15.cyan(name)}${desc ? chalk15.dim(` \u2014 ${desc}`) : ""}`);
1187
1506
  }
1188
1507
  } catch (error) {
1189
1508
  const message = error instanceof SkildError10 ? error.message : error instanceof Error ? error.message : String(error);
1190
- console.error(chalk14.red(message));
1509
+ console.error(chalk15.red(message));
1191
1510
  process.exitCode = 1;
1192
1511
  }
1193
1512
  }
1194
1513
 
1195
1514
  // src/index.ts
1196
- import { PLATFORMS as PLATFORMS3 } from "@skild/core";
1515
+ import { PLATFORMS as PLATFORMS4 } from "@skild/core";
1197
1516
  var require2 = createRequire(import.meta.url);
1198
1517
  var { version } = require2("../package.json");
1199
1518
  var program = new Command();
1200
1519
  program.name("skild").description("The npm for Agent Skills \u2014 Discover, install, manage, and publish AI Agent Skills with ease.").version(version);
1201
- program.command("install <source>").alias("i").description("Install a Skill from a Git URL, degit shorthand, or local directory").option("-t, --target <platform>", `Target platform: ${PLATFORMS3.join(", ")}`).option("--all", `Install to all platforms: ${PLATFORMS3.join(", ")}`).option("--recursive", "If source is a multi-skill directory/repo, install all discovered skills").option("-y, --yes", "Skip confirmation prompts (assume yes)").option("--depth <n>", "Max directory depth to scan for SKILL.md (default: 6)", "6").option("--max-skills <n>", "Max discovered skills to install (default: 200)", "200").option("-l, --local", "Install to project-level directory instead of global").option("-f, --force", "Overwrite existing installation").option("--registry <url>", "Registry base URL (default: https://registry.skild.sh)").option("--json", "Output JSON").action(async (source, options) => {
1520
+ program.command("install <source>").alias("i").description("Install a Skill from a Git URL, degit shorthand, or local directory").option("-t, --target <platform>", `Target platform: ${PLATFORMS4.join(", ")}`).option("--all", `Install to all platforms: ${PLATFORMS4.join(", ")}`).option("--recursive", "If source is a multi-skill directory/repo, install all discovered skills").option("-y, --yes", "Skip confirmation prompts (assume yes)").option("--depth <n>", "Max directory depth to scan for SKILL.md (default: 6)", "6").option("--max-skills <n>", "Max discovered skills to install (default: 200)", "200").option("-l, --local", "Install to project-level directory instead of global").option("-f, --force", "Overwrite existing installation").option("--registry <url>", "Registry base URL (default: https://registry.skild.sh)").option("--json", "Output JSON").action(async (source, options) => {
1202
1521
  await install(source, options);
1203
1522
  });
1204
- program.command("list").alias("ls").description("List installed Skills").option("-t, --target <platform>", `Target platform: ${PLATFORMS3.join(", ")} (optional; omit to list all)`).option("-l, --local", "List project-level directory instead of global").option("--paths", "Show install paths").option("--verbose", "Show skillset dependency details").option("--json", "Output JSON").action(async (options) => list(options));
1205
- program.command("info <skill>").description("Show installed Skill details").option("-t, --target <platform>", `Target platform: ${PLATFORMS3.join(", ")}`, "claude").option("-l, --local", "Use project-level directory instead of global").option("--json", "Output JSON").action(async (skill, options) => info(skill, options));
1206
- program.command("uninstall <skill>").alias("rm").description("Uninstall a Skill").option("-t, --target <platform>", `Target platform: ${PLATFORMS3.join(", ")}`, "claude").option("-l, --local", "Use project-level directory instead of global").option("-f, --force", "Uninstall even if metadata is missing").option("--with-deps", "Uninstall dependencies that are only required by this skill").action(async (skill, options) => uninstall(skill, options));
1207
- program.command("update [skill]").alias("up").description("Update one or all installed Skills").option("-t, --target <platform>", `Target platform: ${PLATFORMS3.join(", ")}`, "claude").option("-l, --local", "Use project-level directory instead of global").option("--json", "Output JSON").action(async (skill, options) => update(skill, options));
1208
- program.command("validate [target]").alias("v").description("Validate a Skill folder (path) or an installed Skill name").option("-t, --target <platform>", `Target platform: ${PLATFORMS3.join(", ")}`, "claude").option("-l, --local", "Use project-level directory instead of global").option("--json", "Output JSON").action(async (target, options) => validate(target, options));
1523
+ program.command("list").alias("ls").description("List installed Skills").option("-t, --target <platform>", `Target platform: ${PLATFORMS4.join(", ")} (optional; omit to list all)`).option("-l, --local", "List project-level directory instead of global").option("--paths", "Show install paths").option("--verbose", "Show skillset dependency details").option("--json", "Output JSON").action(async (options) => list(options));
1524
+ program.command("info <skill>").description("Show installed Skill details").option("-t, --target <platform>", `Target platform: ${PLATFORMS4.join(", ")}`, "claude").option("-l, --local", "Use project-level directory instead of global").option("--json", "Output JSON").action(async (skill, options) => info(skill, options));
1525
+ program.command("uninstall <skill>").alias("rm").description("Uninstall a Skill").option("-t, --target <platform>", `Target platform: ${PLATFORMS4.join(", ")}`, "claude").option("-l, --local", "Use project-level directory instead of global").option("-f, --force", "Uninstall even if metadata is missing").option("--with-deps", "Uninstall dependencies that are only required by this skill").action(async (skill, options) => uninstall(skill, options));
1526
+ program.command("update [skill]").alias("up").description("Update one or all installed Skills").option("-t, --target <platform>", `Target platform: ${PLATFORMS4.join(", ")}`, "claude").option("-l, --local", "Use project-level directory instead of global").option("--json", "Output JSON").action(async (skill, options) => update(skill, options));
1527
+ program.command("validate [target]").alias("v").description("Validate a Skill folder (path) or an installed Skill name").option("-t, --target <platform>", `Target platform: ${PLATFORMS4.join(", ")}`, "claude").option("-l, --local", "Use project-level directory instead of global").option("--json", "Output JSON").action(async (target, options) => validate(target, options));
1209
1528
  program.command("init <name>").description("Create a new Skill project").option("--dir <path>", "Target directory (defaults to <name>)").option("--description <text>", "Skill description").option("-f, --force", "Overwrite target directory if it exists").action(async (name, options) => init(name, options));
1210
1529
  program.command("signup").description("Create a publisher account in the registry (no GitHub required)").option("--registry <url>", "Registry base URL (default: https://registry.skild.sh)").option("--email <email>", "Email (optional; will prompt)").option("--handle <handle>", "Publisher handle (owns @handle/* scope) (optional; will prompt)").option("--password <password>", "Password (optional; will prompt)").option("--json", "Output JSON").action(async (options) => signup(options));
1211
1530
  program.command("login").description("Login to a registry and store an access token locally").option("--registry <url>", "Registry base URL (default: https://registry.skild.sh)").option("--handle-or-email <value>", "Handle or email (optional; will prompt)").option("--password <password>", "Password (optional; will prompt)").option("--token-name <name>", "Token label").option("--json", "Output JSON").action(async (options) => login(options));
@@ -1214,7 +1533,7 @@ program.command("whoami").description("Show current registry identity").action(a
1214
1533
  program.command("publish").description("Publish a Skill directory to the registry (hosted tarball)").option("--dir <path>", "Skill directory (defaults to cwd)").option("--name <@publisher/skill>", "Override skill name (defaults to SKILL.md frontmatter)").option("--skill-version <semver>", "Override version (defaults to SKILL.md frontmatter)").option("--alias <alias>", "Optional short identifier (global unique) for `skild install <alias>`").option("--description <text>", "Override description (defaults to SKILL.md frontmatter)").option("--targets <list>", "Comma-separated target platforms metadata (optional)").option("--tag <tag>", "Dist-tag (default: latest)", "latest").option("--registry <url>", "Registry base URL (defaults to saved login)").option("--json", "Output JSON").action(async (options) => publish(options));
1215
1534
  program.command("search <query>").description("Search Skills in the registry").option("--registry <url>", "Registry base URL (default: https://registry.skild.sh)").option("--limit <n>", "Max results (default: 50)", "50").option("--json", "Output JSON").action(async (query, options) => search(query, options));
1216
1535
  program.action(() => {
1217
- console.log(chalk15.bold("\n\u{1F6E1}\uFE0F skild \u2014 Get your agents skilled.\n"));
1536
+ console.log(chalk16.bold("\n\u{1F6E1}\uFE0F skild \u2014 Get your agents skilled.\n"));
1218
1537
  program.outputHelp();
1219
1538
  });
1220
1539
  var argv = process.argv.slice();