skillops-cli 1.3.0 → 1.3.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.
Files changed (5) hide show
  1. package/README.md +52 -49
  2. package/dist/cli.js +818 -551
  3. package/dist/index.d.ts +181 -138
  4. package/dist/index.js +701 -504
  5. package/package.json +84 -84
package/dist/index.js CHANGED
@@ -1,12 +1,8 @@
1
- // src/auditor/parser.ts
2
- import fs2 from "fs";
3
- import path from "path";
4
-
5
1
  // src/models.ts
6
2
  import fs from "fs";
7
3
  import YAML from "yaml";
8
4
  import { z } from "zod";
9
- var SKILLOPS_VERSION = "1.3.0";
5
+ var SKILLOPS_VERSION = "1.3.2";
10
6
  var SKILL_NAME_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
11
7
  var SEMVER_REGEX = /^\d+\.\d+\.\d+$/;
12
8
  var FRONTMATTER_REGEX = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
@@ -22,7 +18,9 @@ function estimateTokenCount(text) {
22
18
  return 0;
23
19
  }
24
20
  const words = countWords(stripped);
25
- const punctBonus = Math.floor((stripped.match(PUNCT_CODE_REGEX)?.length ?? 0) / 4);
21
+ const punctBonus = Math.floor(
22
+ (stripped.match(PUNCT_CODE_REGEX)?.length ?? 0) / 4
23
+ );
26
24
  return Math.max(1, Math.ceil(words * 1.33) + punctBonus);
27
25
  }
28
26
  function splitFrontmatter(rawText, sourceLabel) {
@@ -36,7 +34,9 @@ function splitFrontmatter(rawText, sourceLabel) {
36
34
  const body = match[2] ?? "";
37
35
  const parsed = YAML.parse(yamlText);
38
36
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
39
- throw new Error(`YAML frontmatter in '${sourceLabel}' must evaluate to a key-value mapping.`);
37
+ throw new Error(
38
+ `YAML frontmatter in '${sourceLabel}' must evaluate to a key-value mapping.`
39
+ );
40
40
  }
41
41
  return [parsed, body];
42
42
  }
@@ -535,7 +535,9 @@ var SubagentManifestSchema = z.object({
535
535
  });
536
536
  }
537
537
  }),
538
- tools: z.array(z.string().min(1)).min(1, { message: "Subagent must declare an explicit non-empty tool allowlist per INV-SKILL-04." }).superRefine((tools, ctx) => {
538
+ tools: z.array(z.string().min(1)).min(1, {
539
+ message: "Subagent must declare an explicit non-empty tool allowlist per INV-SKILL-04."
540
+ }).superRefine((tools, ctx) => {
539
541
  for (const tool of tools) {
540
542
  if (FORBIDDEN_WILDCARD_TOOLS.has(tool.trim().toLowerCase())) {
541
543
  ctx.addIssue({
@@ -726,7 +728,14 @@ var SyncedArtifactSchema = z.object({
726
728
  skill_name: z.string().min(1),
727
729
  relative_path: z.string().min(1),
728
730
  sha256: z.string().regex(/^[0-9a-f]{64}$/),
729
- action: z.enum(["created", "updated", "unchanged", "removed", "planned", "conflict"])
731
+ action: z.enum([
732
+ "created",
733
+ "updated",
734
+ "unchanged",
735
+ "removed",
736
+ "planned",
737
+ "conflict"
738
+ ])
730
739
  }).strict();
731
740
  var SyncLockEntrySchema = z.object({
732
741
  target: RuntimeTargetSchema,
@@ -812,6 +821,8 @@ function loadSkillOpsConfig(repoPath) {
812
821
  }
813
822
 
814
823
  // src/auditor/parser.ts
824
+ import fs2 from "fs";
825
+ import path from "path";
815
826
  function walkForFilesNamed(rootDir, targetFilename) {
816
827
  if (!fs2.existsSync(rootDir)) {
817
828
  return [];
@@ -844,7 +855,10 @@ function parseSkillDirectory(skillDir, options = {}) {
844
855
  const rawText = fs2.readFileSync(skillMdPath, "utf-8");
845
856
  const lines = rawText.split(/\r?\n/);
846
857
  const totalLines = rawText.endsWith("\n") ? lines.length - 1 : lines.length;
847
- const [, markdownBody] = splitFrontmatter(rawText, skillMdPath.replace(/\\/g, "/"));
858
+ const [, markdownBody] = splitFrontmatter(
859
+ rawText,
860
+ skillMdPath.replace(/\\/g, "/")
861
+ );
848
862
  const manifest = parseSkillMdFile(skillMdPath);
849
863
  const declaredScripts = [];
850
864
  const missingDeclaredScripts = [];
@@ -878,7 +892,9 @@ function parseSkillDirectory(skillDir, options = {}) {
878
892
  const referencesDir = path.join(skillDir, "references");
879
893
  const referenceFiles = [];
880
894
  if (fs2.existsSync(referencesDir) && fs2.statSync(referencesDir).isDirectory()) {
881
- for (const entry of fs2.readdirSync(referencesDir, { withFileTypes: true })) {
895
+ for (const entry of fs2.readdirSync(referencesDir, {
896
+ withFileTypes: true
897
+ })) {
882
898
  if (entry.isFile() && entry.name.endsWith(".md")) {
883
899
  referenceFiles.push(path.join(referencesDir, entry.name));
884
900
  }
@@ -943,112 +959,6 @@ function parseSubagentFile(filePath) {
943
959
  };
944
960
  }
945
961
 
946
- // src/auditor/token_budget.ts
947
- function auditSkillTokenBudget(skillDir, options = {}) {
948
- const requireLayout = options.requireLayout ?? false;
949
- try {
950
- const parsed = parseSkillDirectory(skillDir, { requireLayout });
951
- const warnings = [];
952
- const errors = [];
953
- if (parsed.manifest.routing_signals.negative_triggers.length === 0 && !parsed.manifest.description.toLowerCase().includes("do not trigger")) {
954
- warnings.push(
955
- `Skill '${parsed.manifest.name}' has no explicit negative triggers ('Do not trigger for...' or routing_signals.negative_triggers).`
956
- );
957
- }
958
- if (requireLayout && parsed.missingDeclaredScripts.length > 0) {
959
- errors.push(
960
- `Skill '${parsed.manifest.name}' is missing declared script(s): ${parsed.missingDeclaredScripts.join(", ")}`
961
- );
962
- }
963
- return {
964
- skillName: parsed.manifest.name,
965
- skillDir: skillDir.replace(/\\/g, "/"),
966
- l1Words: parsed.manifest.description_words,
967
- l1Tokens: parsed.manifest.description_tokens,
968
- l2Lines: parsed.manifest.body_lines,
969
- l2Tokens: parsed.manifest.body_tokens,
970
- totalLines: parsed.totalLines,
971
- scriptsCount: parsed.declaredScripts.length,
972
- passed: errors.length === 0,
973
- errors,
974
- warnings
975
- };
976
- } catch (err) {
977
- const message = err instanceof Error ? err.message : String(err);
978
- return {
979
- skillName: skillDir.split(/[\\/]/).pop() ?? "unknown",
980
- skillDir: skillDir.replace(/\\/g, "/"),
981
- l1Words: 0,
982
- l1Tokens: 0,
983
- l2Lines: 0,
984
- l2Tokens: 0,
985
- totalLines: 0,
986
- scriptsCount: 0,
987
- passed: false,
988
- errors: [message],
989
- warnings: []
990
- };
991
- }
992
- }
993
- function auditSubagentTokenBudget(filePath) {
994
- try {
995
- const parsed = parseSubagentFile(filePath);
996
- return {
997
- subagentName: parsed.manifest.name,
998
- filePath: filePath.replace(/\\/g, "/"),
999
- descriptionTokens: parsed.manifest.description_tokens,
1000
- systemPromptLines: parsed.manifest.system_prompt_lines,
1001
- systemPromptTokens: parsed.manifest.system_prompt_tokens,
1002
- maxOutputTokens: parsed.manifest.max_output_tokens,
1003
- tools: parsed.manifest.tools,
1004
- passed: true,
1005
- errors: []
1006
- };
1007
- } catch (err) {
1008
- const message = err instanceof Error ? err.message : String(err);
1009
- return {
1010
- subagentName: filePath.split(/[\\/]/).pop() ?? "unknown",
1011
- filePath: filePath.replace(/\\/g, "/"),
1012
- descriptionTokens: 0,
1013
- systemPromptLines: 0,
1014
- systemPromptTokens: 0,
1015
- maxOutputTokens: 0,
1016
- tools: [],
1017
- passed: false,
1018
- errors: [message]
1019
- };
1020
- }
1021
- }
1022
- function auditCatalogTokenBudgets(catalogDir, options = {}) {
1023
- const skillDirs = discoverSkillDirectories(catalogDir);
1024
- const subagentFiles = discoverSubagentFiles(catalogDir);
1025
- const skills = skillDirs.map((dir) => auditSkillTokenBudget(dir, options));
1026
- const subagents = subagentFiles.map((file) => auditSubagentTokenBudget(file));
1027
- const errors = [];
1028
- const warnings = [];
1029
- let totalL1Tokens = 0;
1030
- let totalSubagentPromptTokens = 0;
1031
- for (const s of skills) {
1032
- totalL1Tokens += s.l1Tokens;
1033
- errors.push(...s.errors);
1034
- warnings.push(...s.warnings);
1035
- }
1036
- for (const sa of subagents) {
1037
- totalSubagentPromptTokens += sa.systemPromptTokens;
1038
- errors.push(...sa.errors);
1039
- }
1040
- return {
1041
- catalogPath: catalogDir.replace(/\\/g, "/"),
1042
- skills,
1043
- subagents,
1044
- totalL1Tokens,
1045
- totalSubagentPromptTokens,
1046
- errors,
1047
- warnings,
1048
- passed: errors.length === 0
1049
- };
1050
- }
1051
-
1052
962
  // src/auditor/collision.ts
1053
963
  var ROUTING_STOPWORDS = /* @__PURE__ */ new Set([
1054
964
  "a",
@@ -1377,6 +1287,12 @@ function auditCatalog(catalogDir, options = {}) {
1377
1287
  });
1378
1288
  }
1379
1289
 
1290
+ // src/auditor/doctor.ts
1291
+ import { spawnSync } from "child_process";
1292
+ import crypto from "crypto";
1293
+ import fs4 from "fs";
1294
+ import path3 from "path";
1295
+
1380
1296
  // src/auditor/token_economy.ts
1381
1297
  import fs3 from "fs";
1382
1298
  import path2 from "path";
@@ -1450,7 +1366,7 @@ function padVisible(text, width, align = "left") {
1450
1366
  }
1451
1367
  function renderBox(lines, options) {
1452
1368
  const paddingX = options?.paddingX ?? 2;
1453
- const minWidth = options?.minWidth ?? 64;
1369
+ const minWidth = options?.minWidth ?? 36;
1454
1370
  const colorEnabled = options?.colorEnabled;
1455
1371
  const borderFn = options?.borderColor ?? style.cyan;
1456
1372
  const titleText = options?.title ? ` ${options.title.trim()} ` : "";
@@ -1474,16 +1390,10 @@ function renderBox(lines, options) {
1474
1390
  const bottomBorder = borderFn(`\u2570${"\u2500".repeat(innerWidth)}\u256F`, colorEnabled);
1475
1391
  return [topBorder, ...bodyLines, bottomBorder].join("\n");
1476
1392
  }
1477
- function renderHeaderBanner(subtitle = "Framework & Library for High-End AI Coding Skills & Subagents", options) {
1393
+ function renderHeaderBanner(subtitle = "Framework & Library for AI Skills & Subagents", options) {
1478
1394
  const ver = options?.version ?? SKILLOPS_VERSION;
1479
1395
  const c = options?.colorEnabled;
1480
- const headline = `${style.bold(style.cyan(`\u26A1 SkillOps v${ver}`, c), c)} ${style.dim("\u2014", c)} ${subtitle}`;
1481
- return renderBox([headline], {
1482
- borderColor: style.cyan,
1483
- paddingX: 2,
1484
- minWidth: 72,
1485
- colorEnabled: c
1486
- });
1396
+ return `${style.bold(style.cyan(`\u25C6 SkillOps v${ver}`, c), c)} ${style.dim("\u2014", c)} ${subtitle}`;
1487
1397
  }
1488
1398
  function renderTable(headers, rows, options) {
1489
1399
  const indent = " ".repeat(options?.indent ?? 2);
@@ -1516,7 +1426,7 @@ function renderTable(headers, rows, options) {
1516
1426
  ].join("\n");
1517
1427
  }
1518
1428
  function renderTokenBar(current, max, options) {
1519
- const width = options?.width ?? 18;
1429
+ const width = options?.width ?? 10;
1520
1430
  const unit = options?.unit ?? "tokens";
1521
1431
  const c = options?.colorEnabled;
1522
1432
  const safeMax = max > 0 ? max : 1;
@@ -1534,9 +1444,8 @@ function renderTokenBar(current, max, options) {
1534
1444
  var renderProgressBar = renderTokenBar;
1535
1445
  function renderSectionHeader(title, colorEnabled) {
1536
1446
  const c = colorEnabled;
1537
- return `
1538
- ${style.bold(style.cyan(title, c), c)}
1539
- ${style.dim("\u2500".repeat(Math.max(24, visibleLength(title))), c)}`;
1447
+ return `${style.dim("\u2502", c)}
1448
+ ${style.dim("\u251C\u2500", c)} ${style.bold(style.cyan(title, c), c)}`;
1540
1449
  }
1541
1450
  function formatBadge(type, customLabel, colorEnabled) {
1542
1451
  switch (type) {
@@ -1575,73 +1484,72 @@ function formatBadge(type, customLabel, colorEnabled) {
1575
1484
  function renderStep(step, total, title, detail, status = "done", colorEnabled) {
1576
1485
  const icon = status === "done" ? style.green("\u2714", colorEnabled) : status === "warn" ? style.yellow("\u26A0", colorEnabled) : style.dim("\u25CB", colorEnabled);
1577
1486
  const stepBadge = style.dim(`[${step}/${total}]`, colorEnabled);
1578
- const titleStyled = style.bold(padVisible(title, 28, "left"), colorEnabled);
1579
- const detailStyled = detail ? ` ${style.dim("\u2022", colorEnabled)} ${detail}` : "";
1580
- return ` ${icon} ${stepBadge} ${titleStyled}${detailStyled}`;
1487
+ const titleStyled = style.bold(padVisible(title, 20, "left"), colorEnabled);
1488
+ const detailStyled = detail ? ` ${style.dim("\xB7", colorEnabled)} ${detail}` : "";
1489
+ return `${style.dim("\u2502", colorEnabled)} ${icon} ${stepBadge} ${titleStyled}${detailStyled}`;
1581
1490
  }
1582
1491
  function renderNextSteps(hints, colorEnabled) {
1583
1492
  if (hints.length === 0) {
1584
1493
  return "";
1585
1494
  }
1586
1495
  const c = colorEnabled;
1587
- const maxCmdLen = hints.reduce(
1588
- (m, h) => Math.max(m, visibleLength(h.command)),
1589
- 0
1496
+ const maxCmdLen = Math.min(
1497
+ 44,
1498
+ hints.reduce((m, h) => Math.max(m, visibleLength(h.command)), 0)
1590
1499
  );
1591
1500
  const lines = [
1592
- "",
1593
- ` ${style.bold(style.cyan("\u{1F4A1} Next Steps:", c), c)}`,
1594
- ...hints.map(
1595
- (h) => ` ${style.green(padVisible(h.command, maxCmdLen + 2, "left"), c)} ${style.dim(`# ${h.description}`, c)}`
1596
- ),
1597
- ""
1501
+ style.dim("\u2502", c),
1502
+ `${style.dim("\u2570\u2500", c)} ${style.bold(style.cyan("Next Steps:", c), c)}`,
1503
+ ...hints.map((h) => {
1504
+ const cmdPadded = padVisible(h.command, maxCmdLen, "left");
1505
+ const prefixCols = 5 + visibleLength(cmdPadded) + 3;
1506
+ const maxDescCols = Math.max(10, 76 - prefixCols);
1507
+ const desc = h.description.length > maxDescCols ? `${h.description.slice(0, maxDescCols - 1)}\u2026` : h.description;
1508
+ return ` ${style.dim("$", c)} ${style.green(cmdPadded, c)} ${style.dim(`\u2014 ${desc}`, c)}`;
1509
+ })
1598
1510
  ];
1599
- return lines.join("\n");
1511
+ return `${lines.join("\n")}
1512
+ `;
1600
1513
  }
1601
1514
  function renderAiUsageGuide(targets, skills, subagents, colorEnabled) {
1602
1515
  const c = colorEnabled;
1603
1516
  const sampleSkill = skills[0] ?? "systematic-debugging";
1604
1517
  const sampleAgent = subagents[0] ?? "context-scout";
1518
+ const bar = style.dim("\u2502", c);
1605
1519
  const lines = [
1606
- `${style.bold("How to use your installed Skills & Subagents inside your AI:", c)}`,
1607
- ""
1520
+ bar,
1521
+ `${style.dim("\u251C\u2500", c)} ${style.bold(style.cyan("Using Your Skills & Subagents", c), c)}`
1608
1522
  ];
1609
1523
  const targetSet = new Set(targets);
1610
1524
  if (targetSet.has("claude") || targetSet.size === 0) {
1611
1525
  lines.push(
1612
- `\u2022 ${style.bold("Claude Code:", c)} Ask naturally (auto-routed via .claude/skills/${sampleSkill}/SKILL.md) or delegate to @${sampleAgent}`
1526
+ `${bar} \u2022 ${style.bold("Claude Code:", c)} Auto-routed (${sampleSkill}) or @${sampleAgent}`
1613
1527
  );
1614
1528
  }
1615
1529
  if (targetSet.has("cursor")) {
1616
1530
  lines.push(
1617
- `\u2022 ${style.bold("Cursor IDE:", c)} Type ${style.cyan(`@${sampleSkill}`, c)} in Cursor Chat/Composer or let .cursor/rules/${sampleSkill}.mdc auto-attach`
1531
+ `${bar} \u2022 ${style.bold("Cursor IDE:", c)} Type ${style.cyan(`@${sampleSkill}`, c)} in Chat (.cursor/rules/)`
1618
1532
  );
1619
1533
  }
1620
1534
  if (targetSet.has("antigravity")) {
1621
1535
  lines.push(
1622
- `\u2022 ${style.bold("Antigravity / Gemini:", c)} Auto-activated from .agent/skills/${sampleSkill}/SKILL.md when your prompt matches its domain`
1536
+ `${bar} \u2022 ${style.bold("Antigravity:", c)} Auto-activated (.agent/skills/${sampleSkill})`
1623
1537
  );
1624
1538
  }
1625
1539
  if (targetSet.has("copilot")) {
1626
1540
  lines.push(
1627
- `\u2022 ${style.bold("GitHub Copilot:", c)} Use ${style.cyan(`/${sampleSkill}`, c)} prompt in Copilot Chat or reference .github/instructions/${sampleSkill}.instructions.md`
1541
+ `${bar} \u2022 ${style.bold("Copilot:", c)} Use ${style.cyan(`/${sampleSkill}`, c)} in Chat (.github/instructions/)`
1628
1542
  );
1629
1543
  }
1630
1544
  if (targetSet.has("windsurf") || targetSet.has("cline") || targetSet.has("roocode") || targetSet.has("kilocode")) {
1631
1545
  lines.push(
1632
- `\u2022 ${style.bold("Windsurf / Cline / Roo / Kilo:", c)} Rules in .windsurf/rules/, .clinerules/, .roo/rules/, .kilocode/rules/ activate automatically`
1546
+ `${bar} \u2022 ${style.bold("Windsurf/Cline/Roo/Kilo:", c)} Workspace rules load automatically`
1633
1547
  );
1634
1548
  }
1635
1549
  lines.push(
1636
- `\u2022 ${style.bold("Inspect any Skill/Agent:", c)} Run ${style.green(`npx skillops-cli info ${sampleSkill}`, c)} to view triggers, L3 scripts & prompts`
1550
+ `${bar} \u2022 ${style.bold("Inspect:", c)} ${style.green(`npx skillops-cli info ${sampleSkill}`, c)}`
1637
1551
  );
1638
- return renderBox(lines, {
1639
- title: "\u{1F680} Using Your Skills & Subagents",
1640
- borderColor: style.green,
1641
- paddingX: 2,
1642
- minWidth: 72,
1643
- colorEnabled: c
1644
- });
1552
+ return lines.join("\n");
1645
1553
  }
1646
1554
  function levenshteinDistance(a, b) {
1647
1555
  const s1 = a.toLowerCase();
@@ -2079,7 +1987,7 @@ function formatTokenEconomyReport(report, format = "table") {
2079
1987
  const startupBar = renderProgressBar(
2080
1988
  report.startup_token_tax,
2081
1989
  report.startup_tax_budget,
2082
- { width: 18, unit: "tokens" }
1990
+ { width: 10, unit: "tokens" }
2083
1991
  );
2084
1992
  const lines = [
2085
1993
  "=== SkillOps Token Economy & Startup Context Tax Analyzer ===",
@@ -2104,11 +2012,11 @@ function formatTokenEconomyReport(report, format = "table") {
2104
2012
  renderNextSteps([
2105
2013
  {
2106
2014
  command: "npx skillops-cli quickstart",
2107
- description: "Sync Progressive Disclosure Skills & Context-Isolated Subagents"
2015
+ description: "Sync Progressive Disclosure Skills & Subagents"
2108
2016
  },
2109
2017
  {
2110
2018
  command: "npx skillops-cli doctor",
2111
- description: "Inspect repository lockfile & startup tax diagnostics"
2019
+ description: "Inspect lockfile & startup tax diagnostics"
2112
2020
  }
2113
2021
  ]).trimEnd()
2114
2022
  );
@@ -2117,10 +2025,6 @@ function formatTokenEconomyReport(report, format = "table") {
2117
2025
  }
2118
2026
 
2119
2027
  // src/auditor/doctor.ts
2120
- import { spawnSync } from "child_process";
2121
- import crypto from "crypto";
2122
- import fs4 from "fs";
2123
- import path3 from "path";
2124
2028
  function computeFileSha256(content) {
2125
2029
  return crypto.createHash("sha256").update(content, "utf-8").digest("hex");
2126
2030
  }
@@ -2352,10 +2256,12 @@ function inspectHarnesses(repoPath) {
2352
2256
  const repoLabel = path3.basename(resolvedRepo) || ".";
2353
2257
  const detectedHarnesses = detectInstalledHarnesses(resolvedRepo);
2354
2258
  const detectedSet = new Set(detectedHarnesses);
2355
- const harnesses = ALL_RUNTIME_TARGETS.map((target) => ({
2356
- ...RUNTIME_HARNESS_SPECS[target],
2357
- detected: detectedSet.has(target)
2358
- }));
2259
+ const harnesses = ALL_RUNTIME_TARGETS.map(
2260
+ (target) => ({
2261
+ ...RUNTIME_HARNESS_SPECS[target],
2262
+ detected: detectedSet.has(target)
2263
+ })
2264
+ );
2359
2265
  return {
2360
2266
  repo_path: repoLabel,
2361
2267
  total_supported: harnesses.length,
@@ -2412,9 +2318,13 @@ function formatDoctorReport(report, format = "table") {
2412
2318
  }
2413
2319
  for (const check of report.checks) {
2414
2320
  if (check.status === "fail") {
2415
- lines2.push(`::error title=SkillOps Doctor (${check.title})::${check.summary}`);
2321
+ lines2.push(
2322
+ `::error title=SkillOps Doctor (${check.title})::${check.summary}`
2323
+ );
2416
2324
  } else if (check.status === "warn") {
2417
- lines2.push(`::warning title=SkillOps Doctor (${check.title})::${check.summary}`);
2325
+ lines2.push(
2326
+ `::warning title=SkillOps Doctor (${check.title})::${check.summary}`
2327
+ );
2418
2328
  }
2419
2329
  }
2420
2330
  lines2.push(
@@ -2484,7 +2394,9 @@ function formatDoctorReport(report, format = "table") {
2484
2394
  lines.push("-".repeat(64), "Tracked Lockfile Artifacts:");
2485
2395
  for (const art of report.artifacts) {
2486
2396
  const badge = art.status === "healthy" ? "[HEALTHY]" : art.status === "drifted" ? "[DRIFTED]" : "[MISSING]";
2487
- lines.push(` ${badge} ${art.relative_path} (${art.target} :: ${art.item_name})`);
2397
+ lines.push(
2398
+ ` ${badge} ${art.relative_path} (${art.target} :: ${art.item_name})`
2399
+ );
2488
2400
  }
2489
2401
  }
2490
2402
  if (report.remediation.length > 0) {
@@ -2496,6 +2408,112 @@ function formatDoctorReport(report, format = "table") {
2496
2408
  return lines.join("\n");
2497
2409
  }
2498
2410
 
2411
+ // src/auditor/token_budget.ts
2412
+ function auditSkillTokenBudget(skillDir, options = {}) {
2413
+ const requireLayout = options.requireLayout ?? false;
2414
+ try {
2415
+ const parsed = parseSkillDirectory(skillDir, { requireLayout });
2416
+ const warnings = [];
2417
+ const errors = [];
2418
+ if (parsed.manifest.routing_signals.negative_triggers.length === 0 && !parsed.manifest.description.toLowerCase().includes("do not trigger")) {
2419
+ warnings.push(
2420
+ `Skill '${parsed.manifest.name}' has no explicit negative triggers ('Do not trigger for...' or routing_signals.negative_triggers).`
2421
+ );
2422
+ }
2423
+ if (requireLayout && parsed.missingDeclaredScripts.length > 0) {
2424
+ errors.push(
2425
+ `Skill '${parsed.manifest.name}' is missing declared script(s): ${parsed.missingDeclaredScripts.join(", ")}`
2426
+ );
2427
+ }
2428
+ return {
2429
+ skillName: parsed.manifest.name,
2430
+ skillDir: skillDir.replace(/\\/g, "/"),
2431
+ l1Words: parsed.manifest.description_words,
2432
+ l1Tokens: parsed.manifest.description_tokens,
2433
+ l2Lines: parsed.manifest.body_lines,
2434
+ l2Tokens: parsed.manifest.body_tokens,
2435
+ totalLines: parsed.totalLines,
2436
+ scriptsCount: parsed.declaredScripts.length,
2437
+ passed: errors.length === 0,
2438
+ errors,
2439
+ warnings
2440
+ };
2441
+ } catch (err) {
2442
+ const message = err instanceof Error ? err.message : String(err);
2443
+ return {
2444
+ skillName: skillDir.split(/[\\/]/).pop() ?? "unknown",
2445
+ skillDir: skillDir.replace(/\\/g, "/"),
2446
+ l1Words: 0,
2447
+ l1Tokens: 0,
2448
+ l2Lines: 0,
2449
+ l2Tokens: 0,
2450
+ totalLines: 0,
2451
+ scriptsCount: 0,
2452
+ passed: false,
2453
+ errors: [message],
2454
+ warnings: []
2455
+ };
2456
+ }
2457
+ }
2458
+ function auditSubagentTokenBudget(filePath) {
2459
+ try {
2460
+ const parsed = parseSubagentFile(filePath);
2461
+ return {
2462
+ subagentName: parsed.manifest.name,
2463
+ filePath: filePath.replace(/\\/g, "/"),
2464
+ descriptionTokens: parsed.manifest.description_tokens,
2465
+ systemPromptLines: parsed.manifest.system_prompt_lines,
2466
+ systemPromptTokens: parsed.manifest.system_prompt_tokens,
2467
+ maxOutputTokens: parsed.manifest.max_output_tokens,
2468
+ tools: parsed.manifest.tools,
2469
+ passed: true,
2470
+ errors: []
2471
+ };
2472
+ } catch (err) {
2473
+ const message = err instanceof Error ? err.message : String(err);
2474
+ return {
2475
+ subagentName: filePath.split(/[\\/]/).pop() ?? "unknown",
2476
+ filePath: filePath.replace(/\\/g, "/"),
2477
+ descriptionTokens: 0,
2478
+ systemPromptLines: 0,
2479
+ systemPromptTokens: 0,
2480
+ maxOutputTokens: 0,
2481
+ tools: [],
2482
+ passed: false,
2483
+ errors: [message]
2484
+ };
2485
+ }
2486
+ }
2487
+ function auditCatalogTokenBudgets(catalogDir, options = {}) {
2488
+ const skillDirs = discoverSkillDirectories(catalogDir);
2489
+ const subagentFiles = discoverSubagentFiles(catalogDir);
2490
+ const skills = skillDirs.map((dir) => auditSkillTokenBudget(dir, options));
2491
+ const subagents = subagentFiles.map((file) => auditSubagentTokenBudget(file));
2492
+ const errors = [];
2493
+ const warnings = [];
2494
+ let totalL1Tokens = 0;
2495
+ let totalSubagentPromptTokens = 0;
2496
+ for (const s of skills) {
2497
+ totalL1Tokens += s.l1Tokens;
2498
+ errors.push(...s.errors);
2499
+ warnings.push(...s.warnings);
2500
+ }
2501
+ for (const sa of subagents) {
2502
+ totalSubagentPromptTokens += sa.systemPromptTokens;
2503
+ errors.push(...sa.errors);
2504
+ }
2505
+ return {
2506
+ catalogPath: catalogDir.replace(/\\/g, "/"),
2507
+ skills,
2508
+ subagents,
2509
+ totalL1Tokens,
2510
+ totalSubagentPromptTokens,
2511
+ errors,
2512
+ warnings,
2513
+ passed: errors.length === 0
2514
+ };
2515
+ }
2516
+
2499
2517
  // src/eval/index.ts
2500
2518
  import fs5 from "fs";
2501
2519
  import path4 from "path";
@@ -2555,10 +2573,15 @@ function evaluateSkillDirectory(skillDir) {
2555
2573
  const evalsPath = path4.join(skillDir, "evals", "evals.json");
2556
2574
  const rawSuite = JSON.parse(fs5.readFileSync(evalsPath, "utf-8"));
2557
2575
  const suite = SkillEvalSuiteSchema.parse(rawSuite);
2558
- const assertionsCount = suite.evals.reduce((acc, c) => acc + c.assertions.length, 0);
2576
+ const assertionsCount = suite.evals.reduce(
2577
+ (acc, c) => acc + c.assertions.length,
2578
+ 0
2579
+ );
2559
2580
  const benchmarkPath = path4.join(skillDir, "evals", "benchmark.json");
2560
2581
  if (fs5.existsSync(benchmarkPath) && fs5.statSync(benchmarkPath).isFile()) {
2561
- const rawBench = JSON.parse(fs5.readFileSync(benchmarkPath, "utf-8"));
2582
+ const rawBench = JSON.parse(
2583
+ fs5.readFileSync(benchmarkPath, "utf-8")
2584
+ );
2562
2585
  const bench = SkillBenchmarkSchema.parse({
2563
2586
  ...rawBench,
2564
2587
  eval_cases_count: suite.evals.length,
@@ -2614,18 +2637,25 @@ function evaluateCatalog(catalogDir, options = {}) {
2614
2637
  }
2615
2638
  const count = benchmarks.length;
2616
2639
  const meanWith = count > 0 ? Number(
2617
- (benchmarks.reduce((acc, b) => acc + b.with_skill.pass_rate_mean, 0) / count).toFixed(4)
2640
+ (benchmarks.reduce(
2641
+ (acc, b) => acc + b.with_skill.pass_rate_mean,
2642
+ 0
2643
+ ) / count).toFixed(4)
2618
2644
  ) : 0;
2619
2645
  const meanWithout = count > 0 ? Number(
2620
- (benchmarks.reduce((acc, b) => acc + b.without_skill.pass_rate_mean, 0) / count).toFixed(
2621
- 4
2622
- )
2646
+ (benchmarks.reduce(
2647
+ (acc, b) => acc + b.without_skill.pass_rate_mean,
2648
+ 0
2649
+ ) / count).toFixed(4)
2623
2650
  ) : 0;
2624
2651
  const meanGain = count > 0 ? Number(
2625
2652
  (benchmarks.reduce((acc, b) => acc + b.delta.pass_rate_gain, 0) / count).toFixed(4)
2626
2653
  ) : 0;
2627
2654
  const meanTokRed = count > 0 ? Number(
2628
- (benchmarks.reduce((acc, b) => acc + b.delta.token_reduction_pct, 0) / count).toFixed(2)
2655
+ (benchmarks.reduce(
2656
+ (acc, b) => acc + b.delta.token_reduction_pct,
2657
+ 0
2658
+ ) / count).toFixed(2)
2629
2659
  ) : 0;
2630
2660
  return CatalogEvalSummarySchema.parse({
2631
2661
  catalog_path: resolvedCatalog.replace(/\\/g, "/"),
@@ -2731,6 +2761,9 @@ import path7 from "path";
2731
2761
  import readline from "readline";
2732
2762
  import YAML3 from "yaml";
2733
2763
 
2764
+ // src/router/bundle_compiler.ts
2765
+ import path6 from "path";
2766
+
2734
2767
  // src/router/fingerprinter.ts
2735
2768
  import fs6 from "fs";
2736
2769
  import path5 from "path";
@@ -2830,13 +2863,17 @@ var RepoFingerprinter = class {
2830
2863
  python312Plus = true;
2831
2864
  signals.add("python3.12");
2832
2865
  }
2833
- const quotedSpecs = content.match(/["']([a-zA-Z0-9._-]+(?:\[[a-zA-Z0-9,_-]+\])?\s*(?:[><=~!][^"']+)?)["']/g) ?? [];
2866
+ const quotedSpecs = content.match(
2867
+ /["']([a-zA-Z0-9._-]+(?:\[[a-zA-Z0-9,_-]+\])?\s*(?:[><=~!][^"']+)?)["']/g
2868
+ ) ?? [];
2834
2869
  for (const spec of quotedSpecs) {
2835
2870
  recordDep(spec);
2836
2871
  }
2837
2872
  }
2838
2873
  if (fs6.existsSync(this.repoPath)) {
2839
- for (const entry of fs6.readdirSync(this.repoPath, { withFileTypes: true })) {
2874
+ for (const entry of fs6.readdirSync(this.repoPath, {
2875
+ withFileTypes: true
2876
+ })) {
2840
2877
  if (entry.isFile() && /^requirements.*\.txt$/i.test(entry.name)) {
2841
2878
  detectedFiles.add(entry.name);
2842
2879
  languages.add("python");
@@ -2856,8 +2893,14 @@ var RepoFingerprinter = class {
2856
2893
  signals.add("nodejs");
2857
2894
  signals.add("package.json");
2858
2895
  try {
2859
- const pkgJson = JSON.parse(fs6.readFileSync(pkgJsonPath, "utf-8"));
2860
- const depSections = ["dependencies", "devDependencies", "peerDependencies"];
2896
+ const pkgJson = JSON.parse(
2897
+ fs6.readFileSync(pkgJsonPath, "utf-8")
2898
+ );
2899
+ const depSections = [
2900
+ "dependencies",
2901
+ "devDependencies",
2902
+ "peerDependencies"
2903
+ ];
2861
2904
  for (const section of depSections) {
2862
2905
  const obj = pkgJson[section];
2863
2906
  if (obj && typeof obj === "object") {
@@ -2961,7 +3004,6 @@ function fingerprintRepository(repoPath) {
2961
3004
  }
2962
3005
 
2963
3006
  // src/router/bundle_compiler.ts
2964
- import path6 from "path";
2965
3007
  function scoreSkillAgainstProfile(parsedSkill, profile, taskPrompt = "") {
2966
3008
  const manifest = parsedSkill.manifest;
2967
3009
  const repoSignalSet = new Set(
@@ -3182,7 +3224,7 @@ function formatRoutedBundle(bundle, format = "table", colorEnabled) {
3182
3224
  bundle.total_l1_tokens,
3183
3225
  bundle.max_l1_tokens,
3184
3226
  {
3185
- width: 18,
3227
+ width: 10,
3186
3228
  unit: "tokens",
3187
3229
  colorEnabled
3188
3230
  }
@@ -3191,11 +3233,11 @@ function formatRoutedBundle(bundle, format = "table", colorEnabled) {
3191
3233
  [
3192
3234
  {
3193
3235
  command: "npx skillops-cli quickstart",
3194
- description: "Install this recommended bundle & wire MCP in 1 step"
3236
+ description: "Install recommended bundle & wire MCP"
3195
3237
  },
3196
3238
  {
3197
3239
  command: `npx skillops-cli info ${topSkill}`,
3198
- description: `Inspect ${topSkill} triggers, L3 scripts & AI invocation guide`
3240
+ description: `Inspect ${topSkill} triggers & L3 scripts`
3199
3241
  }
3200
3242
  ],
3201
3243
  colorEnabled
@@ -3222,7 +3264,10 @@ var MCP_TOOLS = [
3222
3264
  inputSchema: {
3223
3265
  type: "object",
3224
3266
  properties: {
3225
- catalog_dir: { type: "string", description: "Optional path to catalog directory." }
3267
+ catalog_dir: {
3268
+ type: "string",
3269
+ description: "Optional path to catalog directory."
3270
+ }
3226
3271
  },
3227
3272
  additionalProperties: false
3228
3273
  }
@@ -3233,8 +3278,14 @@ var MCP_TOOLS = [
3233
3278
  inputSchema: {
3234
3279
  type: "object",
3235
3280
  properties: {
3236
- repo_path: { type: "string", description: "Target repository root path." },
3237
- startup_tax_budget: { type: "number", description: "Max startup token budget." }
3281
+ repo_path: {
3282
+ type: "string",
3283
+ description: "Target repository root path."
3284
+ },
3285
+ startup_tax_budget: {
3286
+ type: "number",
3287
+ description: "Max startup token budget."
3288
+ }
3238
3289
  },
3239
3290
  additionalProperties: false
3240
3291
  }
@@ -3245,8 +3296,14 @@ var MCP_TOOLS = [
3245
3296
  inputSchema: {
3246
3297
  type: "object",
3247
3298
  properties: {
3248
- repo_path: { type: "string", description: "Target repository root path." },
3249
- task_prompt: { type: "string", description: "Optional developer task description." }
3299
+ repo_path: {
3300
+ type: "string",
3301
+ description: "Target repository root path."
3302
+ },
3303
+ task_prompt: {
3304
+ type: "string",
3305
+ description: "Optional developer task description."
3306
+ }
3250
3307
  },
3251
3308
  additionalProperties: false
3252
3309
  }
@@ -3269,7 +3326,10 @@ var MCP_TOOLS = [
3269
3326
  inputSchema: {
3270
3327
  type: "object",
3271
3328
  properties: {
3272
- skill_name: { type: "string", description: "Optional skill name filter." }
3329
+ skill_name: {
3330
+ type: "string",
3331
+ description: "Optional skill name filter."
3332
+ }
3273
3333
  },
3274
3334
  additionalProperties: false
3275
3335
  }
@@ -3289,8 +3349,14 @@ var MCP_TOOLS = [
3289
3349
  inputSchema: {
3290
3350
  type: "object",
3291
3351
  properties: {
3292
- repo_path: { type: "string", description: "Target repository root path." },
3293
- startup_tax_budget: { type: "number", description: "Optional startup token budget override." }
3352
+ repo_path: {
3353
+ type: "string",
3354
+ description: "Target repository root path."
3355
+ },
3356
+ startup_tax_budget: {
3357
+ type: "number",
3358
+ description: "Optional startup token budget override."
3359
+ }
3294
3360
  },
3295
3361
  additionalProperties: false
3296
3362
  }
@@ -3301,7 +3367,10 @@ var MCP_TOOLS = [
3301
3367
  inputSchema: {
3302
3368
  type: "object",
3303
3369
  properties: {
3304
- repo_path: { type: "string", description: "Target repository root path." }
3370
+ repo_path: {
3371
+ type: "string",
3372
+ description: "Target repository root path."
3373
+ }
3305
3374
  },
3306
3375
  additionalProperties: false
3307
3376
  }
@@ -3383,7 +3452,9 @@ function handleMcpJsonRpcRequest(request, context) {
3383
3452
  const skillFilter = typeof args.skill_name === "string" ? args.skill_name : void 0;
3384
3453
  payload = evaluateCatalog(context.catalogDir, { skillFilter });
3385
3454
  } else if (toolName === "list_catalog_items") {
3386
- payload = auditCatalogTokenBudgets(context.catalogDir, { requireLayout: false });
3455
+ payload = auditCatalogTokenBudgets(context.catalogDir, {
3456
+ requireLayout: false
3457
+ });
3387
3458
  } else if (toolName === "diagnose_repo") {
3388
3459
  const repoPath = typeof args.repo_path === "string" ? args.repo_path : context.repoPath;
3389
3460
  const budget = typeof args.startup_tax_budget === "number" ? args.startup_tax_budget : void 0;
@@ -3588,7 +3659,11 @@ function setupMcpForHarnesses(repoPath, options = {}) {
3588
3659
  const absPath = path7.join(resolvedRepo, spec.mcpConfigPath);
3589
3660
  const exists = fs7.existsSync(absPath) && fs7.statSync(absPath).isFile();
3590
3661
  const existingRaw = exists ? fs7.readFileSync(absPath, "utf-8") : null;
3591
- const updatedRaw = buildUpdatedMcpConfigContent(target, existingRaw, serverName);
3662
+ const updatedRaw = buildUpdatedMcpConfigContent(
3663
+ target,
3664
+ existingRaw,
3665
+ serverName
3666
+ );
3592
3667
  let status;
3593
3668
  if (!exists) {
3594
3669
  status = "created";
@@ -3608,7 +3683,9 @@ function setupMcpForHarnesses(repoPath, options = {}) {
3608
3683
  status
3609
3684
  });
3610
3685
  }
3611
- const configuredCount = actions.filter((a) => a.status !== "unsupported").length;
3686
+ const configuredCount = actions.filter(
3687
+ (a) => a.status !== "unsupported"
3688
+ ).length;
3612
3689
  return {
3613
3690
  repo_path: path7.basename(resolvedRepo) || ".",
3614
3691
  dry_run: dryRun,
@@ -4452,29 +4529,21 @@ function formatSyncReport(report, format = "table", colorEnabled) {
4452
4529
  (a) => a.action === "created" || a.action === "updated" || a.action === "unchanged"
4453
4530
  );
4454
4531
  const firstSkill = activeArtifacts.find((a) => a.skill_name !== "codex-agents-index")?.skill_name ?? report.routed_bundle.selected_skills[0]?.name ?? "security-sast-gate";
4455
- const usageBox = activeArtifacts.length > 0 ? renderBox(
4456
- [
4457
- `${style.bold("How to use your installed Skills & Subagents inside your AI:", c)}`,
4458
- ` \u2022 ${style.cyan("Claude Code / Antigravity:", c)} Ask naturally (auto-routed via SKILL.md) or delegate to a Subagent`,
4459
- ` \u2022 ${style.cyan("Cursor / Windsurf / Cline / Copilot:", c)} Reference ${style.green(`@${firstSkill}`, c)} in Chat or let rules auto-attach`,
4460
- ` \u2022 ${style.cyan("Deep-Inspect:", c)} Run ${style.green(`npx skillops-cli info ${firstSkill}`, c)} to view triggers & Level 3 scripts`
4461
- ],
4462
- {
4463
- title: "\u{1F680} Using Your Skills & Subagents",
4464
- borderColor: style.cyan,
4465
- minWidth: 74,
4466
- colorEnabled: c
4467
- }
4532
+ const usageBox = activeArtifacts.length > 0 ? renderAiUsageGuide(
4533
+ report.targets,
4534
+ [firstSkill],
4535
+ report.routed_bundle.recommended_subagents,
4536
+ c
4468
4537
  ) : "";
4469
4538
  const nextSteps = renderNextSteps(
4470
4539
  [
4471
4540
  {
4472
4541
  command: `npx skillops-cli info ${firstSkill}`,
4473
- description: "Inspect triggers, token budget & Level 3 scripts"
4542
+ description: "Inspect triggers, token budget & L3 scripts"
4474
4543
  },
4475
4544
  {
4476
4545
  command: "npx skillops-cli doctor",
4477
- description: "Verify lockfile SHA-256 integrity & Startup Token Tax"
4546
+ description: "Verify lockfile SHA-256 & Startup Token Tax"
4478
4547
  }
4479
4548
  ],
4480
4549
  c
@@ -4501,20 +4570,20 @@ var COMMAND_HELP_SPECS = [
4501
4570
  name: "quickstart",
4502
4571
  aliases: ["setup"],
4503
4572
  pillar: "library",
4504
- summary: "1-step onboarding: detect project stack, route optimal Skills & Subagents, sync to AI harnesses & wire MCP",
4573
+ summary: "1-step onboarding: detect, route & sync",
4505
4574
  usage: "npx skillops-cli quickstart [options]",
4506
4575
  options: [
4507
4576
  {
4508
- flags: "--project, --repo, -p <dir>",
4509
- description: "Target repository directory (default: current directory)"
4577
+ flags: "-p, --project <dir>",
4578
+ description: "Target repository directory (default: cwd)"
4510
4579
  },
4511
4580
  {
4512
- flags: "--harness, --targets, -t <list|auto|all>",
4513
- description: "Target AI coding harnesses (e.g. claude,cursor,windsurf or auto/all)"
4581
+ flags: "-t, --harness <list|auto|all>",
4582
+ description: "Target AI coding harnesses (claude,cursor...)"
4514
4583
  },
4515
4584
  {
4516
4585
  flags: "--top, --max-skills <n>",
4517
- description: "Maximum number of Skills to activate in the bundle (default: 12)"
4586
+ description: "Max Skills to activate in bundle (default: 12)"
4518
4587
  },
4519
4588
  {
4520
4589
  flags: "--skip-mcp, --no-mcp",
@@ -4522,25 +4591,25 @@ var COMMAND_HELP_SPECS = [
4522
4591
  },
4523
4592
  {
4524
4593
  flags: "--dry-run",
4525
- description: "Preview planned changes without writing files to disk"
4594
+ description: "Preview planned changes without writing files"
4526
4595
  },
4527
4596
  {
4528
4597
  flags: "--force",
4529
- description: "Overwrite locally modified artifacts if drift is detected"
4598
+ description: "Overwrite locally modified artifacts"
4530
4599
  },
4531
4600
  {
4532
- flags: "--format, -f <table|json|markdown>",
4601
+ flags: "-f, --format <table|json|md>",
4533
4602
  description: "Output report format (default: table)"
4534
4603
  }
4535
4604
  ],
4536
4605
  examples: [
4537
4606
  {
4538
4607
  command: "npx skillops-cli quickstart",
4539
- description: "Auto-detect stack & harnesses, install optimal Skills/Subagents, and configure MCP"
4608
+ description: "Auto-detect stack, sync Skills & wire MCP"
4540
4609
  },
4541
4610
  {
4542
- command: "npx skillops-cli quickstart --harness cursor,claude --top 6",
4543
- description: "Quickstart specifically for Cursor and Claude Code with top 6 Skills"
4611
+ command: "npx skillops-cli quickstart -t cursor,claude --top 6",
4612
+ description: "Sync top 6 Skills to Cursor & Claude Code"
4544
4613
  }
4545
4614
  ]
4546
4615
  },
@@ -4548,7 +4617,7 @@ var COMMAND_HELP_SPECS = [
4548
4617
  name: "list",
4549
4618
  aliases: [],
4550
4619
  pillar: "library",
4551
- summary: "Browse all bundled Hybrid Executable Skills & Context-Isolated Subagents with token budgets",
4620
+ summary: "Browse all 10 Skills & 9 Subagents",
4552
4621
  usage: "npx skillops-cli list [options]",
4553
4622
  options: [
4554
4623
  {
@@ -4556,18 +4625,18 @@ var COMMAND_HELP_SPECS = [
4556
4625
  description: "Custom catalog directory to list"
4557
4626
  },
4558
4627
  {
4559
- flags: "--format, -f <table|json|markdown>",
4628
+ flags: "-f, --format <table|json|md>",
4560
4629
  description: "Output format (default: table)"
4561
4630
  }
4562
4631
  ],
4563
4632
  examples: [
4564
4633
  {
4565
4634
  command: "npx skillops-cli list",
4566
- description: "Display all 10 Skills and 9 Subagents with L1/L2 token footprints"
4635
+ description: "Display all 10 Skills & 9 Subagents"
4567
4636
  },
4568
4637
  {
4569
4638
  command: "npx skillops-cli info security-sast-gate",
4570
- description: "Deep-inspect a specific Skill from the Library after listing"
4639
+ description: "Inspect a specific Skill from the Library"
4571
4640
  }
4572
4641
  ]
4573
4642
  },
@@ -4575,7 +4644,7 @@ var COMMAND_HELP_SPECS = [
4575
4644
  name: "search",
4576
4645
  aliases: ["find"],
4577
4646
  pillar: "library",
4578
- summary: "Search the Library of Skills & Subagents by keyword, domain, framework, or routing signal",
4647
+ summary: "Search catalog by keyword, stack or domain",
4579
4648
  usage: "npx skillops-cli search <query> [options]",
4580
4649
  options: [
4581
4650
  {
@@ -4583,18 +4652,18 @@ var COMMAND_HELP_SPECS = [
4583
4652
  description: "Custom catalog directory to search"
4584
4653
  },
4585
4654
  {
4586
- flags: "--format, -f <table|json|markdown>",
4655
+ flags: "-f, --format <table|json|md>",
4587
4656
  description: "Output format (default: table)"
4588
4657
  }
4589
4658
  ],
4590
4659
  examples: [
4591
4660
  {
4592
4661
  command: "npx skillops-cli search security",
4593
- description: "Find Skills and Subagents matching security/SAST/OWASP signals"
4662
+ description: "Find Skills/Subagents matching security/SAST"
4594
4663
  },
4595
4664
  {
4596
4665
  command: "npx skillops-cli find postgres",
4597
- description: "Find database & PostgreSQL optimization Skills in the Library"
4666
+ description: "Find database & PostgreSQL optimization Skills"
4598
4667
  }
4599
4668
  ]
4600
4669
  },
@@ -4602,65 +4671,65 @@ var COMMAND_HELP_SPECS = [
4602
4671
  name: "info",
4603
4672
  aliases: ["show", "inspect"],
4604
4673
  pillar: "library",
4605
- summary: "Inspect a Skill or Subagent's L1 routing triggers, L2 token budget, L3 scripts & how to use it in your AI",
4606
- usage: "npx skillops-cli info <skill-or-subagent-name> [options]",
4674
+ summary: "Inspect triggers, L2 budget & AI usage",
4675
+ usage: "npx skillops-cli info <name> [options]",
4607
4676
  options: [
4608
4677
  {
4609
4678
  flags: "--catalog <dir>",
4610
4679
  description: "Custom catalog directory"
4611
4680
  },
4612
4681
  {
4613
- flags: "--format, -f <table|json|markdown>",
4682
+ flags: "-f, --format <table|json|md>",
4614
4683
  description: "Output format (default: table)"
4615
4684
  }
4616
4685
  ],
4617
4686
  examples: [
4618
4687
  {
4619
4688
  command: "npx skillops-cli info bug-reproducer-tdd",
4620
- description: "Inspect routing triggers, L3 scripts & IDE invocation guide for bug-reproducer-tdd"
4689
+ description: "Inspect triggers, L3 scripts & IDE invocation"
4621
4690
  },
4622
4691
  {
4623
4692
  command: "npx skillops-cli show red-team-breaker",
4624
- description: "Inspect the red-team-breaker Context-Isolated Subagent card"
4693
+ description: "Inspect the red-team-breaker Subagent card"
4625
4694
  }
4626
4695
  ]
4627
4696
  },
4628
4697
  {
4629
4698
  name: "add",
4630
- aliases: ["install", "i"],
4699
+ aliases: ["install"],
4631
4700
  pillar: "library",
4632
- summary: "Install one or more Skills or Subagents into your active AI coding harnesses",
4701
+ summary: "Install Skills/Subagents into AI harnesses",
4633
4702
  usage: "npx skillops-cli add <name...> [options]",
4634
4703
  options: [
4635
4704
  {
4636
- flags: "--project, --repo, -p <dir>",
4705
+ flags: "-p, --project <dir>",
4637
4706
  description: "Target repository directory"
4638
4707
  },
4639
4708
  {
4640
- flags: "--harness, --targets, -t <list|auto|all>",
4641
- description: "Target AI coding harnesses (e.g. claude,cursor,windsurf or all)"
4709
+ flags: "-t, --harness <list|auto|all>",
4710
+ description: "Target AI harnesses (claude,cursor,all...)"
4642
4711
  },
4643
4712
  {
4644
4713
  flags: "--dry-run",
4645
- description: "Preview planned file writes without modifying disk"
4714
+ description: "Preview planned writes without modifying disk"
4646
4715
  },
4647
4716
  {
4648
4717
  flags: "--force",
4649
4718
  description: "Overwrite locally drifted files"
4650
4719
  },
4651
4720
  {
4652
- flags: "--format, -f <table|json|markdown>",
4721
+ flags: "-f, --format <table|json|md>",
4653
4722
  description: "Output format (default: table)"
4654
4723
  }
4655
4724
  ],
4656
4725
  examples: [
4657
4726
  {
4658
4727
  command: "npx skillops-cli install security-sast-gate",
4659
- description: "Install the security-sast-gate Skill into configured/default harnesses"
4728
+ description: "Install security-sast-gate into harnesses"
4660
4729
  },
4661
4730
  {
4662
- command: "npx skillops-cli add mcp-architect context-scout --harness claude,cursor",
4663
- description: "Install both a Skill and a Subagent into Claude & Cursor"
4731
+ command: "npx skillops-cli add mcp-architect -t claude,cursor",
4732
+ description: "Install mcp-architect into Claude & Cursor"
4664
4733
  }
4665
4734
  ]
4666
4735
  },
@@ -4668,26 +4737,26 @@ var COMMAND_HELP_SPECS = [
4668
4737
  name: "remove",
4669
4738
  aliases: ["uninstall", "rm"],
4670
4739
  pillar: "library",
4671
- summary: "Surgically uninstall a synced Skill or Subagent from active AI harnesses",
4740
+ summary: "Remove a Skill/Subagent from harnesses",
4672
4741
  usage: "npx skillops-cli remove <name...> [options]",
4673
4742
  options: [
4674
4743
  {
4675
- flags: "--project, --repo, -p <dir>",
4744
+ flags: "-p, --project <dir>",
4676
4745
  description: "Target repository directory"
4677
4746
  },
4678
4747
  {
4679
- flags: "--harness, --targets, -t <list>",
4748
+ flags: "-t, --harness <list>",
4680
4749
  description: "Restrict removal to specific harnesses"
4681
4750
  },
4682
4751
  {
4683
4752
  flags: "--force",
4684
- description: "Remove even if local SHA-256 drift is detected"
4753
+ description: "Remove even if SHA-256 drift is detected"
4685
4754
  }
4686
4755
  ],
4687
4756
  examples: [
4688
4757
  {
4689
4758
  command: "npx skillops-cli uninstall mcp-architect",
4690
- description: "Remove all transpiled runtime files for mcp-architect and update .skillops-lock.json"
4759
+ description: "Remove runtime files & update lockfile"
4691
4760
  }
4692
4761
  ]
4693
4762
  },
@@ -4695,16 +4764,16 @@ var COMMAND_HELP_SPECS = [
4695
4764
  name: "route",
4696
4765
  aliases: ["recommend"],
4697
4766
  pillar: "library",
4698
- summary: "Fingerprint repository stack and recommend the optimal collision-free <=12 Skill bundle",
4767
+ summary: "Recommend optimal <=12 Skill bundle",
4699
4768
  usage: "npx skillops-cli recommend [options]",
4700
4769
  options: [
4701
4770
  {
4702
- flags: "--project, --repo, -p <dir>",
4771
+ flags: "-p, --project <dir>",
4703
4772
  description: "Repository directory to fingerprint"
4704
4773
  },
4705
4774
  {
4706
4775
  flags: "--task <prompt>",
4707
- description: "Optional natural-language task prompt to boost task-specific Skills"
4776
+ description: "Task prompt to boost task-specific Skills"
4708
4777
  },
4709
4778
  {
4710
4779
  flags: "--top, --max-skills <n>",
@@ -4712,21 +4781,21 @@ var COMMAND_HELP_SPECS = [
4712
4781
  },
4713
4782
  {
4714
4783
  flags: "--max-l1-tokens <n>",
4715
- description: "Maximum total L1 routing token budget (default: 1500)"
4784
+ description: "Maximum L1 routing token budget (default: 1500)"
4716
4785
  },
4717
4786
  {
4718
- flags: "--format, -f <table|json|markdown>",
4787
+ flags: "-f, --format <table|json|md>",
4719
4788
  description: "Output format (default: table)"
4720
4789
  }
4721
4790
  ],
4722
4791
  examples: [
4723
4792
  {
4724
4793
  command: "npx skillops-cli recommend",
4725
- description: "Recommend the best Skills & Subagents for the current repository stack"
4794
+ description: "Recommend best Skills for current repo stack"
4726
4795
  },
4727
4796
  {
4728
- command: 'npx skillops-cli route --task "optimize slow postgres queries in FastAPI" --top 4',
4729
- description: "Route top 4 Skills tailored to a specific engineering task"
4797
+ command: 'npx skillops-cli route --task "slow postgres" --top 4',
4798
+ description: "Route top 4 Skills for a specific task"
4730
4799
  }
4731
4800
  ]
4732
4801
  },
@@ -4734,12 +4803,12 @@ var COMMAND_HELP_SPECS = [
4734
4803
  name: "create",
4735
4804
  aliases: ["new"],
4736
4805
  pillar: "framework",
4737
- summary: "Scaffold a custom Skill (SKILL.md + L3 script + evals.json) or Subagent (SUBAGENT.md) using the SkillOps Framework",
4738
- usage: "npx skillops-cli create <skill|subagent> <kebab-case-name> [options]",
4806
+ summary: "Scaffold custom Skill or Subagent template",
4807
+ usage: "npx skillops-cli create <skill|subagent> <name> [options]",
4739
4808
  options: [
4740
4809
  {
4741
- flags: "--description, -d <text>",
4742
- description: "Custom trigger description (automatically normalized to INV-SKILL-01..04 contracts)"
4810
+ flags: "-d, --description <text>",
4811
+ description: "Custom trigger description (INV-SKILL-01..04)"
4743
4812
  },
4744
4813
  {
4745
4814
  flags: "--catalog <dir>",
@@ -4750,18 +4819,18 @@ var COMMAND_HELP_SPECS = [
4750
4819
  description: "Overwrite existing Skill or Subagent template"
4751
4820
  },
4752
4821
  {
4753
- flags: "--format, -f <table|json|markdown>",
4822
+ flags: "-f, --format <table|json|md>",
4754
4823
  description: "Output format (default: table)"
4755
4824
  }
4756
4825
  ],
4757
4826
  examples: [
4758
4827
  {
4759
4828
  command: "npx skillops-cli create skill graphql-schema-guard",
4760
- description: "Scaffold a new INV-SKILL-01..03 compliant Skill with Level 3 script & eval suite"
4829
+ description: "Scaffold a new Skill with L3 script & evals"
4761
4830
  },
4762
4831
  {
4763
4832
  command: "npx skillops-cli create subagent migration-reviewer",
4764
- description: "Scaffold a new INV-SKILL-04 compliant Context-Isolated Subagent"
4833
+ description: "Scaffold a new Context-Isolated Subagent"
4765
4834
  }
4766
4835
  ]
4767
4836
  },
@@ -4769,7 +4838,7 @@ var COMMAND_HELP_SPECS = [
4769
4838
  name: "audit",
4770
4839
  aliases: [],
4771
4840
  pillar: "framework",
4772
- summary: "Run L1/L2/L3 token budget linter, Subagent contract verifier & TF-IDF cosine collision matrix",
4841
+ summary: "Verify L1/L2 budgets & TF-IDF collisions",
4773
4842
  usage: "npx skillops-cli audit [options]",
4774
4843
  options: [
4775
4844
  {
@@ -4778,21 +4847,21 @@ var COMMAND_HELP_SPECS = [
4778
4847
  },
4779
4848
  {
4780
4849
  flags: "--require-layout",
4781
- description: "Enforce full directory layout including evals/evals.json and executable L3 scripts"
4850
+ description: "Enforce evals/evals.json and L3 scripts"
4782
4851
  },
4783
4852
  {
4784
4853
  flags: "--strict",
4785
- description: "Fail with non-zero exit code on HIGH_RISK collisions as well as BLOCKING collisions"
4854
+ description: "Fail on HIGH_RISK as well as BLOCKING collisions"
4786
4855
  },
4787
4856
  {
4788
- flags: "--format, -f <table|json|github>",
4857
+ flags: "-f, --format <table|json|gh>",
4789
4858
  description: "Output format (default: table)"
4790
4859
  }
4791
4860
  ],
4792
4861
  examples: [
4793
4862
  {
4794
4863
  command: "npx skillops-cli audit --require-layout --strict",
4795
- description: "Certify that all Skills & Subagents pass token budgets and zero-collision invariants"
4864
+ description: "Certify token budgets & zero collisions"
4796
4865
  }
4797
4866
  ]
4798
4867
  },
@@ -4800,7 +4869,7 @@ var COMMAND_HELP_SPECS = [
4800
4869
  name: "eval",
4801
4870
  aliases: [],
4802
4871
  pillar: "framework",
4803
- summary: "Execute zero-API deterministic TDD benchmarks (with_skill vs without_skill) and export dashboards",
4872
+ summary: "Run deterministic A/B TDD benchmarks",
4804
4873
  usage: "npx skillops-cli eval [options]",
4805
4874
  options: [
4806
4875
  {
@@ -4813,25 +4882,25 @@ var COMMAND_HELP_SPECS = [
4813
4882
  },
4814
4883
  {
4815
4884
  flags: "--out <file>",
4816
- description: "Write formatted benchmark report (e.g. HTML/Markdown) to disk"
4885
+ description: "Write benchmark report (HTML/Markdown) to disk"
4817
4886
  },
4818
4887
  {
4819
4888
  flags: "--strict",
4820
- description: "Exit with code 4 if any Skill fails CERTIFIED_IMPROVEMENT"
4889
+ description: "Exit 4 if any Skill fails CERTIFIED_IMPROVEMENT"
4821
4890
  },
4822
4891
  {
4823
- flags: "--format, -f <table|json|markdown|html|github>",
4892
+ flags: "-f, --format <table|json|html>",
4824
4893
  description: "Output format (default: table)"
4825
4894
  }
4826
4895
  ],
4827
4896
  examples: [
4828
4897
  {
4829
4898
  command: "npx skillops-cli eval --strict",
4830
- description: "Run deterministic A/B evals across all Skills in the catalog"
4899
+ description: "Run deterministic A/B evals across catalog"
4831
4900
  },
4832
4901
  {
4833
- command: "npx skillops-cli eval --format html --out benchmark.html",
4834
- description: "Export a standalone HTML benchmark dashboard"
4902
+ command: "npx skillops-cli eval -f html --out benchmark.html",
4903
+ description: "Export standalone HTML benchmark dashboard"
4835
4904
  }
4836
4905
  ]
4837
4906
  },
@@ -4839,22 +4908,22 @@ var COMMAND_HELP_SPECS = [
4839
4908
  name: "init",
4840
4909
  aliases: [],
4841
4910
  pillar: "runtime",
4842
- summary: "Scaffold declarative .skillops.yml and detect repository AI coding harnesses",
4911
+ summary: "Create .skillops.yml and detect harnesses",
4843
4912
  usage: "npx skillops-cli init [options]",
4844
4913
  options: [
4845
4914
  {
4846
- flags: "--project, --repo, -p <dir>",
4915
+ flags: "-p, --project <dir>",
4847
4916
  description: "Target repository directory"
4848
4917
  },
4849
4918
  {
4850
- flags: "--harness, --targets, -t <list|auto|all>",
4851
- description: "Initial target harnesses to record in .skillops.yml"
4919
+ flags: "-t, --harness <list|auto|all>",
4920
+ description: "Initial target harnesses for .skillops.yml"
4852
4921
  }
4853
4922
  ],
4854
4923
  examples: [
4855
4924
  {
4856
4925
  command: "npx skillops-cli init",
4857
- description: "Create .skillops.yml with auto-detected stack and harnesses"
4926
+ description: "Create .skillops.yml with detected harnesses"
4858
4927
  }
4859
4928
  ]
4860
4929
  },
@@ -4862,16 +4931,16 @@ var COMMAND_HELP_SPECS = [
4862
4931
  name: "sync",
4863
4932
  aliases: [],
4864
4933
  pillar: "runtime",
4865
- summary: "Transpile routed Skills & Subagents across up to 20 AI coding agents with SHA-256 lockfile protection",
4934
+ summary: "Transpile bundle across 20 AI agents",
4866
4935
  usage: "npx skillops-cli sync [options]",
4867
4936
  options: [
4868
4937
  {
4869
- flags: "--project, --repo, -p <dir>",
4938
+ flags: "-p, --project <dir>",
4870
4939
  description: "Target repository directory"
4871
4940
  },
4872
4941
  {
4873
- flags: "--harness, --targets, -t <list|auto|all>",
4874
- description: "Target AI coding harnesses (default: .skillops.yml targets or core 5)"
4942
+ flags: "-t, --harness <list|auto|all>",
4943
+ description: "Target AI harnesses (default: .skillops.yml)"
4875
4944
  },
4876
4945
  {
4877
4946
  flags: "--top, --max-skills <n>",
@@ -4879,7 +4948,7 @@ var COMMAND_HELP_SPECS = [
4879
4948
  },
4880
4949
  {
4881
4950
  flags: "--dry-run",
4882
- description: "Preview planned artifacts without writing files"
4951
+ description: "Preview planned artifacts without writing"
4883
4952
  },
4884
4953
  {
4885
4954
  flags: "--force",
@@ -4889,11 +4958,11 @@ var COMMAND_HELP_SPECS = [
4889
4958
  examples: [
4890
4959
  {
4891
4960
  command: "npx skillops-cli sync --auto",
4892
- description: "Sync optimal Skills & Subagents into all AI harnesses detected in the repo"
4961
+ description: "Sync bundle into all detected AI harnesses"
4893
4962
  },
4894
4963
  {
4895
4964
  command: "npx skillops-cli sync --harness all",
4896
- description: "Transpile across all 20 supported AI coding agents"
4965
+ description: "Transpile across all 20 supported AI agents"
4897
4966
  }
4898
4967
  ]
4899
4968
  },
@@ -4901,11 +4970,11 @@ var COMMAND_HELP_SPECS = [
4901
4970
  name: "clean",
4902
4971
  aliases: [],
4903
4972
  pillar: "runtime",
4904
- summary: "Remove all SkillOps-managed runtime artifacts tracked in .skillops-lock.json",
4973
+ summary: "Remove all tracked runtime artifacts",
4905
4974
  usage: "npx skillops-cli clean [options]",
4906
4975
  options: [
4907
4976
  {
4908
- flags: "--project, --repo, -p <dir>",
4977
+ flags: "-p, --project <dir>",
4909
4978
  description: "Target repository directory"
4910
4979
  },
4911
4980
  {
@@ -4920,7 +4989,7 @@ var COMMAND_HELP_SPECS = [
4920
4989
  examples: [
4921
4990
  {
4922
4991
  command: "npx skillops-cli clean",
4923
- description: "Cleanly remove all synced artifacts and .skillops-lock.json"
4992
+ description: "Remove all synced artifacts & lockfile"
4924
4993
  }
4925
4994
  ]
4926
4995
  },
@@ -4928,11 +4997,11 @@ var COMMAND_HELP_SPECS = [
4928
4997
  name: "tokens",
4929
4998
  aliases: ["budget"],
4930
4999
  pillar: "runtime",
4931
- summary: "Analyze repository Startup Token Tax, Progressive Disclosure savings & context bloat hotspots",
5000
+ summary: "Analyze Startup Token Tax & context bloat",
4932
5001
  usage: "npx skillops-cli budget [options]",
4933
5002
  options: [
4934
5003
  {
4935
- flags: "--project, --repo, -p <dir>",
5004
+ flags: "-p, --project <dir>",
4936
5005
  description: "Repository directory to inspect"
4937
5006
  },
4938
5007
  {
@@ -4941,17 +5010,17 @@ var COMMAND_HELP_SPECS = [
4941
5010
  },
4942
5011
  {
4943
5012
  flags: "--strict",
4944
- description: "Fail with exit code 3 if Startup Token Tax exceeds budget"
5013
+ description: "Exit 3 if Startup Token Tax exceeds budget"
4945
5014
  },
4946
5015
  {
4947
- flags: "--format, -f <table|json|markdown|github>",
5016
+ flags: "-f, --format <table|json|md>",
4948
5017
  description: "Output format (default: table)"
4949
5018
  }
4950
5019
  ],
4951
5020
  examples: [
4952
5021
  {
4953
5022
  command: "npx skillops-cli budget",
4954
- description: "Inspect repository Startup Token Tax and Progressive Disclosure savings"
5023
+ description: "Inspect repository Startup Token Tax & savings"
4955
5024
  }
4956
5025
  ]
4957
5026
  },
@@ -4959,11 +5028,11 @@ var COMMAND_HELP_SPECS = [
4959
5028
  name: "doctor",
4960
5029
  aliases: ["status"],
4961
5030
  pillar: "runtime",
4962
- summary: "Diagnose Node/Python environment, .skillops.yml validity, lockfile SHA-256 drift & Startup Token Tax",
5031
+ summary: "Diagnose environment, drift & token budget",
4963
5032
  usage: "npx skillops-cli doctor [options]",
4964
5033
  options: [
4965
5034
  {
4966
- flags: "--project, --repo, -p <dir>",
5035
+ flags: "-p, --project <dir>",
4967
5036
  description: "Repository directory to diagnose"
4968
5037
  },
4969
5038
  {
@@ -4971,7 +5040,7 @@ var COMMAND_HELP_SPECS = [
4971
5040
  description: "Fail on warnings as well as errors"
4972
5041
  },
4973
5042
  {
4974
- flags: "--format, -f <table|json|markdown|github>",
5043
+ flags: "-f, --format <table|json|md>",
4975
5044
  description: "Output format (default: table)"
4976
5045
  }
4977
5046
  ],
@@ -4986,22 +5055,22 @@ var COMMAND_HELP_SPECS = [
4986
5055
  name: "harnesses",
4987
5056
  aliases: [],
4988
5057
  pillar: "runtime",
4989
- summary: "List all 20 supported AI coding agents, target paths, MCP support & repository detection status",
5058
+ summary: "List 20 supported AI agents & repo status",
4990
5059
  usage: "npx skillops-cli harnesses [options]",
4991
5060
  options: [
4992
5061
  {
4993
- flags: "--project, --repo, -p <dir>",
5062
+ flags: "-p, --project <dir>",
4994
5063
  description: "Repository directory to scan for AI harnesses"
4995
5064
  },
4996
5065
  {
4997
- flags: "--format, -f <table|json|markdown>",
5066
+ flags: "-f, --format <table|json|md>",
4998
5067
  description: "Output format (default: table)"
4999
5068
  }
5000
5069
  ],
5001
5070
  examples: [
5002
5071
  {
5003
5072
  command: "npx skillops-cli harnesses",
5004
- description: "View all 20 supported AI coding IDEs/CLI agents and which ones are active in your repo"
5073
+ description: "View all 20 supported AI IDEs/CLI agents"
5005
5074
  }
5006
5075
  ]
5007
5076
  },
@@ -5009,15 +5078,15 @@ var COMMAND_HELP_SPECS = [
5009
5078
  name: "mcp-setup",
5010
5079
  aliases: [],
5011
5080
  pillar: "runtime",
5012
- summary: "Register SkillOps MCP server across all 13 MCP-compatible AI coding IDEs & agents",
5081
+ summary: "Wire MCP server across 13 AI IDEs & agents",
5013
5082
  usage: "npx skillops-cli mcp-setup [options]",
5014
5083
  options: [
5015
5084
  {
5016
- flags: "--project, --repo, -p <dir>",
5085
+ flags: "-p, --project <dir>",
5017
5086
  description: "Target repository directory"
5018
5087
  },
5019
5088
  {
5020
- flags: "--harness, --targets, -t <list|auto|all>",
5089
+ flags: "-t, --harness <list|auto|all>",
5021
5090
  description: "Target harnesses to configure MCP for"
5022
5091
  },
5023
5092
  {
@@ -5028,7 +5097,7 @@ var COMMAND_HELP_SPECS = [
5028
5097
  examples: [
5029
5098
  {
5030
5099
  command: "npx skillops-cli mcp-setup --auto",
5031
- description: "Automatically wire SkillOps MCP server into detected IDEs (.mcp.json, .cursor/mcp.json, etc.)"
5100
+ description: "Wire SkillOps MCP into detected IDEs"
5032
5101
  }
5033
5102
  ]
5034
5103
  },
@@ -5036,18 +5105,18 @@ var COMMAND_HELP_SPECS = [
5036
5105
  name: "mcp",
5037
5106
  aliases: [],
5038
5107
  pillar: "runtime",
5039
- summary: "Start native JSON-RPC 2.0 stdio Model Context Protocol server",
5108
+ summary: "Start stdio JSON-RPC 2.0 MCP server",
5040
5109
  usage: "npx skillops-cli mcp [options]",
5041
5110
  options: [
5042
5111
  {
5043
- flags: "--project, --repo, -p <dir>",
5112
+ flags: "-p, --project <dir>",
5044
5113
  description: "Repository root served over MCP"
5045
5114
  }
5046
5115
  ],
5047
5116
  examples: [
5048
5117
  {
5049
5118
  command: "npx skillops-cli mcp",
5050
- description: "Start stdio MCP server (invoked automatically by AI IDEs)"
5119
+ description: "Start stdio MCP server for AI IDEs"
5051
5120
  }
5052
5121
  ]
5053
5122
  }
@@ -5060,117 +5129,264 @@ function findCommandHelpSpec(commandOrAlias) {
5060
5129
  }
5061
5130
  function renderGlobalHelp(version, colorEnabled) {
5062
5131
  const c = colorEnabled;
5132
+ const bar = style.dim("\u2502", c);
5063
5133
  const banner = renderHeaderBanner(
5064
- "The Zero-API Framework & Library for High-End AI Coding Skills & Context-Isolated Subagents",
5134
+ "Skills & Agents Library for AI Coding IDEs",
5065
5135
  {
5066
5136
  version,
5067
5137
  colorEnabled: c
5068
5138
  }
5069
5139
  );
5070
- const quickstartBox = renderBox(
5071
- [
5072
- `${style.bold(style.green("npx skillops-cli quickstart", c), c)} ${style.dim("# 1-step setup: detect stack, install Skills/Subagents & wire MCP", c)}`,
5073
- `${style.bold(style.cyan("npx skillops-cli info <name>", c), c)} ${style.dim("# Inspect any Skill/Subagent & see how to invoke it in your AI", c)}`,
5074
- `${style.bold(style.magenta("npx skillops-cli create skill <name>", c), c)} ${style.dim("# Scaffold your own custom Skill using the SkillOps Framework", c)}`
5075
- ],
5140
+ const coreCmds = [
5076
5141
  {
5077
- title: "\u{1F680} 10-Second Quickstart (Library + Framework)",
5078
- borderColor: style.cyan,
5079
- minWidth: 88,
5080
- colorEnabled: c
5142
+ cmd: "add [name...]",
5143
+ desc: "Import Skills or Agents (interactive if no name given)"
5144
+ },
5145
+ {
5146
+ cmd: "list [query]",
5147
+ desc: "List or filter available Skills & Agents in catalog"
5148
+ },
5149
+ {
5150
+ cmd: "info <name>",
5151
+ desc: "View details and how to use a Skill or Agent"
5152
+ },
5153
+ {
5154
+ cmd: "remove <name>",
5155
+ desc: "Remove an imported Skill or Agent from your project"
5156
+ },
5157
+ {
5158
+ cmd: "init",
5159
+ desc: "Auto-detect stack & IDE and import recommended bundle"
5081
5160
  }
5082
- );
5083
- const formatCmdSection = (pillar) => {
5084
- const specs = COMMAND_HELP_SPECS.filter((s) => s.pillar === pillar);
5085
- return renderTable(
5086
- ["Command", "Aliases", "Description"],
5087
- specs.map((s) => [
5088
- style.bold(style.cyan(s.name, c), c),
5089
- s.aliases.length > 0 ? style.dim(s.aliases.join(", "), c) : style.dim("\u2014", c),
5090
- s.summary
5091
- ]),
5092
- { colorEnabled: c, indent: 2 }
5093
- );
5094
- };
5095
- const globalFlagsTable = renderTable(
5096
- ["Global Flag", "Description"],
5097
- [
5098
- [
5099
- style.cyan("--project, --repo, -p <dir>", c),
5100
- "Target project/repository directory (default: current working directory)"
5101
- ],
5102
- [
5103
- style.cyan("--harness, --targets, -t <list|auto|all>", c),
5104
- "Target AI coding harnesses (e.g. claude,cursor,windsurf,copilot or auto/all)"
5105
- ],
5106
- [
5107
- style.cyan("--format, -f <table|json|markdown|github>", c),
5108
- "Output format for reports and CI pipelines (default: table)"
5109
- ],
5110
- [
5111
- style.cyan("--help, -h / --version, -V", c),
5112
- "Show global or per-command help (`npx skillops-cli <cmd> --help`) / CLI version"
5113
- ]
5114
- ],
5115
- { colorEnabled: c, indent: 2 }
5116
- );
5161
+ ];
5162
+ const cmdRows = coreCmds.map(
5163
+ (item) => `${bar} ${padVisible(style.bold(style.cyan(item.cmd, c), c), 18, "left")}${item.desc}`
5164
+ ).join("\n");
5117
5165
  return [
5118
- `SkillOps v${version} \u2014 The Zero-API NPX Engine for High-End AI Skills & Subagents`,
5119
- "Usage: npx skillops-cli <command> [options]",
5120
- "",
5121
5166
  banner,
5122
- quickstartBox,
5123
- renderSectionHeader(
5124
- "\u{1F4DA} 1. Library of High-End Skills & Subagents (Explore, Search & Install)",
5125
- c
5126
- ),
5127
- formatCmdSection("library"),
5128
- renderSectionHeader(
5129
- "\u{1F6E0}\uFE0F 2. Framework for Building Custom Skills & Subagents (Scaffold, Audit & Certify)",
5130
- c
5131
- ),
5132
- formatCmdSection("framework"),
5133
- renderSectionHeader(
5134
- "\u2699\uFE0F 3. Universal Runtime Sync, Token Economy & Diagnostics (Top 20 AI Harnesses)",
5135
- c
5136
- ),
5137
- formatCmdSection("runtime"),
5138
- renderSectionHeader("\u{1F310} Global Options", c),
5139
- globalFlagsTable,
5140
- "",
5141
- ` ${style.dim("\u{1F4A1} Tip: Run", c)} ${style.bold(style.cyan("npx skillops-cli <command> --help", c), c)} ${style.dim("for detailed flags and copy-paste examples.", c)}`,
5142
- ""
5167
+ `${bar} Usage: skillops <command> [options]`,
5168
+ renderSectionHeader("Commands", c),
5169
+ cmdRows,
5170
+ renderSectionHeader("Options", c),
5171
+ `${bar} ${padVisible(style.cyan("-t, --target <ide>", c), 22, "left")}AI IDE (cursor, claude, copilot, windsurf, auto)`,
5172
+ `${bar} ${padVisible(style.cyan("-p, --project <dir>", c), 22, "left")}Project folder (default: current directory)`,
5173
+ `${bar} ${padVisible(style.cyan("--all", c), 22, "left")}Import all 10 Skills & 9 Agents`,
5174
+ renderSectionHeader("Examples", c),
5175
+ `${bar} ${style.dim("$", c)} ${style.green("skillops add", c)} ${style.dim("\u2014 Interactive selector", c)}`,
5176
+ `${bar} ${style.dim("$", c)} ${style.green("skillops add bug-reproducer-tdd red-team-breaker", c)} ${style.dim("\u2014 Direct import", c)}`,
5177
+ `${bar} ${style.dim("$", c)} ${style.green("skillops list", c)} ${style.dim("\u2014 Browse catalog", c)}`,
5178
+ bar,
5179
+ `${style.dim("\u2570\u2500", c)} ${style.dim("Run", c)} ${style.cyan("skillops <cmd> -h", c)} ${style.dim("for command options.", c)}`
5143
5180
  ].join("\n");
5144
5181
  }
5145
5182
  function renderCommandHelp(spec, version, colorEnabled) {
5146
5183
  const c = colorEnabled;
5184
+ const bar = style.dim("\u2502", c);
5147
5185
  const pillarBadge = spec.pillar === "library" ? formatBadge("info", "LIBRARY", c) : spec.pillar === "framework" ? formatBadge("pass", "FRAMEWORK", c) : formatBadge("subagent", "RUNTIME", c);
5148
5186
  const aliasText = spec.aliases.length > 0 ? ` (aliases: ${spec.aliases.map((a) => style.cyan(a, c)).join(", ")})` : "";
5149
- const headerBox = renderBox(
5150
- [
5151
- `${pillarBadge} ${style.bold(style.cyan(`skillops ${spec.name}`, c), c)}${aliasText}`,
5152
- "",
5153
- spec.summary,
5154
- "",
5155
- `${style.bold("Usage:", c)} ${style.green(spec.usage, c)}`
5156
- ],
5157
- {
5158
- title: `SkillOps v${version} \u2014 Command Reference`,
5159
- borderColor: style.cyan,
5160
- minWidth: 78,
5161
- colorEnabled: c
5162
- }
5163
- );
5187
+ const headerLines = [
5188
+ `${style.bold(style.cyan(`\u25C6 SkillOps v${version}`, c), c)} ${style.dim("\u2014", c)} ${style.bold(`skillops ${spec.name}`, c)}${aliasText} ${pillarBadge}`,
5189
+ `${bar} ${spec.summary}`,
5190
+ `${bar} ${style.bold("Usage:", c)} ${style.green(spec.usage, c)}`
5191
+ ].join("\n");
5164
5192
  const optionsSection = spec.options.length > 0 ? [
5165
5193
  renderSectionHeader("Options & Flags", c),
5166
5194
  renderTable(
5167
5195
  ["Flag", "Description"],
5168
5196
  spec.options.map((o) => [style.cyan(o.flags, c), o.description]),
5169
- { colorEnabled: c, indent: 2 }
5197
+ { colorEnabled: c, indent: 3 }
5170
5198
  )
5171
5199
  ].join("\n") : "";
5172
5200
  const examplesSection = renderNextSteps(spec.examples, c);
5173
- return [headerBox, optionsSection, examplesSection].filter(Boolean).join("\n");
5201
+ return [headerLines, optionsSection, examplesSection].filter(Boolean).join("\n");
5202
+ }
5203
+
5204
+ // src/ui/prompt.ts
5205
+ function createMultiSelectState(options) {
5206
+ const initial = /* @__PURE__ */ new Set();
5207
+ for (const opt of options) {
5208
+ if (opt.initialSelected) {
5209
+ initial.add(opt.value);
5210
+ }
5211
+ }
5212
+ return {
5213
+ options,
5214
+ cursor: 0,
5215
+ selected: initial,
5216
+ status: "active"
5217
+ };
5218
+ }
5219
+ function applyMultiSelectKey(state, key) {
5220
+ if (state.status !== "active" || state.options.length === 0) {
5221
+ return state;
5222
+ }
5223
+ const count = state.options.length;
5224
+ if (key === "" || key === "\x1B" || key === "q" || key === "Q") {
5225
+ return {
5226
+ ...state,
5227
+ status: "cancelled"
5228
+ };
5229
+ }
5230
+ if (key === "\r" || key === "\n") {
5231
+ return {
5232
+ ...state,
5233
+ status: "submitted"
5234
+ };
5235
+ }
5236
+ if (key === "\x1B[A" || key === "\x1BOA" || key === "k" || key === "K") {
5237
+ const nextCursor = (state.cursor - 1 + count) % count;
5238
+ return {
5239
+ ...state,
5240
+ cursor: nextCursor
5241
+ };
5242
+ }
5243
+ if (key === "\x1B[B" || key === "\x1BOB" || key === "j" || key === "J") {
5244
+ const nextCursor = (state.cursor + 1) % count;
5245
+ return {
5246
+ ...state,
5247
+ cursor: nextCursor
5248
+ };
5249
+ }
5250
+ if (key === " ") {
5251
+ const currentOpt = state.options[state.cursor];
5252
+ if (!currentOpt) {
5253
+ return state;
5254
+ }
5255
+ const nextSelected = new Set(state.selected);
5256
+ if (nextSelected.has(currentOpt.value)) {
5257
+ nextSelected.delete(currentOpt.value);
5258
+ } else {
5259
+ nextSelected.add(currentOpt.value);
5260
+ }
5261
+ return {
5262
+ ...state,
5263
+ selected: nextSelected
5264
+ };
5265
+ }
5266
+ if (key === "a" || key === "A") {
5267
+ const allSelected = state.selected.size === count;
5268
+ const nextSelected = /* @__PURE__ */ new Set();
5269
+ if (!allSelected) {
5270
+ for (const opt of state.options) {
5271
+ nextSelected.add(opt.value);
5272
+ }
5273
+ }
5274
+ return {
5275
+ ...state,
5276
+ selected: nextSelected
5277
+ };
5278
+ }
5279
+ return state;
5280
+ }
5281
+ function renderMultiSelectFrame(title, state, options = {}) {
5282
+ const c = options.colorEnabled;
5283
+ const bar = style.dim("\u2502", c);
5284
+ const maxVisible = options.maxVisible ?? 10;
5285
+ const total = state.options.length;
5286
+ const header = `${style.bold(style.cyan(`\u25C6 ${title}`, c), c)}`;
5287
+ const instructions = `${bar} ${style.dim("(\u2191/\u2193 move \xB7 Space select \xB7 'a' toggle all \xB7 Enter confirm)", c)}`;
5288
+ const lines = [header];
5289
+ if (options.subtitle) {
5290
+ lines.push(`${bar} ${options.subtitle}`);
5291
+ }
5292
+ lines.push(instructions, bar);
5293
+ let startIdx = 0;
5294
+ if (total > maxVisible) {
5295
+ const half = Math.floor(maxVisible / 2);
5296
+ startIdx = Math.max(0, Math.min(state.cursor - half, total - maxVisible));
5297
+ }
5298
+ const endIdx = Math.min(total, startIdx + maxVisible);
5299
+ if (startIdx > 0) {
5300
+ lines.push(`${bar} ${style.dim(`\u2191 ${startIdx} more above...`, c)}`);
5301
+ }
5302
+ const maxLabelCols = Math.min(
5303
+ 26,
5304
+ state.options.reduce((m, o) => Math.max(m, visibleLength(o.label)), 14)
5305
+ );
5306
+ for (let i = startIdx; i < endIdx; i++) {
5307
+ const opt = state.options[i];
5308
+ if (!opt) continue;
5309
+ const isCurrent = i === state.cursor;
5310
+ const isChecked = state.selected.has(opt.value);
5311
+ const pointer = isCurrent ? style.cyan("\u276F", c) : " ";
5312
+ const checkbox = isChecked ? style.green("\u25FC", c) : style.dim("\u25FB", c);
5313
+ const kindTag = opt.kind === "skill" ? style.cyan("skill ", c) : opt.kind === "agent" ? style.magenta("agent ", c) : "";
5314
+ const labelRaw = opt.label.length > maxLabelCols ? `${opt.label.slice(0, maxLabelCols - 1)}\u2026` : opt.label;
5315
+ const labelPadded = padVisible(labelRaw, maxLabelCols + 1, "left");
5316
+ const styledLabel = isCurrent ? style.bold(labelPadded, c) : isChecked ? style.green(labelPadded, c) : labelPadded;
5317
+ const prefixWidth = 6 + (opt.kind === "skill" || opt.kind === "agent" ? 6 : 0) + maxLabelCols + 1;
5318
+ const maxHintCols = Math.max(10, 75 - prefixWidth);
5319
+ const rawHint = opt.hint ?? "";
5320
+ const shortHint = rawHint.length > maxHintCols ? `${rawHint.slice(0, maxHintCols - 1)}\u2026` : rawHint;
5321
+ const hintPart = shortHint ? ` ${style.dim(shortHint, c)}` : "";
5322
+ lines.push(
5323
+ `${bar} ${pointer} ${checkbox} ${kindTag}${styledLabel}${hintPart}`
5324
+ );
5325
+ }
5326
+ if (endIdx < total) {
5327
+ lines.push(`${bar} ${style.dim(`\u2193 ${total - endIdx} more below...`, c)}`);
5328
+ }
5329
+ lines.push(bar);
5330
+ const targetSuffix = options.targetHint ? ` \xB7 IDE: ${options.targetHint}` : "";
5331
+ lines.push(
5332
+ `${style.dim("\u2570\u2500", c)} ${style.bold(`${state.selected.size} selected`, c)}${style.dim(`${targetSuffix} \u2014 Enter to import`, c)}`
5333
+ );
5334
+ return lines.join("\n");
5335
+ }
5336
+ async function runMultiSelectPrompt(title, options, renderOpts = {}) {
5337
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
5338
+ return null;
5339
+ }
5340
+ let state = createMultiSelectState(options);
5341
+ let renderedLineCount = 0;
5342
+ const render = () => {
5343
+ const frame = renderMultiSelectFrame(title, state, renderOpts);
5344
+ if (renderedLineCount > 0) {
5345
+ process.stdout.write(`\x1B[${renderedLineCount}A\x1B[J`);
5346
+ }
5347
+ process.stdout.write(`${frame}
5348
+ `);
5349
+ renderedLineCount = frame.split("\n").length;
5350
+ };
5351
+ return new Promise((resolve) => {
5352
+ const stdin = process.stdin;
5353
+ const wasRaw = stdin.isRaw;
5354
+ stdin.setRawMode(true);
5355
+ stdin.resume();
5356
+ stdin.setEncoding("utf-8");
5357
+ process.stdout.write("\x1B[?25l");
5358
+ render();
5359
+ const cleanup = () => {
5360
+ stdin.removeListener("data", onData);
5361
+ if (stdin.isTTY) {
5362
+ stdin.setRawMode(Boolean(wasRaw));
5363
+ }
5364
+ stdin.pause();
5365
+ process.stdout.write("\x1B[?25h");
5366
+ };
5367
+ const onData = (chunk) => {
5368
+ const key = typeof chunk === "string" ? chunk : chunk.toString("utf-8");
5369
+ state = applyMultiSelectKey(state, key);
5370
+ if (state.status === "cancelled") {
5371
+ if (renderedLineCount > 0) {
5372
+ process.stdout.write(`\x1B[${renderedLineCount}A\x1B[J`);
5373
+ }
5374
+ cleanup();
5375
+ resolve(null);
5376
+ return;
5377
+ }
5378
+ if (state.status === "submitted") {
5379
+ if (renderedLineCount > 0) {
5380
+ process.stdout.write(`\x1B[${renderedLineCount}A\x1B[J`);
5381
+ }
5382
+ cleanup();
5383
+ resolve([...state.selected]);
5384
+ return;
5385
+ }
5386
+ render();
5387
+ };
5388
+ stdin.on("data", onData);
5389
+ });
5174
5390
  }
5175
5391
 
5176
5392
  // src/framework/index.ts
@@ -5272,71 +5488,66 @@ function formatCatalogItemInfo(info, format = "table", colorEnabled) {
5272
5488
  return lines.join("\n");
5273
5489
  }
5274
5490
  const c = colorEnabled;
5491
+ const bar = style.dim("\u2502", c);
5275
5492
  const badge = info.kind === "skill" ? formatBadge("skill", "HYBRID EXECUTABLE SKILL", c) : formatBadge("subagent", "CONTEXT-ISOLATED SUBAGENT", c);
5493
+ const shortDesc = info.description.length > 68 ? `${info.description.slice(0, 65)}...` : info.description;
5276
5494
  const cardLines = [
5277
- `${badge} ${style.bold(style.cyan(info.name, c), c)}`,
5278
- "",
5279
- `${style.bold("Description:", c)}`,
5280
- ` ${info.description}`,
5281
- ""
5495
+ `${style.bold(style.cyan(`\u25C6 SkillOps Library Inspector \u2014 ${info.name}`, c), c)}`,
5496
+ `${bar} ${badge}`,
5497
+ `${bar} ${shortDesc}`,
5498
+ bar
5282
5499
  ];
5283
5500
  if (info.kind === "skill") {
5284
5501
  cardLines.push(
5285
- `${style.bold("Token Economy (INV-SKILL-01..03):", c)}`,
5286
- ` \u2022 L1 Routing Footprint : ${style.green(`${info.l1Tokens} tokens`, c)} (<= 160 budget)`,
5287
- ` \u2022 L2 Playbook Body : ${info.l2Lines} lines (${info.l2Tokens} tokens, <= 250 lines)`,
5288
- ` \u2022 Progressive Savings : ${style.bold(style.green(`${info.savingsPct}%`, c), c)} Startup Token Tax saved until triggered`,
5289
- ` \u2022 L3 Scripts (${info.scripts.length}) : ${info.scripts.length > 0 ? style.cyan(info.scripts.join(", "), c) : "none"}`,
5290
- ` \u2022 TDD Eval Cases : ${info.evalCasesCount} deterministic benchmark cases`
5502
+ `${style.dim("\u251C\u2500", c)} ${style.bold(style.cyan("Token Economy (INV-SKILL-01..03)", c), c)}`,
5503
+ `${bar} \u2022 L1 Routing : ${style.green(`${info.l1Tokens} tokens`, c)} (<= 160 budget)`,
5504
+ `${bar} \u2022 L2 Playbook : ${info.l2Lines} lines (${info.l2Tokens}t, <= 250 lines)`,
5505
+ `${bar} \u2022 Token Savings : ${style.bold(style.green(`${info.savingsPct}%`, c), c)} Startup Tax saved`,
5506
+ `${bar} \u2022 L3 Scripts (${info.scripts.length}) : ${info.scripts.length > 0 ? style.cyan(info.scripts.join(", "), c) : "none"}`,
5507
+ `${bar} \u2022 TDD Evals : ${info.evalCasesCount} deterministic cases`
5291
5508
  );
5292
5509
  } else {
5293
5510
  cardLines.push(
5294
- `${style.bold("Context Isolation Contract (INV-SKILL-04):", c)}`,
5295
- ` \u2022 System Prompt Tokens : ${style.green(`${info.l1Tokens} tokens`, c)}`,
5296
- ` \u2022 Max Output Cap : <= ${style.bold(`${info.maxOutputTokens} tokens`, c)}`,
5297
- ` \u2022 Isolation Mode : ${style.cyan(info.isolation ?? "context-isolated", c)}`,
5298
- ` \u2022 Allowed Tools (${info.tools.length}) : ${info.tools.join(", ")}`
5511
+ `${style.dim("\u251C\u2500", c)} ${style.bold(style.cyan("Context Isolation Contract (INV-SKILL-04)", c), c)}`,
5512
+ `${bar} \u2022 System Prompt : ${style.green(`${info.l1Tokens} tokens`, c)}`,
5513
+ `${bar} \u2022 Max Output Cap : <= ${style.bold(`${info.maxOutputTokens} tokens`, c)}`,
5514
+ `${bar} \u2022 Isolation Mode : ${style.cyan(info.isolation ?? "context-isolated", c)}`,
5515
+ `${bar} \u2022 Allowed Tools : ${info.tools.join(", ")}`
5299
5516
  );
5300
5517
  }
5301
5518
  if (info.headings.length > 0) {
5302
5519
  cardLines.push(
5303
- "",
5304
- `${style.bold("Workflow Playbook Sections:", c)}`,
5305
- ...info.headings.slice(0, 6).map((h) => ` \u2022 ${h}`)
5520
+ bar,
5521
+ `${style.dim("\u251C\u2500", c)} ${style.bold(style.cyan("Playbook Sections", c), c)}`,
5522
+ ...info.headings.slice(0, 5).map((h) => `${bar} \u2022 ${h}`)
5306
5523
  );
5307
5524
  }
5308
5525
  cardLines.push(
5309
- "",
5310
- `${style.bold("How to Invoke in Your AI Agent:", c)}`,
5311
- ` \u2022 ${style.bold("Install into repo:", c)} ${style.green(`npx skillops-cli add ${info.name}`, c)}`,
5312
- info.kind === "skill" ? ` \u2022 ${style.bold("Cursor / Copilot / Claude:", c)} Reference ${style.cyan(`@${info.name}`, c)} or ${style.cyan(`/${info.name}`, c)} in chat` : ` \u2022 ${style.bold("Delegate Subagent:", c)} Ask your main agent to delegate heavy exploration to ${style.magenta(`@${info.name}`, c)}`
5526
+ bar,
5527
+ `${style.dim("\u251C\u2500", c)} ${style.bold(style.cyan("How to Invoke in Your AI Agent", c), c)}`,
5528
+ `${bar} \u2022 ${style.bold("Install:", c)} ${style.green(`npx skillops-cli add ${info.name}`, c)}`,
5529
+ info.kind === "skill" ? `${bar} \u2022 ${style.bold("IDE Chat:", c)} Reference ${style.cyan(`@${info.name}`, c)} or ${style.cyan(`/${info.name}`, c)}` : `${bar} \u2022 ${style.bold("Delegate:", c)} Ask main agent to run ${style.magenta(`@${info.name}`, c)}`
5313
5530
  );
5314
- const box = renderBox(cardLines, {
5315
- title: `\u{1F4E6} SkillOps Library Inspector \u2014 ${info.name}`,
5316
- borderColor: info.kind === "skill" ? style.cyan : style.magenta,
5317
- minWidth: 74,
5318
- colorEnabled: c
5319
- });
5320
5531
  const nextSteps = renderNextSteps(
5321
5532
  [
5322
5533
  {
5323
5534
  command: `npx skillops-cli add ${info.name}`,
5324
- description: `Install '${info.name}' into your active AI coding agents`
5535
+ description: "Install into AI agents"
5325
5536
  },
5326
5537
  ...info.kind === "skill" ? [
5327
5538
  {
5328
5539
  command: `npx skillops-cli eval --skill ${info.name}`,
5329
- description: `Run deterministic TDD benchmark for '${info.name}'`
5540
+ description: "Run TDD benchmark"
5330
5541
  }
5331
5542
  ] : [],
5332
5543
  {
5333
5544
  command: "npx skillops-cli list",
5334
- description: "Browse all 10 Skills & 9 Subagents in the Library"
5545
+ description: "Browse 10 Skills & 9 Subagents"
5335
5546
  }
5336
5547
  ],
5337
5548
  c
5338
5549
  );
5339
- return `${box}
5550
+ return `${cardLines.join("\n")}
5340
5551
  ${nextSteps}`;
5341
5552
  }
5342
5553
  function searchCatalog(catalogDir, query) {
@@ -5365,7 +5576,7 @@ function searchCatalog(catalogDir, query) {
5365
5576
  name: parsed.manifest.name,
5366
5577
  score,
5367
5578
  tokens: parsed.manifest.description_tokens,
5368
- summary: parsed.manifest.description.length > 78 ? `${parsed.manifest.description.slice(0, 75)}...` : parsed.manifest.description
5579
+ summary: parsed.manifest.description.length > 30 ? `${parsed.manifest.description.slice(0, 27)}...` : parsed.manifest.description
5369
5580
  });
5370
5581
  }
5371
5582
  }
@@ -5392,7 +5603,7 @@ function searchCatalog(catalogDir, query) {
5392
5603
  name: parsed.manifest.name,
5393
5604
  score,
5394
5605
  tokens: parsed.manifest.system_prompt_tokens,
5395
- summary: parsed.manifest.description.length > 78 ? `${parsed.manifest.description.slice(0, 75)}...` : parsed.manifest.description
5606
+ summary: parsed.manifest.description.length > 30 ? `${parsed.manifest.description.slice(0, 27)}...` : parsed.manifest.description
5396
5607
  });
5397
5608
  }
5398
5609
  }
@@ -5422,43 +5633,39 @@ function formatCatalogSearchReport(report, format = "table", colorEnabled) {
5422
5633
  return lines.join("\n");
5423
5634
  }
5424
5635
  const c = colorEnabled;
5425
- const header = renderBox(
5426
- [
5427
- `${style.bold(style.cyan("\u{1F50D} SkillOps Library Search", c), c)} \u2014 Query: ${style.bold(`"${report.query || "*"}"`, c)} (${report.total_matches} matches)`
5428
- ],
5429
- { minWidth: 74, colorEnabled: c }
5430
- );
5636
+ const bar = style.dim("\u2502", c);
5637
+ const header = `${style.bold(style.cyan("\u25C6 SkillOps Library Search", c), c)} ${style.dim("\u2014", c)} Query: ${style.bold(`"${report.query || "*"}"`, c)} (${report.total_matches} matches)`;
5431
5638
  if (report.matches.length === 0) {
5432
5639
  return `${header}
5433
- ${formatBadge("warn", "No matching Skills or Subagents found.", c)}
5434
- ${renderNextSteps([{ command: "npx skillops-cli list", description: "View all 10 Skills & 9 Subagents in the Library" }], c)}`;
5640
+ ${bar} ${formatBadge("warn", "No matching Skills or Subagents found.", c)}
5641
+ ${renderNextSteps([{ command: "npx skillops-cli list", description: "View all 10 Skills & 9 Subagents" }], c)}`;
5435
5642
  }
5436
5643
  const table = renderTable(
5437
- ["Type", "Name", "Tokens", "When to Use / Summary"],
5644
+ ["Type", "Name", "Tokens", "Summary"],
5438
5645
  report.matches.map((m) => [
5439
5646
  m.kind === "skill" ? formatBadge("skill", "SKILL", c) : formatBadge("subagent", "SUBAGENT", c),
5440
5647
  style.bold(m.name, c),
5441
5648
  `${m.tokens}t`,
5442
5649
  m.summary
5443
5650
  ]),
5444
- { align: ["left", "left", "right", "left"], colorEnabled: c }
5651
+ { align: ["left", "left", "right", "left"], colorEnabled: c, indent: 3 }
5445
5652
  );
5446
5653
  const topItem = report.matches[0]?.name ?? "bug-reproducer-tdd";
5447
5654
  const nextSteps = renderNextSteps(
5448
5655
  [
5449
5656
  {
5450
5657
  command: `npx skillops-cli info ${topItem}`,
5451
- description: `Inspect '${topItem}' in detail`
5658
+ description: "Inspect triggers & usage"
5452
5659
  },
5453
5660
  {
5454
5661
  command: `npx skillops-cli add ${topItem}`,
5455
- description: `Install '${topItem}' into your project's AI agents`
5662
+ description: "Install into AI agents"
5456
5663
  }
5457
5664
  ],
5458
5665
  c
5459
5666
  );
5460
5667
  return `${header}
5461
-
5668
+ ${bar}
5462
5669
  ${table}
5463
5670
  ${nextSteps}`;
5464
5671
  }
@@ -5676,38 +5883,31 @@ function formatScaffoldReport(result, format = "table", colorEnabled) {
5676
5883
  ].join("\n");
5677
5884
  }
5678
5885
  const c = colorEnabled;
5679
- const box = renderBox(
5680
- [
5681
- `${formatBadge("pass", "CREATED", c)} Scaffolded new SkillOps Framework ${style.bold(result.kind.toUpperCase(), c)}: ${style.bold(style.cyan(result.name, c), c)}`,
5682
- "",
5683
- `${style.bold("Generated Files:", c)}`,
5684
- ...result.created_files.map((f) => ` \u2022 ${style.green(f, c)}`)
5685
- ],
5686
- {
5687
- title: "\u{1F6E0}\uFE0F SkillOps Framework Scaffolder",
5688
- borderColor: style.green,
5689
- minWidth: 74,
5690
- colorEnabled: c
5691
- }
5692
- );
5886
+ const bar = style.dim("\u2502", c);
5887
+ const treeHeader = [
5888
+ `${style.bold(style.cyan("\u25C6 SkillOps Framework Scaffolder", c), c)} ${style.dim("\u2014", c)} ${formatBadge("pass", "CREATED", c)} ${style.bold(result.kind.toUpperCase(), c)} ${style.bold(style.cyan(result.name, c), c)}`,
5889
+ bar,
5890
+ `${style.dim("\u251C\u2500", c)} ${style.bold("Generated Files:", c)}`,
5891
+ ...result.created_files.map((f) => `${bar} \u2022 ${style.green(f, c)}`)
5892
+ ].join("\n");
5693
5893
  const nextSteps = renderNextSteps(
5694
5894
  [
5695
5895
  {
5696
5896
  command: `npx skillops-cli info ${result.name}`,
5697
- description: `Inspect your new ${result.kind} metadata & token budget`
5897
+ description: `Inspect new ${result.kind} metadata & budget`
5698
5898
  },
5699
5899
  {
5700
5900
  command: "npx skillops-cli audit --require-layout",
5701
- description: "Verify INV-SKILL-01..04 contract compliance & cosine collisions"
5901
+ description: "Verify INV-SKILL-01..04 & collisions"
5702
5902
  },
5703
5903
  {
5704
5904
  command: `npx skillops-cli add ${result.name}`,
5705
- description: `Transpile & install '${result.name}' into your AI coding agents`
5905
+ description: `Install '${result.name}' into AI agents`
5706
5906
  }
5707
5907
  ],
5708
5908
  c
5709
5909
  );
5710
- return `${box}
5910
+ return `${treeHeader}
5711
5911
  ${nextSteps}`;
5712
5912
  }
5713
5913
  function runQuickstart(repoPath, catalogDir, options = {}) {
@@ -5806,34 +6006,35 @@ function formatQuickstartReport(report, format = "table", colorEnabled) {
5806
6006
  ].join("\n");
5807
6007
  }
5808
6008
  const c = colorEnabled;
5809
- const stackLabel = [...report.detected_languages, ...report.detected_frameworks].join(", ") || "general-purpose";
5810
- const targetsLabel = report.active_targets.length > 5 ? `${report.active_targets.slice(0, 5).join(", ")} (+${report.active_targets.length - 5} more)` : report.active_targets.join(", ");
6009
+ const bar = style.dim("\u2502", c);
6010
+ const stackLabel = [...report.detected_languages, ...report.detected_frameworks].join(", ") || "general";
6011
+ const targetsLabel = report.active_targets.length > 4 ? `${report.active_targets.slice(0, 4).join(", ")} (+${report.active_targets.length - 4})` : report.active_targets.join(", ");
5811
6012
  const banner = renderHeaderBanner(
5812
- `1-Step Quickstart & AI Agent Library Setup ${report.dry_run ? "[DRY-RUN]" : "[READY]"}`,
6013
+ `Quickstart Setup ${report.dry_run ? "[DRY-RUN]" : "[READY]"}`,
5813
6014
  { colorEnabled: c }
5814
6015
  );
5815
6016
  const stepsBlock = [
5816
6017
  renderStep(
5817
6018
  1,
5818
6019
  4,
5819
- "Detect Stack & AI Agents",
5820
- `Stack: ${style.cyan(stackLabel, c)} \u2022 Targets: ${style.bold(targetsLabel, c)}`,
6020
+ "Detect Stack & Agents",
6021
+ `${style.cyan(stackLabel, c)} \xB7 ${style.bold(targetsLabel, c)}`,
5821
6022
  "done",
5822
6023
  c
5823
6024
  ),
5824
6025
  renderStep(
5825
6026
  2,
5826
6027
  4,
5827
- "Route Optimal Library Bundle",
5828
- `${style.green(`${report.selected_skills.length} Skills`, c)} + ${style.magenta(`${report.selected_subagents.length} Subagents`, c)} selected`,
6028
+ "Route Library Bundle",
6029
+ `${style.green(`${report.selected_skills.length} Skills`, c)} + ${style.magenta(`${report.selected_subagents.length} Subagents`, c)}`,
5829
6030
  "done",
5830
6031
  c
5831
6032
  ),
5832
6033
  renderStep(
5833
6034
  3,
5834
6035
  4,
5835
- "Transpile & Sync Artifacts",
5836
- `${report.synced_files_count} files synced (${report.dry_run ? "dry-run" : ".skillops.yml + .skillops-lock.json"})`,
6036
+ "Transpile & Sync",
6037
+ `${report.synced_files_count} files (${report.dry_run ? "dry-run" : ".skillops.yml + lockfile"})`,
5837
6038
  "done",
5838
6039
  c
5839
6040
  ),
@@ -5841,12 +6042,12 @@ function formatQuickstartReport(report, format = "table", colorEnabled) {
5841
6042
  4,
5842
6043
  4,
5843
6044
  "Register MCP Server",
5844
- `${report.mcp_configured_count} MCP-compatible agent config(s) updated`,
6045
+ `${report.mcp_configured_count} MCP agent config(s) wired`,
5845
6046
  "done",
5846
6047
  c
5847
6048
  )
5848
6049
  ].join("\n");
5849
- const tokenBar = ` ${renderTokenBar(
6050
+ const tokenBar = `${bar} ${renderTokenBar(
5850
6051
  report.total_l1_tokens,
5851
6052
  report.max_l1_budget,
5852
6053
  {
@@ -5854,21 +6055,16 @@ function formatQuickstartReport(report, format = "table", colorEnabled) {
5854
6055
  colorEnabled: c
5855
6056
  }
5856
6057
  )}`;
5857
- const bundleBox = renderBox(
5858
- [
5859
- `${style.bold("Installed Hybrid Executable Skills:", c)}`,
5860
- ` ${report.selected_skills.map((s) => style.cyan(s, c)).join(", ")}`,
5861
- "",
5862
- `${style.bold("Installed Context-Isolated Subagents:", c)}`,
5863
- ` ${report.selected_subagents.map((a) => style.magenta(a, c)).join(", ")}`
5864
- ],
5865
- {
5866
- title: "\u{1F4E6} Active Skills & Subagents Bundle",
5867
- borderColor: style.cyan,
5868
- minWidth: 72,
5869
- colorEnabled: c
5870
- }
5871
- );
6058
+ const bundleTree = [
6059
+ bar,
6060
+ `${style.dim("\u251C\u2500", c)} ${style.bold(style.cyan(`Active Bundle (${report.selected_skills.length} Skills \xB7 ${report.selected_subagents.length} Subagents)`, c), c)}`,
6061
+ `${bar} \u2022 ${style.bold("Skills:", c)} ${report.selected_skills.slice(0, 2).map((s) => style.cyan(s, c)).join(
6062
+ ", "
6063
+ )}${report.selected_skills.length > 2 ? ` (+${report.selected_skills.length - 2} more)` : ""}`,
6064
+ `${bar} \u2022 ${style.bold("Subagents:", c)} ${report.selected_subagents.slice(0, 2).map((a) => style.magenta(a, c)).join(
6065
+ ", "
6066
+ )}${report.selected_subagents.length > 2 ? ` (+${report.selected_subagents.length - 2} more)` : ""}`
6067
+ ].join("\n");
5872
6068
  const usageGuide = renderAiUsageGuide(
5873
6069
  report.active_targets,
5874
6070
  report.selected_skills,
@@ -5879,32 +6075,29 @@ function formatQuickstartReport(report, format = "table", colorEnabled) {
5879
6075
  [
5880
6076
  {
5881
6077
  command: `npx skillops-cli info ${report.selected_skills[0] ?? "bug-reproducer-tdd"}`,
5882
- description: "Inspect a Skill's triggers, L3 scripts & AI invocation syntax"
6078
+ description: "Inspect Skill triggers & L3 scripts"
5883
6079
  },
5884
6080
  {
5885
6081
  command: "npx skillops-cli list",
5886
- description: "Browse all 10 Skills & 9 Subagents in the Library"
6082
+ description: "Browse all 10 Skills & 9 Subagents"
5887
6083
  },
5888
6084
  {
5889
- command: "npx skillops-cli create skill my-custom-skill",
5890
- description: "Create your own custom Skill using the SkillOps Framework"
6085
+ command: "npx skillops-cli create skill my-skill",
6086
+ description: "Create a custom Skill"
5891
6087
  },
5892
6088
  {
5893
6089
  command: "npx skillops-cli doctor",
5894
- description: "Verify lockfile integrity & Startup Token Tax savings"
6090
+ description: "Verify lockfile & Startup Token Tax"
5895
6091
  }
5896
6092
  ],
5897
6093
  c
5898
6094
  );
5899
6095
  return [
5900
6096
  banner,
5901
- "",
6097
+ bar,
5902
6098
  stepsBlock,
5903
- "",
5904
6099
  tokenBar,
5905
- "",
5906
- bundleBox,
5907
- "",
6100
+ bundleTree,
5908
6101
  usageGuide,
5909
6102
  nextSteps
5910
6103
  ].join("\n");
@@ -5952,6 +6145,7 @@ export {
5952
6145
  TokenWasteHotspotSchema,
5953
6146
  addSkillOrSubagent,
5954
6147
  analyzeRepoTokenEconomy,
6148
+ applyMultiSelectKey,
5955
6149
  auditCatalog,
5956
6150
  auditCatalogTokenBudgets,
5957
6151
  auditSkillTokenBudget,
@@ -5966,6 +6160,7 @@ export {
5966
6160
  countWords,
5967
6161
  createCollisionPair,
5968
6162
  createCollisionReport,
6163
+ createMultiSelectState,
5969
6164
  createSkillManifest,
5970
6165
  createSubagentManifest,
5971
6166
  detectInstalledHarnesses,
@@ -6009,6 +6204,7 @@ export {
6009
6204
  renderCommandHelp,
6010
6205
  renderGlobalHelp,
6011
6206
  renderHeaderBanner,
6207
+ renderMultiSelectFrame,
6012
6208
  renderNextSteps,
6013
6209
  renderProgressBar,
6014
6210
  renderSectionHeader,
@@ -6017,6 +6213,7 @@ export {
6017
6213
  renderTokenBar,
6018
6214
  resolveRuntimeTargets,
6019
6215
  routeRepository,
6216
+ runMultiSelectPrompt,
6020
6217
  runQuickstart,
6021
6218
  scaffoldFrameworkItem,
6022
6219
  scoreSkillAgainstProfile,