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.
- package/README.md +52 -49
- package/dist/cli.js +818 -551
- package/dist/index.d.ts +181 -138
- package/dist/index.js +701 -504
- 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.
|
|
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(
|
|
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(
|
|
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, {
|
|
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([
|
|
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(
|
|
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, {
|
|
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 ??
|
|
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
|
|
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
|
-
|
|
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 ??
|
|
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
|
-
|
|
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,
|
|
1579
|
-
const detailStyled = detail ? ` ${style.dim("\
|
|
1580
|
-
return
|
|
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 =
|
|
1588
|
-
|
|
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
|
-
|
|
1594
|
-
...hints.map(
|
|
1595
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1546
|
+
`${bar} \u2022 ${style.bold("Windsurf/Cline/Roo/Kilo:", c)} Workspace rules load automatically`
|
|
1633
1547
|
);
|
|
1634
1548
|
}
|
|
1635
1549
|
lines.push(
|
|
1636
|
-
|
|
1550
|
+
`${bar} \u2022 ${style.bold("Inspect:", c)} ${style.green(`npx skillops-cli info ${sampleSkill}`, c)}`
|
|
1637
1551
|
);
|
|
1638
|
-
return
|
|
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:
|
|
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 &
|
|
2015
|
+
description: "Sync Progressive Disclosure Skills & Subagents"
|
|
2108
2016
|
},
|
|
2109
2017
|
{
|
|
2110
2018
|
command: "npx skillops-cli doctor",
|
|
2111
|
-
description: "Inspect
|
|
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(
|
|
2356
|
-
|
|
2357
|
-
|
|
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(
|
|
2321
|
+
lines2.push(
|
|
2322
|
+
`::error title=SkillOps Doctor (${check.title})::${check.summary}`
|
|
2323
|
+
);
|
|
2416
2324
|
} else if (check.status === "warn") {
|
|
2417
|
-
lines2.push(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
2621
|
-
|
|
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(
|
|
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(
|
|
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, {
|
|
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(
|
|
2860
|
-
|
|
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:
|
|
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
|
|
3236
|
+
description: "Install recommended bundle & wire MCP"
|
|
3195
3237
|
},
|
|
3196
3238
|
{
|
|
3197
3239
|
command: `npx skillops-cli info ${topSkill}`,
|
|
3198
|
-
description: `Inspect ${topSkill} triggers
|
|
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: {
|
|
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: {
|
|
3237
|
-
|
|
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: {
|
|
3249
|
-
|
|
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: {
|
|
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: {
|
|
3293
|
-
|
|
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: {
|
|
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, {
|
|
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(
|
|
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(
|
|
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 ?
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
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 &
|
|
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
|
|
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
|
|
4573
|
+
summary: "1-step onboarding: detect, route & sync",
|
|
4505
4574
|
usage: "npx skillops-cli quickstart [options]",
|
|
4506
4575
|
options: [
|
|
4507
4576
|
{
|
|
4508
|
-
flags: "
|
|
4509
|
-
description: "Target repository directory (default:
|
|
4577
|
+
flags: "-p, --project <dir>",
|
|
4578
|
+
description: "Target repository directory (default: cwd)"
|
|
4510
4579
|
},
|
|
4511
4580
|
{
|
|
4512
|
-
flags: "
|
|
4513
|
-
description: "Target AI coding harnesses (
|
|
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: "
|
|
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
|
|
4594
|
+
description: "Preview planned changes without writing files"
|
|
4526
4595
|
},
|
|
4527
4596
|
{
|
|
4528
4597
|
flags: "--force",
|
|
4529
|
-
description: "Overwrite locally modified artifacts
|
|
4598
|
+
description: "Overwrite locally modified artifacts"
|
|
4530
4599
|
},
|
|
4531
4600
|
{
|
|
4532
|
-
flags: "--format
|
|
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
|
|
4608
|
+
description: "Auto-detect stack, sync Skills & wire MCP"
|
|
4540
4609
|
},
|
|
4541
4610
|
{
|
|
4542
|
-
command: "npx skillops-cli quickstart
|
|
4543
|
-
description: "
|
|
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
|
|
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
|
|
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
|
|
4635
|
+
description: "Display all 10 Skills & 9 Subagents"
|
|
4567
4636
|
},
|
|
4568
4637
|
{
|
|
4569
4638
|
command: "npx skillops-cli info security-sast-gate",
|
|
4570
|
-
description: "
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
4606
|
-
usage: "npx skillops-cli info <
|
|
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
|
|
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
|
|
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
|
|
4693
|
+
description: "Inspect the red-team-breaker Subagent card"
|
|
4625
4694
|
}
|
|
4626
4695
|
]
|
|
4627
4696
|
},
|
|
4628
4697
|
{
|
|
4629
4698
|
name: "add",
|
|
4630
|
-
aliases: ["install"
|
|
4699
|
+
aliases: ["install"],
|
|
4631
4700
|
pillar: "library",
|
|
4632
|
-
summary: "Install
|
|
4701
|
+
summary: "Install Skills/Subagents into AI harnesses",
|
|
4633
4702
|
usage: "npx skillops-cli add <name...> [options]",
|
|
4634
4703
|
options: [
|
|
4635
4704
|
{
|
|
4636
|
-
flags: "
|
|
4705
|
+
flags: "-p, --project <dir>",
|
|
4637
4706
|
description: "Target repository directory"
|
|
4638
4707
|
},
|
|
4639
4708
|
{
|
|
4640
|
-
flags: "
|
|
4641
|
-
description: "Target AI
|
|
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
|
|
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
|
|
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
|
|
4728
|
+
description: "Install security-sast-gate into harnesses"
|
|
4660
4729
|
},
|
|
4661
4730
|
{
|
|
4662
|
-
command: "npx skillops-cli add mcp-architect
|
|
4663
|
-
description: "Install
|
|
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: "
|
|
4740
|
+
summary: "Remove a Skill/Subagent from harnesses",
|
|
4672
4741
|
usage: "npx skillops-cli remove <name...> [options]",
|
|
4673
4742
|
options: [
|
|
4674
4743
|
{
|
|
4675
|
-
flags: "
|
|
4744
|
+
flags: "-p, --project <dir>",
|
|
4676
4745
|
description: "Target repository directory"
|
|
4677
4746
|
},
|
|
4678
4747
|
{
|
|
4679
|
-
flags: "
|
|
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
|
|
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
|
|
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: "
|
|
4767
|
+
summary: "Recommend optimal <=12 Skill bundle",
|
|
4699
4768
|
usage: "npx skillops-cli recommend [options]",
|
|
4700
4769
|
options: [
|
|
4701
4770
|
{
|
|
4702
|
-
flags: "
|
|
4771
|
+
flags: "-p, --project <dir>",
|
|
4703
4772
|
description: "Repository directory to fingerprint"
|
|
4704
4773
|
},
|
|
4705
4774
|
{
|
|
4706
4775
|
flags: "--task <prompt>",
|
|
4707
|
-
description: "
|
|
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
|
|
4784
|
+
description: "Maximum L1 routing token budget (default: 1500)"
|
|
4716
4785
|
},
|
|
4717
4786
|
{
|
|
4718
|
-
flags: "--format
|
|
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
|
|
4794
|
+
description: "Recommend best Skills for current repo stack"
|
|
4726
4795
|
},
|
|
4727
4796
|
{
|
|
4728
|
-
command: 'npx skillops-cli route --task "
|
|
4729
|
-
description: "Route top 4 Skills
|
|
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
|
|
4738
|
-
usage: "npx skillops-cli create <skill|subagent> <
|
|
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
|
|
4742
|
-
description: "Custom trigger description (
|
|
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
|
|
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
|
|
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
|
|
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: "
|
|
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
|
|
4850
|
+
description: "Enforce evals/evals.json and L3 scripts"
|
|
4782
4851
|
},
|
|
4783
4852
|
{
|
|
4784
4853
|
flags: "--strict",
|
|
4785
|
-
description: "Fail
|
|
4854
|
+
description: "Fail on HIGH_RISK as well as BLOCKING collisions"
|
|
4786
4855
|
},
|
|
4787
4856
|
{
|
|
4788
|
-
flags: "--format
|
|
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
|
|
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: "
|
|
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
|
|
4885
|
+
description: "Write benchmark report (HTML/Markdown) to disk"
|
|
4817
4886
|
},
|
|
4818
4887
|
{
|
|
4819
4888
|
flags: "--strict",
|
|
4820
|
-
description: "Exit
|
|
4889
|
+
description: "Exit 4 if any Skill fails CERTIFIED_IMPROVEMENT"
|
|
4821
4890
|
},
|
|
4822
4891
|
{
|
|
4823
|
-
flags: "--format
|
|
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
|
|
4899
|
+
description: "Run deterministic A/B evals across catalog"
|
|
4831
4900
|
},
|
|
4832
4901
|
{
|
|
4833
|
-
command: "npx skillops-cli eval
|
|
4834
|
-
description: "Export
|
|
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: "
|
|
4911
|
+
summary: "Create .skillops.yml and detect harnesses",
|
|
4843
4912
|
usage: "npx skillops-cli init [options]",
|
|
4844
4913
|
options: [
|
|
4845
4914
|
{
|
|
4846
|
-
flags: "
|
|
4915
|
+
flags: "-p, --project <dir>",
|
|
4847
4916
|
description: "Target repository directory"
|
|
4848
4917
|
},
|
|
4849
4918
|
{
|
|
4850
|
-
flags: "
|
|
4851
|
-
description: "Initial target harnesses
|
|
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
|
|
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
|
|
4934
|
+
summary: "Transpile bundle across 20 AI agents",
|
|
4866
4935
|
usage: "npx skillops-cli sync [options]",
|
|
4867
4936
|
options: [
|
|
4868
4937
|
{
|
|
4869
|
-
flags: "
|
|
4938
|
+
flags: "-p, --project <dir>",
|
|
4870
4939
|
description: "Target repository directory"
|
|
4871
4940
|
},
|
|
4872
4941
|
{
|
|
4873
|
-
flags: "
|
|
4874
|
-
description: "Target AI
|
|
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
|
|
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
|
|
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
|
|
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
|
|
4973
|
+
summary: "Remove all tracked runtime artifacts",
|
|
4905
4974
|
usage: "npx skillops-cli clean [options]",
|
|
4906
4975
|
options: [
|
|
4907
4976
|
{
|
|
4908
|
-
flags: "
|
|
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: "
|
|
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
|
|
5000
|
+
summary: "Analyze Startup Token Tax & context bloat",
|
|
4932
5001
|
usage: "npx skillops-cli budget [options]",
|
|
4933
5002
|
options: [
|
|
4934
5003
|
{
|
|
4935
|
-
flags: "
|
|
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: "
|
|
5013
|
+
description: "Exit 3 if Startup Token Tax exceeds budget"
|
|
4945
5014
|
},
|
|
4946
5015
|
{
|
|
4947
|
-
flags: "--format
|
|
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
|
|
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
|
|
5031
|
+
summary: "Diagnose environment, drift & token budget",
|
|
4963
5032
|
usage: "npx skillops-cli doctor [options]",
|
|
4964
5033
|
options: [
|
|
4965
5034
|
{
|
|
4966
|
-
flags: "
|
|
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
|
|
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
|
|
5058
|
+
summary: "List 20 supported AI agents & repo status",
|
|
4990
5059
|
usage: "npx skillops-cli harnesses [options]",
|
|
4991
5060
|
options: [
|
|
4992
5061
|
{
|
|
4993
|
-
flags: "
|
|
5062
|
+
flags: "-p, --project <dir>",
|
|
4994
5063
|
description: "Repository directory to scan for AI harnesses"
|
|
4995
5064
|
},
|
|
4996
5065
|
{
|
|
4997
|
-
flags: "--format
|
|
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
|
|
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: "
|
|
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: "
|
|
5085
|
+
flags: "-p, --project <dir>",
|
|
5017
5086
|
description: "Target repository directory"
|
|
5018
5087
|
},
|
|
5019
5088
|
{
|
|
5020
|
-
flags: "
|
|
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: "
|
|
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
|
|
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: "
|
|
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
|
|
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
|
-
"
|
|
5134
|
+
"Skills & Agents Library for AI Coding IDEs",
|
|
5065
5135
|
{
|
|
5066
5136
|
version,
|
|
5067
5137
|
colorEnabled: c
|
|
5068
5138
|
}
|
|
5069
5139
|
);
|
|
5070
|
-
const
|
|
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
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
|
|
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
|
|
5084
|
-
|
|
5085
|
-
|
|
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
|
-
|
|
5123
|
-
renderSectionHeader(
|
|
5124
|
-
|
|
5125
|
-
|
|
5126
|
-
),
|
|
5127
|
-
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
),
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
|
|
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
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
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:
|
|
5197
|
+
{ colorEnabled: c, indent: 3 }
|
|
5170
5198
|
)
|
|
5171
5199
|
].join("\n") : "";
|
|
5172
5200
|
const examplesSection = renderNextSteps(spec.examples, c);
|
|
5173
|
-
return [
|
|
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
|
-
`${
|
|
5278
|
-
|
|
5279
|
-
`${
|
|
5280
|
-
|
|
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)
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5289
|
-
|
|
5290
|
-
|
|
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)
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
|
|
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("
|
|
5305
|
-
...info.headings.slice(0,
|
|
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
|
|
5311
|
-
|
|
5312
|
-
info.kind === "skill" ?
|
|
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:
|
|
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:
|
|
5540
|
+
description: "Run TDD benchmark"
|
|
5330
5541
|
}
|
|
5331
5542
|
] : [],
|
|
5332
5543
|
{
|
|
5333
5544
|
command: "npx skillops-cli list",
|
|
5334
|
-
description: "Browse
|
|
5545
|
+
description: "Browse 10 Skills & 9 Subagents"
|
|
5335
5546
|
}
|
|
5336
5547
|
],
|
|
5337
5548
|
c
|
|
5338
5549
|
);
|
|
5339
|
-
return `${
|
|
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 >
|
|
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 >
|
|
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
|
|
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
|
|
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", "
|
|
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:
|
|
5658
|
+
description: "Inspect triggers & usage"
|
|
5452
5659
|
},
|
|
5453
5660
|
{
|
|
5454
5661
|
command: `npx skillops-cli add ${topItem}`,
|
|
5455
|
-
description:
|
|
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
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
5684
|
-
|
|
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
|
|
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
|
|
5901
|
+
description: "Verify INV-SKILL-01..04 & collisions"
|
|
5702
5902
|
},
|
|
5703
5903
|
{
|
|
5704
5904
|
command: `npx skillops-cli add ${result.name}`,
|
|
5705
|
-
description: `
|
|
5905
|
+
description: `Install '${result.name}' into AI agents`
|
|
5706
5906
|
}
|
|
5707
5907
|
],
|
|
5708
5908
|
c
|
|
5709
5909
|
);
|
|
5710
|
-
return `${
|
|
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
|
|
5810
|
-
const
|
|
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
|
-
`
|
|
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 &
|
|
5820
|
-
|
|
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
|
|
5828
|
-
`${style.green(`${report.selected_skills.length} Skills`, c)} + ${style.magenta(`${report.selected_subagents.length} Subagents`, c)}
|
|
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
|
|
5836
|
-
`${report.synced_files_count} files
|
|
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
|
|
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 =
|
|
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
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
""
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
{
|
|
5866
|
-
|
|
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
|
|
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
|
|
6082
|
+
description: "Browse all 10 Skills & 9 Subagents"
|
|
5887
6083
|
},
|
|
5888
6084
|
{
|
|
5889
|
-
command: "npx skillops-cli create skill my-
|
|
5890
|
-
description: "Create
|
|
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
|
|
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,
|