mathiasandClaude Opus 5 88c54399fe feat(doctor): fail loud on skills drift, wired to SessionStart
Every failure this fleet actually hit was silent. 243 dangling symlinks were
invisible to git because **/.claude/skills/ is in the global gitignore. A
checkout 20 skills behind still resolved, so nothing complained. A loose
secret-hygiene.md loaded in no harness and errored in none. Two machines had
the library missing entirely. Exit status is the signal that was absent.

bin/doctor reports, with a non-zero exit:
  - dangling links, anywhere under the harness dirs
  - links that RESOLVE but land outside the active checkout — the dangerous
    case, because it works while serving stale content
  - skill-count mismatch between a harness and the checkout
  - stray entries where <name>/SKILL.md was expected
  - leftover per-skill Claude symlinks (plugin skills do not override
    same-named user skills, so leftovers mean everything loads twice)
  - divergence between the plugin copy and the copy the other harnesses link to

Wired as a SessionStart hook with --quiet, so a healthy host prints nothing and
a drifting one says so at the top of the next session. That beats a timer:
no launchd/systemd wiring, and it reaches every host that installs the plugin.
27ms on koala, no network, no git fetch.

Two design points found by the tests, both worth keeping:
  - The canonical checkout is whatever ~/.agents/skills resolves to, NOT the
    copy doctor runs from. As a plugin hook $0 lives in the plugin cache, which
    is legitimately a second copy; judging harness links against it flagged
    every one of them as "outside".
  - "cd X/.." resolves ".." lexically against the link path and lands back in
    ~/.agents. Resolve the link first, then take the parent.

tests/doctor_test.sh drives seven fixtures through $HOME and $DOCTOR_CHECKOUT,
so no test touches the real host. Each asserts both the non-zero exit and that
the report names the fault — an exit-code-only assertion would pass while the
message said nothing useful.

Bump-Type: minor

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BeAp5LTscnz2W7Ubt4eJ6m
2026-08-23 14:34:32 +02:00

skills

Engineering skills library — markdown SKILL.md files that plug into any project or AI-coding harness. Installed via task skills:install in consumer projects, or directly by install.sh on hosts without Task.

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 (consumer project)

The expected pattern: each consumer project's Taskfile.yml has a skills:install target that delegates here. From a project root:

task skills:install

Bare-shell fallback for hosts without Task installed:

curl -fsSL https://gitea.d-ma.be/mathias/skills/raw/branch/main/install.sh | bash

Both forms are idempotent and re-runnable. On every run they:

  1. git clone (or git pull) this repo into ~/.local/share/skills/ — the canonical local checkout on every host.
  2. Wire per-skill symlinks into the harnesses found on the host (see Wired harnesses).

Re-run after git pull upstream to pick up new skills or version changes. CI tags every change as a vX.Y.Z release (see Versioning).

Wired harnesses

Harness Target path Notes
Claude Code (global) ~/.claude/skills/<name> Visible in every Claude Code session on the host.
Claude Code (per-repo) <repo>/.claude/skills/<name> Created when install is invoked inside a git repo (not the skills repo itself). Gitignored globally via **/.claude/skills/.
Crush ~/.config/crush/skills/<name> Charmbracelet Crush — successor to opencode-ai/opencode (archived).
Antigravity ~/.gemini/antigravity/skills/<name> Google Antigravity (VS Code extension). Our SKILL.md frontmatter (name + description) is already in the format Antigravity expects, so symlinks suffice — no manifest translation.

Not wired (and why)

  • opencode (opencode-ai/opencode): archive notice; succeeded by Crush. Its only "skill"-like surface — Custom Commands at ~/.config/opencode/commands/ — is for user-facing prompt templates, not system-level instructions. Misaligned with how we use skills. Skipped.
  • gitea-resident agents (cobalt-dingo, agentsquad): they consume skills via their containing project's .claude/skills directory (populated by the per-repo wirer when run from the host), or via the brain MCP. No special target needed.

Per-host env-var overrides

Each target path can be overridden by setting the matching env var before running install.sh:

Env var Default
SKILLS_REPO_URL https://gitea.d-ma.be/mathias/skills.git
SKILLS_REF main (set to e.g. v0.1.0 to pin a release)
SKILLS_CHECKOUT_DIR $HOME/.local/share/skills
CLAUDE_SKILLS_DIR $HOME/.claude/skills
CRUSH_SKILLS_DIR $HOME/.config/crush/skills
ANTIGRAVITY_SKILLS_DIR $HOME/.gemini/antigravity/skills

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 <short-kebab-name>/.
  2. Create <short-kebab-name>/SKILL.md — start with one-paragraph purpose, then triggers ("use when …"), then mechanics.
  3. Add a row to SKILLS_INDEX.md (description + use-when).
  4. 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.

S
Description
Engineering skills library — markdown SKILL.md files installed into any project or harness via task skills:install
Readme
853 KiB
Languages
Shell 84%
JavaScript 9.5%
HTML 3.9%
TypeScript 2.6%