skillops-cli 1.3.1 → 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 +335 -45
- package/dist/index.d.ts +46 -3
- package/dist/index.js +231 -32
- package/package.json +84 -84
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.2`)**
|
|
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)
|
|
@@ -47,24 +47,27 @@ npx skillops-cli@latest eval --strict
|
|
|
47
47
|
|
|
48
48
|
As engineering teams adopt the **Top 20 AI Coding Agents, IDEs, and CLI Harnesses** (**Claude Code**, **Antigravity / Gemini CLI**, **Cursor**, **OpenAI Codex CLI**, **GitHub Copilot**, **Windsurf**, **Cline**, **Roo Code**, **Kilo Code**, **Zed AI**, **Continue.dev**, **Aider**, **OpenHands**, **Sourcegraph Amp**, **OpenCode**, **Block Goose**, **AWS Kiro**, **Trae IDE**, **JetBrains Junie**, and **Amazon Q Developer**), two systemic failure modes documented in 2026 empirical AI research break production workflows:
|
|
49
49
|
|
|
50
|
-
1. **Implicit Routing Collapse (
|
|
50
|
+
1. **Implicit Routing Collapse (_Lost in Implicit Routing_, `arXiv:2610.18522`):**
|
|
51
51
|
Dumping 50–100+ skills with overlapping natural-language descriptions into an agent's workspace causes **semantic routing recall to collapse from `73.6%` to `27.4%`**, while burning **8,000–15,000+ context tokens** before the developer writes a single prompt.
|
|
52
|
-
2. **Skill-Induced Regressions & Startup Token Tax (
|
|
52
|
+
2. **Skill-Induced Regressions & Startup Token Tax (_Agent Skills Can Be Harmful_, `arXiv:2608.11888`):**
|
|
53
53
|
Static, prose-heavy `SKILL.md` files without deterministic verification scripts or comparative `with_skill` vs. `without_skill` benchmarks frequently **degrade pass rates** on complex engineering tasks while inflating token overhead by **30%–200%**.
|
|
54
54
|
|
|
55
55
|
**SkillOps** solves both problems by uniting **three pillars** in a single 100% offline, zero-API Node.js 20+ / TypeScript engine:
|
|
56
56
|
|
|
57
57
|
### 📚 Pillar 1 — The Benchmark-Verified Library of Skills & Subagents
|
|
58
|
+
|
|
58
59
|
- **10 Hybrid Executable Skills (`catalog/<track>/<name>/`):** Every skill pairs a concise `<= 250`-line `SKILL.md` (`40–110` word L1 trigger description) with a zero-hallucination **Python 3.12+ Level 3 CLI tool (`scripts/*.py --json`)** and a **deterministic TDD evaluation suite (`evals/evals.json` + `evals/benchmark.json`)** proving `CERTIFIED_IMPROVEMENT` ($\Delta\text{PassRate} \ge +15\%$).
|
|
59
60
|
- **9 Context-Isolated Subagents (`catalog/subagents/` & `.github/agents/`):** Specialized read-only scouts and auditors that execute heavy AST/codebase exploration in an isolated context window and return a strict `<= 400`-token structured digest (`INV-SKILL-04`) to the parent agent.
|
|
60
61
|
- **Interactive Library Explorer:** Discover, filter, inspect, and install artifacts via `skillops list`, `skillops search <query>`, `skillops info <name>`, `skillops recommend`, and `skillops install <name>`.
|
|
61
62
|
|
|
62
63
|
### 🛠️ Pillar 2 — The Framework for Building Custom Skills & Subagents
|
|
64
|
+
|
|
63
65
|
- **1-Command Scaffolder (`skillops create skill|subagent <name>`):** Generates contract-compliant `SKILL.md` manifests (automatically meeting `INV-SKILL-01..04` word and token budgets), executable Python 3.12+ `--json` Level 3 AST/CLI scripts, and `with_skill` vs. `without_skill` TDD evaluation suites (`evals/evals.json`), or context-isolated `SUBAGENT.md` manifests (`max_output_tokens: 400`).
|
|
64
66
|
- **Zero-API Semantic Collision & Budget Linter (`skillops audit`):** Computes TF-IDF + char-trigram cosine similarity and MinHash Jaccard across your catalog to catch routing collisions (`>= 0.72` warning, `>= 0.85` error) and enforce 3-level progressive disclosure budgets before deployment.
|
|
65
67
|
- **Deterministic TDD Evaluation Runner (`skillops eval`):** Executes comparative `with_skill` vs. `without_skill` evaluations offline and generates `table`, `markdown`, `json`, or interactive `html` benchmark dashboards.
|
|
66
68
|
|
|
67
69
|
### ⚙️ Pillar 3 — Universal Multi-Runtime Sync, Token Economy & MCP Engine
|
|
70
|
+
|
|
68
71
|
- **Universal Top-20 AI Harness Transpiler (`skillops quickstart`, `sync`, `install`, `uninstall`, `clean`):** Transpiles Skills and Subagents into the native progressive-disclosure or scoped rule formats of all 20 AI coding agents with `.skillops-lock.json` SHA-256 drift protection.
|
|
69
72
|
- **Startup Token Tax Analyzer (`skillops budget` / `tokens`):** Audits 22 always-on instruction files (`CLAUDE.md`, `AGENTS.md`, `GEMINI.md`, `.windsurfrules`, `.clinerules`, `.goosehints`, `CONVENTIONS.md`, etc.) and 13 MCP config formats against a strict `<= 2,500`-token startup budget.
|
|
70
73
|
- **Local JSON-RPC 2.0 Stdio MCP Server (`skillops mcp-setup` & `mcp`):** Exposes 8 native tools (`audit_catalog`, `analyze_repo_tokens`, `route_repo_skills`, `run_skill_script`, `get_skill_benchmark`, `list_catalog_items`, `diagnose_repo`, `list_supported_harnesses`) across 13 MCP-capable IDEs and CLI agents.
|
|
@@ -106,63 +109,63 @@ flowchart LR
|
|
|
106
109
|
|
|
107
110
|
### 📚 1. Library Commands (Explore, Search, Recommend & Install)
|
|
108
111
|
|
|
109
|
-
| Command
|
|
110
|
-
|
|
|
111
|
-
| **`npx skillops-cli quickstart`**
|
|
112
|
-
| **`npx skillops-cli list`**
|
|
113
|
-
| **`npx skillops-cli search <query>`**
|
|
114
|
-
| **`npx skillops-cli info <name>`**
|
|
115
|
-
| **`npx skillops-cli install <name...>`**
|
|
116
|
-
| **`npx skillops-cli uninstall <name...>`** | `remove`, `rm`
|
|
117
|
-
| **`npx skillops-cli recommend`**
|
|
112
|
+
| Command | Aliases | Purpose & Key Flags |
|
|
113
|
+
| :----------------------------------------- | :---------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
114
|
+
| **`npx skillops-cli quickstart`** | `setup` | **1-Command Onboarding:** Auto-detects repo stack & active AI harnesses, routes optimal collision-free Skills + Subagents, transpiles runtime files, registers MCP, and prints how to invoke them (`--project <dir>`, `--harness <list\|auto\|all>`, `--dry-run`). |
|
|
115
|
+
| **`npx skillops-cli list`** | `ls` | Lists all catalog Skills and Context-Isolated Subagents with a visual L1 Token Budget Meter (`--type skill\|subagent`, `--format table\|json`). |
|
|
116
|
+
| **`npx skillops-cli search <query>`** | `find` | Searches the Library by keyword, domain tag, track, or trigger phrase (`--type skill\|subagent`, `--format table\|json\|markdown`). |
|
|
117
|
+
| **`npx skillops-cli info <name>`** | `show`, `inspect` | Renders a detailed TUI inspection card for a Skill or Subagent: L1/L2 token metrics, Level 3 scripts, TDD benchmark lift, and **how to invoke it in your AI IDE**. |
|
|
118
|
+
| **`npx skillops-cli install <name...>`** | `add`, `i` | Installs one or more Skills or Subagents into your active AI coding harnesses (`--harness claude,cursor,windsurf`, `--dry-run`, `--force`). |
|
|
119
|
+
| **`npx skillops-cli uninstall <name...>`** | `remove`, `rm` | Surgically removes synced Skills or Subagents from active AI harnesses while respecting `.skillops-lock.json` SHA-256 drift protection. |
|
|
120
|
+
| **`npx skillops-cli recommend`** | `route` | Fingerprints your repository (`package.json`, `pyproject.toml`, `Cargo.toml`, `go.mod`, `Dockerfile`, AST) and recommends an optimal `<= 12` Skill bundle (`--task "<prompt>"`, `--top <n>`). |
|
|
118
121
|
|
|
119
122
|
### 🛠️ 2. Framework Commands (Scaffold, Audit & Certify Custom Skills/Subagents)
|
|
120
123
|
|
|
121
|
-
| Command
|
|
122
|
-
|
|
|
123
|
-
| **`npx skillops-cli create <type> <name>`** | `new`
|
|
124
|
-
| **`npx skillops-cli audit`**
|
|
125
|
-
| **`npx skillops-cli eval`**
|
|
126
|
-
| **`npx skillops-cli init`**
|
|
124
|
+
| Command | Aliases | Purpose & Key Flags |
|
|
125
|
+
| :------------------------------------------ | :------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
126
|
+
| **`npx skillops-cli create <type> <name>`** | `new` | Scaffolds a contract-compliant custom **Skill** (`create skill <name> --track <track>`) with `SKILL.md`, `scripts/<name>_check.py --json`, and `evals/evals.json`, or a **Context-Isolated Subagent** (`create subagent <name>`). |
|
|
127
|
+
| **`npx skillops-cli audit`** | — | Audits any catalog for pairwise TF-IDF/MinHash semantic routing collisions (`< 0.72` / `< 0.85`), 3-level progressive disclosure token budgets, and subagent `max_output_tokens <= 400` (`--strict`, `--require-layout`, `--format table\|json\|markdown\|github`). |
|
|
128
|
+
| **`npx skillops-cli eval`** | — | Runs 100% offline deterministic `with_skill` vs. `without_skill` AST & subprocess TDD evaluations and enforces $\Delta\text{PassRate} \ge +15\%$ (`--skill <name>`, `--output <path>`, `--format table\|json\|markdown\|html\|github`). |
|
|
129
|
+
| **`npx skillops-cli init`** | — | Initializes a declarative `.skillops.yml` workspace configuration and empty `catalog/` tracks (`ai-engineering`, `python-backend`, `arch-quality`, `subagents`). |
|
|
127
130
|
|
|
128
131
|
### ⚙️ 3. Universal Runtime Sync, Token Economy & Diagnostics
|
|
129
132
|
|
|
130
|
-
| Command
|
|
131
|
-
|
|
|
132
|
-
| **`npx skillops-cli budget`**
|
|
133
|
-
| **`npx skillops-cli sync`**
|
|
134
|
-
| **`npx skillops-cli clean`**
|
|
135
|
-
| **`npx skillops-cli doctor`**
|
|
136
|
-
| **`npx skillops-cli harnesses`** | —
|
|
137
|
-
| **`npx skillops-cli mcp-setup`** | —
|
|
138
|
-
| **`npx skillops-cli mcp`**
|
|
133
|
+
| Command | Aliases | Purpose & Key Flags |
|
|
134
|
+
| :------------------------------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
135
|
+
| **`npx skillops-cli budget`** | `tokens` | Audits repository Startup Token Tax across 22 always-on instruction files (`CLAUDE.md`, `AGENTS.md`, `GEMINI.md`, `.windsurfrules`, `.clinerules`, etc.) and 13 MCP server configs with a visual budget meter (`--budget 2500`, `--strict`). |
|
|
136
|
+
| **`npx skillops-cli sync`** | — | Fingerprints the repository and transpiles the full routed Skill + Subagent bundle across selected harnesses (`--harness auto\|all\|core\|<list>`, `--task "<prompt>"`, `--dry-run`, `--force`). |
|
|
137
|
+
| **`npx skillops-cli clean`** | — | Removes all SkillOps-managed runtime artifacts tracked in `.skillops-lock.json` across all 20 harnesses and cleans managed index blocks. |
|
|
138
|
+
| **`npx skillops-cli doctor`** | `status` | Diagnoses Node.js/Python runtimes, `.skillops.yml` schema validity, `.skillops-lock.json` SHA-256 artifact drift (`healthy`, `drifted`, `missing`), Startup Token Tax, and detected AI harnesses. |
|
|
139
|
+
| **`npx skillops-cli harnesses`** | — | Lists all 20 supported AI coding agents with auto-detection status, target directories, and MCP support (`--format table\|json\|markdown`). |
|
|
140
|
+
| **`npx skillops-cli mcp-setup`** | — | Idempotently registers the `skillops` stdio MCP server across all 13 MCP-capable IDEs and CLI agents (`--harness auto\|all\|<list>`, `--dry-run`). |
|
|
141
|
+
| **`npx skillops-cli mcp`** | — | Starts the local JSON-RPC 2.0 `stdio` Model Context Protocol server exposing 8 SkillOps tools. |
|
|
139
142
|
|
|
140
143
|
---
|
|
141
144
|
|
|
142
145
|
## 🌐 Universal Top-20 AI Coding Agents & Harnesses Matrix
|
|
143
146
|
|
|
144
|
-
| #
|
|
145
|
-
|
|
|
146
|
-
| 1
|
|
147
|
-
| 2
|
|
148
|
-
| 3
|
|
149
|
-
| 4
|
|
150
|
-
| 5
|
|
151
|
-
| 6
|
|
152
|
-
| 7
|
|
153
|
-
| 8
|
|
154
|
-
| 9
|
|
155
|
-
| 10
|
|
156
|
-
| 11
|
|
157
|
-
| 12
|
|
158
|
-
| 13
|
|
159
|
-
| 14
|
|
160
|
-
| 15
|
|
161
|
-
| 16
|
|
162
|
-
| 17
|
|
163
|
-
| 18
|
|
164
|
-
| 19
|
|
165
|
-
| 20
|
|
147
|
+
| # | Target ID | AI Coding Agent / IDE | Category | Native Transpiled Skill / Rule Output | Native Subagent Output | Project MCP Config (`mcp-setup`) |
|
|
148
|
+
| :-- | :------------ | :---------------------------------- | :--------------- | :------------------------------------------------------- | :--------------------------------------- | :----------------------------------- |
|
|
149
|
+
| 1 | `claude` | **Claude Code (Anthropic)** | CLI Agent | `.claude/skills/<name>/SKILL.md` | `.claude/agents/<name>.md` | `.mcp.json` |
|
|
150
|
+
| 2 | `antigravity` | **Google Antigravity / Gemini CLI** | Agentic IDE | `.agent/skills/<name>/SKILL.md` | `.agent/agents/<name>.md` | `.gemini/settings.json` |
|
|
151
|
+
| 3 | `cursor` | **Cursor IDE** | AI IDE | `.cursor/rules/<name>.mdc` | `.cursor/rules/agent-<name>.mdc` | `.cursor/mcp.json` |
|
|
152
|
+
| 4 | `codex` | **OpenAI Codex CLI** | CLI Agent | `.codex/skills/<name>/SKILL.md` + `AGENTS.md` | `.codex/agents/<name>.md` | `.codex/config.toml` |
|
|
153
|
+
| 5 | `copilot` | **GitHub Copilot (VS Code)** | IDE Extension | `.github/instructions/<name>.instructions.md` | `.github/agents/<name>.agent.md` | `.vscode/mcp.json` |
|
|
154
|
+
| 6 | `windsurf` | **Windsurf (Codeium Cascade)** | AI IDE | `.windsurf/rules/<name>.md` (`trigger: model_decision`) | `.windsurf/workflows/agent-<name>.md` | — |
|
|
155
|
+
| 7 | `cline` | **Cline** | IDE Extension | `.clinerules/<name>.md` | `.clinerules/workflows/agent-<name>.md` | — |
|
|
156
|
+
| 8 | `roocode` | **Roo Code** | IDE Extension | `.roo/rules/<name>.md` | `.roo/rules-architect/agent-<name>.md` | `.roo/mcp.json` |
|
|
157
|
+
| 9 | `kilocode` | **Kilo Code** | IDE Extension | `.kilocode/rules/<name>.md` | `.kilocode/workflows/agent-<name>.md` | `.kilocode/mcp.json` |
|
|
158
|
+
| 10 | `zed` | **Zed AI** | AI IDE | `.zed/rules/<name>.md` + `.rules` | `.zed/prompts/agent-<name>.md` | `.zed/settings.json` |
|
|
159
|
+
| 11 | `continue` | **Continue.dev** | IDE Extension | `.continue/rules/<name>.md` | `.continue/prompts/agent-<name>.prompt` | `.continue/mcpServers/skillops.yaml` |
|
|
160
|
+
| 12 | `aider` | **Aider CLI** | CLI Agent | `.aider/skills/<name>/SKILL.md` + `CONVENTIONS.md` | `.aider/agents/<name>.md` | — |
|
|
161
|
+
| 13 | `openhands` | **OpenHands (All Hands AI)** | Autonomous Agent | `.openhands/microagents/<name>.md` | `.openhands/microagents/agent-<name>.md` | — |
|
|
162
|
+
| 14 | `amp` | **Sourcegraph Amp** | CLI Agent | `.amp/skills/<name>/SKILL.md` | `.amp/agents/<name>.md` | `.amp/settings.json` |
|
|
163
|
+
| 15 | `opencode` | **OpenCode CLI** | CLI Agent | `.opencode/skills/<name>/SKILL.md` | `.opencode/agent/<name>.md` | `opencode.json` |
|
|
164
|
+
| 16 | `goose` | **Block Goose** | CLI Agent | `.goose/skills/<name>/SKILL.md` + `.goosehints` | `.goose/agents/<name>.md` | — |
|
|
165
|
+
| 17 | `kiro` | **AWS Kiro IDE** | AI IDE | `.kiro/steering/<name>.md` (`inclusion: fileMatch`) | `.kiro/agents/<name>.md` | `.kiro/settings/mcp.json` |
|
|
166
|
+
| 18 | `trae` | **Trae IDE (ByteDance)** | AI IDE | `.trae/rules/<name>.md` | `.trae/agents/<name>.md` | — |
|
|
167
|
+
| 19 | `junie` | **JetBrains Junie** | IDE Extension | `.junie/skills/<name>/SKILL.md` + `.junie/guidelines.md` | `.junie/agents/<name>.md` | — |
|
|
168
|
+
| 20 | `amazonq` | **Amazon Q Developer** | IDE Extension | `.amazonq/rules/<name>.md` | `.amazonq/cli-agents/<name>.md` | `.amazonq/mcp.json` |
|
|
166
169
|
|
|
167
170
|
---
|
|
168
171
|
|
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.2";
|
|
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]*)$/;
|
|
@@ -5113,45 +5113,52 @@ function renderGlobalHelp(version, colorEnabled) {
|
|
|
5113
5113
|
const c = colorEnabled;
|
|
5114
5114
|
const bar = style.dim("\u2502", c);
|
|
5115
5115
|
const banner = renderHeaderBanner(
|
|
5116
|
-
"
|
|
5116
|
+
"Skills & Agents Library for AI Coding IDEs",
|
|
5117
5117
|
{
|
|
5118
5118
|
version,
|
|
5119
5119
|
colorEnabled: c
|
|
5120
5120
|
}
|
|
5121
5121
|
);
|
|
5122
|
-
const
|
|
5123
|
-
|
|
5124
|
-
|
|
5125
|
-
|
|
5126
|
-
|
|
5127
|
-
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
|
|
5122
|
+
const coreCmds = [
|
|
5123
|
+
{
|
|
5124
|
+
cmd: "add [name...]",
|
|
5125
|
+
desc: "Import Skills or Agents (interactive if no name given)"
|
|
5126
|
+
},
|
|
5127
|
+
{
|
|
5128
|
+
cmd: "list [query]",
|
|
5129
|
+
desc: "List or filter available Skills & Agents in catalog"
|
|
5130
|
+
},
|
|
5131
|
+
{
|
|
5132
|
+
cmd: "info <name>",
|
|
5133
|
+
desc: "View details and how to use a Skill or Agent"
|
|
5134
|
+
},
|
|
5135
|
+
{
|
|
5136
|
+
cmd: "remove <name>",
|
|
5137
|
+
desc: "Remove an imported Skill or Agent from your project"
|
|
5138
|
+
},
|
|
5139
|
+
{
|
|
5140
|
+
cmd: "init",
|
|
5141
|
+
desc: "Auto-detect stack & IDE and import recommended bundle"
|
|
5142
|
+
}
|
|
5143
|
+
];
|
|
5144
|
+
const cmdRows = coreCmds.map(
|
|
5145
|
+
(item) => `${bar} ${padVisible(style.bold(style.cyan(item.cmd, c), c), 18, "left")}${item.desc}`
|
|
5146
|
+
).join("\n");
|
|
5134
5147
|
return [
|
|
5135
5148
|
banner,
|
|
5136
|
-
`${bar} Usage:
|
|
5137
|
-
renderSectionHeader("
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
`${bar} ${
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
renderSectionHeader(
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
),
|
|
5147
|
-
formatCmdSection("framework"),
|
|
5148
|
-
renderSectionHeader(
|
|
5149
|
-
"3. Universal Runtime Sync, Token Economy & Diagnostics",
|
|
5150
|
-
c
|
|
5151
|
-
),
|
|
5152
|
-
formatCmdSection("runtime"),
|
|
5149
|
+
`${bar} Usage: skillops <command> [options]`,
|
|
5150
|
+
renderSectionHeader("Commands", c),
|
|
5151
|
+
cmdRows,
|
|
5152
|
+
renderSectionHeader("Options", c),
|
|
5153
|
+
`${bar} ${padVisible(style.cyan("-t, --target <ide>", c), 22, "left")}AI IDE (cursor, claude, copilot, windsurf, auto)`,
|
|
5154
|
+
`${bar} ${padVisible(style.cyan("-p, --project <dir>", c), 22, "left")}Project folder (default: current directory)`,
|
|
5155
|
+
`${bar} ${padVisible(style.cyan("--all", c), 22, "left")}Import all 10 Skills & 9 Agents`,
|
|
5156
|
+
renderSectionHeader("Examples", c),
|
|
5157
|
+
`${bar} ${style.dim("$", c)} ${style.green("skillops add", c)} ${style.dim("\u2014 Interactive selector", c)}`,
|
|
5158
|
+
`${bar} ${style.dim("$", c)} ${style.green("skillops add bug-reproducer-tdd red-team-breaker", c)} ${style.dim("\u2014 Direct import", c)}`,
|
|
5159
|
+
`${bar} ${style.dim("$", c)} ${style.green("skillops list", c)} ${style.dim("\u2014 Browse catalog", c)}`,
|
|
5153
5160
|
bar,
|
|
5154
|
-
`${style.dim("\u2570\u2500", c)} ${style.
|
|
5161
|
+
`${style.dim("\u2570\u2500", c)} ${style.dim("Run", c)} ${style.cyan("skillops <cmd> -h", c)} ${style.dim("for command options.", c)}`
|
|
5155
5162
|
].join("\n");
|
|
5156
5163
|
}
|
|
5157
5164
|
function renderCommandHelp(spec, version, colorEnabled) {
|
|
@@ -5176,6 +5183,194 @@ function renderCommandHelp(spec, version, colorEnabled) {
|
|
|
5176
5183
|
return [headerLines, optionsSection, examplesSection].filter(Boolean).join("\n");
|
|
5177
5184
|
}
|
|
5178
5185
|
|
|
5186
|
+
// src/ui/prompt.ts
|
|
5187
|
+
function createMultiSelectState(options) {
|
|
5188
|
+
const initial = /* @__PURE__ */ new Set();
|
|
5189
|
+
for (const opt of options) {
|
|
5190
|
+
if (opt.initialSelected) {
|
|
5191
|
+
initial.add(opt.value);
|
|
5192
|
+
}
|
|
5193
|
+
}
|
|
5194
|
+
return {
|
|
5195
|
+
options,
|
|
5196
|
+
cursor: 0,
|
|
5197
|
+
selected: initial,
|
|
5198
|
+
status: "active"
|
|
5199
|
+
};
|
|
5200
|
+
}
|
|
5201
|
+
function applyMultiSelectKey(state, key) {
|
|
5202
|
+
if (state.status !== "active" || state.options.length === 0) {
|
|
5203
|
+
return state;
|
|
5204
|
+
}
|
|
5205
|
+
const count = state.options.length;
|
|
5206
|
+
if (key === "" || key === "\x1B" || key === "q" || key === "Q") {
|
|
5207
|
+
return {
|
|
5208
|
+
...state,
|
|
5209
|
+
status: "cancelled"
|
|
5210
|
+
};
|
|
5211
|
+
}
|
|
5212
|
+
if (key === "\r" || key === "\n") {
|
|
5213
|
+
return {
|
|
5214
|
+
...state,
|
|
5215
|
+
status: "submitted"
|
|
5216
|
+
};
|
|
5217
|
+
}
|
|
5218
|
+
if (key === "\x1B[A" || key === "\x1BOA" || key === "k" || key === "K") {
|
|
5219
|
+
const nextCursor = (state.cursor - 1 + count) % count;
|
|
5220
|
+
return {
|
|
5221
|
+
...state,
|
|
5222
|
+
cursor: nextCursor
|
|
5223
|
+
};
|
|
5224
|
+
}
|
|
5225
|
+
if (key === "\x1B[B" || key === "\x1BOB" || key === "j" || key === "J") {
|
|
5226
|
+
const nextCursor = (state.cursor + 1) % count;
|
|
5227
|
+
return {
|
|
5228
|
+
...state,
|
|
5229
|
+
cursor: nextCursor
|
|
5230
|
+
};
|
|
5231
|
+
}
|
|
5232
|
+
if (key === " ") {
|
|
5233
|
+
const currentOpt = state.options[state.cursor];
|
|
5234
|
+
if (!currentOpt) {
|
|
5235
|
+
return state;
|
|
5236
|
+
}
|
|
5237
|
+
const nextSelected = new Set(state.selected);
|
|
5238
|
+
if (nextSelected.has(currentOpt.value)) {
|
|
5239
|
+
nextSelected.delete(currentOpt.value);
|
|
5240
|
+
} else {
|
|
5241
|
+
nextSelected.add(currentOpt.value);
|
|
5242
|
+
}
|
|
5243
|
+
return {
|
|
5244
|
+
...state,
|
|
5245
|
+
selected: nextSelected
|
|
5246
|
+
};
|
|
5247
|
+
}
|
|
5248
|
+
if (key === "a" || key === "A") {
|
|
5249
|
+
const allSelected = state.selected.size === count;
|
|
5250
|
+
const nextSelected = /* @__PURE__ */ new Set();
|
|
5251
|
+
if (!allSelected) {
|
|
5252
|
+
for (const opt of state.options) {
|
|
5253
|
+
nextSelected.add(opt.value);
|
|
5254
|
+
}
|
|
5255
|
+
}
|
|
5256
|
+
return {
|
|
5257
|
+
...state,
|
|
5258
|
+
selected: nextSelected
|
|
5259
|
+
};
|
|
5260
|
+
}
|
|
5261
|
+
return state;
|
|
5262
|
+
}
|
|
5263
|
+
function renderMultiSelectFrame(title, state, options = {}) {
|
|
5264
|
+
const c = options.colorEnabled;
|
|
5265
|
+
const bar = style.dim("\u2502", c);
|
|
5266
|
+
const maxVisible = options.maxVisible ?? 10;
|
|
5267
|
+
const total = state.options.length;
|
|
5268
|
+
const header = `${style.bold(style.cyan(`\u25C6 ${title}`, c), c)}`;
|
|
5269
|
+
const instructions = `${bar} ${style.dim("(\u2191/\u2193 move \xB7 Space select \xB7 'a' toggle all \xB7 Enter confirm)", c)}`;
|
|
5270
|
+
const lines = [header];
|
|
5271
|
+
if (options.subtitle) {
|
|
5272
|
+
lines.push(`${bar} ${options.subtitle}`);
|
|
5273
|
+
}
|
|
5274
|
+
lines.push(instructions, bar);
|
|
5275
|
+
let startIdx = 0;
|
|
5276
|
+
if (total > maxVisible) {
|
|
5277
|
+
const half = Math.floor(maxVisible / 2);
|
|
5278
|
+
startIdx = Math.max(0, Math.min(state.cursor - half, total - maxVisible));
|
|
5279
|
+
}
|
|
5280
|
+
const endIdx = Math.min(total, startIdx + maxVisible);
|
|
5281
|
+
if (startIdx > 0) {
|
|
5282
|
+
lines.push(`${bar} ${style.dim(`\u2191 ${startIdx} more above...`, c)}`);
|
|
5283
|
+
}
|
|
5284
|
+
const maxLabelCols = Math.min(
|
|
5285
|
+
26,
|
|
5286
|
+
state.options.reduce((m, o) => Math.max(m, visibleLength(o.label)), 14)
|
|
5287
|
+
);
|
|
5288
|
+
for (let i = startIdx; i < endIdx; i++) {
|
|
5289
|
+
const opt = state.options[i];
|
|
5290
|
+
if (!opt) continue;
|
|
5291
|
+
const isCurrent = i === state.cursor;
|
|
5292
|
+
const isChecked = state.selected.has(opt.value);
|
|
5293
|
+
const pointer = isCurrent ? style.cyan("\u276F", c) : " ";
|
|
5294
|
+
const checkbox = isChecked ? style.green("\u25FC", c) : style.dim("\u25FB", c);
|
|
5295
|
+
const kindTag = opt.kind === "skill" ? style.cyan("skill ", c) : opt.kind === "agent" ? style.magenta("agent ", c) : "";
|
|
5296
|
+
const labelRaw = opt.label.length > maxLabelCols ? `${opt.label.slice(0, maxLabelCols - 1)}\u2026` : opt.label;
|
|
5297
|
+
const labelPadded = padVisible(labelRaw, maxLabelCols + 1, "left");
|
|
5298
|
+
const styledLabel = isCurrent ? style.bold(labelPadded, c) : isChecked ? style.green(labelPadded, c) : labelPadded;
|
|
5299
|
+
const prefixWidth = 6 + (opt.kind === "skill" || opt.kind === "agent" ? 6 : 0) + maxLabelCols + 1;
|
|
5300
|
+
const maxHintCols = Math.max(10, 75 - prefixWidth);
|
|
5301
|
+
const rawHint = opt.hint ?? "";
|
|
5302
|
+
const shortHint = rawHint.length > maxHintCols ? `${rawHint.slice(0, maxHintCols - 1)}\u2026` : rawHint;
|
|
5303
|
+
const hintPart = shortHint ? ` ${style.dim(shortHint, c)}` : "";
|
|
5304
|
+
lines.push(
|
|
5305
|
+
`${bar} ${pointer} ${checkbox} ${kindTag}${styledLabel}${hintPart}`
|
|
5306
|
+
);
|
|
5307
|
+
}
|
|
5308
|
+
if (endIdx < total) {
|
|
5309
|
+
lines.push(`${bar} ${style.dim(`\u2193 ${total - endIdx} more below...`, c)}`);
|
|
5310
|
+
}
|
|
5311
|
+
lines.push(bar);
|
|
5312
|
+
const targetSuffix = options.targetHint ? ` \xB7 IDE: ${options.targetHint}` : "";
|
|
5313
|
+
lines.push(
|
|
5314
|
+
`${style.dim("\u2570\u2500", c)} ${style.bold(`${state.selected.size} selected`, c)}${style.dim(`${targetSuffix} \u2014 Enter to import`, c)}`
|
|
5315
|
+
);
|
|
5316
|
+
return lines.join("\n");
|
|
5317
|
+
}
|
|
5318
|
+
async function runMultiSelectPrompt(title, options, renderOpts = {}) {
|
|
5319
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
5320
|
+
return null;
|
|
5321
|
+
}
|
|
5322
|
+
let state = createMultiSelectState(options);
|
|
5323
|
+
let renderedLineCount = 0;
|
|
5324
|
+
const render = () => {
|
|
5325
|
+
const frame = renderMultiSelectFrame(title, state, renderOpts);
|
|
5326
|
+
if (renderedLineCount > 0) {
|
|
5327
|
+
process.stdout.write(`\x1B[${renderedLineCount}A\x1B[J`);
|
|
5328
|
+
}
|
|
5329
|
+
process.stdout.write(`${frame}
|
|
5330
|
+
`);
|
|
5331
|
+
renderedLineCount = frame.split("\n").length;
|
|
5332
|
+
};
|
|
5333
|
+
return new Promise((resolve) => {
|
|
5334
|
+
const stdin = process.stdin;
|
|
5335
|
+
const wasRaw = stdin.isRaw;
|
|
5336
|
+
stdin.setRawMode(true);
|
|
5337
|
+
stdin.resume();
|
|
5338
|
+
stdin.setEncoding("utf-8");
|
|
5339
|
+
process.stdout.write("\x1B[?25l");
|
|
5340
|
+
render();
|
|
5341
|
+
const cleanup = () => {
|
|
5342
|
+
stdin.removeListener("data", onData);
|
|
5343
|
+
if (stdin.isTTY) {
|
|
5344
|
+
stdin.setRawMode(Boolean(wasRaw));
|
|
5345
|
+
}
|
|
5346
|
+
stdin.pause();
|
|
5347
|
+
process.stdout.write("\x1B[?25h");
|
|
5348
|
+
};
|
|
5349
|
+
const onData = (chunk) => {
|
|
5350
|
+
const key = typeof chunk === "string" ? chunk : chunk.toString("utf-8");
|
|
5351
|
+
state = applyMultiSelectKey(state, key);
|
|
5352
|
+
if (state.status === "cancelled") {
|
|
5353
|
+
if (renderedLineCount > 0) {
|
|
5354
|
+
process.stdout.write(`\x1B[${renderedLineCount}A\x1B[J`);
|
|
5355
|
+
}
|
|
5356
|
+
cleanup();
|
|
5357
|
+
resolve(null);
|
|
5358
|
+
return;
|
|
5359
|
+
}
|
|
5360
|
+
if (state.status === "submitted") {
|
|
5361
|
+
if (renderedLineCount > 0) {
|
|
5362
|
+
process.stdout.write(`\x1B[${renderedLineCount}A\x1B[J`);
|
|
5363
|
+
}
|
|
5364
|
+
cleanup();
|
|
5365
|
+
resolve([...state.selected]);
|
|
5366
|
+
return;
|
|
5367
|
+
}
|
|
5368
|
+
render();
|
|
5369
|
+
};
|
|
5370
|
+
stdin.on("data", onData);
|
|
5371
|
+
});
|
|
5372
|
+
}
|
|
5373
|
+
|
|
5179
5374
|
// src/framework/index.ts
|
|
5180
5375
|
function extractMarkdownHeadings(markdownBody) {
|
|
5181
5376
|
const headings = [];
|
|
@@ -5986,6 +6181,41 @@ function resolveCatalogDir(args, repoPath, loadedConfig) {
|
|
|
5986
6181
|
}
|
|
5987
6182
|
return path10.join(PACKAGE_ROOT, "catalog");
|
|
5988
6183
|
}
|
|
6184
|
+
function buildInteractiveCatalogOptions(catalogDir) {
|
|
6185
|
+
const options = [];
|
|
6186
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6187
|
+
for (const skillDir of discoverSkillDirectories(catalogDir)) {
|
|
6188
|
+
try {
|
|
6189
|
+
const parsed = parseSkillDirectory(skillDir, { requireLayout: false });
|
|
6190
|
+
if (!seen.has(parsed.manifest.name)) {
|
|
6191
|
+
seen.add(parsed.manifest.name);
|
|
6192
|
+
options.push({
|
|
6193
|
+
value: parsed.manifest.name,
|
|
6194
|
+
label: parsed.manifest.name,
|
|
6195
|
+
kind: "skill",
|
|
6196
|
+
hint: parsed.manifest.description
|
|
6197
|
+
});
|
|
6198
|
+
}
|
|
6199
|
+
} catch {
|
|
6200
|
+
}
|
|
6201
|
+
}
|
|
6202
|
+
for (const saPath of discoverSubagentFiles(catalogDir)) {
|
|
6203
|
+
try {
|
|
6204
|
+
const parsed = parseSubagentFile(saPath);
|
|
6205
|
+
if (!seen.has(parsed.manifest.name)) {
|
|
6206
|
+
seen.add(parsed.manifest.name);
|
|
6207
|
+
options.push({
|
|
6208
|
+
value: parsed.manifest.name,
|
|
6209
|
+
label: parsed.manifest.name,
|
|
6210
|
+
kind: "agent",
|
|
6211
|
+
hint: parsed.manifest.description
|
|
6212
|
+
});
|
|
6213
|
+
}
|
|
6214
|
+
} catch {
|
|
6215
|
+
}
|
|
6216
|
+
}
|
|
6217
|
+
return options;
|
|
6218
|
+
}
|
|
5989
6219
|
function runCli(argv) {
|
|
5990
6220
|
const args = argv.slice(2);
|
|
5991
6221
|
if (args.includes("--version") || args.includes("-V") || args[0] === "version") {
|
|
@@ -6184,6 +6414,7 @@ function runCli(argv) {
|
|
|
6184
6414
|
return ExitCode.SUCCESS;
|
|
6185
6415
|
}
|
|
6186
6416
|
if (command === "list") {
|
|
6417
|
+
const positionals = getPositionalArgs(args);
|
|
6187
6418
|
const repoPath = getFlagValue(args, "--repo", "--project", "-p") ?? process.cwd();
|
|
6188
6419
|
const cfgRes = loadSkillOpsConfig(repoPath);
|
|
6189
6420
|
if (cfgRes.error) {
|
|
@@ -6195,6 +6426,12 @@ function runCli(argv) {
|
|
|
6195
6426
|
}
|
|
6196
6427
|
const catalogDir = resolveCatalogDir(args, repoPath, cfgRes.config);
|
|
6197
6428
|
const rawFormat = getFlagValue(args, "--format", "-f") ?? "table";
|
|
6429
|
+
if (positionals.length > 0) {
|
|
6430
|
+
const format = rawFormat === "json" || rawFormat === "markdown" ? rawFormat : "table";
|
|
6431
|
+
const report = searchCatalog(catalogDir, positionals.join(" "));
|
|
6432
|
+
process.stdout.write(formatCatalogSearchReport(report, format));
|
|
6433
|
+
return ExitCode.SUCCESS;
|
|
6434
|
+
}
|
|
6198
6435
|
const summary = auditCatalogTokenBudgets(catalogDir, {
|
|
6199
6436
|
requireLayout: false
|
|
6200
6437
|
});
|
|
@@ -6444,7 +6681,9 @@ function runCli(argv) {
|
|
|
6444
6681
|
const force = args.includes("--force");
|
|
6445
6682
|
const rawFormat = getFlagValue(args, "--format", "-f") ?? "table";
|
|
6446
6683
|
const format = rawFormat === "json" || rawFormat === "markdown" ? rawFormat : "table";
|
|
6447
|
-
|
|
6684
|
+
const importAll = args.includes("--all");
|
|
6685
|
+
const itemsToAdd = importAll && positionals.length === 0 ? buildInteractiveCatalogOptions(catalogDir).map((o) => o.value) : positionals;
|
|
6686
|
+
if (itemsToAdd.length === 0) {
|
|
6448
6687
|
if (command === "add") {
|
|
6449
6688
|
process.stderr.write(
|
|
6450
6689
|
"Usage: npx skillops-cli add <skill-or-subagent-name> [more-names...] [options]\n"
|
|
@@ -6465,19 +6704,27 @@ function runCli(argv) {
|
|
|
6465
6704
|
return report.passed ? ExitCode.SUCCESS : ExitCode.ERROR;
|
|
6466
6705
|
}
|
|
6467
6706
|
try {
|
|
6468
|
-
|
|
6469
|
-
|
|
6470
|
-
const report = addSkillOrSubagent(repoPath, catalogDir, itemName, {
|
|
6707
|
+
const reports = itemsToAdd.map(
|
|
6708
|
+
(itemName) => addSkillOrSubagent(repoPath, catalogDir, itemName, {
|
|
6471
6709
|
targets,
|
|
6472
6710
|
dryRun,
|
|
6473
6711
|
force
|
|
6474
|
-
})
|
|
6475
|
-
|
|
6476
|
-
|
|
6477
|
-
|
|
6478
|
-
|
|
6712
|
+
})
|
|
6713
|
+
);
|
|
6714
|
+
const firstReport = reports[0];
|
|
6715
|
+
if (!firstReport) {
|
|
6716
|
+
return ExitCode.ERROR;
|
|
6479
6717
|
}
|
|
6480
|
-
|
|
6718
|
+
const finalReport = reports.length === 1 ? firstReport : {
|
|
6719
|
+
...firstReport,
|
|
6720
|
+
artifacts: reports.flatMap((r) => r.artifacts),
|
|
6721
|
+
drift_conflicts: [
|
|
6722
|
+
...new Set(reports.flatMap((r) => r.drift_conflicts))
|
|
6723
|
+
],
|
|
6724
|
+
passed: reports.every((r) => r.passed)
|
|
6725
|
+
};
|
|
6726
|
+
process.stdout.write(formatSyncReport(finalReport, format));
|
|
6727
|
+
return finalReport.passed ? ExitCode.SUCCESS : ExitCode.ERROR;
|
|
6481
6728
|
} catch (err) {
|
|
6482
6729
|
const msg = err instanceof Error ? err.message : String(err);
|
|
6483
6730
|
process.stderr.write(`Error: ${msg}
|
|
@@ -6654,6 +6901,46 @@ function runCli(argv) {
|
|
|
6654
6901
|
);
|
|
6655
6902
|
return ExitCode.ERROR;
|
|
6656
6903
|
}
|
|
6904
|
+
async function runCliInteractive(argv) {
|
|
6905
|
+
const args = argv.slice(2);
|
|
6906
|
+
const command = args[0];
|
|
6907
|
+
if (command === "add" && !args.includes("--help") && !args.includes("-h") && !args.includes("--all") && getPositionalArgs(args).length === 0 && process.stdin.isTTY && process.stdout.isTTY) {
|
|
6908
|
+
const repoPath = getFlagValue(args, "--repo", "--project", "-p") ?? process.cwd();
|
|
6909
|
+
const cfgRes = loadSkillOpsConfig(repoPath);
|
|
6910
|
+
if (cfgRes.error) {
|
|
6911
|
+
process.stderr.write(
|
|
6912
|
+
`Invalid .skillops.yml at ${cfgRes.configPath}: ${cfgRes.error}
|
|
6913
|
+
`
|
|
6914
|
+
);
|
|
6915
|
+
return ExitCode.BUDGET_OR_CONTRACT_ERROR;
|
|
6916
|
+
}
|
|
6917
|
+
const catalogDir = resolveCatalogDir(args, repoPath, cfgRes.config);
|
|
6918
|
+
const targetsArg = resolveTargetsArg(args);
|
|
6919
|
+
let targets;
|
|
6920
|
+
try {
|
|
6921
|
+
targets = targetsArg ? resolveRuntimeTargets(targetsArg, repoPath) : cfgRes.config?.targets ?? [...CORE_RUNTIME_TARGETS];
|
|
6922
|
+
} catch (err) {
|
|
6923
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
6924
|
+
process.stderr.write(`Invalid --targets: ${msg}
|
|
6925
|
+
`);
|
|
6926
|
+
return ExitCode.BUDGET_OR_CONTRACT_ERROR;
|
|
6927
|
+
}
|
|
6928
|
+
const options = buildInteractiveCatalogOptions(catalogDir);
|
|
6929
|
+
const selected = await runMultiSelectPrompt(
|
|
6930
|
+
"SkillOps \u2014 Select Skills & Agents to Import",
|
|
6931
|
+
options,
|
|
6932
|
+
{
|
|
6933
|
+
targetHint: `${targets.join(", ")} -> ${repoPath.replace(/\\/g, "/")}`
|
|
6934
|
+
}
|
|
6935
|
+
);
|
|
6936
|
+
if (!selected || selected.length === 0) {
|
|
6937
|
+
process.stdout.write("No Skills or Agents selected.\n");
|
|
6938
|
+
return ExitCode.SUCCESS;
|
|
6939
|
+
}
|
|
6940
|
+
return runCli([...argv, ...selected]);
|
|
6941
|
+
}
|
|
6942
|
+
return runCli(argv);
|
|
6943
|
+
}
|
|
6657
6944
|
function isDirectCliInvocation() {
|
|
6658
6945
|
const entryArg = process.argv[1];
|
|
6659
6946
|
if (!entryArg) {
|
|
@@ -6670,9 +6957,12 @@ function isDirectCliInvocation() {
|
|
|
6670
6957
|
}
|
|
6671
6958
|
}
|
|
6672
6959
|
if (isDirectCliInvocation()) {
|
|
6673
|
-
|
|
6674
|
-
|
|
6960
|
+
runCliInteractive(process.argv).then((code) => {
|
|
6961
|
+
process.exit(code);
|
|
6962
|
+
});
|
|
6675
6963
|
}
|
|
6676
6964
|
export {
|
|
6677
|
-
|
|
6965
|
+
buildInteractiveCatalogOptions,
|
|
6966
|
+
runCli,
|
|
6967
|
+
runCliInteractive
|
|
6678
6968
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { z } from 'zod';
|
|
|
8
8
|
* telemetry and Multi-Runtime Transpilation lockfiles.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
declare const SKILLOPS_VERSION = "1.3.
|
|
11
|
+
declare const SKILLOPS_VERSION = "1.3.2";
|
|
12
12
|
/**
|
|
13
13
|
* Count whitespace-delimited words in text.
|
|
14
14
|
*/
|
|
@@ -2165,7 +2165,7 @@ declare const COMMAND_HELP_SPECS: readonly CommandHelpSpec[];
|
|
|
2165
2165
|
*/
|
|
2166
2166
|
declare function findCommandHelpSpec(commandOrAlias: string): CommandHelpSpec | undefined;
|
|
2167
2167
|
/**
|
|
2168
|
-
* Render the compact, emoji-free
|
|
2168
|
+
* Render the compact, emoji-free global help tree (`npx skillops-cli --help`) focused on the 5 core commands.
|
|
2169
2169
|
*/
|
|
2170
2170
|
declare function renderGlobalHelp(version: string, colorEnabled?: boolean): string;
|
|
2171
2171
|
/**
|
|
@@ -2173,6 +2173,49 @@ declare function renderGlobalHelp(version: string, colorEnabled?: boolean): stri
|
|
|
2173
2173
|
*/
|
|
2174
2174
|
declare function renderCommandHelp(spec: CommandHelpSpec, version: string, colorEnabled?: boolean): string;
|
|
2175
2175
|
|
|
2176
|
+
/**
|
|
2177
|
+
* Zero-dependency interactive terminal multi-select prompt (`src/ui/prompt.ts`).
|
|
2178
|
+
*
|
|
2179
|
+
* Supports keyboard navigation (`↑`/`↓` or `j`/`k`), `Space` to toggle selection,
|
|
2180
|
+
* `a` to toggle all, `Enter` to confirm, and `Esc`/`Ctrl+C` to cancel.
|
|
2181
|
+
*/
|
|
2182
|
+
interface MultiSelectOption {
|
|
2183
|
+
readonly value: string;
|
|
2184
|
+
readonly label: string;
|
|
2185
|
+
readonly kind?: "skill" | "agent" | "ide";
|
|
2186
|
+
readonly hint?: string;
|
|
2187
|
+
readonly initialSelected?: boolean;
|
|
2188
|
+
}
|
|
2189
|
+
interface MultiSelectState {
|
|
2190
|
+
readonly options: readonly MultiSelectOption[];
|
|
2191
|
+
readonly cursor: number;
|
|
2192
|
+
readonly selected: ReadonlySet<string>;
|
|
2193
|
+
readonly status: "active" | "submitted" | "cancelled";
|
|
2194
|
+
}
|
|
2195
|
+
interface RenderMultiSelectOptions {
|
|
2196
|
+
readonly subtitle?: string;
|
|
2197
|
+
readonly targetHint?: string;
|
|
2198
|
+
readonly maxVisible?: number;
|
|
2199
|
+
readonly colorEnabled?: boolean;
|
|
2200
|
+
}
|
|
2201
|
+
/**
|
|
2202
|
+
* Initialize a deterministic multi-select state from a list of options.
|
|
2203
|
+
*/
|
|
2204
|
+
declare function createMultiSelectState(options: readonly MultiSelectOption[]): MultiSelectState;
|
|
2205
|
+
/**
|
|
2206
|
+
* Pure state reducer for keyboard input in the multi-select TUI.
|
|
2207
|
+
*/
|
|
2208
|
+
declare function applyMultiSelectKey(state: MultiSelectState, key: string): MultiSelectState;
|
|
2209
|
+
/**
|
|
2210
|
+
* Render a single frame of the multi-select tree prompt (guaranteed <= 78 columns).
|
|
2211
|
+
*/
|
|
2212
|
+
declare function renderMultiSelectFrame(title: string, state: MultiSelectState, options?: RenderMultiSelectOptions): string;
|
|
2213
|
+
/**
|
|
2214
|
+
* Run an interactive multi-select prompt in a TTY terminal.
|
|
2215
|
+
* Returns the array of selected values, or `null` if cancelled by user.
|
|
2216
|
+
*/
|
|
2217
|
+
declare function runMultiSelectPrompt(title: string, options: readonly MultiSelectOption[], renderOpts?: RenderMultiSelectOptions): Promise<string[] | null>;
|
|
2218
|
+
|
|
2176
2219
|
/**
|
|
2177
2220
|
* SkillOps Zero-Dependency Terminal UI (TUI) Aesthetic Engine.
|
|
2178
2221
|
*
|
|
@@ -2292,4 +2335,4 @@ declare const DEFAULT_VALID_COMMANDS: readonly string[];
|
|
|
2292
2335
|
*/
|
|
2293
2336
|
declare function suggestCommand(unknownCommand: string, validCommands?: readonly string[]): string | null;
|
|
2294
2337
|
|
|
2295
|
-
export { ALL_RUNTIME_TARGETS, type AddOptions, type AnalyzeTokenEconomyOptions, type AuditCatalogOptions, type BadgeType, type BenchmarkArm, BenchmarkArmSchema, type BenchmarkDelta, BenchmarkDeltaSchema, type BoxOptions, COMMAND_HELP_SPECS, CORE_RUNTIME_TARGETS, type CatalogEvalSummary, CatalogEvalSummarySchema, type CatalogItemInfo, type CatalogSearchMatch, type CatalogSearchReport, type CatalogTokenBudgetSummary, type CatalogTrack, CatalogTrackSchema, type CleanOptions, type CollisionPair, CollisionPairSchema, type CollisionReport, CollisionReportSchema, type CollisionSeverity, CollisionSeveritySchema, type ColorOverrideOptions, type CommandHelpSpec, type CommandOptionSpec, DEFAULT_VALID_COMMANDS, type DiagnoseRepositoryOptions, type DoctorCheckItem, type DoctorReport, type EvalAssertion, EvalAssertionSchema, type EvalCase, EvalCaseSchema, ExitCode, type ExitCodeValue, type HarnessCategory, type HarnessInspectionEntry, type HarnessInspectionReport, type HarnessSkillFormat, type JsonRpcRequest, type JsonRpcResponse, type LoadedSkillOpsConfigResult, type LockfileArtifactDiagnostic, type McpConfigAction, type McpServerContext, type McpSetupOptions, type McpSetupReport, type NextStepHint, type ParseSkillOptions, type ParsedSkillDirectory, type ParsedSubagentFile, type QuickstartOptions, type QuickstartReport, RUNTIME_HARNESS_SPECS, type RemoveOptions, RepoFingerprinter, type RepoProfile, RepoProfileSchema, type RouteOptions, type RoutedBundle, RoutedBundleSchema, type RoutingSignals, RoutingSignalsSchema, type RuntimeHarnessSpec, type RuntimeTarget, RuntimeTargetSchema, SKILLOPS_VERSION, type ScaffoldOptions, type ScaffoldResult, type ScoredSkill, ScoredSkillSchema, type ScriptEntrypoint, ScriptEntrypointSchema, type SkillBenchmark, SkillBenchmarkSchema, type SkillEntrypoints, SkillEntrypointsSchema, type SkillEvalSuite, SkillEvalSuiteSchema, type SkillManifest, type SkillManifestInput, SkillManifestSchema, type SkillOpsConfig, SkillOpsConfigSchema, type SkillOpsDetectedStackConfig, SkillOpsDetectedStackConfigSchema, type SkillOpsTokenEconomyConfig, SkillOpsTokenEconomyConfigSchema, type SkillTokenBudgetAudit, type SkippedSkill, SkippedSkillSchema, type SubagentManifest, SubagentManifestSchema, type SubagentTokenBudgetAudit, type SyncLockEntry, SyncLockEntrySchema, type SyncLockfile, SyncLockfileSchema, type SyncOptions, type SyncReport, SyncReportSchema, type SyncedArtifact, SyncedArtifactSchema, type TableOptions, type TokenBarOptions, type TokenEconomyReport, TokenEconomyReportSchema, type TokenFileCategory, TokenFileCategorySchema, type TokenFileEntry, TokenFileEntrySchema, type TokenWasteHotspot, TokenWasteHotspotSchema, addSkillOrSubagent, analyzeRepoTokenEconomy, auditCatalog, auditCatalogTokenBudgets, auditSkillTokenBudget, auditSubagentTokenBudget, classifyCollisionSeverity, cleanSyncedArtifacts, compileSkillBundle, computeCollisionMatrix, computeFeatureCosine, computeIdfWeights, computeSha256, countWords, createCollisionPair, createCollisionReport, createSkillManifest, createSubagentManifest, detectInstalledHarnesses, diagnoseRepository, discoverSkillDirectories, discoverSubagentFiles, estimateTokenCount, evaluateCatalog, evaluateSkillDirectory, extractSkillFeatures, findCommandHelpSpec, fingerprintRepository, formatBadge, formatCatalogItemInfo, formatCatalogSearchReport, formatDoctorReport, formatEvalSummary, formatHarnessInspectionReport, formatMcpSetupReport, formatQuickstartReport, formatRoutedBundle, formatScaffoldReport, formatSyncReport, formatTokenEconomyReport, handleMcpJsonRpcRequest, inspectCatalogItem, inspectHarnesses, isColorEnabled, levenshteinDistance, loadSkillOpsConfig, normalizePackageName, padVisible, parseSkillDirectory, parseSkillMdFile, parseSubagentFile, parseSubagentMdFile, removeSkillOrSubagent, renderAiUsageGuide, renderBox, renderCodexAgentsIndex, renderCommandHelp, renderGlobalHelp, renderHeaderBanner, renderNextSteps, renderProgressBar, renderSectionHeader, renderStep, renderTable, renderTokenBar, resolveRuntimeTargets, routeRepository, runQuickstart, scaffoldFrameworkItem, scoreSkillAgainstProfile, searchCatalog, setupMcpForHarnesses, splitFrontmatter, startMcpStdioServer, stripAnsi, stripCodexAgentsBlock, stripNegativeTriggerClauses, style, suggestCommand, syncRepository, tokenizeRoutingText, visibleLength };
|
|
2338
|
+
export { ALL_RUNTIME_TARGETS, type AddOptions, type AnalyzeTokenEconomyOptions, type AuditCatalogOptions, type BadgeType, type BenchmarkArm, BenchmarkArmSchema, type BenchmarkDelta, BenchmarkDeltaSchema, type BoxOptions, COMMAND_HELP_SPECS, CORE_RUNTIME_TARGETS, type CatalogEvalSummary, CatalogEvalSummarySchema, type CatalogItemInfo, type CatalogSearchMatch, type CatalogSearchReport, type CatalogTokenBudgetSummary, type CatalogTrack, CatalogTrackSchema, type CleanOptions, type CollisionPair, CollisionPairSchema, type CollisionReport, CollisionReportSchema, type CollisionSeverity, CollisionSeveritySchema, type ColorOverrideOptions, type CommandHelpSpec, type CommandOptionSpec, DEFAULT_VALID_COMMANDS, type DiagnoseRepositoryOptions, type DoctorCheckItem, type DoctorReport, type EvalAssertion, EvalAssertionSchema, type EvalCase, EvalCaseSchema, ExitCode, type ExitCodeValue, type HarnessCategory, type HarnessInspectionEntry, type HarnessInspectionReport, type HarnessSkillFormat, type JsonRpcRequest, type JsonRpcResponse, type LoadedSkillOpsConfigResult, type LockfileArtifactDiagnostic, type McpConfigAction, type McpServerContext, type McpSetupOptions, type McpSetupReport, type MultiSelectOption, type MultiSelectState, type NextStepHint, type ParseSkillOptions, type ParsedSkillDirectory, type ParsedSubagentFile, type QuickstartOptions, type QuickstartReport, RUNTIME_HARNESS_SPECS, type RemoveOptions, type RenderMultiSelectOptions, RepoFingerprinter, type RepoProfile, RepoProfileSchema, type RouteOptions, type RoutedBundle, RoutedBundleSchema, type RoutingSignals, RoutingSignalsSchema, type RuntimeHarnessSpec, type RuntimeTarget, RuntimeTargetSchema, SKILLOPS_VERSION, type ScaffoldOptions, type ScaffoldResult, type ScoredSkill, ScoredSkillSchema, type ScriptEntrypoint, ScriptEntrypointSchema, type SkillBenchmark, SkillBenchmarkSchema, type SkillEntrypoints, SkillEntrypointsSchema, type SkillEvalSuite, SkillEvalSuiteSchema, type SkillManifest, type SkillManifestInput, SkillManifestSchema, type SkillOpsConfig, SkillOpsConfigSchema, type SkillOpsDetectedStackConfig, SkillOpsDetectedStackConfigSchema, type SkillOpsTokenEconomyConfig, SkillOpsTokenEconomyConfigSchema, type SkillTokenBudgetAudit, type SkippedSkill, SkippedSkillSchema, type SubagentManifest, SubagentManifestSchema, type SubagentTokenBudgetAudit, type SyncLockEntry, SyncLockEntrySchema, type SyncLockfile, SyncLockfileSchema, type SyncOptions, type SyncReport, SyncReportSchema, type SyncedArtifact, SyncedArtifactSchema, type TableOptions, type TokenBarOptions, type TokenEconomyReport, TokenEconomyReportSchema, type TokenFileCategory, TokenFileCategorySchema, type TokenFileEntry, TokenFileEntrySchema, type TokenWasteHotspot, TokenWasteHotspotSchema, addSkillOrSubagent, analyzeRepoTokenEconomy, applyMultiSelectKey, auditCatalog, auditCatalogTokenBudgets, auditSkillTokenBudget, auditSubagentTokenBudget, classifyCollisionSeverity, cleanSyncedArtifacts, compileSkillBundle, computeCollisionMatrix, computeFeatureCosine, computeIdfWeights, computeSha256, countWords, createCollisionPair, createCollisionReport, createMultiSelectState, createSkillManifest, createSubagentManifest, detectInstalledHarnesses, diagnoseRepository, discoverSkillDirectories, discoverSubagentFiles, estimateTokenCount, evaluateCatalog, evaluateSkillDirectory, extractSkillFeatures, findCommandHelpSpec, fingerprintRepository, formatBadge, formatCatalogItemInfo, formatCatalogSearchReport, formatDoctorReport, formatEvalSummary, formatHarnessInspectionReport, formatMcpSetupReport, formatQuickstartReport, formatRoutedBundle, formatScaffoldReport, formatSyncReport, formatTokenEconomyReport, handleMcpJsonRpcRequest, inspectCatalogItem, inspectHarnesses, isColorEnabled, levenshteinDistance, loadSkillOpsConfig, normalizePackageName, padVisible, parseSkillDirectory, parseSkillMdFile, parseSubagentFile, parseSubagentMdFile, removeSkillOrSubagent, renderAiUsageGuide, renderBox, renderCodexAgentsIndex, renderCommandHelp, renderGlobalHelp, renderHeaderBanner, renderMultiSelectFrame, renderNextSteps, renderProgressBar, renderSectionHeader, renderStep, renderTable, renderTokenBar, resolveRuntimeTargets, routeRepository, runMultiSelectPrompt, runQuickstart, scaffoldFrameworkItem, scoreSkillAgainstProfile, searchCatalog, setupMcpForHarnesses, splitFrontmatter, startMcpStdioServer, stripAnsi, stripCodexAgentsBlock, stripNegativeTriggerClauses, style, suggestCommand, syncRepository, tokenizeRoutingText, visibleLength };
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import fs from "fs";
|
|
3
3
|
import YAML from "yaml";
|
|
4
4
|
import { z } from "zod";
|
|
5
|
-
var SKILLOPS_VERSION = "1.3.
|
|
5
|
+
var SKILLOPS_VERSION = "1.3.2";
|
|
6
6
|
var SKILL_NAME_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
7
7
|
var SEMVER_REGEX = /^\d+\.\d+\.\d+$/;
|
|
8
8
|
var FRONTMATTER_REGEX = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
|
|
@@ -5131,45 +5131,52 @@ function renderGlobalHelp(version, colorEnabled) {
|
|
|
5131
5131
|
const c = colorEnabled;
|
|
5132
5132
|
const bar = style.dim("\u2502", c);
|
|
5133
5133
|
const banner = renderHeaderBanner(
|
|
5134
|
-
"
|
|
5134
|
+
"Skills & Agents Library for AI Coding IDEs",
|
|
5135
5135
|
{
|
|
5136
5136
|
version,
|
|
5137
5137
|
colorEnabled: c
|
|
5138
5138
|
}
|
|
5139
5139
|
);
|
|
5140
|
-
const
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5140
|
+
const coreCmds = [
|
|
5141
|
+
{
|
|
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"
|
|
5160
|
+
}
|
|
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");
|
|
5152
5165
|
return [
|
|
5153
5166
|
banner,
|
|
5154
|
-
`${bar} Usage:
|
|
5155
|
-
renderSectionHeader("
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
`${bar} ${
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
renderSectionHeader(
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
),
|
|
5165
|
-
formatCmdSection("framework"),
|
|
5166
|
-
renderSectionHeader(
|
|
5167
|
-
"3. Universal Runtime Sync, Token Economy & Diagnostics",
|
|
5168
|
-
c
|
|
5169
|
-
),
|
|
5170
|
-
formatCmdSection("runtime"),
|
|
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)}`,
|
|
5171
5178
|
bar,
|
|
5172
|
-
`${style.dim("\u2570\u2500", c)} ${style.
|
|
5179
|
+
`${style.dim("\u2570\u2500", c)} ${style.dim("Run", c)} ${style.cyan("skillops <cmd> -h", c)} ${style.dim("for command options.", c)}`
|
|
5173
5180
|
].join("\n");
|
|
5174
5181
|
}
|
|
5175
5182
|
function renderCommandHelp(spec, version, colorEnabled) {
|
|
@@ -5194,6 +5201,194 @@ function renderCommandHelp(spec, version, colorEnabled) {
|
|
|
5194
5201
|
return [headerLines, optionsSection, examplesSection].filter(Boolean).join("\n");
|
|
5195
5202
|
}
|
|
5196
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
|
+
});
|
|
5390
|
+
}
|
|
5391
|
+
|
|
5197
5392
|
// src/framework/index.ts
|
|
5198
5393
|
function extractMarkdownHeadings(markdownBody) {
|
|
5199
5394
|
const headings = [];
|
|
@@ -5950,6 +6145,7 @@ export {
|
|
|
5950
6145
|
TokenWasteHotspotSchema,
|
|
5951
6146
|
addSkillOrSubagent,
|
|
5952
6147
|
analyzeRepoTokenEconomy,
|
|
6148
|
+
applyMultiSelectKey,
|
|
5953
6149
|
auditCatalog,
|
|
5954
6150
|
auditCatalogTokenBudgets,
|
|
5955
6151
|
auditSkillTokenBudget,
|
|
@@ -5964,6 +6160,7 @@ export {
|
|
|
5964
6160
|
countWords,
|
|
5965
6161
|
createCollisionPair,
|
|
5966
6162
|
createCollisionReport,
|
|
6163
|
+
createMultiSelectState,
|
|
5967
6164
|
createSkillManifest,
|
|
5968
6165
|
createSubagentManifest,
|
|
5969
6166
|
detectInstalledHarnesses,
|
|
@@ -6007,6 +6204,7 @@ export {
|
|
|
6007
6204
|
renderCommandHelp,
|
|
6008
6205
|
renderGlobalHelp,
|
|
6009
6206
|
renderHeaderBanner,
|
|
6207
|
+
renderMultiSelectFrame,
|
|
6010
6208
|
renderNextSteps,
|
|
6011
6209
|
renderProgressBar,
|
|
6012
6210
|
renderSectionHeader,
|
|
@@ -6015,6 +6213,7 @@ export {
|
|
|
6015
6213
|
renderTokenBar,
|
|
6016
6214
|
resolveRuntimeTargets,
|
|
6017
6215
|
routeRepository,
|
|
6216
|
+
runMultiSelectPrompt,
|
|
6018
6217
|
runQuickstart,
|
|
6019
6218
|
scaffoldFrameworkItem,
|
|
6020
6219
|
scoreSkillAgainstProfile,
|
package/package.json
CHANGED
|
@@ -1,86 +1,86 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
2
|
+
"name": "skillops-cli",
|
|
3
|
+
"version": "1.3.2",
|
|
4
|
+
"description": "SkillOps — The Zero-API Framework & Benchmark-Verified Library for High-End AI Coding Skills & Context-Isolated Subagents with Universal Top-20 AI Agent Transpilation & Token Economy Auditing.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "OdevMatheus <matheusvita007@gmail.com>",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/OdevMatheus/SkillOps.git"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/OdevMatheus/SkillOps#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/OdevMatheus/SkillOps/issues"
|
|
15
|
+
},
|
|
16
|
+
"bin": {
|
|
17
|
+
"skillops-cli": "./dist/cli.js",
|
|
18
|
+
"skillops": "./dist/cli.js"
|
|
19
|
+
},
|
|
20
|
+
"main": "./dist/index.js",
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"import": "./dist/index.js"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"catalog",
|
|
31
|
+
".github/agents",
|
|
32
|
+
"docs/BENCHMARKS.md",
|
|
33
|
+
"SKILL_CONTRACT.md",
|
|
34
|
+
"README.md",
|
|
35
|
+
"LICENSE"
|
|
36
|
+
],
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=20.0.0"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "tsup",
|
|
42
|
+
"prepublishOnly": "npm run build && npm test",
|
|
43
|
+
"lint": "tsc --noEmit",
|
|
44
|
+
"typecheck": "tsc --noEmit",
|
|
45
|
+
"test": "vitest run",
|
|
46
|
+
"skillops": "node dist/cli.js"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"yaml": "^2.7.0",
|
|
50
|
+
"zod": "^3.24.2"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@types/node": "^22.13.0",
|
|
54
|
+
"tsup": "^8.4.0",
|
|
55
|
+
"typescript": "^5.8.2",
|
|
56
|
+
"vitest": "^3.0.7"
|
|
57
|
+
},
|
|
58
|
+
"keywords": [
|
|
59
|
+
"ai-agents",
|
|
60
|
+
"agent-skills",
|
|
61
|
+
"subagents",
|
|
62
|
+
"token-economy",
|
|
63
|
+
"claude-code",
|
|
64
|
+
"cursor",
|
|
65
|
+
"antigravity",
|
|
66
|
+
"codex",
|
|
67
|
+
"github-copilot",
|
|
68
|
+
"windsurf",
|
|
69
|
+
"cline",
|
|
70
|
+
"roocode",
|
|
71
|
+
"kilocode",
|
|
72
|
+
"zed",
|
|
73
|
+
"continue",
|
|
74
|
+
"aider",
|
|
75
|
+
"openhands",
|
|
76
|
+
"amp",
|
|
77
|
+
"goose",
|
|
78
|
+
"opencode",
|
|
79
|
+
"kiro",
|
|
80
|
+
"trae",
|
|
81
|
+
"amazon-q",
|
|
82
|
+
"junie",
|
|
83
|
+
"mcp",
|
|
84
|
+
"context-engineering"
|
|
85
|
+
]
|
|
86
86
|
}
|