Seven skills carried a `## Mode 2 Routing Note` citing a routing pod ("Plan 6")
that does not exist. Several admitted in their own text that nothing about the
skill changes between modes — so it was roughly ten lines of context on every
load for zero behavioural effect. The content is not worthless, just not
per-skill: it now lives as one table in README.md, with the caveat that nothing
depends on it.
The related line inside the session_log sections stays, because that one does
motivate behaviour — but it no longer cites a component that has never shipped.
It now says what is true: pass-rate is what a future routing decision would be
based on, and a skill that never logs contributes no evidence either way.
While in README: the contributing steps were stale enough to fail CI for anyone
who followed them. They said to add a row to SKILLS_INDEX.md by hand — the table
is generated now, and `task check` fails on a hand-edited diff — and listed none
of the four frontmatter keys the gates require. Step 4 now names the
pressure-test bar from #19 rather than leaving it to be discovered.
Closes #36
Bump-Type: patch
178 lines
8.6 KiB
Markdown
178 lines
8.6 KiB
Markdown
# skills
|
|
|
|
Engineering skills library — markdown `SKILL.md` files that plug into any
|
|
AI-coding harness.
|
|
|
|
For **Claude Code** this repo is a plugin, installed from the marketplace it
|
|
also hosts; that path carries the hooks and MCP servers too. For **Crush, Pi
|
|
and OpenCode** it is a plain library wired by `install.sh` as one directory
|
|
symlink per harness. See [`SKILLS_INDEX.md`](./SKILLS_INDEX.md#wiring-into-tools).
|
|
|
|
## What is a skill?
|
|
|
|
A skill is a single directory containing one or more markdown files. The
|
|
canonical entrypoint is `<name>/SKILL.md`. Additional reference material
|
|
lives alongside in the same directory (e.g.
|
|
`clean-code/references/code-smells.md`). Harnesses load skills on
|
|
demand — keep `SKILL.md` short and triggerable; push depth into
|
|
references.
|
|
|
|
See [`SKILLS_INDEX.md`](./SKILLS_INDEX.md) for the full catalogue with
|
|
descriptions and "use when" triggers.
|
|
|
|
## Install
|
|
|
|
### Claude Code — the plugin
|
|
|
|
```
|
|
/plugin marketplace add https://git.d-ma.be/mathias/skills.git
|
|
/plugin install skills@mathias
|
|
```
|
|
|
|
The plugin ships skills, the `secret-guard` + `pre-task-ritual` hooks, and the
|
|
brain/gitea/infra MCP servers as one versioned unit. Skills are namespaced
|
|
(`skills:tdd`). Updates land when `.claude-plugin/plugin.json`'s `version`
|
|
moves — CI bumps it on every release.
|
|
|
|
### Crush, Pi, OpenCode — `install.sh`
|
|
|
|
```bash
|
|
curl -fsSL https://git.d-ma.be/mathias/skills/raw/branch/main/install.sh | bash
|
|
```
|
|
|
|
Idempotent. It clones or fast-forwards the checkout, then populates one
|
|
**managed directory** and gives each harness a single link to it:
|
|
|
|
| Path | Target |
|
|
|---|---|
|
|
| `~/.agents/skills/` | a real directory, one symlink per skill (Pi reads this path directly) |
|
|
| `~/.agents/skills/<skill>` | `$SKILLS_CHECKOUT_DIR/skills/<skill>`, or another configured source |
|
|
| `~/.config/crush/skills` | `~/.agents/skills` |
|
|
| `~/.config/opencode/skills` | `~/.agents/skills` |
|
|
|
|
Total links are N + one per harness — not N x harnesses, which is what #23 was
|
|
actually about.
|
|
|
|
### More than one source of skills
|
|
|
|
`~/.agents/skills` used to be a single link straight at this checkout. That
|
|
encoded an assumption nobody had stated — that this checkout is the only source
|
|
of skills on the host — and on flamingo the only way to install this library
|
|
was to displace Anthropic's official set, which lived in Crush's directory.
|
|
Real capability loss dressed up as a tidy-up (#27).
|
|
|
|
Point `SKILLS_EXTRA_SOURCES` at any number of extra directories, colon
|
|
separated, each holding `<skill>/SKILL.md`:
|
|
|
|
```
|
|
SKILLS_EXTRA_SOURCES=~/.config/crush/skills.anthropic bash install.sh
|
|
```
|
|
|
|
- The checkout is always first and always wins a name collision — but the
|
|
collision is **logged**, never resolved in silence. Quietly picking one is
|
|
how stale content wins.
|
|
- Removing a skill from a source removes its link on the next run.
|
|
- Anything in the managed directory that is not a symlink is reported and left
|
|
alone. install.sh does not delete content it did not create.
|
|
- The source list is recorded at `~/.agents/skills-sources` so `bin/doctor`
|
|
can tell a link into a known source from a link into a forgotten one.
|
|
|
|
### Where the checkout must live
|
|
|
|
`SKILLS_CHECKOUT_DIR` defaults to `~/.local/share/skills`, and that default is
|
|
load-bearing: it is **host-local, outside any synced or shared directory**.
|
|
|
|
On this fleet `~/dev` is an iCloud folder shared by flamingo and iguana, and it
|
|
spans two path roots — `/Users/mathias` on the Macs, `/home/mathias` on koala.
|
|
A checkout there is a git working tree with two concurrent writers, and any
|
|
absolute symlink stored there is broken on one side by construction. That is
|
|
what produced 243 dangling links across 12 repos (#23). Do not "fix" the
|
|
default to point into `~/dev`.
|
|
|
|
### Per-host env-var overrides
|
|
|
|
| Env var | Default |
|
|
|---|---|
|
|
| `SKILLS_REPO_URL` | `https://git.d-ma.be/mathias/skills.git` |
|
|
| `SKILLS_REF` | `main` (set to e.g. `v0.4.0` to pin a release) |
|
|
| `SKILLS_CHECKOUT_DIR` | `$HOME/.local/share/skills` |
|
|
| `SKILLS_SKIP_FETCH` | unset (`1` wires an existing checkout without touching HEAD) |
|
|
| `AGENTS_SKILLS_DIR` | `$HOME/.agents/skills` |
|
|
| `CRUSH_SKILLS_DIR` | `$HOME/.config/crush/skills` |
|
|
| `OPENCODE_SKILLS_DIR` | `$HOME/.config/opencode/skills` |
|
|
| `SKILLS_EXTRA_SOURCES` | unset (colon-separated extra source directories) |
|
|
|
|
Antigravity and Mistral Vibe targets were removed — unused.
|
|
|
|
## Checking a host
|
|
|
|
```bash
|
|
task doctor # or bin/doctor
|
|
```
|
|
|
|
Reports dangling links, links resolving into a foreign checkout, skill-count
|
|
mismatches, stray entries, and leftover per-skill Claude symlinks. Non-zero
|
|
exit on drift. It also runs at session start via the plugin, so a drifting
|
|
host says so rather than waiting to be discovered.
|
|
|
|
## Versioning
|
|
|
|
Every commit to `main` is auto-tagged as a semver release by the
|
|
`.gitea/workflows/release.yml` action. Bump direction follows the commit
|
|
footer:
|
|
|
|
- `Bump-Type: major` → `X.0.0`
|
|
- `Bump-Type: minor` → `0.Y.0`
|
|
- *anything else* → `0.0.Z` (patch, the default)
|
|
|
|
Consumer projects can pin a version by setting `SKILLS_REF=v0.1.0`
|
|
before `task skills:install`; default is `main` for always-current.
|
|
|
|
## Contributing a skill
|
|
|
|
1. Add a directory `skills/<short-kebab-name>/`.
|
|
2. Create `skills/<short-kebab-name>/SKILL.md` with this frontmatter — all four
|
|
keys are gated by `task check`, and the index table is generated from the
|
|
last three:
|
|
|
|
```yaml
|
|
---
|
|
name: <short-kebab-name>
|
|
surfaces: [claude-code, library] # any of claude-code | library | chat
|
|
summary: "<one line for the index table>"
|
|
use_when: "<the trigger, for the index table>"
|
|
description: <the paragraph the model selects on>
|
|
---
|
|
```
|
|
|
|
Then: one-paragraph purpose, triggers ("use when …"), mechanics.
|
|
3. Run `task index` and commit the regenerated `SKILLS_INDEX.md`. Do **not**
|
|
hand-edit the table — `task check` regenerates it and fails on a diff.
|
|
4. Pressure-test it before shipping: run the scenario against a subagent that
|
|
does *not* have the skill, write the skill against what that run actually
|
|
did, then re-run with it. See `superpowers-writing-skills` and #19.
|
|
5. Commit directly to `main`. Conventional-commit prefix
|
|
(`feat:` / `fix:` / `docs:`). Add `Bump-Type: minor` footer when
|
|
adding a new skill or expanding scope; default patch covers edits.
|
|
|
|
This repo is markdown-only and public — never include secrets, client
|
|
names, or anything under NDA in a skill.
|
|
|
|
## Mode 2 routing candidates
|
|
|
|
These notes used to sit in each SKILL.md as a `## Mode 2 Routing Note` section.
|
|
They changed nothing about how the skill is invoked — several said so outright —
|
|
and cost context on every load, so they live here instead. Nothing in the repo
|
|
depends on this table; it is a record of which skills looked mechanical enough
|
|
to route to a local model, should a routing layer ever exist.
|
|
|
|
| Skill | Note |
|
|
|---|---|
|
|
| `cad-babysit` | Phases 2-4 (reading comments/logs, classifying fault vs outcome) are judgment-heavy and should stay Mode 1. Phase 1 (running `cad stuck` and grouping its output) is mechanical and a Mode 2 routing candidate once Plan 6 ships the routing pod. |
|
|
| `code-review` | This skill is invoked identically in Mode 1 (cloud Claude) and Mode 2 (client-local with supervisor routing). The routing layer (Plan 6) does not exist yet; treat this skill as Mode 1 only for now. Findings format and severity classification are unchanged across modes. |
|
|
| `debug` | This skill produces high-volume mechanical output (hypothesis enumeration) and is a candidate for Mode 2 routing to a local model in the future. Until Plan 6 ships the routing pod, treat as Mode 1 only. The hypothesis format and discipline are identical regardless of which model generates them. |
|
|
| `feature-spec` | Spec writing requires interpretation of intent and tradeoff reasoning — work where Claude generally outperforms a 9-13B local model. This skill is intentionally **not** a Mode 2 routing candidate. In Mode 2, the routing layer should leave `feature-spec` calls on Claude. |
|
|
| `session-retrospective` | Reading long session logs and pulling themes is high-volume, mechanical pattern-recognition work — a strong Mode 2 routing candidate. Until Plan 6 ships the routing pod, treat as Mode 1 only. |
|
|
| `tdd` | This skill is invoked identically whether the agent is running in Mode 1 (cloud Claude, no routing) or Mode 2 (client-local, supervisor routing layer). The routing pod (Plan 6) does not exist yet; until it does, treat this skill as Mode 1 only. The discipline does not change between modes — only the model behind the call. |
|
|
| `trainer` | Trainer is the same shape as `session-retrospective` — long-context reading, mechanical filtering — and is a Mode 2 routing candidate. Until Plan 6, treat as Mode 1 only. |
|