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.
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 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, mcp-destructive-guard and 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
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-sourcessobin/doctorcan 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 |
ANTIGRAVITY_SKILLS_JSON |
$HOME/.gemini/config/skills.json (registers AGENTS_SKILLS_DIR as a path entry; needs jq) |
SKILLS_EXTRA_SOURCES |
unset (colon-separated extra source directories) |
The Mistral Vibe target was removed — unused. Antigravity's was removed for the same reason and re-added once it came back into use.
Checking a host
task doctor # or bin/doctor
Reports dangling links, links into a source nobody configured, skills in the checkout with no link, stray entries, leftover per-skill Claude symlinks, and a Claude Code plugin sitting on an older generation than the host already has. 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.
All of that compares copies already on the machine — deliberately, since it runs in a session hook where latency shows. That leaves one case invisible: a host where the checkout, the marketplace clone and the installed plugin all agree, and all three are a release behind origin.
task doctor -- --online # or bin/doctor --online
One git ls-remote against origin, opt-in. Belongs in a scheduled per-host job,
not the session hook. An unreachable remote is reported as its own fault rather
than as staleness — "I could not check" and "you are behind" are different
answers and only one of them is about the host.
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.0Bump-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
-
Add a directory
skills/<short-kebab-name>/. -
Create
skills/<short-kebab-name>/SKILL.mdwith this frontmatter — all four keys are gated bytask check, and the index table is generated from the last three:--- 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.
-
Run
task indexand commit the regeneratedSKILLS_INDEX.md. Do not hand-edit the table —task checkregenerates it and fails on a diff. -
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-skillsand #19. -
Commit directly to
main. Conventional-commit prefix (feat:/fix:/docs:). AddBump-Type: minorfooter 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. |