@rhize/skill-forge 0.13.0 → 0.16.0
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/LICENSE +7 -0
- package/README.md +63 -930
- package/dist/cli.js +3159 -333
- package/dist/cli.js.map +1 -1
- package/dist/workflows/source-insight-planning/SKILL.md +130 -0
- package/dist/workflows/source-insight-planning/agents/openai.yaml +6 -0
- package/dist/workflows/source-insight-planning/references/capability-mapping.md +65 -0
- package/dist/workflows/source-insight-planning/references/jira-and-measurement.md +70 -0
- package/dist/workflows/source-insight-planning/references/source-and-evidence.md +87 -0
- package/dist/workflows/source-insight-planning/scripts/claude-source-insight-hook.sh +29 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
**The supply-chain gate for agent skills.**
|
|
4
4
|
|
|
5
|
-
Status:
|
|
5
|
+
Status: published — `@rhize/skill-forge@0.14.0` on npm (`0.16.0` in this repo, pending release),
|
|
6
|
+
0.x beta (Pro features free until 1.0)
|
|
6
7
|
|
|
7
8
|
> This project is unrelated to the [`skillforge`](https://www.npmjs.com/package/skillforge)
|
|
8
9
|
> package on npm, which is a Claude Skills *evaluation* framework. `skill-forge` (this package,
|
|
@@ -27,19 +28,15 @@ promote/hold/reject decision**, before it is allowed anywhere near your working
|
|
|
27
28
|
npx @rhize/skill-forge init
|
|
28
29
|
```
|
|
29
30
|
|
|
30
|
-
Optional, but recommended first: `init` detects which coding agents you have installed
|
|
31
|
-
|
|
32
|
-
and
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
[
|
|
39
|
-
required for a first run either way — skip `init` and skill-forge defaults to `<cwd>/.claude/skills`
|
|
40
|
-
as its promotion target and `~/.skill-forge/quarantine` as its sandbox (and offers to run `init` for
|
|
41
|
-
you the first time `add`/`scan`/`list`/`status` runs with no config present, in an interactive
|
|
42
|
-
terminal). See [docs/configuration.md](docs/configuration.md) for the full field reference.
|
|
31
|
+
Optional, but recommended first: `init` detects which coding agents you have installed (73 known
|
|
32
|
+
agents) and lets you pick which of their skill directories to gate, a default promotion target,
|
|
33
|
+
and an optional agent to hand follow-up prompts off to. It also checks whether each picked root is
|
|
34
|
+
under Git version control yet and, if not, offers to give it a baseline commit (exact commands
|
|
35
|
+
shown first, default No). No configuration is required either way — skip `init` and skill-forge
|
|
36
|
+
defaults to `<cwd>/.claude/skills` as its promotion target (and offers to run `init` for you the
|
|
37
|
+
first time `add`/`scan`/`list`/`status` runs with no config present, in an interactive terminal).
|
|
38
|
+
See [docs/commands/init.md](docs/commands/init.md) for the full detection/menu/Git-preflight
|
|
39
|
+
behavior and [docs/configuration.md](docs/configuration.md) for the config field reference.
|
|
43
40
|
|
|
44
41
|
```bash
|
|
45
42
|
npx @rhize/skill-forge add <owner>/<skill-name>
|
|
@@ -64,864 +61,31 @@ anything ending in `.git`), or a local filesystem path.
|
|
|
64
61
|
|
|
65
62
|
## Commands
|
|
66
63
|
|
|
67
|
-
|
|
68
|
-
skill-forge init [options] Detect installed agents and set gate targets / handoff agent
|
|
69
|
-
skill-forge add <source> [options] Quarantine-install a skill and run it through the gate
|
|
70
|
-
skill-forge scan <source> [options] Gate a skill without installing it (always cleans up)
|
|
71
|
-
skill-forge evolve <skill-dir> [options] Self-evolve an installed skill via SkillOpt-Sleep, re-gate, decide (Pro)
|
|
72
|
-
skill-forge audit [options] Doctor-style health check over the configured skill/MCP set (alias: doctor)
|
|
73
|
-
skill-forge finding accept <fp-prefix> Acknowledge a LOW/MEDIUM audit finding you've reviewed (human-only, no gate effect)
|
|
74
|
-
skill-forge finding revoke <fp-prefix> Remove a stored acceptance so the finding reports again
|
|
75
|
-
skill-forge finding list [options] List every accepted finding
|
|
76
|
-
skill-forge organize [options] Set-level capability registry + dependency graph across configured skills roots (Pro)
|
|
77
|
-
skill-forge find [query] [options] Discover skills via skills.sh and check partner security audits (free)
|
|
78
|
-
skill-forge watch [options] Drift check across every SOURCES.md provenance ledger (Pro)
|
|
79
|
-
skill-forge ingest [options] Hand the pending-ingestion queue off to a coding agent for the decide/absorb pass (Pro)
|
|
80
|
-
skill-forge queue close <id> --status <s> Close a queue entry after the decide pass (Pro)
|
|
81
|
-
skill-forge refine [options] Capture a project-scope override from real usage feedback (Pro)
|
|
82
|
-
skill-forge refine list [options] Show refinement history
|
|
83
|
-
skill-forge refine patterns [options] List tracked/ready/generalized/dismissed patterns
|
|
84
|
-
skill-forge refine promote <PATTERN-ID> Merge a ready pattern into the user-scope skill (Pro)
|
|
85
|
-
skill-forge refine rollback <backup-id> Restore a promotion backup (Pro)
|
|
86
|
-
skill-forge refine which <skill> Print override-resolution order for a skill
|
|
87
|
-
skill-forge routine [options] One scheduled maintenance pass: audit + drift + registry, cron-friendly (Pro)
|
|
88
|
-
skill-forge promote <id> [options] Re-gate a held quarantine entry and promote it
|
|
89
|
-
skill-forge reject <id> [options] Discard a held quarantine entry
|
|
90
|
-
skill-forge config <sub> [args] Read/write open-ended preferences (list|get|set|unset|propose|review)
|
|
91
|
-
skill-forge list List skills currently held in quarantine
|
|
92
|
-
skill-forge status Show configuration and quarantine summary
|
|
93
|
-
skill-forge guide [topic] Orientation: what this does, your current state, the next command
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
### `init`
|
|
97
|
-
|
|
98
|
-
```bash
|
|
99
|
-
skill-forge init # interactive: pick targets, default target, handoff agent
|
|
100
|
-
skill-forge init --defaults # non-interactive: agents found on PATH, first as default (CI)
|
|
101
|
-
skill-forge init --list # print detected agent skill roots and exit — no writes
|
|
102
|
-
skill-forge init --all-agents # don't narrow to agents whose CLI is on PATH — keep every root
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
Probes the known agent matrix (`src/agents.ts`) for both project-relative (`.claude/skills`, ...)
|
|
106
|
-
and global (`~/.codex/skills`, ...) skill directories that already exist on disk, then writes
|
|
107
|
-
`skillsRoots`, `agents`, `defaultTarget`, and (if you pick a handoff agent) `handoffCommand` to
|
|
108
|
-
`config.json`. Safe to re-run any time — it always starts from your existing config and only
|
|
109
|
-
overwrites the fields it's responsible for. If no `config.json` exists yet, `add`/`scan`/`list`/
|
|
110
|
-
`status` offer to run this for you on first use (skipped entirely for `--json`/`--yes`/non-TTY
|
|
111
|
-
invocations, so scripted runs never block on a prompt).
|
|
112
|
-
|
|
113
|
-
**Menus are keyed on the PATH, not the agent (v0.11).** Many agents share one skills directory —
|
|
114
|
-
18 entries in the agent matrix use `.agents/skills` as their project root — so the gate-target and
|
|
115
|
-
default-target menus list each *distinct* root once, labelled with the agents that resolve to it
|
|
116
|
-
(`19 agents (project): Amp, Replit, Universal, +16 more`), and `skillsRoots`/`mcpTargets` are
|
|
117
|
-
written deduped. `config.agents` still records every agent, since it's an id→root map. Detection
|
|
118
|
-
output says so explicitly when roots collapse (`→ 21 agents share 3 distinct skills root(s)`).
|
|
119
|
-
Configs written by earlier versions are deduped on load, so no re-run is required to clean one up.
|
|
120
|
-
|
|
121
|
-
**Narrowed to agents you actually have (v0.11).** Because a shared directory can't tell you which
|
|
122
|
-
of its 18 agents you use, init also checks PATH: a root is pre-selected when at least one agent
|
|
123
|
-
mapped to it has its CLI installed, and roots with none are still listed, just switched off with
|
|
124
|
-
the reason shown.
|
|
125
|
-
|
|
126
|
-
```
|
|
127
|
-
[x] 1. /Users/you/.agents/skills
|
|
128
|
-
on PATH: Codex, Gemini CLI (project) (+17 other agents share this path)
|
|
129
|
-
[ ] 3. /Users/you/.openclaw/skills
|
|
130
|
-
OpenClaw (global) — no verified CLI name to check
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
The PATH check is a **look-up only — nothing found is ever executed** (no `--version` probe), and
|
|
134
|
-
binary names are held to the same evidence bar as the skill paths: an agent with no verified
|
|
135
|
-
command name reports "unknown", never "not installed". `--all-agents` turns narrowing off, and it
|
|
136
|
-
disables itself automatically if no agent CLI is found at all, so it can never reduce a working
|
|
137
|
-
detection to an empty config. The handoff menu is only *reordered* by it — installed CLIs float to
|
|
138
|
-
the top and everything detected stays pickable.
|
|
139
|
-
|
|
140
|
-
**Selecting things (v0.11).** The multi-selects take a whole answer at once — `2`, `1 3`, `2, 4`,
|
|
141
|
-
`2-5`, plus `all` and `none` — and Enter confirms. Anything unrecognized is named back to you and
|
|
142
|
-
ignored, never silently swallowed. The single-choice prompts (default target, handoff agent)
|
|
143
|
-
**re-ask** on an answer that isn't one listed number instead of falling back to option 1, so a
|
|
144
|
-
multi-value or mistyped answer can no longer write a target you didn't choose. Ctrl+D at any
|
|
145
|
-
prompt exits cleanly.
|
|
146
|
-
|
|
147
|
-
**Init now ends by offering the audit (v0.8).** After an interactive run writes its config, it
|
|
148
|
-
asks "Run the skills & MCP audit now? [Y/n]" (default yes) and, if accepted, runs
|
|
149
|
-
`skill-forge audit` interactively — see [`audit`](#audit-v08) below. `init --defaults` runs it too,
|
|
150
|
-
but non-interactively (`--yes`): a report is written, with no business-profile prompt, no
|
|
151
|
-
foundation scaffold, and no agent handoff. `init --list` and an aborted/empty selection stay
|
|
152
|
-
write-free, so neither writes a config nor runs the audit.
|
|
153
|
-
|
|
154
|
-
### `add`
|
|
155
|
-
|
|
156
|
-
```bash
|
|
157
|
-
skill-forge add owner/name
|
|
158
|
-
skill-forge add https://github.com/owner/repo.git --target ./.claude/skills
|
|
159
|
-
skill-forge add ./local-skill-dir --yes
|
|
160
|
-
skill-forge add owner/name --json
|
|
161
|
-
skill-forge add owner/name --yes --ingest
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
Installs the source into a quarantine sandbox, then runs it through the gate: profile → safety
|
|
165
|
-
scan → overlap analysis against the configured skills root (Pro) → report. Nothing touches the
|
|
166
|
-
target skills root until you decide.
|
|
167
|
-
|
|
168
|
-
| Option | Effect |
|
|
169
|
-
|---|---|
|
|
170
|
-
| *(none)* | Prompts you to **promote**, **hold**, or **reject** the candidate. |
|
|
171
|
-
| `-y, --yes` | Skips the prompt and honors the gate verdict: a `block` safety verdict is rejected (process exits nonzero); anything else (`pass`/`warn`) is promoted. |
|
|
172
|
-
| `-t, --target <dir>` | Skills root to promote into. Defaults to the config's `defaultTarget`, then `skillsRoots[0]`. |
|
|
173
|
-
| `--json` | Prints the gate result (profile, safety findings, overlap) as JSON instead of the terminal report box. Implies non-interactive: the decision is made the same way `--yes` makes it (verdict decides promote/hold/reject), never an interactive prompt. |
|
|
174
|
-
| `--ingest` | Pro (free during the 0.x beta). After a successful promote, hands off to a coding agent — see [Ingestion handoff](#ingestion-handoff---ingest). |
|
|
175
|
-
| `--skill-map <path>` | Path to a generated `rhize-plugins` skill map (Phase 4 of that repo's skill-map-graph-substrate plan). When given, ranks the candidate's name/description against every `skill` node in the map — a near-duplicate of an already-shipped marketplace skill is folded into the safety findings as a `HIGH`-severity finding (escalates the verdict to `block`, so it's held rather than silently promoted); a moderate overlap is `MEDIUM` (`warn`). Free (not Pro-gated) — this enforces the marketplace's own curation rule ("close the gap, don't duplicate"), not a premium ranking feature. Missing/unreadable map: printed to stderr, never fatal. **Two map variants exist, with different coverage**: the **static** map (`rhize-plugins/generated/skill-map.static.json`) is first-party-only — it only knows about that marketplace's own skills, so it cannot catch a candidate that duplicates an *installed third-party plugin's* skill. The **resolved** map (`~/.claude/context-manager/skill-map.resolved.json`, produced by `rhize-context-manager`) additionally carries the full third-party ecosystem inventory. Point `--skill-map` at the resolved map when you want ecosystem-wide duplicate detection; the static map is enough only when you're curating a single first-party marketplace against itself. |
|
|
176
|
-
|
|
177
|
-
**Bugfix (v0.13.0):** `--skill-map` previously matched nothing against either real map variant — the loader read a `type` field that the real generated artifact never sets (it uses `kind`), so every node was silently invisible to the overlap check. `loadSkillMap()` now normalizes `kind` → `type` at load time; regression coverage lives in `test/mapOverlap.realmap.test.ts` against vendored real-map snapshots. If you were relying on `--skill-map` before v0.13.0, it was a no-op — re-run `add`/`scan` on anything you're unsure about.
|
|
178
|
-
|
|
179
|
-
**Extends-declared overlap exemption**: a candidate can declare `metadata.rhize.extends:
|
|
180
|
-
["<skill-name>" | "<plugin>/<skill-name>"]` in its SKILL.md frontmatter to mark itself a
|
|
181
|
-
deliberate specialization/layering of an existing map skill. When the top `--skill-map` match is
|
|
182
|
-
a skill the candidate declares it extends, that finding is downgraded from a HOLD-level safety
|
|
183
|
-
finding to an informational notice printed above the report — it never escalates the verdict.
|
|
184
|
-
Overlap with any *other* skill (a different match, or a second candidate/skill pair) still holds
|
|
185
|
-
at full severity: the exemption applies per declared pair, not globally, so declaring an
|
|
186
|
-
extension of skill X never waives overlap with skill Y.
|
|
187
|
-
|
|
188
|
-
A promoted skill gets a provenance entry appended to `<target>/SOURCES.md`, and every promote or
|
|
189
|
-
hold decision is recorded to `~/.skill-forge/queue.json` (or `$SKILL_FORGE_HOME/queue.json`) — see
|
|
190
|
-
[`docs/queue-schema.md`](docs/queue-schema.md) for the entry schema. A reject writes neither —
|
|
191
|
-
nothing is left behind to record. These are Pro features that run free during the 0.x beta (see
|
|
192
|
-
[docs/pro.md](docs/pro.md#beta-pricing-0x)): with no valid license, `add` still writes them, and
|
|
193
|
-
prints a one-line notice above the report instead of skipping them.
|
|
194
|
-
|
|
195
|
-
`add`/`scan` also accept `--artifact mcp` (plus `add`-only `--mcp-target <file>`/`--force`) to gate
|
|
196
|
-
an MCP server instead of a skill — see [MCP gating](#mcp-gating-v05) below.
|
|
197
|
-
|
|
198
|
-
### `scan`
|
|
199
|
-
|
|
200
|
-
```bash
|
|
201
|
-
skill-forge scan owner/name
|
|
202
|
-
skill-forge scan owner/name --json
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
Runs the same gate pipeline as `add` (profile → safety → overlap → report) but never promotes
|
|
206
|
-
anything — the quarantine sandbox is always cleaned up afterward, on success or failure. Exits
|
|
207
|
-
nonzero when the safety verdict is `block`. `--json` prints the same gate-result payload shape as
|
|
208
|
-
`add`'s. Also accepts `--skill-map <path>` — see `add`'s option table above.
|
|
209
|
-
|
|
210
|
-
### `evolve` (v0.7)
|
|
211
|
-
|
|
212
|
-
```bash
|
|
213
|
-
skill-forge evolve .claude/skills/my-skill
|
|
214
|
-
skill-forge evolve .claude/skills/my-skill --yes
|
|
215
|
-
skill-forge evolve .claude/skills/my-skill --dry-run
|
|
216
|
-
skill-forge evolve .claude/skills/my-skill --backend claude --yes
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
Pro (free during the 0.x beta). Orchestrates [microsoft/SkillOpt](https://github.com/microsoft/SkillOpt)'s
|
|
220
|
-
`skillopt-sleep` CLI (`pip install skillopt`) to propose a self-evolution of an already-installed
|
|
221
|
-
skill — harvest recent sessions, generate a candidate replacement `SKILL.md`/`CLAUDE.md`, and stage
|
|
222
|
-
it — then runs the **staged proposal**, never the live skill, back through skill-forge's own static
|
|
223
|
-
safety ruleset before you decide anything. SkillOpt-Sleep's own validation gate is score-only; it
|
|
224
|
-
never content-vets the generated markdown. This closes that gap.
|
|
225
|
-
|
|
226
|
-
| Option | Effect |
|
|
227
|
-
|---|---|
|
|
228
|
-
| `--project <dir>` | Project dir passed to SkillOpt-Sleep as `--project`. Defaults to cwd. |
|
|
229
|
-
| `--dry-run` | Uses SkillOpt-Sleep's `dry-run` subcommand — report only, nothing staged. |
|
|
230
|
-
| `--backend <name>` | SkillOpt-Sleep backend. Defaults to `mock` (offline, deterministic, no network). |
|
|
231
|
-
| `--lookback-hours <n>` | Hours of session history for SkillOpt-Sleep to harvest. |
|
|
232
|
-
| `-y, --yes` | Skips interactive prompts (the disclosure confirm below, and the promote/hold/reject prompt) and honors the re-gate verdict automatically. |
|
|
233
|
-
| `--json` | Prints the re-gate result as JSON instead of the terminal report. Implies non-interactive, same as `add`'s `--json`. |
|
|
234
|
-
| `--force` | Allows re-adopting a staging dir whose proposed content already matches the live skill (see the double-adopt guard below). |
|
|
235
|
-
|
|
236
|
-
**Requires `skillopt-sleep` on PATH** — skill-forge never installs it for you. If it's missing,
|
|
237
|
-
`evolve` prints `pip install skillopt` + a docs pointer and exits, rather than attempting an
|
|
238
|
-
auto-install (the same "detect, don't install" discipline the rest of the gate follows).
|
|
239
|
-
|
|
240
|
-
**Data boundary.** The default `mock` backend is fully offline — harvesting and proposal
|
|
241
|
-
generation both run locally, no session data leaves the machine. Any other backend (`claude`,
|
|
242
|
-
`codex`, `azure_openai`, ...) sends truncated excerpts from harvested sessions and derived tasks to
|
|
243
|
-
the provider you selected; per SkillOpt-Sleep's own docs this is not currently guaranteed to be
|
|
244
|
-
secret-free. `evolve` prints that disclosure and requires either `--yes` or an interactive `y/N`
|
|
245
|
-
confirmation before a non-`mock` run proceeds — `--json` is non-interactive, so a non-`mock` run
|
|
246
|
-
under `--json` without `--yes` is refused rather than silently sending data off-machine.
|
|
247
|
-
|
|
248
|
-
**Re-gate.** SkillOpt-Sleep only ever *stages* a proposal (`<project>/.skillopt-sleep/staging/<timestamp>/`
|
|
249
|
-
— full replacement files, never auto-adopted). `evolve` copies just `proposed_SKILL.md` (and
|
|
250
|
-
`proposed_CLAUDE.md`, if present) into a fresh temporary directory and runs skill-forge's own
|
|
251
|
-
static safety ruleset over that copy — the same one `add`/`scan` use, at your configured
|
|
252
|
-
`strictness`. `report.json`/`diagnostics.json` (SkillOpt-Sleep's own redacted holdout evidence) are
|
|
253
|
-
never scanned. The result renders through the same terminal report / `--json` shape as `add`/`scan`.
|
|
254
|
-
|
|
255
|
-
**Decision.** Same promote/hold/reject semantics as `add`: `--yes`/`--json` honor the re-gate
|
|
256
|
-
verdict (a `block` is rejected); otherwise you're prompted.
|
|
257
|
-
|
|
258
|
-
- **promote** — runs SkillOpt-Sleep's own `adopt --staging <dir>` (which backs up the live file(s)
|
|
259
|
-
before copying the proposal over them), then records a provenance entry to the target skill's
|
|
260
|
-
`SOURCES.md` and a pending-ingestion queue entry (`origin: "evolve"`, see
|
|
261
|
-
[docs/queue-schema.md](docs/queue-schema.md)) so a later ingest pass reviews the evolution rather
|
|
262
|
-
than an external source.
|
|
263
|
-
- **hold** — leaves the staging dir exactly as SkillOpt-Sleep produced it (its own `status` command
|
|
264
|
-
still lists it); `report.md` has the full evidence.
|
|
265
|
-
- **reject** — deletes the staging dir.
|
|
266
|
-
|
|
267
|
-
**Double-adopt guard.** SkillOpt-Sleep's `adopt` has no confirmation of its own, and adopting the
|
|
268
|
-
same staging dir twice overwrites *its* backup — the pre-evolution original would be lost. Before
|
|
269
|
-
adopting, `evolve` refuses (unless `--force`) when the staged proposal is already byte-identical to
|
|
270
|
-
the live skill it would replace, since that's the signature of a staging dir that was already
|
|
271
|
-
adopted once.
|
|
272
|
-
|
|
273
|
-
### `audit` (v0.8)
|
|
274
|
-
|
|
275
|
-
```bash
|
|
276
|
-
skill-forge audit
|
|
277
|
-
skill-forge doctor # alias
|
|
278
|
-
skill-forge audit --json --report ./audit.md
|
|
279
|
-
skill-forge audit --yes
|
|
280
|
-
skill-forge audit --foundation
|
|
281
|
-
skill-forge audit --handoff
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
A re-runnable, doctor-style health check over the skill/MCP set you've **already** configured —
|
|
285
|
-
unlike `add`/`scan`, which gate a new candidate before it's installed, `audit` inventories what's
|
|
286
|
-
already there and looks for hygiene issues and consolidation/refinement opportunities. Requires a
|
|
287
|
-
real, saved config (`skill-forge init` first) — it never silently audits an invented default.
|
|
288
|
-
`init` now ends by offering to run it (see [`init`](#init) above); it's equally safe to run any
|
|
289
|
-
time on its own.
|
|
290
|
-
|
|
291
|
-
| Option | Effect |
|
|
292
|
-
|---|---|
|
|
293
|
-
| *(none)* | Interactive: offers to capture/reuse a business profile, then runs the audit, then offers the foundation scaffold and agent handoff. |
|
|
294
|
-
| `--json` | Prints the full audit report as JSON instead of the terminal summary. Non-interactive — skips the business-profile prompt. |
|
|
295
|
-
| `-y, --yes` | Skips every interactive prompt (business profile, foundation, handoff). Never implies `--foundation` or `--handoff`. |
|
|
296
|
-
| `--report <file>` | Write the report here instead of the default `~/.skill-forge/reports/audit-<ISO-timestamp>.md`. Refuses an existing path — never overwrites. |
|
|
297
|
-
| `--foundation` | The one skills-root write this command can make: scaffold a `business-foundation` skill from the captured business profile (see below). |
|
|
298
|
-
| `--handoff` | Hand the written report off to your configured coding agent with the bundled curation prompt, via the same handoff plumbing as `add --ingest`. |
|
|
299
|
-
|
|
300
|
-
**What it inventories/checks.** Every configured `skillsRoots` entry — symlink-aware, deduped by
|
|
301
|
-
realpath so a skill reachable via two roots or an aliased symlink is reported once, with alias
|
|
302
|
-
locations kept rather than dropped. Per skill: strict frontmatter validation (a missing/unclosed
|
|
303
|
-
fence or missing `name`/`description` is a finding, not silently backfilled), `SKILL.md` size and
|
|
304
|
-
an estimated token count, and a full `scanSafety` pass — the same safety ruleset `add`/`scan` run.
|
|
305
|
-
Every configured `mcpTargets` file: JSON targets get full server enumeration (name, command
|
|
306
|
-
basename, package spec, arg/env **counts** — never values); TOML targets (e.g. Codex CLI's
|
|
307
|
-
`config.toml`) get the same textual MCP safety scan `--artifact mcp` uses, since there's no
|
|
308
|
-
structured TOML enumeration. A per-item failure (unreadable skill, broken symlink, malformed MCP
|
|
309
|
-
config) becomes a finding — it never aborts the run.
|
|
310
|
-
|
|
311
|
-
**Accepted findings (v0.12).** Every finding in the report carries a fingerprint
|
|
312
|
-
(`(fp a1b2c3d4e5f6)`); `Findings` shows **active** findings only, and a separate
|
|
313
|
-
**Accepted findings** section lists whatever you've reviewed and accepted via
|
|
314
|
-
[`skill-forge finding accept`](#finding-v012) — permanently, with reason and date, even after it
|
|
315
|
-
stops matching (see that section for the full contract). `summary.acceptedCount` and each
|
|
316
|
-
finding's `fingerprint` are additive `--json` fields; nothing accepted is ever silently deleted.
|
|
317
|
-
|
|
318
|
-
**Opportunity pass.** Beyond hygiene, the report surfaces:
|
|
319
|
-
|
|
320
|
-
- **Overlap clusters** (Pro, free during the 0.x beta) — cross-root overlap scoring across every
|
|
321
|
-
inventoried skill, grouped into connected components, each with a top pairwise score and a
|
|
322
|
-
suggested verb code (`ABSORB`/`FORK`/`DEFER` — `opportunities.overlapLocked` in `--json` output
|
|
323
|
-
says whether this ran or was Pro-locked, without string-matching `notices`). The fuller
|
|
324
|
-
five-verb matrix (adding `REJECT`/`WATCH`) belongs to the agent-side curation prompt's deeper
|
|
325
|
-
decide pass (`--handoff`), not this report. Locked → that section shows the standard upgrade
|
|
326
|
-
notice and empty clusters; everything else in the report still runs.
|
|
327
|
-
- **Evolve-eligible skills** — structurally valid, safety-passing skills, labeled as eligible for
|
|
328
|
-
`skill-forge evolve` — an eligibility list, not a judgment that they need refining.
|
|
329
|
-
- **A business-foundation opportunity** — offered whenever `config.foundationSkillPath` isn't set
|
|
330
|
-
yet.
|
|
331
|
-
|
|
332
|
-
**Business profile.** Interactive runs (never under `--yes`/`--json`/non-TTY) open with a
|
|
333
|
-
business-name/industry/audiences/workflows/constraints Q&A, preceded by an explicit "don't enter
|
|
334
|
-
credentials or confidential customer data" warning. An existing stored profile is offered for
|
|
335
|
-
reuse rather than re-asked, and a fresh capture is shown back as a summary before it's saved to
|
|
336
|
-
`config.businessProfile`. This profile grounds both the foundation scaffold and the curation
|
|
337
|
-
handoff prompt.
|
|
338
|
-
|
|
339
|
-
**Report location + privacy.** Written to `~/.skill-forge/reports/audit-<ISO-timestamp>.md` by
|
|
340
|
-
default (`--report <file>` to override), created with `{ flag: 'wx', mode: 0o600 }` — exclusive
|
|
341
|
-
create (refuses to overwrite an existing report) and owner-only permissions. MCP `env` values and
|
|
342
|
-
arbitrary arg values are never written into the report or the `--json` payload — only server/
|
|
343
|
-
command names, package specs, and counts.
|
|
344
|
-
|
|
345
|
-
**Explicit opt-ins.** `--foundation` is the *only* way this command writes to a skills root: it
|
|
346
|
-
scaffolds `<targetRoot>/business-foundation/SKILL.md` from the captured business profile
|
|
347
|
-
(containment-checked against `config.skillsRoots`, refuses an existing or symlinked destination,
|
|
348
|
-
writes atomically, and runs `scanSafety` on the generated content before it's placed), then
|
|
349
|
-
records the path to `config.foundationSkillPath`. `--handoff` is the *only* way this command
|
|
350
|
-
launches an agent — same argv-array, no-shell discipline as `--ingest` (see
|
|
351
|
-
[Ingestion handoff](#ingestion-handoff---ingest)), using the bundled `assets/curation-prompt.md`
|
|
352
|
-
in place of `ingest-prompt.md`. `--yes` (and `init --defaults`, which passes it through) never
|
|
353
|
-
implies either — a non-interactive run writes only the report and, if a profile was already
|
|
354
|
-
stored, the config; nothing else.
|
|
355
|
-
|
|
356
|
-
### `finding` (v0.12)
|
|
357
|
-
|
|
358
|
-
```bash
|
|
359
|
-
skill-forge finding accept <fingerprint-prefix> --reason "Funnel genuinely needs root; verified"
|
|
360
|
-
skill-forge finding revoke <fingerprint-prefix>
|
|
361
|
-
skill-forge finding list [--stale] [--json]
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
Acknowledge an `audit` finding you've reviewed and accepted, so it stops counting against
|
|
365
|
-
`routine --fail-on` and the `add`/`scan` advisory while staying **permanently visible** in its own
|
|
366
|
-
report section — an audit you can't triage decays into noise, and noise is how the one real
|
|
367
|
-
finding gets skimmed. Every finding in an `audit`/`routine` report now carries a 12-char
|
|
368
|
-
fingerprint (`(fp a1b2c3d4e5f6)`) you copy into `accept`/`revoke`.
|
|
369
|
-
|
|
370
|
-
| Command | Effect |
|
|
371
|
-
|---|---|
|
|
372
|
-
| `finding accept <fp-prefix> --reason <text>` | Records an acceptance. Re-runs the read-only audit engine to resolve the prefix against what's **currently active** — you can only accept a finding that exists right now, never from a stale report. `--reason` is mandatory (1-200 chars, no control characters). |
|
|
373
|
-
| `finding revoke <fp-prefix>` | Removes a stored acceptance so the finding reports again. Resolves against the **store**, not a fresh audit run — the target may no longer be producible, which is exactly when you'd want to clean up. |
|
|
374
|
-
| `finding list [--stale] [--json]` | Lists every accepted finding (severity, rule, target, reason, accepted date, fingerprint). `--stale` filters to records whose target no longer exists on disk. |
|
|
375
|
-
|
|
376
|
-
**Identity is content-derived, not a name you pick.** A finding's fingerprint is
|
|
377
|
-
`sha256(severity + rule + target + the offending line's text)` — deliberately excluding the LINE
|
|
378
|
-
NUMBER (drifts on unrelated edits) and deliberately including SEVERITY (so a rule re-tuned to a
|
|
379
|
-
higher severity for the same content can't inherit an ack minted against the lower one). Any change
|
|
380
|
-
to the offending content **fails open to re-reporting** — this is the design, not a bug: the
|
|
381
|
-
alternative (key on rule+path only) is the classic baseline trap, where accepting one benign line
|
|
382
|
-
silently suppresses every future line the same rule matches in that file. Full contract, the
|
|
383
|
-
per-rule `context` table, and fail-open read semantics: see
|
|
384
|
-
[docs/accepted-findings-schema.md](docs/accepted-findings-schema.md).
|
|
385
|
-
|
|
386
|
-
**Severity-capped, human-only, no override.** `finding accept` refuses `HIGH`/`CRITICAL` findings
|
|
387
|
-
outright — there is no `--force`. The precision problem this command exists to solve lives at
|
|
388
|
-
`LOW`/`MEDIUM`; a `HIGH` false positive is a rule bug to fix, not something to baseline. This is a
|
|
389
|
-
human-door CLI (`config set` model), not the agent-facing propose/review queue — both
|
|
390
|
-
`assets/ingest-prompt.md` and `assets/curation-prompt.md` instruct agents to never run
|
|
391
|
-
`finding accept`/`finding revoke` themselves; an agent that judges a finding a false positive says
|
|
392
|
-
so in its summary and lets the user run the command.
|
|
393
|
-
|
|
394
|
-
**Never a gate input.** Acceptances only ever affect `audit`'s own report classification (and,
|
|
395
|
-
downstream, `routine --fail-on` and the `add`/`scan` advisory) — `add`/`scan`/`promote <id>`/
|
|
396
|
-
`evolve`'s re-gate never reads the accepted-findings store. See
|
|
397
|
-
[docs/gate-policy.md](docs/gate-policy.md#accepted-findings-v012).
|
|
398
|
-
|
|
399
|
-
### `organize` (v0.9, Pro)
|
|
400
|
-
|
|
401
|
-
```bash
|
|
402
|
-
skill-forge organize
|
|
403
|
-
skill-forge organize --json
|
|
404
|
-
skill-forge organize --out ./registry.json
|
|
405
|
-
skill-forge organize --usage-snapshot ./skill-monitor-snapshot.json
|
|
406
|
-
```
|
|
407
|
-
|
|
408
|
-
Pro (free during the 0.x beta). Builds a set-level view across every configured `skillsRoots`
|
|
409
|
-
entry: a **capability registry** (per-skill row — `tier`/`domain`/`consumes`/`provenance`/
|
|
410
|
-
`maturity` frontmatter, plus untagged/rot flags) and a **dependency graph** (nodes, `consumes`
|
|
411
|
-
edges, orphans, hot resources, dangling edges, cycles). This is the TS port of the plugin's
|
|
412
|
-
`index_skills.py` + `build_dependency_graph.py`, merged into one command — graph nodes are keyed
|
|
413
|
-
by realpath-qualified stable IDs (not bare frontmatter names), so duplicate names across roots
|
|
414
|
-
don't collapse adjacency; duplicate-name ambiguity and unresolved `consumes` targets are reported
|
|
415
|
-
rather than silently dropped.
|
|
416
|
-
|
|
417
|
-
| Option | Effect |
|
|
418
|
-
|---|---|
|
|
419
|
-
| `--json` | Print the registry + graph as JSON instead of the terminal summary. |
|
|
420
|
-
| `--out <file>` | Write the full report JSON to this path. Refuses an existing path (`wx`, `0o600` — same discipline as `audit --report`). |
|
|
421
|
-
| `--usage-snapshot <file>` | Join per-skill usage counts from a skill-monitor snapshot JSON (`usage_joined` in the output); a zero-match snapshot is warned about, not silently ignored. |
|
|
422
|
-
|
|
423
|
-
`organize` performs its own self-contained scan — it does not reuse `audit`'s inventory walker
|
|
424
|
-
— and, like every other command, never executes anything found under a scanned skills root.
|
|
425
|
-
|
|
426
|
-
### `find` (v0.9, free)
|
|
427
|
-
|
|
428
|
-
```bash
|
|
429
|
-
skill-forge find "pdf form filling"
|
|
430
|
-
skill-forge find "pdf form filling" --limit 20 --json
|
|
431
|
-
skill-forge find --audit owner/skill-name
|
|
432
|
-
skill-forge find --get owner/skill-name
|
|
433
|
-
skill-forge find --curated
|
|
434
|
-
```
|
|
435
|
-
|
|
436
|
-
Free. TS port of the plugin's `skills_sh.py` — discovery only, exactly one mode per invocation
|
|
437
|
-
(search, `--audit`, `--get`, or `--curated`; mutually exclusive):
|
|
438
|
-
|
|
439
|
-
| Mode | Effect |
|
|
440
|
-
|---|---|
|
|
441
|
-
| `<query>` (default) | Search skills.sh; each result shows id, install count, and the install hint `skill-forge add <id>` — **not** `npx skills add`, since `add` runs the full local quarantine/gate. |
|
|
442
|
-
| `--audit <id>` | Partner security-audit verdicts (Socket, Snyk, Gen Agent Trust Hub, …) for a specific skills.sh id — pass/warn/fail + risk. No auto-audit of search results. |
|
|
443
|
-
| `--get <id>` | Detail + file tree for a specific skills.sh id. |
|
|
444
|
-
| `--curated` | List skills.sh's curated skills. |
|
|
445
|
-
| `--limit <n>` | Max search results (default 10). |
|
|
446
|
-
| `--json` | Print the raw API payload as JSON. |
|
|
447
|
-
|
|
448
|
-
Search results are labeled **unvetted** — `find` never installs or gates anything itself. Think
|
|
449
|
-
of `find --audit` as the partner-verdict layer and `add`/`scan` as the deep local gate; they're
|
|
450
|
-
two independent checks, not a replacement for one another.
|
|
451
|
-
|
|
452
|
-
**Auth: `VERCEL_OIDC_TOKEN`.** All requests are HTTPS GETs to `https://skills.sh/api/v1`, using a
|
|
453
|
-
bearer token read from `process.env.VERCEL_OIDC_TOKEN` — never stored in config, never printed.
|
|
454
|
-
Without it, `find` fails loud (exit code 3) with setup guidance:
|
|
455
|
-
|
|
456
|
-
```
|
|
457
|
-
1. skills.sh authenticates with a short-lived Vercel OIDC token
|
|
458
|
-
2. npm i -g vercel && vercel link && vercel env pull (writes VERCEL_OIDC_TOKEN to .env.local)
|
|
459
|
-
3. export VERCEL_OIDC_TOKEN from .env.local into your shell before running this command
|
|
460
|
-
(or set it directly: export VERCEL_OIDC_TOKEN=...) — docs: https://skills.sh/docs/api
|
|
461
|
-
```
|
|
462
|
-
|
|
463
|
-
Note step 3: `vercel env pull` writes the token into `.env.local`, it does not export it into your
|
|
464
|
-
shell — you (or your shell's dotenv loader) still need to export it before `find` can see it.
|
|
465
|
-
|
|
466
|
-
### `watch` (v0.9, Pro)
|
|
467
|
-
|
|
468
|
-
```bash
|
|
469
|
-
skill-forge watch
|
|
470
|
-
skill-forge watch --offline
|
|
471
|
-
skill-forge watch --json
|
|
472
|
-
skill-forge watch --skill-map generated/skill-map.static.json
|
|
473
|
-
```
|
|
474
|
-
|
|
475
|
-
Pro (free during the 0.x beta). TS port of the plugin's `record_provenance.py --check-drift`.
|
|
476
|
-
Scans **every** configured `skillsRoots` entry's `SOURCES.md` provenance ledger (deduped by
|
|
477
|
-
realpath, each reported row names its ledger) and reports, per tracked entry, whether the
|
|
478
|
-
recorded upstream ref still matches what the source currently resolves to.
|
|
479
|
-
|
|
480
|
-
For entries whose `Source` parses as a git URL and whose `Upstream ref` looks like a commit/tag,
|
|
481
|
-
`watch` runs a fixed, first-party `git ls-remote <url> [ref]` (argv array, no shell) to compare —
|
|
482
|
-
`--offline` skips all network checks and just lists entries for manual comparison. Every other
|
|
483
|
-
entry is listed for manual checking regardless.
|
|
484
|
-
|
|
485
|
-
**`watch` NEVER executes a ledger's stored drift-check command string.** That string is
|
|
486
|
-
attacker-influenceable data — anyone who can write to a skills root's `SOURCES.md` controls it.
|
|
487
|
-
It is only ever printed, sanitized, as a suggestion for you (or an agent) to run yourself.
|
|
488
|
-
|
|
489
|
-
**`--skill-map <path>` (Phase 4 of `rhize-plugins`' skill-map-graph-substrate plan)** additionally
|
|
490
|
-
drift-checks every `fork-of` edge in a generated skill map: for each edge it resolves the local
|
|
491
|
-
`skill` node's `path`/`contentHash` and the upstream (`external`) node's `url`/`path`, fetches or
|
|
492
|
-
reads the upstream content, and compares content hashes. Same never-execute posture as the ledger
|
|
493
|
-
check above: nothing derived from the map — including a fork-of edge's own `driftCheck`
|
|
494
|
-
metadata — is ever executed; only fetch/read/hash/compare. A missing/unreadable map is a warning,
|
|
495
|
-
never fatal. A node's repo-relative `path` (e.g. `rhize-context-manager/skills/x/SKILL.md`) is
|
|
496
|
-
resolved against cwd, the map's own directory, and that directory's parent (in that order) — not
|
|
497
|
-
cwd alone — so `watch --skill-map <path>` gives correct verdicts regardless of the directory you
|
|
498
|
-
run it from.
|
|
499
|
-
|
|
500
|
-
**Verdict**, per fork-of edge — three-way comparison, four verdict states when both hashes below
|
|
501
|
-
are present on the map, else the older two-way fallback (`in-sync`/`drifted`, `contentHash` vs
|
|
502
|
-
freshly-fetched upstream):
|
|
503
|
-
|
|
504
|
-
| local-normalized vs baseline | upstream-now vs baseline | status | actionable |
|
|
505
|
-
|---|---|---|---|
|
|
506
|
-
| == | == | `in-sync` | no |
|
|
507
|
-
| != | == | `local-only` | no (deliberate fork divergence, e.g. Rhize's added frontmatter) |
|
|
508
|
-
| == | != | `upstream-moved` | yes |
|
|
509
|
-
| != | != | `diverged` | yes |
|
|
510
|
-
|
|
511
|
-
The three-way matrix fires only when the local `skill` node carries `contentHashNormalized` (a
|
|
512
|
-
hash of the file with Rhize-injected frontmatter stripped, computed once by the rhize-plugins
|
|
513
|
-
compiler) **and** the upstream `external` node carries `baselineHash` (the upstream content hash
|
|
514
|
-
as of the last human review, recorded in `rhize-plugins`' SOURCES.md and copied onto the node by
|
|
515
|
-
that compiler — skill-forge never computes or fetches it itself). Either field missing on a given
|
|
516
|
-
edge falls back to the two-way compare for that edge, so older maps keep working. All four
|
|
517
|
-
three-way verdicts — `in-sync`, `local-only`, `upstream-moved`, and `diverged` — carry
|
|
518
|
-
`baselineHash`/`upstreamHash` in the JSON output; the two-way-fallback rows and
|
|
519
|
-
`upstream-unreachable`/`local-missing` never do (no verdict without a successful fetch/read, so
|
|
520
|
-
there is nothing to compare against a baseline). Every row also carries an `actionable` boolean
|
|
521
|
-
(from `isActionable`), so callers don't have to re-derive "needs attention" from `status`/`detail`
|
|
522
|
-
prose — it's `true` for `drifted`, `upstream-moved`, `diverged`, `upstream-unreachable`, and
|
|
523
|
-
`local-missing`; `false` for `in-sync` and `local-only`. **Re-baselining**: after reviewing and
|
|
524
|
-
adopting an `upstream-moved`/`diverged` change, re-run `rhize-plugins`' `scripts/baseline_upstreams.py`
|
|
525
|
-
and commit the updated SOURCES.md — that's the "I reviewed upstream, accept its state" action that
|
|
526
|
-
clears the row back to `in-sync`/`local-only`.
|
|
527
|
-
|
|
528
|
-
### `ingest` + `queue close` (v0.9, Pro)
|
|
529
|
-
|
|
530
|
-
```bash
|
|
531
|
-
skill-forge ingest
|
|
532
|
-
skill-forge ingest --list
|
|
533
|
-
skill-forge ingest --list --json
|
|
534
|
-
skill-forge queue close <id> --status ingested
|
|
535
|
-
skill-forge queue close <id> --status dismissed
|
|
536
|
-
```
|
|
537
|
-
|
|
538
|
-
Pro (free during the 0.x beta). The queue-drain UX for pending ingestions. `ingest` (no args)
|
|
539
|
-
validates every pending `~/.skill-forge/queue.json` entry — each entry's `quarantinePath`/`installedPath` must
|
|
540
|
-
canonicalize under the configured quarantine dir or a configured skills root/MCP target;
|
|
541
|
-
mismatched or escaping entries are reported and excluded — then hands the surviving summary off to
|
|
542
|
-
the configured coding agent (same handoff plumbing as `add --ingest`) with `assets/ingest-prompt.md`,
|
|
543
|
-
which now carries the full queue-drain workflow. `--list` is read-only: it prints pending entries
|
|
544
|
-
(`--json` for machine-readable output) without any handoff.
|
|
545
|
-
|
|
546
|
-
For a single new source, use `skill-forge add <source> --ingest` instead — that runs the full
|
|
547
|
-
quarantine/gate pipeline first; `ingest` only ever drains what's already queued.
|
|
548
|
-
|
|
549
|
-
`skill-forge queue close <id> --status ingested|dismissed` lets an agent close out a queue entry
|
|
550
|
-
after its decide pass without hand-editing `queue.json` — writes are atomic (temp file + rename).
|
|
551
|
-
|
|
552
|
-
### `refine` (v0.10, Pro)
|
|
553
|
-
|
|
554
|
-
```bash
|
|
555
|
-
skill-forge refine --skill my-skill --category hook --override-type patch \
|
|
556
|
-
--action insert-after --marker "Only check paths" \
|
|
557
|
-
--content "..." --expected "..." --actual "..." --dry-run
|
|
558
|
-
skill-forge refine list [--status <s>] [--skill <s>] [--project <p>]
|
|
559
|
-
skill-forge refine patterns [--status tracking|ready|generalized|dismissed] [--skill <s>]
|
|
560
|
-
skill-forge refine promote <PATTERN-ID> [--dry-run] [--force] [--user-root <dir>]
|
|
561
|
-
skill-forge refine rollback <backup-id> [--force]
|
|
562
|
-
skill-forge refine which <skill> [--user-root <dir>]
|
|
563
|
-
```
|
|
564
|
-
|
|
565
|
-
Pro (free during the 0.x beta). Captures, applies, and generalizes improvements to installed
|
|
566
|
-
skills from real usage feedback (see [CLAUDE.md's "refine (v0.10)" section](CLAUDE.md) for the
|
|
567
|
-
full architecture notes, or `docs/refinement-schema.md` for the store shape).
|
|
568
|
-
|
|
569
|
-
**Capture never mutates a base `SKILL.md`.** `refine` capture/apply writes ONLY project-scope
|
|
570
|
-
override artifacts — `SKILL.patch.md` / `SKILL.extend.md` / `skill-config.json`, or a whole-file
|
|
571
|
-
override copy for `full`/`hook`/`script` override types. The only command that ever touches a
|
|
572
|
-
user-scope base skill is `refine promote`, and only against a `ready` pattern (or with `--force`).
|
|
573
|
-
|
|
574
|
-
**Override precedence** (configurable roots):
|
|
575
|
-
|
|
576
|
-
```
|
|
577
|
-
1. PROJECT LOCAL <cwd>/.claude/skills/<skill>/ highest
|
|
578
|
-
2. PROJECT SHARED <cwd>/skills/<skill>/
|
|
579
|
-
3. USER SCOPE first configured skillsRoots entry outside cwd (fallback ~/.claude/skills)
|
|
580
|
-
```
|
|
581
|
-
|
|
582
|
-
`refine which <skill>` prints this resolution order and which override files exist at each scope —
|
|
583
|
-
the "why didn't my patch take effect" debugging aid, made explicit and read-only. Both `refine
|
|
584
|
-
which` and `refine promote` accept `--user-root <dir>` to override the detected user-scope skills
|
|
585
|
-
root (default: the first configured `skillsRoots` entry outside the current working directory,
|
|
586
|
-
falling back to `~/.claude/skills`) — useful when the config's default root doesn't match the
|
|
587
|
-
skill you're targeting.
|
|
588
|
-
|
|
589
|
-
**Non-interactive capture contract.** Capture flags: `--skill --category --target --override-type
|
|
590
|
-
<patch|extend|config|full|hook|script|new> --action <append|prepend|replace-section|insert-after|
|
|
591
|
-
insert-before|delete-section> --marker --content <text> --content-file <file> --expected --actual
|
|
592
|
-
--example --outcome --root-cause --pattern-id --scope <local|shared> --dry-run --json --yes
|
|
593
|
-
--handoff`. `--content` takes override content inline; `--content-file <file>` reads it from a
|
|
594
|
-
file instead (mutually exclusive with `--content`) — use it for anything multi-line rather than
|
|
595
|
-
fighting shell quoting. All seven override types
|
|
596
|
-
are supported: `patch`/`extend`/`config` are rendered from the flags; `full`/`hook`/`script` are
|
|
597
|
-
verbatim override-file writes at project scope (content required); `new` creates an extension file
|
|
598
|
-
for a capability that doesn't exist in the base skill yet. Always run `--dry-run` first and confirm
|
|
599
|
-
the preview before writing for real — `--yes` skips re-prompting for a confirmation already given,
|
|
600
|
-
it does not replace the dry-run preview.
|
|
601
|
-
|
|
602
|
-
**The judgment step is the agent's job**, same pattern as `--ingest`/`audit --handoff`: a
|
|
603
|
-
bundled `assets/refine-prompt.md` carries the gap-analysis rubric (category/override-type decision
|
|
604
|
-
tables, guided-mode triggers), the patch-action syntax, the pattern-fingerprint/generalization
|
|
605
|
-
criteria, and the verification step. `refine --handoff`
|
|
606
|
-
(opt-in) launches your configured agent with it, same handoff plumbing as `--ingest`; `--yes` never
|
|
607
|
-
implies `--handoff`.
|
|
608
|
-
|
|
609
|
-
**Pattern tracking and promotion.** A pattern becomes `ready` only when it recurs in a **second,
|
|
610
|
-
genuinely different project** — repeat captures in the same project never flip it (occurrence
|
|
611
|
-
`count` is derived from unique project identities, not raw refinement counts; see
|
|
612
|
-
`docs/refinement-schema.md`). `refine patterns` lists tracked/ready/generalized/dismissed patterns,
|
|
613
|
-
filterable by `--status --skill --project`. `refine promote <PATTERN-ID>` merges a `ready` pattern
|
|
614
|
-
into the user-scope base skill: it backs up affected files first (manifest with per-file sha256 +
|
|
615
|
-
original bytes + mode, tombstones for files that didn't exist), stages the write, validates, then
|
|
616
|
-
renames into place — `--dry-run` previews the diff without writing, `refine rollback <backup-id>`
|
|
617
|
-
restores from the manifest (refusing if current files have drifted since promote, unless
|
|
618
|
-
`--force`). On promote, a `SOURCES.md` provenance entry is appended (verb `DEFER`, notes
|
|
619
|
-
`"generalized from PAT-xxxx via skill-forge refine"`).
|
|
620
|
-
|
|
621
|
-
**`evolve` vs. `refine`.** Both improve an already-installed skill, but at different scopes and
|
|
622
|
-
triggers: `evolve` (v0.7) is *automated, whole-skill* optimization — it hands the entire skill off
|
|
623
|
-
to SkillOpt-Sleep to propose a fresh replacement, re-gates the proposal, and lets you adopt or
|
|
624
|
-
reject it wholesale. `refine` is *targeted, human/agent-driven* — it captures one specific observed
|
|
625
|
-
gap ("expected X, got Y") and writes the smallest override that closes it, tracked and eventually
|
|
626
|
-
generalized only once the same gap recurs elsewhere. A `refine` patch on top of an `evolve`d skill
|
|
627
|
-
is fine; both record their own provenance entry, so the `SOURCES.md` ledger shows which change came
|
|
628
|
-
from which mechanism.
|
|
629
|
-
|
|
630
|
-
**Legacy store — deliberate skip, not a migration.** `~/.claude/skill-refinements/` is a legacy
|
|
631
|
-
location some users may have from earlier tooling — three flat markdown notes, no structured
|
|
632
|
-
ledgers, no schema — and there is no migration from it. Files there stay readable in place; if
|
|
633
|
-
anything in them still matters, re-capture it via `skill-forge refine` against the greenfield JSON
|
|
634
|
-
store described in [`docs/refinement-schema.md`](docs/refinement-schema.md). Markdown ledgers like
|
|
635
|
-
`refinement-history/*.md`, `aggregated-patterns.md`, or `generalization-queue.md` are not
|
|
636
|
-
recreated — JSON is the store; `refine list`/`refine patterns` are the human-readable view over it.
|
|
637
|
-
|
|
638
|
-
**Auto-trigger hooks — templates, not automation.** A CLI cannot hook a running Claude Code
|
|
639
|
-
session, so two auto-trigger hooks ship here as documented templates instead:
|
|
640
|
-
`assets/hooks/refinement-detector.sh` (detects refinement-shaped language in a prompt) and
|
|
641
|
-
`assets/hooks/session-end.sh` (prompts after a substantial session). Both are optional, inert if
|
|
642
|
-
`skill-forge` isn't on `PATH`, and never call `skill-forge` themselves — they only print a
|
|
643
|
-
suggestion. Wire either one in by adding it to your `.claude/settings.json` (or
|
|
644
|
-
`~/.claude/settings.json`) hooks section — the exact snippet is in each script's own header
|
|
645
|
-
comment:
|
|
646
|
-
|
|
647
|
-
```json
|
|
648
|
-
{
|
|
649
|
-
"hooks": {
|
|
650
|
-
"UserPromptSubmit": [
|
|
651
|
-
{ "hooks": [{ "type": "command", "command": "bash /path/to/refinement-detector.sh" }] }
|
|
652
|
-
],
|
|
653
|
-
"SessionEnd": [
|
|
654
|
-
{ "hooks": [{ "type": "command", "command": "bash /path/to/session-end.sh" }] }
|
|
655
|
-
]
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
```
|
|
659
|
-
|
|
660
|
-
**Security invariants** (same regime as v0.8/v0.9): nothing from a skill being refined is ever
|
|
661
|
-
executed. Patch application writes ONLY under the resolved target scope dir for the named skill
|
|
662
|
-
(containment-checked realpath, refuses a symlinked destination file); promotion writes ONLY under
|
|
663
|
-
user scope, backup first. All child processes are argv arrays (git only, for context gathering).
|
|
664
|
-
Control-char sanitization on every untrusted string that lands in human-readable output. `--yes`
|
|
665
|
-
never implies `--handoff`. Applying a patch whose target `SKILL.md` is missing is refused; promoting
|
|
666
|
-
a non-`ready` pattern without `--force` is refused.
|
|
667
|
-
|
|
668
|
-
### `routine` (v0.11, Pro)
|
|
669
|
-
|
|
670
|
-
```bash
|
|
671
|
-
skill-forge routine # audit + drift + registry, one report, writes nothing else
|
|
672
|
-
skill-forge routine --json --offline # for a scheduler: one JSON document, no network
|
|
673
|
-
skill-forge routine --fail-on high # exit 1 when a high/critical finding exists
|
|
674
|
-
skill-forge routine --housekeeping # opt in to bounded writes (see below)
|
|
675
|
-
```
|
|
676
|
-
|
|
677
|
-
The whole maintenance pipeline in one command, shaped for cron. Every other command answers one
|
|
678
|
-
question; keeping a set healthy means running four and correlating them by hand, which is exactly
|
|
679
|
-
what nobody does on a schedule. `routine` runs the audit, drift, and registry **engines**,
|
|
680
|
-
correlates them into one report and one summary, and exits with a code a scheduler can alert on.
|
|
681
|
-
|
|
682
|
-
**Non-interactive by construction** — it never prompts, so it cannot hang a scheduled job. It is
|
|
683
|
-
also the only schedulable command that writes, so what it may write is fenced:
|
|
684
|
-
|
|
685
|
-
| | writes |
|
|
686
|
-
|---|---|
|
|
687
|
-
| always | the combined report + `audit-state.json`, both under `~/.skill-forge` |
|
|
688
|
-
| `--housekeeping` | prunes quarantine sandboxes older than `--prune-days` (default 30); closes queue entries whose skill is gone from disk |
|
|
689
|
-
| `--handoff` | launches your configured agent with the curation prompt |
|
|
690
|
-
|
|
691
|
-
Housekeeping and handoff are **opt-in**: a bare `skill-forge routine` in a crontab reports and
|
|
692
|
-
nothing else. A step that was requested but could not run — a crashed drift check, a failed
|
|
693
|
-
prune, an unreadable queue — is listed under **Incomplete steps** and **always exits nonzero**,
|
|
694
|
-
independent of `--fail-on`: `--fail-on` grades what the audit *found*, whereas a degraded run
|
|
695
|
-
means the routine did not do what was scheduled, and a cron job that exits 0 on that is blind. Pruning only ever deletes inside the quarantine dir — never a skills root — is
|
|
696
|
-
age-bounded, `--dry-run`-able, and lists every path in the report. A queue entry is only closed
|
|
697
|
-
when the skill it points at no longer exists; a pending entry whose skill is still installed is
|
|
698
|
-
undone work, not an orphan. `routine` never installs, promotes, or rejects: no candidate enters a
|
|
699
|
-
skills root without a human or agent decision, and a cron job is not that.
|
|
700
|
-
|
|
701
|
-
**Accepted findings (v0.12)** are honored the same way `audit` honors them: `--fail-on` grades
|
|
702
|
-
**active** findings only, so accepting every remaining finding via `skill-forge finding accept`
|
|
703
|
-
turns a red `--fail-on any` green, and any new or changed finding turns it red again. A
|
|
704
|
-
corrupt/missing accepted-findings store fails open (nothing gets suppressed) and surfaces as a
|
|
705
|
-
report **notice**, never as an "Incomplete step" — see
|
|
706
|
-
[docs/accepted-findings-schema.md](docs/accepted-findings-schema.md).
|
|
707
|
-
|
|
708
|
-
```
|
|
709
|
-
0 9 * * 1 skill-forge routine --offline --fail-on high --housekeeping
|
|
710
|
-
```
|
|
711
|
-
|
|
712
|
-
### `promote <id>` / `reject <id>` (v0.11)
|
|
713
|
-
|
|
714
|
-
Answering **hold** at the gate used to be a dead end: the sandbox sat in quarantine and no command
|
|
715
|
-
could ever finish the decision. These close that loop.
|
|
716
|
-
|
|
717
|
-
```bash
|
|
718
|
-
skill-forge promote <id> # re-gate the held sandbox, then promote/hold/reject
|
|
719
|
-
skill-forge reject <id> # discard it
|
|
720
|
-
```
|
|
721
|
-
|
|
722
|
-
Works for both artifact types: a held MCP candidate is re-gated as an MCP server and written into
|
|
723
|
-
your MCP config (`--mcp-target`), with env values emptied and unpinned `npx` specs pinned, exactly
|
|
724
|
-
as `add --artifact mcp` would.
|
|
725
|
-
|
|
726
|
-
Promotion also re-validates the candidate against the state it was gated in: each skill dir must
|
|
727
|
-
still be a real directory rather than a symlink, no symlink inside it may resolve out of the
|
|
728
|
-
sandbox, and its content digest must still match the one captured at gate time. Otherwise the gap
|
|
729
|
-
between "scanned" and "installed" — days, for a hold — is a window in which vetted content can be
|
|
730
|
-
swapped for something that never passed the gate.
|
|
731
|
-
|
|
732
|
-
`promote` **re-gates** rather than promoting blind. The original run's gate result was never
|
|
733
|
-
persisted, so the alternative would be a queue entry with a fabricated gate record — and a hold
|
|
734
|
-
may be days old, with the ruleset and your installed set since changed. Re-scanning is static and
|
|
735
|
-
cheap. Ids come from `skill-forge list`; anything that resolves outside your quarantine dir
|
|
736
|
-
(traversal, absolute path, symlink) is refused.
|
|
737
|
-
|
|
738
|
-
### `config` (v0.11)
|
|
739
|
-
|
|
740
|
-
`businessProfile` is five fixed fields, so anything else learned about you has nowhere to live.
|
|
741
|
-
Preferences are open-ended key/value facts that accumulate without a schema change:
|
|
742
|
-
|
|
743
|
-
```bash
|
|
744
|
-
skill-forge config set prefers-typescript "strict mode, no any"
|
|
745
|
-
skill-forge config list
|
|
746
|
-
skill-forge config review
|
|
747
|
-
```
|
|
748
|
-
|
|
749
|
-
**Agents get a different door.** `set` is for a human at a keyboard and takes effect immediately;
|
|
750
|
-
`propose` only ever queues something for review:
|
|
751
|
-
|
|
752
|
-
```bash
|
|
753
|
-
skill-forge config propose deploys-on vercel --origin "ingest agent" --note "seen in 3 skills"
|
|
754
|
-
```
|
|
755
|
-
|
|
756
|
-
An agent draining the queue reads untrusted skill content, so anything it concludes about you is
|
|
757
|
-
downstream of text an attacker may have written. If agents could write preferences directly, a
|
|
758
|
-
malicious `SKILL.md` could talk one into persisting an instruction into your config, where every
|
|
759
|
-
later run would read it back as *your stated preference* — a durable prompt-injection foothold
|
|
760
|
-
with a laundering step in the middle. Routing agent writes through review means the worst case is
|
|
761
|
-
a proposal you decline. `review` is interactive, or takes an explicit `--accept-all`/`--reject-all`;
|
|
762
|
-
it refuses to fall through to a default in a non-interactive shell.
|
|
763
|
-
|
|
764
|
-
Both doors run the same validation: kebab-case keys, a length cap, no control characters, and a
|
|
765
|
-
refusal for anything credential-shaped — by key name (`api-key`, `*-token`) or by value shape
|
|
766
|
-
(`sk-…`, `ghp_…`, `AKIA…`, PEM blocks, JWTs). `config.json` is plain text; secrets belong in your
|
|
767
|
-
keychain. Hand-edited entries that fail those checks are dropped on load rather than rendered.
|
|
768
|
-
|
|
769
|
-
### `list` / `status`
|
|
770
|
-
|
|
771
|
-
`list` shows what's currently held in quarantine (installed via `add`, answered "hold", not yet
|
|
772
|
-
promoted or rejected). `status` shows the resolved configuration (skills roots, quarantine dir,
|
|
773
|
-
strictness) plus a count of held entries.
|
|
774
|
-
|
|
775
|
-
### `guide` (v0.11)
|
|
776
|
-
|
|
777
|
-
```bash
|
|
778
|
-
skill-forge guide # what this does, where you are, what to run next
|
|
779
|
-
skill-forge guide verbs # a single topic
|
|
780
|
-
```
|
|
781
|
-
|
|
782
|
-
Orientation for someone — or some agent — dropping into an existing session. `--help` lists flags
|
|
783
|
-
but can't tell you what to do with them, and `status` prints configuration without saying what it
|
|
784
|
-
means; `guide` answers "what is my current state, and what is the next command". It reads your
|
|
785
|
-
config, quarantine, and queue and names one next step, unfinished work first: nothing configured →
|
|
786
|
-
`init`; entries awaiting a decide-pass verb → `ingest`; candidates still held → `list`; no audit
|
|
787
|
-
ever run → `audit`.
|
|
788
|
-
|
|
789
|
-
```
|
|
790
|
-
Where you are:
|
|
791
|
-
config: /Users/you/.skill-forge/config.json
|
|
792
|
-
gate targets: 3 (default: /Users/you/.agents/skills)
|
|
793
|
-
quarantined: 2
|
|
794
|
-
queue: 12 pending
|
|
795
|
-
|
|
796
|
-
Suggested next step:
|
|
797
|
-
skill-forge ingest
|
|
798
|
-
12 promoted items still awaiting a decide-pass verb
|
|
799
|
-
```
|
|
800
|
-
|
|
801
|
-
Topics: `pipeline`, `verbs`, `queue`, `mcp`, `refine`, `maintenance`, `pro`. **Read-only and
|
|
802
|
-
non-interactive** — it writes nothing and never prompts, so it's safe to run inside an agent turn,
|
|
803
|
-
and with no config it says so rather than reciting default placeholder paths as if they were
|
|
804
|
-
settings.
|
|
805
|
-
|
|
806
|
-
## MCP gating (v0.5)
|
|
807
|
-
|
|
808
|
-
`add` and `scan` can also gate an **MCP server** instead of a skill — the same quarantine →
|
|
809
|
-
profile → safety scan → overlap analysis → report → promote/hold/reject pipeline, applied to an
|
|
810
|
-
MCP server candidate rather than a skill:
|
|
811
|
-
|
|
812
|
-
```bash
|
|
813
|
-
skill-forge scan ./my-mcp-server --artifact mcp
|
|
814
|
-
skill-forge add @scope/some-mcp-server --artifact mcp --mcp-target ~/.claude.json
|
|
815
|
-
skill-forge add https://github.com/owner/mcp-server.git --artifact mcp --yes
|
|
816
|
-
```
|
|
817
|
-
|
|
818
|
-
Pass `--artifact mcp` explicitly — skill-forge never guesses. In particular, an npm package name
|
|
819
|
-
(`@scope/name`, or a bare `some-mcp-server` name) is only treated as an npm source with this flag;
|
|
820
|
-
without it, the same string resolves as a skills.sh `owner/name` slug instead (no ambiguity
|
|
821
|
-
guessing between the two).
|
|
822
|
-
|
|
823
|
-
**Source forms**
|
|
824
|
-
|
|
825
|
-
| Form | Example | How it's fetched |
|
|
64
|
+
| Command | Description | Docs |
|
|
826
65
|
|---|---|---|
|
|
827
|
-
|
|
|
828
|
-
|
|
|
829
|
-
|
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
[
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
(`server.tool(...)`, `setRequestHandler(ListToolsRequestSchema, ...)`, etc.):
|
|
848
|
-
|
|
849
|
-
```
|
|
850
|
-
Artifact type : mcp
|
|
851
|
-
Capabilities : 2 tools, 1 resource, 0 prompts (declaredConfidence: high)
|
|
852
|
-
```
|
|
853
|
-
|
|
854
|
-
This is free (it's profiling, not a Pro feature) and **never derived by running the candidate
|
|
855
|
-
server** — anything that can't be determined from source text is reported as undetermined rather
|
|
856
|
-
than discovered by executing it. `--json` includes the full `tools`/`resources`/`prompts` name
|
|
857
|
-
lists under `profile.capabilities`.
|
|
858
|
-
|
|
859
|
-
**Promote semantics**
|
|
860
|
-
|
|
861
|
-
Promoting an MCP candidate writes ONE server entry into a target MCP config file's `mcpServers`
|
|
862
|
-
map — it never touches a skills root:
|
|
863
|
-
|
|
864
|
-
```json
|
|
865
|
-
{ "mcpServers": { "<name>": { "command": "...", "args": ["..."], "env": { "SOME_KEY": "" } } } }
|
|
866
|
-
```
|
|
867
|
-
|
|
868
|
-
- **Env values are never copied** from the candidate — every declared env var is written as an
|
|
869
|
-
empty string, and skill-forge prints the var names you need to fill in yourself.
|
|
870
|
-
- **Target resolution:** `--mcp-target <file>`, else `config.mcpTargets[0]`, else `<cwd>/.mcp.json`.
|
|
871
|
-
- **Existing target file:** backed up first to `<file>.bak-<timestamp>`.
|
|
872
|
-
- **Existing same-name server entry:** refused unless `--force` is passed.
|
|
873
|
-
- **Missing target file/parent dirs:** created.
|
|
874
|
-
- A candidate config listing more than one server gates/promotes the first (same "N found — using
|
|
875
|
-
the first" convention `add`/`scan` already use for a multi-skill source), noted on stderr.
|
|
876
|
-
- **Version pinning is enforced, including on a candidate's own documented entry (v0.7).** A
|
|
877
|
-
candidate's `.mcp.json` server entry is used for `command`/`args` when present, but an unpinned
|
|
878
|
-
`npx` spec there (`"args": ["-y", "pkg@latest"]`) is no longer written through as-is: it's
|
|
879
|
-
**auto-pinned** to `<package>@<version>` when it matches the version skill-forge scanned from the
|
|
880
|
-
candidate's own (self-declared) `package.json`, or **promotion is refused** (with an explanation
|
|
881
|
-
and no override flag) when it can't be safely auto-pinned — a different package name, no version
|
|
882
|
-
found, or a more complex shape (e.g. a `-p`/`--package` dependency, or more than one spec).
|
|
883
|
-
See [docs/gate-policy.md](docs/gate-policy.md#mcp-promote-version-pin-enforcement-v07).
|
|
884
|
-
|
|
885
|
-
There's no MCP equivalent of the skill provenance ledger (`SOURCES.md`) — the pending-ingestion
|
|
886
|
-
queue (Pro) and `--ingest` handoff both apply the same way, keyed on the written config file path
|
|
887
|
-
instead of an installed skill directory. The queued entry carries the candidate's static capability
|
|
888
|
-
profile (`capabilities`, v0.6, above), so a `--ingest` handoff run on an MCP promote has real
|
|
889
|
-
material to work with: `assets/ingest-prompt.md` branches on `artifactType: "mcp"` and walks the
|
|
890
|
-
same five-verb decide (DEFER/ABSORB/FORK/REJECT/WATCH) applied to a server instead of a skill —
|
|
891
|
-
compare declared capabilities against what's already configured, then keep/tighten/remove the
|
|
892
|
-
promoted config entry accordingly. Same static-only rule as the CLI's own profiling: the deep pass
|
|
893
|
-
never runs or installs the candidate server to inspect it.
|
|
894
|
-
|
|
895
|
-
**TOML-format agents: detect-only.** `skill-forge init` detects MCP config files for every known
|
|
896
|
-
agent, including TOML-format ones (Codex CLI's `config.toml`) — they show up in `init`'s MCP-target
|
|
897
|
-
list and can be selected into `config.mcpTargets` for **overlap ranking**. But **promote only
|
|
898
|
-
writes JSON-shaped targets** (`{ "mcpServers": { ... } }`); pointing `--mcp-target` at (or letting
|
|
899
|
-
`config.mcpTargets[0]` resolve to) a TOML file fails when the promote step tries to parse it as
|
|
900
|
-
JSON. Detection/overlap is agent-format-agnostic; writing is JSON-only.
|
|
66
|
+
| `init [options]` | Detect installed agents and set gate targets / handoff agent | [docs/commands/init.md](docs/commands/init.md) |
|
|
67
|
+
| `add <source> [options]` | Quarantine-install a skill and run it through the gate | [docs/commands/add.md](docs/commands/add.md) |
|
|
68
|
+
| `scan <source> [options]` | Gate a skill without installing it (always cleans up) | [docs/commands/scan.md](docs/commands/scan.md) |
|
|
69
|
+
| `evolve <skill-dir> [options]` (Pro) | Self-evolve an installed skill via SkillOpt-Sleep, re-gate, decide | [docs/commands/evolve.md](docs/commands/evolve.md) |
|
|
70
|
+
| `audit [options]` (alias `doctor`) | Doctor-style health check over the configured skill/MCP set | [docs/commands/audit.md](docs/commands/audit.md) |
|
|
71
|
+
| `finding accept\|revoke\|list` | Acknowledge, revoke, or list reviewed audit findings (human-only, no gate effect) | [docs/commands/finding.md](docs/commands/finding.md) |
|
|
72
|
+
| `organize [options]` (Pro) | Set-level capability registry + dependency graph across configured skills roots | [docs/commands/organize.md](docs/commands/organize.md) |
|
|
73
|
+
| `find [query] [options]` | Discover skills via skills.sh and check partner security audits (free) | [docs/commands/find.md](docs/commands/find.md) |
|
|
74
|
+
| `watch [options]` (Pro) | Drift check across every `SOURCES.md` provenance ledger | [docs/commands/watch.md](docs/commands/watch.md) |
|
|
75
|
+
| `ingest [options]` / `queue close <id>` (Pro) | Hand the pending-ingestion queue off to a coding agent for the decide/absorb pass | [docs/commands/ingest.md](docs/commands/ingest.md) |
|
|
76
|
+
| `refine [options]` (Pro) | Capture, list, review, promote, and roll back project-scope skill overrides | [docs/commands/refine.md](docs/commands/refine.md) |
|
|
77
|
+
| `insight <subcommand>` (Pro) | Turn sources into evidence-backed capability plans and Jira manifests | [docs/commands/insight.md](docs/commands/insight.md) |
|
|
78
|
+
| `routine [options]` (Pro) | One scheduled maintenance pass: audit + drift + registry, cron-friendly | [docs/commands/routine.md](docs/commands/routine.md) |
|
|
79
|
+
| `promote <id>` / `reject <id>` [options] | Re-gate and finish a held quarantine decision, or discard it | [docs/commands/promote-reject.md](docs/commands/promote-reject.md) |
|
|
80
|
+
| `config <sub> [args]` | Read/write open-ended preferences (`list`\|`get`\|`set`\|`unset`\|`propose`\|`review`) | [docs/commands/config.md](docs/commands/config.md) |
|
|
81
|
+
| `list` / `status` | List held quarantine entries, or show configuration and quarantine summary | [docs/commands/list-status.md](docs/commands/list-status.md) |
|
|
82
|
+
| `guide [topic]` | Orientation: what this does, your current state, the next command | [docs/commands/guide.md](docs/commands/guide.md) |
|
|
83
|
+
|
|
84
|
+
`add`/`scan` also gate an **MCP server** instead of a skill via `--artifact mcp` — see
|
|
85
|
+
[docs/mcp-gating.md](docs/mcp-gating.md).
|
|
901
86
|
|
|
902
87
|
## Free vs. Pro
|
|
903
88
|
|
|
904
|
-
| Capability | Free | Pro |
|
|
905
|
-
|---|:---:|:---:|
|
|
906
|
-
| Quarantine install (skills.sh slug / git / local path) | ✓ | ✓ |
|
|
907
|
-
| Profile (name, version, license, structure, MCP/tool deps) | ✓ | ✓ |
|
|
908
|
-
| Safety gate — built-in ruleset + SkillSpector shell-out | ✓ | ✓ |
|
|
909
|
-
| Terminal report + `--json` | ✓ | ✓ |
|
|
910
|
-
| Promote / hold / reject decision | ✓ | ✓ |
|
|
911
|
-
| `init` setup wizard (agent detection, gate targets, handoff agent) | ✓ | ✓ |
|
|
912
|
-
| Overlap analysis against your configured skill set | | ✓ |
|
|
913
|
-
| Provenance ledger (`SOURCES.md` audit trail) | | ✓ |
|
|
914
|
-
| Pending-ingestion queue + `--ingest` handoff | | ✓ |
|
|
915
|
-
| `evolve` — SkillOpt-Sleep self-evolution, re-gating, provenance, queueing (v0.7) | | ✓ |
|
|
916
|
-
| `audit` — inventory, hygiene findings, report, business profile, foundation scaffold (v0.8) | ✓ | ✓ |
|
|
917
|
-
| `audit`'s cross-root overlap clusters (v0.8) | | ✓ |
|
|
918
|
-
| `organize` — set-level capability registry + dependency graph (v0.9) | | ✓ |
|
|
919
|
-
| `find` — skills.sh discovery + partner audit verdicts (v0.9) | ✓ | ✓ |
|
|
920
|
-
| `watch` — provenance drift check across every `SOURCES.md` ledger (v0.9) | | ✓ |
|
|
921
|
-
| `ingest` + `queue close` — pending-queue drain handoff (v0.9) | | ✓ |
|
|
922
|
-
| `refine` — capture/apply/generalize project-scope skill overrides (v0.10) | | ✓ |
|
|
923
|
-
| `finding accept`/`revoke`/`list` — acknowledge audit findings, never a gate input (v0.12) | ✓ | ✓ |
|
|
924
|
-
|
|
925
89
|
Free is the complete safety gate on its own — quarantine, profile, safety scan, and an explicit
|
|
926
90
|
promote/reject decision, with nothing held back. Pro is the curation layer on top: whether a new
|
|
927
91
|
candidate duplicates something you already have, and an ongoing provenance record across your
|
|
@@ -929,73 +93,29 @@ whole skill set rather than a single install-time decision.
|
|
|
929
93
|
|
|
930
94
|
**Everything free until 1.0.** This is a 0.x beta build, and the Pro tier's runtime license check
|
|
931
95
|
is intentionally asleep for the whole 0.x line: overlap analysis, the provenance ledger, and the
|
|
932
|
-
pending-ingestion queue / `--ingest` handoff all run for everyone, licensed or not
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
CLI command, licensed or not, beta or not. See [docs/pro.md](docs/pro.md) for the per-feature
|
|
939
|
-
implementation status.
|
|
96
|
+
pending-ingestion queue / `--ingest` handoff all run for everyone, licensed or not — `add` prints a
|
|
97
|
+
one-line "free during the beta" notice above the report when no valid license is set, and otherwise
|
|
98
|
+
runs exactly as a licensed run would.
|
|
99
|
+
|
|
100
|
+
See [docs/pro.md](docs/pro.md#free-vs-pro) for the full Free/Pro capability table and the
|
|
101
|
+
per-feature implementation status.
|
|
940
102
|
|
|
941
103
|
## Security model
|
|
942
104
|
|
|
943
|
-
- **Quarantine-first.** Every source
|
|
944
|
-
|
|
945
|
-
reaches your working skill set without an explicit promote decision.
|
|
105
|
+
- **Quarantine-first.** Every source is installed into an isolated sandbox before anything is
|
|
106
|
+
inspected — nothing reaches your working skill set without an explicit promote decision.
|
|
946
107
|
- **Built-in safety ruleset, always on, fully offline.** A deny-pattern scan (curl/wget-into-shell,
|
|
947
|
-
base64-obfuscated exec, reverse shells,
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
[docs/gate-policy.md](docs/gate-policy.md) for the full rule table.
|
|
108
|
+
base64-obfuscated exec, reverse shells, credential-file access/exfil, `shell=True` subprocess,
|
|
109
|
+
persistence via shell rc files or cron, `sudo` usage, and more) runs against every candidate with
|
|
110
|
+
no external dependency and no network call.
|
|
951
111
|
- **Block on HIGH/CRITICAL.** Any finding at `HIGH` or `CRITICAL` severity blocks the candidate
|
|
952
|
-
outright
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
with `tar -tzf` before extraction — any absolute path or `..` path segment refuses the extract
|
|
957
|
-
with an error instead of running `tar -xzf` (a path-traversal guard against a malicious tarball
|
|
958
|
-
writing outside the quarantine sandbox).
|
|
959
|
-
- **SkillSpector, when installed.** If [SkillSpector](https://github.com/NVIDIA/SkillSpector)
|
|
960
|
-
(Apache-2.0) is on `PATH`, skill-forge shells out to it (`--no-llm` by default, so scanned skill
|
|
961
|
-
content is never sent to an external LLM provider) and merges its findings into the same report.
|
|
962
|
-
Purely additive — its absence never blocks the gate.
|
|
963
|
-
- **skills.sh partner audits — implemented, not yet wired into the CLI pipeline.** skill-forge
|
|
964
|
-
ships a client for skills.sh's documented `/api/v1/skills/audit` endpoint (partner verdicts from
|
|
965
|
-
Socket, Snyk, Gen Agent Trust Hub, Runlayer, ZeroLeaks), gated on a user-supplied
|
|
966
|
-
`VERCEL_OIDC_TOKEN`. The client exists (`src/gate/skillsSh.ts`) but `add`/`scan` do not call it
|
|
967
|
-
yet in this build — see [docs/gate-policy.md](docs/gate-policy.md) for current status.
|
|
968
|
-
|
|
969
|
-
## Ingestion handoff (`--ingest`)
|
|
970
|
-
|
|
971
|
-
`skill-forge` deliberately doesn't try to decide *what to extract* from a skill worth adopting —
|
|
972
|
-
that deeper judgment (which patterns to keep, whether to absorb into an existing skill vs. fork a
|
|
973
|
-
new one, verifying the result beats baseline) is a job for a coding agent, not the gate. `--ingest`
|
|
974
|
-
hands a promoted skill off to one, running the bundled, agent-neutral prompt at
|
|
975
|
-
`assets/ingest-prompt.md` — works with any agent. ABSORB extractions from an ingest pass route
|
|
976
|
-
through `skill-forge refine` in this same package — see [`refine`](#refine-v010-pro) above and
|
|
977
|
-
[docs/forge-workflow.md](docs/forge-workflow.md).
|
|
978
|
-
The same flag works on an MCP server promote (`--artifact mcp --ingest`, v0.6): the bundled prompt branches on the
|
|
979
|
-
queue entry's `artifactType` and runs the matching decide pass — see
|
|
980
|
-
[MCP gating](#mcp-gating-v05) above.
|
|
981
|
-
|
|
982
|
-
```bash
|
|
983
|
-
skill-forge add owner/name --yes --ingest
|
|
984
|
-
```
|
|
985
|
-
|
|
986
|
-
The command that gets run, in order:
|
|
112
|
+
outright; a lower-severity finding produces `warn`; a clean scan is `pass`.
|
|
113
|
+
- **npm-sourced MCP candidates:** fetched with `--ignore-scripts`, and every tarball member path is
|
|
114
|
+
validated before extraction (a path-traversal guard).
|
|
115
|
+
- **SkillSpector, when installed,** is purely additive — its absence never blocks the gate.
|
|
987
116
|
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
(the bundled prompt file) substituted in. Never shell-parsed, so it's safe even if a substituted
|
|
991
|
-
path contains shell metacharacters.
|
|
992
|
-
2. Otherwise, the first known agent binary found on `PATH` (`claude`, `codex`, `cursor-agent`,
|
|
993
|
-
`windsurf`, `opencode`, `gemini`), invoked generically with the prompt.
|
|
994
|
-
3. Otherwise, skill-forge prints the prompt path and skill path for you to hand off yourself.
|
|
995
|
-
|
|
996
|
-
Every promote or hold is recorded to the pending queue (`~/.skill-forge/queue.json`) regardless of
|
|
997
|
-
`--ingest` — nothing is lost if you skip the handoff. See [`docs/queue-schema.md`](docs/queue-schema.md)
|
|
998
|
-
for the entry schema.
|
|
117
|
+
See [docs/security-model.md](docs/security-model.md) for the full rule table and current status of
|
|
118
|
+
each check.
|
|
999
119
|
|
|
1000
120
|
## Configuration
|
|
1001
121
|
|
|
@@ -1047,6 +167,18 @@ the provenance ledger, and the pending-ingestion queue / `--ingest` handoff all
|
|
|
1047
167
|
with a one-line "free during the beta" notice if no valid key is set. See
|
|
1048
168
|
[docs/pro.md](docs/pro.md) for details.
|
|
1049
169
|
|
|
170
|
+
**How do I roll back a customization?**
|
|
171
|
+
It depends what changed. If `skill-forge init` gave a skills root a Git baseline (or you'd already
|
|
172
|
+
committed it yourself), rolling back a change under that root is ordinary Git —
|
|
173
|
+
`git checkout -- <path>` or `git reset`, run by you; skill-forge doesn't ship its own rollback for
|
|
174
|
+
that. `refine rollback <backup-id>` is different and narrower: it only undoes a `refine promote`
|
|
175
|
+
(a base-skill update recorded by `skill-forge refine`), not a Git commit or anything else. See
|
|
176
|
+
[Git preflight](docs/commands/init.md#git-preflight-v016) and
|
|
177
|
+
[`refine`](docs/commands/refine.md) for both.
|
|
178
|
+
|
|
179
|
+
**Where's the full documentation?**
|
|
180
|
+
See the [docs index](docs/README.md) for every command reference and background doc.
|
|
181
|
+
|
|
1050
182
|
## License
|
|
1051
183
|
|
|
1052
184
|
skill-forge is open-core with a split license (as of v0.2.0):
|
|
@@ -1056,7 +188,8 @@ skill-forge is open-core with a split license (as of v0.2.0):
|
|
|
1056
188
|
- **Pro modules — Rhize Commercial License.** `src/license.ts`, `src/gate/overlap.ts`,
|
|
1057
189
|
`src/provenance.ts`, `src/queue.ts` (overlap analysis, provenance ledger, pending
|
|
1058
190
|
queue / `--ingest` handoff), and `src/refine/` (v0.10 — capture/apply/generalize skill
|
|
1059
|
-
overrides)
|
|
191
|
+
overrides), plus `src/insights/` (source studies, evidence validation, inventory mapping,
|
|
192
|
+
plans, and Jira manifests). The source is available to read and audit, but production use of Pro
|
|
1060
193
|
functionality requires a license key — see [LICENSE-COMMERCIAL](LICENSE-COMMERCIAL).
|
|
1061
194
|
|
|
1062
195
|
[LICENSE](LICENSE) is the authoritative map of which files fall under which license.
|