skillops-cli 1.3.3 → 1.3.5
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 +1 -1
- package/dist/cli.js +357 -43
- package/dist/index.d.ts +54 -44
- package/dist/index.js +268 -30
- package/package.json +10 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# SkillOps (`npx skillops-cli@latest`)
|
|
2
2
|
|
|
3
|
-
> **The Zero-API Framework & Benchmark-Verified Library for High-End AI Coding Skills & Context-Isolated Subagents (`v1.3.
|
|
3
|
+
> **The Zero-API Framework & Benchmark-Verified Library for High-End AI Coding Skills & Context-Isolated Subagents (`v1.3.4`)**
|
|
4
4
|
> *Explore, search, inspect, and install benchmark-verified AI Coding Skills and Context-Isolated Subagents in 10 seconds (`npx skillops-cli@latest quickstart`), scaffold and certify your own custom Skills & Subagents (`npx skillops-cli@latest create skill <name>`), enforce Startup Token Tax budgets (`npx skillops-cli@latest budget`), and transpile natively across the Top 20 AI coding agents & IDEs — 100% offline with zero API keys.*
|
|
5
5
|
|
|
6
6
|
[](./AGENTS.md)
|
package/dist/cli.js
CHANGED
|
@@ -10,7 +10,7 @@ import YAML6 from "yaml";
|
|
|
10
10
|
import fs from "fs";
|
|
11
11
|
import YAML from "yaml";
|
|
12
12
|
import { z } from "zod";
|
|
13
|
-
var SKILLOPS_VERSION = "1.3.
|
|
13
|
+
var SKILLOPS_VERSION = "1.3.5";
|
|
14
14
|
var SKILL_NAME_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
15
15
|
var SEMVER_REGEX = /^\d+\.\d+\.\d+$/;
|
|
16
16
|
var FRONTMATTER_REGEX = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
|
|
@@ -87,7 +87,15 @@ var RuntimeTargetSchema = z.enum([
|
|
|
87
87
|
"kiro",
|
|
88
88
|
"trae",
|
|
89
89
|
"amazonq",
|
|
90
|
-
"junie"
|
|
90
|
+
"junie",
|
|
91
|
+
"gemini",
|
|
92
|
+
"factory",
|
|
93
|
+
"qwen",
|
|
94
|
+
"augment",
|
|
95
|
+
"vibe",
|
|
96
|
+
"warp",
|
|
97
|
+
"crush",
|
|
98
|
+
"idx"
|
|
91
99
|
]);
|
|
92
100
|
var CORE_RUNTIME_TARGETS = [
|
|
93
101
|
"claude",
|
|
@@ -116,7 +124,15 @@ var ALL_RUNTIME_TARGETS = [
|
|
|
116
124
|
"kiro",
|
|
117
125
|
"trae",
|
|
118
126
|
"amazonq",
|
|
119
|
-
"junie"
|
|
127
|
+
"junie",
|
|
128
|
+
"gemini",
|
|
129
|
+
"factory",
|
|
130
|
+
"qwen",
|
|
131
|
+
"augment",
|
|
132
|
+
"vibe",
|
|
133
|
+
"warp",
|
|
134
|
+
"crush",
|
|
135
|
+
"idx"
|
|
120
136
|
];
|
|
121
137
|
var RUNTIME_HARNESS_SPECS = {
|
|
122
138
|
claude: {
|
|
@@ -134,15 +150,15 @@ var RUNTIME_HARNESS_SPECS = {
|
|
|
134
150
|
},
|
|
135
151
|
antigravity: {
|
|
136
152
|
id: "antigravity",
|
|
137
|
-
displayName: "Google Antigravity
|
|
153
|
+
displayName: "Google Antigravity IDE",
|
|
138
154
|
vendor: "Google DeepMind",
|
|
139
155
|
category: "ai-ide",
|
|
140
156
|
skillFormat: "progressive-skill-dir",
|
|
141
157
|
skillsDir: ".agent/skills",
|
|
142
158
|
subagentsDir: ".agent/agents",
|
|
143
|
-
detectionPaths: [".agent", "
|
|
144
|
-
alwaysOnFiles: ["GEMINI.md"
|
|
145
|
-
mcpConfigPath: ".
|
|
159
|
+
detectionPaths: [".agent", "GEMINI.md"],
|
|
160
|
+
alwaysOnFiles: ["GEMINI.md"],
|
|
161
|
+
mcpConfigPath: ".agent/mcp_config.json",
|
|
146
162
|
supportsMcp: true
|
|
147
163
|
},
|
|
148
164
|
cursor: {
|
|
@@ -387,6 +403,110 @@ var RUNTIME_HARNESS_SPECS = {
|
|
|
387
403
|
alwaysOnFiles: [".junie/guidelines.md"],
|
|
388
404
|
mcpConfigPath: null,
|
|
389
405
|
supportsMcp: false
|
|
406
|
+
},
|
|
407
|
+
gemini: {
|
|
408
|
+
id: "gemini",
|
|
409
|
+
displayName: "Google Gemini CLI",
|
|
410
|
+
vendor: "Google",
|
|
411
|
+
category: "cli-agent",
|
|
412
|
+
skillFormat: "progressive-skill-dir",
|
|
413
|
+
skillsDir: ".gemini/skills",
|
|
414
|
+
subagentsDir: ".gemini/agents",
|
|
415
|
+
detectionPaths: [".gemini", "GEMINI.md"],
|
|
416
|
+
alwaysOnFiles: ["GEMINI.md", ".gemini/GEMINI.md", ".gemini/STYLEGUIDE.md"],
|
|
417
|
+
mcpConfigPath: ".gemini/settings.json",
|
|
418
|
+
supportsMcp: true
|
|
419
|
+
},
|
|
420
|
+
factory: {
|
|
421
|
+
id: "factory",
|
|
422
|
+
displayName: "Factory AI Droid",
|
|
423
|
+
vendor: "Factory AI",
|
|
424
|
+
category: "cli-agent",
|
|
425
|
+
skillFormat: "progressive-skill-dir",
|
|
426
|
+
skillsDir: ".factory/skills",
|
|
427
|
+
subagentsDir: ".factory/droids",
|
|
428
|
+
detectionPaths: [".factory"],
|
|
429
|
+
alwaysOnFiles: ["AGENTS.md", ".factory/instructions.md"],
|
|
430
|
+
mcpConfigPath: ".factory/mcp.json",
|
|
431
|
+
supportsMcp: true
|
|
432
|
+
},
|
|
433
|
+
qwen: {
|
|
434
|
+
id: "qwen",
|
|
435
|
+
displayName: "Qwen Code CLI",
|
|
436
|
+
vendor: "Alibaba Cloud / Qwen",
|
|
437
|
+
category: "cli-agent",
|
|
438
|
+
skillFormat: "progressive-skill-dir",
|
|
439
|
+
skillsDir: ".qwen/skills",
|
|
440
|
+
subagentsDir: ".qwen/agents",
|
|
441
|
+
detectionPaths: [".qwen", "QWEN.md"],
|
|
442
|
+
alwaysOnFiles: ["QWEN.md", "AGENTS.md"],
|
|
443
|
+
mcpConfigPath: ".qwen/settings.json",
|
|
444
|
+
supportsMcp: true
|
|
445
|
+
},
|
|
446
|
+
augment: {
|
|
447
|
+
id: "augment",
|
|
448
|
+
displayName: "Augment Code",
|
|
449
|
+
vendor: "Augment",
|
|
450
|
+
category: "ide-extension",
|
|
451
|
+
skillFormat: "markdown-rule",
|
|
452
|
+
skillsDir: ".augment/rules",
|
|
453
|
+
subagentsDir: ".augment/agents",
|
|
454
|
+
detectionPaths: [".augment", ".augment-guidelines"],
|
|
455
|
+
alwaysOnFiles: [".augment-guidelines", "AGENTS.md"],
|
|
456
|
+
mcpConfigPath: ".augment/settings.json",
|
|
457
|
+
supportsMcp: true
|
|
458
|
+
},
|
|
459
|
+
vibe: {
|
|
460
|
+
id: "vibe",
|
|
461
|
+
displayName: "Mistral Vibe CLI",
|
|
462
|
+
vendor: "Mistral AI",
|
|
463
|
+
category: "cli-agent",
|
|
464
|
+
skillFormat: "progressive-skill-dir",
|
|
465
|
+
skillsDir: ".vibe/skills",
|
|
466
|
+
subagentsDir: ".vibe/agents",
|
|
467
|
+
detectionPaths: [".vibe"],
|
|
468
|
+
alwaysOnFiles: [".vibe/config.toml", "AGENTS.md"],
|
|
469
|
+
mcpConfigPath: ".vibe/config.toml",
|
|
470
|
+
supportsMcp: true
|
|
471
|
+
},
|
|
472
|
+
warp: {
|
|
473
|
+
id: "warp",
|
|
474
|
+
displayName: "Warp AI Terminal",
|
|
475
|
+
vendor: "Warp",
|
|
476
|
+
category: "cli-agent",
|
|
477
|
+
skillFormat: "progressive-skill-dir",
|
|
478
|
+
skillsDir: ".warp/skills",
|
|
479
|
+
subagentsDir: ".warp/agents",
|
|
480
|
+
detectionPaths: [".warp", "WARP.md"],
|
|
481
|
+
alwaysOnFiles: ["WARP.md", "AGENTS.md"],
|
|
482
|
+
mcpConfigPath: null,
|
|
483
|
+
supportsMcp: false
|
|
484
|
+
},
|
|
485
|
+
crush: {
|
|
486
|
+
id: "crush",
|
|
487
|
+
displayName: "Charmbracelet Crush",
|
|
488
|
+
vendor: "Charmbracelet",
|
|
489
|
+
category: "cli-agent",
|
|
490
|
+
skillFormat: "progressive-skill-dir",
|
|
491
|
+
skillsDir: ".crush/skills",
|
|
492
|
+
subagentsDir: ".crush/agents",
|
|
493
|
+
detectionPaths: [".crush", ".crush.json", "CRUSH.md"],
|
|
494
|
+
alwaysOnFiles: ["CRUSH.md", "AGENTS.md"],
|
|
495
|
+
mcpConfigPath: ".crush.json",
|
|
496
|
+
supportsMcp: true
|
|
497
|
+
},
|
|
498
|
+
idx: {
|
|
499
|
+
id: "idx",
|
|
500
|
+
displayName: "Firebase Studio (Project IDX)",
|
|
501
|
+
vendor: "Google",
|
|
502
|
+
category: "ai-ide",
|
|
503
|
+
skillFormat: "markdown-rule",
|
|
504
|
+
skillsDir: ".idx/rules",
|
|
505
|
+
subagentsDir: ".idx/agents",
|
|
506
|
+
detectionPaths: [".idx"],
|
|
507
|
+
alwaysOnFiles: [".idx/airules.md", "GEMINI.md"],
|
|
508
|
+
mcpConfigPath: ".idx/mcp.json",
|
|
509
|
+
supportsMcp: true
|
|
390
510
|
}
|
|
391
511
|
};
|
|
392
512
|
function detectInstalledHarnesses(repoPath) {
|
|
@@ -418,7 +538,7 @@ function resolveRuntimeTargets(rawSpec, repoPath, fallbackTargets = CORE_RUNTIME
|
|
|
418
538
|
}
|
|
419
539
|
};
|
|
420
540
|
for (const token of tokens) {
|
|
421
|
-
if (token === "all" || token === "*" || token === "top20") {
|
|
541
|
+
if (token === "all" || token === "*" || token === "top20" || token === "top28") {
|
|
422
542
|
for (const t of ALL_RUNTIME_TARGETS) {
|
|
423
543
|
pushUnique(t);
|
|
424
544
|
}
|
|
@@ -1613,6 +1733,10 @@ var ALWAYS_ON_INSTRUCTION_CANDIDATES = [
|
|
|
1613
1733
|
"AGENTS.md",
|
|
1614
1734
|
"GEMINI.md",
|
|
1615
1735
|
".gemini/GEMINI.md",
|
|
1736
|
+
".gemini/STYLEGUIDE.md",
|
|
1737
|
+
"QWEN.md",
|
|
1738
|
+
"WARP.md",
|
|
1739
|
+
"CRUSH.md",
|
|
1616
1740
|
"AGENT.md",
|
|
1617
1741
|
"CONVENTIONS.md",
|
|
1618
1742
|
".github/copilot-instructions.md",
|
|
@@ -1622,17 +1746,22 @@ var ALWAYS_ON_INSTRUCTION_CANDIDATES = [
|
|
|
1622
1746
|
".roorules",
|
|
1623
1747
|
".kilocoderules",
|
|
1624
1748
|
".continuerules",
|
|
1749
|
+
".augment-guidelines",
|
|
1625
1750
|
".rules",
|
|
1626
1751
|
".goosehints",
|
|
1627
1752
|
".junie/guidelines.md",
|
|
1628
1753
|
".openhands/microagents/repo.md",
|
|
1629
1754
|
".trae/rules/project_rules.md",
|
|
1755
|
+
".factory/instructions.md",
|
|
1756
|
+
".idx/airules.md",
|
|
1757
|
+
".vibe/config.toml",
|
|
1630
1758
|
".kiro/steering/product.md",
|
|
1631
1759
|
".kiro/steering/tech.md",
|
|
1632
1760
|
".kiro/steering/structure.md"
|
|
1633
1761
|
];
|
|
1634
1762
|
var MCP_CONFIG_CANDIDATES = [
|
|
1635
1763
|
".mcp.json",
|
|
1764
|
+
".agent/mcp_config.json",
|
|
1636
1765
|
".cursor/mcp.json",
|
|
1637
1766
|
".vscode/mcp.json",
|
|
1638
1767
|
".gemini/settings.json",
|
|
@@ -1644,7 +1773,13 @@ var MCP_CONFIG_CANDIDATES = [
|
|
|
1644
1773
|
".amp/settings.json",
|
|
1645
1774
|
"opencode.json",
|
|
1646
1775
|
".kiro/settings/mcp.json",
|
|
1647
|
-
".amazonq/mcp.json"
|
|
1776
|
+
".amazonq/mcp.json",
|
|
1777
|
+
".factory/mcp.json",
|
|
1778
|
+
".qwen/settings.json",
|
|
1779
|
+
".augment/settings.json",
|
|
1780
|
+
".vibe/config.toml",
|
|
1781
|
+
".crush.json",
|
|
1782
|
+
".idx/mcp.json"
|
|
1648
1783
|
];
|
|
1649
1784
|
function countMcpServersInConfig(rawText, relPath) {
|
|
1650
1785
|
if (relPath.endsWith(".toml")) {
|
|
@@ -2074,9 +2209,9 @@ function diagnoseRepository(repoPath, options = {}) {
|
|
|
2074
2209
|
const detectedHarnesses = detectInstalledHarnesses(resolvedRepo);
|
|
2075
2210
|
checks.push({
|
|
2076
2211
|
id: "detected_harnesses",
|
|
2077
|
-
title: "Detected AI Coding Harnesses (Top
|
|
2212
|
+
title: "Detected AI Coding Harnesses (Top 28)",
|
|
2078
2213
|
status: "pass",
|
|
2079
|
-
summary: detectedHarnesses.length > 0 ? `Detected ${detectedHarnesses.length} AI coding harness(es): ${detectedHarnesses.join(", ")}.` : "No repo-local AI harness folders detected yet (ready to sync all
|
|
2214
|
+
summary: detectedHarnesses.length > 0 ? `Detected ${detectedHarnesses.length} AI coding harness(es): ${detectedHarnesses.join(", ")}.` : "No repo-local AI harness folders detected yet (ready to sync all 28 agents)."
|
|
2080
2215
|
});
|
|
2081
2216
|
const loadedCfg = loadSkillOpsConfig(resolvedRepo);
|
|
2082
2217
|
const configPresent = loadedCfg.exists;
|
|
@@ -2259,7 +2394,7 @@ function formatHarnessInspectionReport(report, format = "table") {
|
|
|
2259
2394
|
}
|
|
2260
2395
|
if (format === "markdown") {
|
|
2261
2396
|
const lines2 = [
|
|
2262
|
-
`## SkillOps Universal Top-
|
|
2397
|
+
`## SkillOps Universal Top-28 AI Coding Agent Harnesses (\`${report.repo_path}\`)`,
|
|
2263
2398
|
"",
|
|
2264
2399
|
`- **Supported AI Coding Harnesses:** \`${report.total_supported}\``,
|
|
2265
2400
|
`- **Detected in Repository:** \`${report.detected_count}\` (${report.detected_harnesses.length > 0 ? report.detected_harnesses.join(", ") : "none"})`,
|
|
@@ -2274,7 +2409,7 @@ function formatHarnessInspectionReport(report, format = "table") {
|
|
|
2274
2409
|
return lines2.join("\n");
|
|
2275
2410
|
}
|
|
2276
2411
|
const lines = [
|
|
2277
|
-
`=== SkillOps Universal Top-
|
|
2412
|
+
`=== SkillOps Universal Top-28 AI Coding Harnesses (${report.repo_path}) ===`,
|
|
2278
2413
|
`Supported Harnesses : ${report.total_supported}`,
|
|
2279
2414
|
`Detected in Repo : ${report.detected_count} (${report.detected_harnesses.length > 0 ? report.detected_harnesses.join(", ") : "none"})`,
|
|
2280
2415
|
"-".repeat(92),
|
|
@@ -3345,7 +3480,7 @@ var MCP_TOOLS = [
|
|
|
3345
3480
|
},
|
|
3346
3481
|
{
|
|
3347
3482
|
name: "list_supported_harnesses",
|
|
3348
|
-
description: "Inspect all
|
|
3483
|
+
description: "Inspect all 28 supported AI coding agents, IDEs, and CLI harnesses (target paths, MCP support, and repository auto-detection).",
|
|
3349
3484
|
inputSchema: {
|
|
3350
3485
|
type: "object",
|
|
3351
3486
|
properties: {
|
|
@@ -3517,7 +3652,7 @@ function startMcpStdioServer(context) {
|
|
|
3517
3652
|
}
|
|
3518
3653
|
function buildUpdatedMcpConfigContent(target, existingRaw, serverName) {
|
|
3519
3654
|
const mcpArgs = ["-y", "skillops-cli@latest", "mcp"];
|
|
3520
|
-
if (target === "codex") {
|
|
3655
|
+
if (target === "codex" || target === "vibe") {
|
|
3521
3656
|
const tomlBlock = [
|
|
3522
3657
|
`[mcp_servers.${serverName}]`,
|
|
3523
3658
|
'command = "npx"',
|
|
@@ -3610,6 +3745,20 @@ ${tomlBlock}
|
|
|
3610
3745
|
};
|
|
3611
3746
|
parsedObj.mcp = mcpMap;
|
|
3612
3747
|
return `${JSON.stringify(parsedObj, null, 2)}
|
|
3748
|
+
`;
|
|
3749
|
+
}
|
|
3750
|
+
if (target === "crush") {
|
|
3751
|
+
if (!("$schema" in parsedObj)) {
|
|
3752
|
+
parsedObj.$schema = "https://charm.land/crush.json";
|
|
3753
|
+
}
|
|
3754
|
+
const mcpMap = parsedObj.mcp && typeof parsedObj.mcp === "object" && !Array.isArray(parsedObj.mcp) ? { ...parsedObj.mcp } : {};
|
|
3755
|
+
mcpMap[serverName] = {
|
|
3756
|
+
type: "stdio",
|
|
3757
|
+
command: "npx",
|
|
3758
|
+
args: mcpArgs
|
|
3759
|
+
};
|
|
3760
|
+
parsedObj.mcp = mcpMap;
|
|
3761
|
+
return `${JSON.stringify(parsedObj, null, 2)}
|
|
3613
3762
|
`;
|
|
3614
3763
|
}
|
|
3615
3764
|
const mcpServers = parsedObj.mcpServers && typeof parsedObj.mcpServers === "object" && !Array.isArray(parsedObj.mcpServers) ? { ...parsedObj.mcpServers } : {};
|
|
@@ -3860,6 +4009,24 @@ ${body}
|
|
|
3860
4009
|
${kiroFrontmatter}
|
|
3861
4010
|
---
|
|
3862
4011
|
|
|
4012
|
+
${body}
|
|
4013
|
+
`
|
|
4014
|
+
});
|
|
4015
|
+
return files;
|
|
4016
|
+
}
|
|
4017
|
+
if (target === "augment") {
|
|
4018
|
+
const augFrontmatter = YAML4.stringify({
|
|
4019
|
+
type: "agent_requested",
|
|
4020
|
+
description: parsed.manifest.description
|
|
4021
|
+
}).trim();
|
|
4022
|
+
files.push({
|
|
4023
|
+
target,
|
|
4024
|
+
itemName: name,
|
|
4025
|
+
relativePath: `.augment/rules/skillops-${name}.md`,
|
|
4026
|
+
content: `---
|
|
4027
|
+
${augFrontmatter}
|
|
4028
|
+
---
|
|
4029
|
+
|
|
3863
4030
|
${body}
|
|
3864
4031
|
`
|
|
3865
4032
|
});
|
|
@@ -3893,6 +4060,7 @@ function renderSubagentFilesForRuntime(subagent, target) {
|
|
|
3893
4060
|
const fm = YAML4.stringify({
|
|
3894
4061
|
name: subagent.manifest.name,
|
|
3895
4062
|
description: subagent.manifest.description,
|
|
4063
|
+
model: "inherit",
|
|
3896
4064
|
model_tier: subagent.manifest.model_tier,
|
|
3897
4065
|
tools: subagent.manifest.tools,
|
|
3898
4066
|
max_output_tokens: subagent.manifest.max_output_tokens
|
|
@@ -3903,7 +4071,7 @@ ${fm}
|
|
|
3903
4071
|
|
|
3904
4072
|
${promptBody}
|
|
3905
4073
|
`;
|
|
3906
|
-
if (target === "claude" || target === "antigravity" || target === "codex" || target === "amp" || target === "goose" || target === "opencode") {
|
|
4074
|
+
if (target === "claude" || target === "antigravity" || target === "gemini" || target === "codex" || target === "amp" || target === "goose" || target === "opencode" || target === "qwen" || target === "warp" || target === "crush") {
|
|
3907
4075
|
return [
|
|
3908
4076
|
{
|
|
3909
4077
|
target,
|
|
@@ -3913,6 +4081,44 @@ ${promptBody}
|
|
|
3913
4081
|
}
|
|
3914
4082
|
];
|
|
3915
4083
|
}
|
|
4084
|
+
if (target === "factory") {
|
|
4085
|
+
const droidFm = YAML4.stringify({
|
|
4086
|
+
name,
|
|
4087
|
+
description: subagent.manifest.description,
|
|
4088
|
+
model: "inherit"
|
|
4089
|
+
}).trim();
|
|
4090
|
+
return [
|
|
4091
|
+
{
|
|
4092
|
+
target,
|
|
4093
|
+
itemName: name,
|
|
4094
|
+
relativePath: `.factory/droids/skillops-agent-${name}.md`,
|
|
4095
|
+
content: `---
|
|
4096
|
+
${droidFm}
|
|
4097
|
+
---
|
|
4098
|
+
|
|
4099
|
+
${promptBody}
|
|
4100
|
+
`
|
|
4101
|
+
}
|
|
4102
|
+
];
|
|
4103
|
+
}
|
|
4104
|
+
if (target === "vibe") {
|
|
4105
|
+
const escapedDesc = JSON.stringify(subagent.manifest.description);
|
|
4106
|
+
const escapedPrompt = JSON.stringify(promptBody);
|
|
4107
|
+
const tomlDoc = [
|
|
4108
|
+
`name = "${name}"`,
|
|
4109
|
+
`description = ${escapedDesc}`,
|
|
4110
|
+
`system_prompt = ${escapedPrompt}`,
|
|
4111
|
+
""
|
|
4112
|
+
].join("\n");
|
|
4113
|
+
return [
|
|
4114
|
+
{
|
|
4115
|
+
target,
|
|
4116
|
+
itemName: name,
|
|
4117
|
+
relativePath: `.vibe/agents/skillops-agent-${name}.toml`,
|
|
4118
|
+
content: tomlDoc
|
|
4119
|
+
}
|
|
4120
|
+
];
|
|
4121
|
+
}
|
|
3916
4122
|
if (target === "copilot") {
|
|
3917
4123
|
return [
|
|
3918
4124
|
{
|
|
@@ -4913,7 +5119,7 @@ var COMMAND_HELP_SPECS = [
|
|
|
4913
5119
|
name: "sync",
|
|
4914
5120
|
aliases: [],
|
|
4915
5121
|
pillar: "runtime",
|
|
4916
|
-
summary: "Transpile bundle across
|
|
5122
|
+
summary: "Transpile bundle across 28 AI agents",
|
|
4917
5123
|
usage: "npx skillops-cli sync [options]",
|
|
4918
5124
|
options: [
|
|
4919
5125
|
{
|
|
@@ -4944,7 +5150,7 @@ var COMMAND_HELP_SPECS = [
|
|
|
4944
5150
|
},
|
|
4945
5151
|
{
|
|
4946
5152
|
command: "npx skillops-cli sync --harness all",
|
|
4947
|
-
description: "Transpile across all
|
|
5153
|
+
description: "Transpile across all 28 supported AI agents"
|
|
4948
5154
|
}
|
|
4949
5155
|
]
|
|
4950
5156
|
},
|
|
@@ -5037,7 +5243,7 @@ var COMMAND_HELP_SPECS = [
|
|
|
5037
5243
|
name: "harnesses",
|
|
5038
5244
|
aliases: [],
|
|
5039
5245
|
pillar: "runtime",
|
|
5040
|
-
summary: "List
|
|
5246
|
+
summary: "List 28 supported AI agents & repo status",
|
|
5041
5247
|
usage: "npx skillops-cli harnesses [options]",
|
|
5042
5248
|
options: [
|
|
5043
5249
|
{
|
|
@@ -5052,7 +5258,7 @@ var COMMAND_HELP_SPECS = [
|
|
|
5052
5258
|
examples: [
|
|
5053
5259
|
{
|
|
5054
5260
|
command: "npx skillops-cli harnesses",
|
|
5055
|
-
description: "View all
|
|
5261
|
+
description: "View all 28 supported AI IDEs/CLI agents"
|
|
5056
5262
|
}
|
|
5057
5263
|
]
|
|
5058
5264
|
},
|
|
@@ -5060,7 +5266,7 @@ var COMMAND_HELP_SPECS = [
|
|
|
5060
5266
|
name: "mcp-setup",
|
|
5061
5267
|
aliases: [],
|
|
5062
5268
|
pillar: "runtime",
|
|
5063
|
-
summary: "Wire MCP server across
|
|
5269
|
+
summary: "Wire MCP server across 20 AI IDEs & agents",
|
|
5064
5270
|
usage: "npx skillops-cli mcp-setup [options]",
|
|
5065
5271
|
options: [
|
|
5066
5272
|
{
|
|
@@ -5189,6 +5395,9 @@ function renderCommandHelp(spec, version, colorEnabled) {
|
|
|
5189
5395
|
|
|
5190
5396
|
// src/ui/prompt.ts
|
|
5191
5397
|
function optionMatchesTab(opt, tab) {
|
|
5398
|
+
if (opt.tab) {
|
|
5399
|
+
return opt.tab === tab;
|
|
5400
|
+
}
|
|
5192
5401
|
if (opt.kind === "agent") {
|
|
5193
5402
|
return tab === "agent";
|
|
5194
5403
|
}
|
|
@@ -5224,7 +5433,7 @@ function createMultiSelectState(options) {
|
|
|
5224
5433
|
status: "active"
|
|
5225
5434
|
};
|
|
5226
5435
|
}
|
|
5227
|
-
function applyMultiSelectKey(state, key) {
|
|
5436
|
+
function applyMultiSelectKey(state, key, options = {}) {
|
|
5228
5437
|
if (state.status !== "active" || state.options.length === 0) {
|
|
5229
5438
|
return state;
|
|
5230
5439
|
}
|
|
@@ -5249,14 +5458,29 @@ function applyMultiSelectKey(state, key) {
|
|
|
5249
5458
|
};
|
|
5250
5459
|
}
|
|
5251
5460
|
if (key === "\r" || key === "\n") {
|
|
5461
|
+
let finalSelected = state.selected;
|
|
5462
|
+
if (options.selectCursorOnEmptySubmit && state.selected.size === 0) {
|
|
5463
|
+
const visibleOnSubmit = getFilteredTabOptions(state, state.activeTab);
|
|
5464
|
+
const currentOpt = visibleOnSubmit[state.cursor];
|
|
5465
|
+
if (currentOpt) {
|
|
5466
|
+
finalSelected = /* @__PURE__ */ new Set([currentOpt.value]);
|
|
5467
|
+
}
|
|
5468
|
+
}
|
|
5252
5469
|
return {
|
|
5253
5470
|
...state,
|
|
5471
|
+
selected: finalSelected,
|
|
5254
5472
|
searchMode: false,
|
|
5255
5473
|
status: "submitted"
|
|
5256
5474
|
};
|
|
5257
5475
|
}
|
|
5258
5476
|
if (key === "\x1B[D" || key === "\x1BOD" || key === "\x1B[C" || key === "\x1BOC" || key === " " || !state.searchMode && (key === "h" || key === "H" || key === "l" || key === "L")) {
|
|
5259
5477
|
const nextTab = state.activeTab === "skill" ? "agent" : "skill";
|
|
5478
|
+
const hasNextTabOptions = state.options.some(
|
|
5479
|
+
(opt) => optionMatchesTab(opt, nextTab)
|
|
5480
|
+
);
|
|
5481
|
+
if (!hasNextTabOptions) {
|
|
5482
|
+
return state;
|
|
5483
|
+
}
|
|
5260
5484
|
return {
|
|
5261
5485
|
...state,
|
|
5262
5486
|
activeTab: nextTab,
|
|
@@ -5390,8 +5614,13 @@ function renderMultiSelectFrame(title, state, options = {}) {
|
|
|
5390
5614
|
const filteredAgents = getFilteredTabOptions(state, "agent");
|
|
5391
5615
|
const visible = state.activeTab === "skill" ? filteredSkills : filteredAgents;
|
|
5392
5616
|
const total = visible.length;
|
|
5617
|
+
const skillTabTitle = options.tabLabels?.skill ?? "Skills";
|
|
5618
|
+
const agentTabTitle = options.tabLabels?.agent ?? "Agents";
|
|
5619
|
+
const submitVerb = options.submitActionLabel ?? "import";
|
|
5620
|
+
const isSinglePage = totalAgents === 0;
|
|
5393
5621
|
const header = `${style.bold(style.cyan(`\u25C6 ${title}`, c), c)}`;
|
|
5394
|
-
const
|
|
5622
|
+
const tabHint = isSinglePage ? "" : " \xB7 \u2190/\u2192 tab";
|
|
5623
|
+
const instructions = state.searchMode ? `${bar} ${style.dim(`\u2191/\u2193 move${tabHint} \xB7 Space select \xB7 Esc clear \xB7 Enter ${submitVerb}`, c)}` : `${bar} ${style.dim(`\u2191/\u2193 move${tabHint} \xB7 Space select \xB7 / search \xB7 a all \xB7 Enter ${submitVerb}`, c)}`;
|
|
5395
5624
|
const lines = [header];
|
|
5396
5625
|
if (options.subtitle) {
|
|
5397
5626
|
lines.push(`${bar} ${options.subtitle}`);
|
|
@@ -5400,16 +5629,22 @@ function renderMultiSelectFrame(title, state, options = {}) {
|
|
|
5400
5629
|
const hasQuery = state.searchQuery.length > 0;
|
|
5401
5630
|
const skillCountStr = hasQuery ? `${filteredSkills.length}/${totalSkills}` : `${totalSkills}`;
|
|
5402
5631
|
const agentCountStr = hasQuery ? `${filteredAgents.length}/${totalAgents}` : `${totalAgents}`;
|
|
5403
|
-
const skillTabLabel = state.activeTab === "skill" ? style.bold(
|
|
5404
|
-
|
|
5632
|
+
const skillTabLabel = state.activeTab === "skill" ? style.bold(
|
|
5633
|
+
style.cyan(`[ \u25C6 ${skillTabTitle} (${skillCountStr}) ]`, c),
|
|
5634
|
+
c
|
|
5635
|
+
) : style.dim(`\u25CB ${skillTabTitle} (${skillCountStr})`, c);
|
|
5636
|
+
const agentTabLabel = state.activeTab === "agent" ? style.bold(
|
|
5637
|
+
style.magenta(`[ \u25C6 ${agentTabTitle} (${agentCountStr}) ]`, c),
|
|
5638
|
+
c
|
|
5639
|
+
) : style.dim(`\u25CB ${agentTabTitle} (${agentCountStr})`, c);
|
|
5405
5640
|
const rawQuerySlice = state.searchQuery.length > 14 ? `\u2026${state.searchQuery.slice(-13)}` : state.searchQuery;
|
|
5406
5641
|
const searchSuffix = state.searchMode || hasQuery ? ` ${style.yellow(`/ Filter: ${rawQuerySlice}${state.searchMode ? "\u2588" : ""}`, c)}` : ` ${style.dim("(/ search)", c)}`;
|
|
5407
5642
|
lines.push(
|
|
5408
|
-
`${style.dim("\u251C\u2500", c)} ${skillTabLabel} ${agentTabLabel}${searchSuffix}`,
|
|
5643
|
+
isSinglePage ? `${style.dim("\u251C\u2500", c)} ${skillTabLabel}${searchSuffix}` : `${style.dim("\u251C\u2500", c)} ${skillTabLabel} ${agentTabLabel}${searchSuffix}`,
|
|
5409
5644
|
bar
|
|
5410
5645
|
);
|
|
5411
5646
|
if (total === 0) {
|
|
5412
|
-
const tabName = state.activeTab === "skill" ?
|
|
5647
|
+
const tabName = state.activeTab === "skill" ? skillTabTitle : agentTabTitle;
|
|
5413
5648
|
lines.push(
|
|
5414
5649
|
`${bar} ${style.dim(`No ${tabName} match "${state.searchQuery}". Press Esc to clear filter.`, c)}`
|
|
5415
5650
|
);
|
|
@@ -5457,12 +5692,13 @@ function renderMultiSelectFrame(title, state, options = {}) {
|
|
|
5457
5692
|
const selectedAgentsCount = state.options.filter(
|
|
5458
5693
|
(o) => optionMatchesTab(o, "agent") && state.selected.has(o.value)
|
|
5459
5694
|
).length;
|
|
5460
|
-
const
|
|
5695
|
+
const currentOptLabel = visible[state.cursor]?.label ?? "";
|
|
5696
|
+
const summaryText = options.tabLabels ? state.selected.size > 0 ? `${state.selected.size} selected` : options.selectCursorOnEmptySubmit && currentOptLabel ? `Target: ${currentOptLabel}` : "0 selected" : `${state.selected.size} selected (${selectedSkillsCount} ${skillTabTitle}, ${selectedAgentsCount} ${agentTabTitle})`;
|
|
5461
5697
|
const rawTarget = options.targetHint ?? "";
|
|
5462
5698
|
const shortTarget = rawTarget.length > 18 ? `${rawTarget.slice(0, 17)}\u2026` : rawTarget;
|
|
5463
5699
|
const targetSuffix = shortTarget ? ` \xB7 IDE: ${shortTarget}` : "";
|
|
5464
5700
|
lines.push(
|
|
5465
|
-
`${style.dim("\u2570\u2500", c)} ${style.bold(summaryText, c)}${style.dim(`${targetSuffix} \u2014 Enter to
|
|
5701
|
+
`${style.dim("\u2570\u2500", c)} ${style.bold(summaryText, c)}${style.dim(`${targetSuffix} \u2014 Enter to ${submitVerb}`, c)}`
|
|
5466
5702
|
);
|
|
5467
5703
|
return lines.join("\n");
|
|
5468
5704
|
}
|
|
@@ -5499,7 +5735,9 @@ async function runMultiSelectPrompt(title, options, renderOpts = {}) {
|
|
|
5499
5735
|
};
|
|
5500
5736
|
const onData = (chunk) => {
|
|
5501
5737
|
const key = typeof chunk === "string" ? chunk : chunk.toString("utf-8");
|
|
5502
|
-
state = applyMultiSelectKey(state, key
|
|
5738
|
+
state = applyMultiSelectKey(state, key, {
|
|
5739
|
+
selectCursorOnEmptySubmit: renderOpts.selectCursorOnEmptySubmit
|
|
5740
|
+
});
|
|
5503
5741
|
if (state.status === "cancelled") {
|
|
5504
5742
|
if (renderedLineCount > 0) {
|
|
5505
5743
|
process.stdout.write(`\x1B[${renderedLineCount}A\x1B[J`);
|
|
@@ -6332,6 +6570,53 @@ function resolveCatalogDir(args, repoPath, loadedConfig) {
|
|
|
6332
6570
|
}
|
|
6333
6571
|
return path10.join(PACKAGE_ROOT, "catalog");
|
|
6334
6572
|
}
|
|
6573
|
+
var POPULAR_AI_ORDER = [
|
|
6574
|
+
"cursor",
|
|
6575
|
+
"claude",
|
|
6576
|
+
"copilot",
|
|
6577
|
+
"antigravity",
|
|
6578
|
+
"windsurf",
|
|
6579
|
+
"codex",
|
|
6580
|
+
"gemini",
|
|
6581
|
+
"cline",
|
|
6582
|
+
"roocode",
|
|
6583
|
+
"kilocode",
|
|
6584
|
+
"zed",
|
|
6585
|
+
"continue",
|
|
6586
|
+
"aider",
|
|
6587
|
+
"kiro",
|
|
6588
|
+
"trae",
|
|
6589
|
+
"augment",
|
|
6590
|
+
"factory",
|
|
6591
|
+
"qwen",
|
|
6592
|
+
"opencode",
|
|
6593
|
+
"openhands",
|
|
6594
|
+
"amp",
|
|
6595
|
+
"goose",
|
|
6596
|
+
"warp",
|
|
6597
|
+
"crush",
|
|
6598
|
+
"vibe",
|
|
6599
|
+
"junie",
|
|
6600
|
+
"amazonq",
|
|
6601
|
+
"idx"
|
|
6602
|
+
];
|
|
6603
|
+
function buildInteractiveTargetOptions() {
|
|
6604
|
+
const popularSet = new Set(POPULAR_AI_ORDER);
|
|
6605
|
+
const orderedTargets = [
|
|
6606
|
+
...POPULAR_AI_ORDER,
|
|
6607
|
+
...ALL_RUNTIME_TARGETS.filter((t) => !popularSet.has(t))
|
|
6608
|
+
];
|
|
6609
|
+
return orderedTargets.map((targetId) => {
|
|
6610
|
+
const spec = RUNTIME_HARNESS_SPECS[targetId];
|
|
6611
|
+
return {
|
|
6612
|
+
value: spec.id,
|
|
6613
|
+
label: spec.id,
|
|
6614
|
+
kind: "ide",
|
|
6615
|
+
tab: "skill",
|
|
6616
|
+
hint: `${spec.displayName} (${spec.skillsDir})`
|
|
6617
|
+
};
|
|
6618
|
+
});
|
|
6619
|
+
}
|
|
6335
6620
|
function buildInteractiveCatalogOptions(catalogDir) {
|
|
6336
6621
|
const options = [];
|
|
6337
6622
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -7055,7 +7340,7 @@ function runCli(argv) {
|
|
|
7055
7340
|
async function runCliInteractive(argv) {
|
|
7056
7341
|
const args = argv.slice(2);
|
|
7057
7342
|
const command = args[0];
|
|
7058
|
-
if (command === "add" && !args.includes("--help") && !args.includes("-h") &&
|
|
7343
|
+
if (command === "add" && !args.includes("--help") && !args.includes("-h") && process.stdin.isTTY && process.stdout.isTTY) {
|
|
7059
7344
|
const repoPath = getFlagValue(args, "--repo", "--project", "-p") ?? process.cwd();
|
|
7060
7345
|
const cfgRes = loadSkillOpsConfig(repoPath);
|
|
7061
7346
|
if (cfgRes.error) {
|
|
@@ -7066,29 +7351,57 @@ async function runCliInteractive(argv) {
|
|
|
7066
7351
|
return ExitCode.BUDGET_OR_CONTRACT_ERROR;
|
|
7067
7352
|
}
|
|
7068
7353
|
const catalogDir = resolveCatalogDir(args, repoPath, cfgRes.config);
|
|
7069
|
-
const
|
|
7354
|
+
const explicitTargetsArg = resolveTargetsArg(args);
|
|
7355
|
+
const positionals = getPositionalArgs(args);
|
|
7356
|
+
const needsCatalogPrompt = !args.includes("--all") && positionals.length === 0;
|
|
7357
|
+
let resolvedTargetsArg = explicitTargetsArg;
|
|
7358
|
+
if (!resolvedTargetsArg) {
|
|
7359
|
+
const targetOptions = buildInteractiveTargetOptions();
|
|
7360
|
+
const step1Title = needsCatalogPrompt ? "SkillOps \u2014 Step 1/2: Select Your AI IDE / Agent" : "SkillOps \u2014 Select Your AI IDE / Agent";
|
|
7361
|
+
const selectedTargets = await runMultiSelectPrompt(
|
|
7362
|
+
step1Title,
|
|
7363
|
+
targetOptions,
|
|
7364
|
+
{
|
|
7365
|
+
tabLabels: {
|
|
7366
|
+
skill: "AI IDEs & Agents",
|
|
7367
|
+
agent: ""
|
|
7368
|
+
},
|
|
7369
|
+
submitActionLabel: "continue",
|
|
7370
|
+
selectCursorOnEmptySubmit: true
|
|
7371
|
+
}
|
|
7372
|
+
);
|
|
7373
|
+
if (!selectedTargets || selectedTargets.length === 0) {
|
|
7374
|
+
process.stdout.write("No AI IDE selected.\n");
|
|
7375
|
+
return ExitCode.SUCCESS;
|
|
7376
|
+
}
|
|
7377
|
+
resolvedTargetsArg = selectedTargets.join(",");
|
|
7378
|
+
}
|
|
7070
7379
|
let targets;
|
|
7071
7380
|
try {
|
|
7072
|
-
targets =
|
|
7381
|
+
targets = resolveRuntimeTargets(resolvedTargetsArg, repoPath);
|
|
7073
7382
|
} catch (err) {
|
|
7074
7383
|
const msg = err instanceof Error ? err.message : String(err);
|
|
7075
7384
|
process.stderr.write(`Invalid --targets: ${msg}
|
|
7076
7385
|
`);
|
|
7077
7386
|
return ExitCode.BUDGET_OR_CONTRACT_ERROR;
|
|
7078
7387
|
}
|
|
7079
|
-
const
|
|
7080
|
-
|
|
7081
|
-
"
|
|
7082
|
-
|
|
7083
|
-
|
|
7388
|
+
const extraArgs = [];
|
|
7389
|
+
if (!explicitTargetsArg) {
|
|
7390
|
+
extraArgs.push("-t", targets.join(","));
|
|
7391
|
+
}
|
|
7392
|
+
if (needsCatalogPrompt) {
|
|
7393
|
+
const options = buildInteractiveCatalogOptions(catalogDir);
|
|
7394
|
+
const step2Title = !explicitTargetsArg ? "SkillOps \u2014 Step 2/2: Select Skills & Agents to Import" : "SkillOps \u2014 Select Skills & Agents to Import";
|
|
7395
|
+
const selected = await runMultiSelectPrompt(step2Title, options, {
|
|
7084
7396
|
targetHint: targets.join(", ")
|
|
7397
|
+
});
|
|
7398
|
+
if (!selected || selected.length === 0) {
|
|
7399
|
+
process.stdout.write("No Skills or Agents selected.\n");
|
|
7400
|
+
return ExitCode.SUCCESS;
|
|
7085
7401
|
}
|
|
7086
|
-
|
|
7087
|
-
if (!selected || selected.length === 0) {
|
|
7088
|
-
process.stdout.write("No Skills or Agents selected.\n");
|
|
7089
|
-
return ExitCode.SUCCESS;
|
|
7402
|
+
extraArgs.push(...selected);
|
|
7090
7403
|
}
|
|
7091
|
-
return runCli([...argv, ...
|
|
7404
|
+
return runCli([...argv, ...extraArgs]);
|
|
7092
7405
|
}
|
|
7093
7406
|
return runCli(argv);
|
|
7094
7407
|
}
|
|
@@ -7114,6 +7427,7 @@ if (isDirectCliInvocation()) {
|
|
|
7114
7427
|
}
|
|
7115
7428
|
export {
|
|
7116
7429
|
buildInteractiveCatalogOptions,
|
|
7430
|
+
buildInteractiveTargetOptions,
|
|
7117
7431
|
runCli,
|
|
7118
7432
|
runCliInteractive
|
|
7119
7433
|
};
|