The GREEN run confirmed the gate works: given "builds are flaky again... what's the fix?" with no run id and no log, it produced zero hypotheses and an ordered list of artifacts, each justified by what it would discriminate. It also caught that the retry already shipped in that pipeline is destroying the evidence needed to diagnose it, which is a better finding than any hypothesis would have been. Then it found eight problems, and the first two are mine: **The template contradicted the rule.** I banned high/medium/low labels in Step 2 and left them in the Step 3 output template and all three worked-example hypotheses. "Prose loses to a format block every time" — correct, and the template is what gets imitated. Labels are gone from both; the slot is now WHY FIRST, which asks for the evidence that sets the order rather than a restatement of it. **The description never mentioned the gate.** That is the text a harness shows before an agent decides to load anything, and it read "Generate 3-5 ranked hypotheses" — so an agent routing on the description alone does exactly the thing this skill was rewritten to prevent. Both description and use_when now lead with the refusal. The rest: - Intake vs the failed-fixes section pointed opposite ways for a report that fires both, and nothing stated precedence. Intake wins, and says so: you cannot aim hypotheses at a premise you have no evidence about either. - "One run narrows the search to a single component" was overclaimed exactly where it gets used — CI flakiness. One run *that reproduces* narrows it; a passing run narrows nothing. - session_log had no phase for a correct refusal, so an intake stop logged as a failed read-failure. A metric that penalises the skill's best behaviour trains the next model to guess. Added an `intake` phase. - The Anti-Patterns table — the part people scan in a hurry — was missing the failure this whole rewrite is about: answering "what's the fix?" from a report with no artifact. - brain_query told you to search on an error string you may have just refused to proceed without. Now: query symptom + component, which may itself name the artifact to ask for. - condition-based-waiting was an unconditional load on any mention of a timeout, including during an intake stop, which is the wrong side of the gate. Closes #36 Bump-Type: minor
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 + 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 |
SKILLS_EXTRA_SOURCES |
unset (colon-separated extra source directories) |
Antigravity and Mistral Vibe targets were removed — unused.
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. |