# Agents

This repository is a catalogue of skills and small utilities for AI coding
agents. It targets any agent that can read Markdown instructions — Claude
Code, Codex CLI, opencode, Continue, Aider, Cursor, and others.

## Start here

- Documentation map: [`docs/README.md`](docs/README.md).
- Add or change a skill: [`docs/contributing.md`](docs/contributing.md); the
  conventions below are the reference.
- Install and use the catalogue: [`README.md`](README.md) and
  [`docs/install.md`](docs/install.md).
- Vocabulary: [`GLOSSARY.md`](GLOSSARY.md). Decisions:
  [`docs/adr/README.md`](docs/adr/README.md).

## How to use this repo

- Each directory under `skills/` that contains a `SKILL.md` file is a
  self-contained skill.
- `skills.json` (repo root) is the machine-readable manifest of all
  skills. Read it once to discover what is available without crawling the
  tree.
- `install.sh` (repo root) symlinks the skills into the conventional
  install paths for Codex CLI and opencode. It also renders the plugins'
  subagents through `scripts/plugin_agents.py` — Codex custom agents in
  `~/.codex/agents/`, opencode subagents in `~/.config/opencode/agents/` —
  and for Codex CLI disables routed members via a marker-delimited block in
  `~/.codex/config.toml` (all removed by `--uninstall`).
  `--merge-guard` adds the model-free hook `scripts/pr_merge_guard.py` that
  stops agents from merging PRs (only the human merges); this repo's
  `.claude/settings.json` carries it via `scripts/build_project_claude.py`.
  `--secret-guard` adds the same kind of hook, `scripts/secret_read_guard.py`,
  which stops agents from reading credential files or dumping the environment.
  Claude Code gets skills, subagents, the merge guard and the secret read guard
  from the plugin marketplace only; `--target=claude` syncs just
  `--instructions`, installs the guard plugins through the `claude` CLI, and
  removes the links and settings entry older versions created.
  See `./install.sh --help` and `docs/install.md`.
- `instructions/` holds single-topic rule fragments, ordered by numeric
  filename prefix, in three tiers: 20, 25, 45, 50, 55 and 60 are always on;
  Python and R rules are path-scoped in Claude, while Codex and opencode get
  the Python baseline by pointer and keep the R rules in their block; 70, 80
  and 85 are on demand; 85 is also repeated in this repository's `AGENTS.md`.
  `install.sh --instructions` composes the always-on
  rules and pointers into marker-delimited blocks in each agent's global
  instruction file (`~/.claude/CLAUDE.md`, `~/.codex/AGENTS.md`,
  `~/.config/opencode/AGENTS.md`) and installs on-demand files under
  `~/.agents/instructions/`. Claude loads `paths:` fragments from
  `~/.claude/rules/`; a `Bash(uv init*)` hook supplies the Python baseline
  before a Python file exists. The 70 and 85 sources live in
  `instructions/on-demand/`; 80 lives at
  `skills/llm-application-engineering/references/agent-pipelines.md`. Content
  outside the managed markers is never touched.
- `plugins/` packages the same skills as Claude plugins, one plugin per
  category (each bundles its skills via symlinks into `skills/`).
  `.claude-plugin/marketplace.json` makes the repo installable as a
  plugin marketplace in Claude Code, claude.ai, Claude Desktop, and
  Cowork. The `architecture` plugin additionally ships two read-only
  analysis subagents (`coupling-analyst`, `cohesion-analyst`). The
  hook-only `merge-guard` and `secret-guard` plugins carry the PR merge
  guard and the secret read guard as `PreToolUse` hooks in `hooks/hooks.json`.
- `.claude/` makes the same skills, subagents and instruction fragments
  available to Claude Code cloud sessions in this repo, which load neither
  plugins nor `~/.claude/`: symlinks and rendered rules generated by
  `scripts/build_project_claude.py` (CI checks drift), including the
  `Bash(uv init*)` hook that reads `instructions/30-python.md`, plus Matt
  Pocock's skills vendored by `scripts/vendor_mattpocock_skills.py`. See
  `docs/maintainers/install-internals.md`.
- Reference material stays inside the skill that owns it, under
  `skills/<skill>/references/`. SKILL.md names the pages it has; an agent
  opens one only when it needs it. There is no lookup service in front of
   them — plain progressive disclosure is the whole mechanism.

## Skill catalogue

Each skill carries a `category` frontmatter field; the sections below
group the catalogue by those categories.

Some categories ship a **router** skill (`activation: router`, named after
the category) as their single registered entry point. Its description is
deliberately broad, and its body routes to the specific sub-skill to read
before acting; the sub-skills nest under the router's `members/` directory
and load only when routed to (progressive disclosure), so the category adds
one trigger entry instead of many. The router's SKILL.md member table is
generated from `skills.json` by `scripts/build_routers.py` (CI checks it for
drift). The tables below still list every sub-skill individually.

Claude registers only top-level skills, so the members stay hidden there. Codex
discovers skills recursively and follows symlinks
([openai/codex#22275](https://github.com/openai/codex/issues/22275)), so it
would otherwise register each nested `members/<name>/SKILL.md` as its own skill;
`install.sh --target=codex` therefore disables every nested member by path in
`~/.codex/config.toml` (a managed `[[skills.config]]` block, `enabled = false`),
dropping them from the model's skill list. `--uninstall` removes the block.

### Architecture & design (`architecture`)

Registered through the [`architecture`](skills/architecture/SKILL.md) router.

| Skill | When to use |
|---|---|
| [architecture-pattern-advisor](skills/architecture-pattern-advisor/SKILL.md) | Choosing or restructuring the architecture of a new or existing repository — system topology (monolith, modular monolith, microservices, serverless, event-driven) and code organization (layered, by-domain, hexagonal, clean/onion). |
| [c4-modeling](skills/c4-modeling/SKILL.md) | Drafting a C4 model of a system interactively and rendering it as Mermaid diagrams — System Context, Container, and Component views plus landscape, dynamic, and deployment — per c4model.com best practices. |
| [coupling-cohesion](skills/coupling-cohesion/SKILL.md) | Measuring coupling or cohesion of existing code — a module's cohesion and LCOM, codebase-wide coupling metrics (instability, abstractness, Zones of Pain/Uselessness), or whether one specific dependency is balanced (Khononov strength/distance/volatility). |
| [ddd](skills/ddd/SKILL.md) | Domain-Driven Design across strategy and code — subdomain classification, context mapping, choosing an implementation pattern, and the correctness conventions for aggregates, value objects, domain events, and event sourcing. |
| [fitness-functions](skills/fitness-functions/SKILL.md) | Designing architecture fitness functions — automated, CI-wired checks (cycle detection, layer rules, metric thresholds, chaos/conformity monitors) that govern architecture characteristics. |
| [logical-component-design](skills/logical-component-design/SKILL.md) | Decomposing a new system or feature into named logical components — the iterative Workflow / Actor-Action identification cycle, the Entity-Trap antipattern, cohesion and coupling refinement, and the Law of Demeter. |
| [microservices-design](skills/microservices-design/SKILL.md) | Designing or reviewing how microservices interact — boundaries, coupling, communication style, contract versioning, cross-service code reuse, sagas, and resiliency patterns (timeouts, bulkheads, circuit breakers, retries) — via a distilled Newman ruleset. |

### Refactoring & code quality (`refactoring`)

| Skill | When to use |
|---|---|
| [improve-codebase](skills/improve-codebase/SKILL.md) | Reviewing a repository's architecture for deepening opportunities — a visual HTML report of candidates with before/after diagrams and a top recommendation, then a round-by-round interview on the one you pick, keeping the glossary and ADRs current. |
| [refactoring](skills/refactoring/SKILL.md) | Finding where to start refactoring in a codebase nobody knows well — ranking files by git churn, reading the hotspots, and keeping restructuring separate from behavior change. |

### AI & ML (`ai-ml`)

Registered through the [`ai-ml`](skills/ai-ml/SKILL.md) router.

| Skill | When to use |
|---|---|
| [llm-application-engineering](skills/llm-application-engineering/SKILL.md) | Diagnosing LLM output failures, ordering LLM app architecture builds, defining production monitoring metrics, or applying craft-level conventions for prompting, evaluation/LLM-judges, guardrails, finetuning, and training data. |
| [ml-project-lifecycle](skills/ml-project-lifecycle/SKILL.md) | Scoping an ML project, picking a model/baseline, handling missing data, or planning pipelines and staged deployment. |

### Workflow & planning (`workflow`)

| Skill | When to use |
|---|---|
| [natural-planning](skills/natural-planning/SKILL.md) | When a project feels stuck, vague, or overwhelming, or a to-do isn't yet a concrete physical next action. |
| [oss-scouting](skills/oss-scouting/SKILL.md) | Scouting one third-party open-source repo for issues worth a small contribution — policy gate, repro, root-cause analysis, fix diff, and a submit checklist, written locally for the user to submit themselves. |
| [poc-spec-loop](skills/poc-spec-loop/SKILL.md) | Bring a greenfield R, Python, or bash PoC to production readiness in two gated phases — interactive spec (SPEC.md + prd.json), then a per-task TDD loop with fresh context up to a pull request. |
| [pypet-snippets](skills/pypet-snippets/SKILL.md) | Curating pypet command snippets — creating, finding, editing, running and aliasing them on request, or proposing one for recurring terminal commands. |
| [release-pr](skills/release-pr/SKILL.md) | Turning the current branch into a release PR for an R or Python package — confirmed version bump, NEWS.md/CHANGELOG.md, checks, PR body — and, after merge, tagging and publishing the release (GitHub, Azure Repos, GitLab). |
| [repo-status](skills/repo-status/SKILL.md) | Generating a status update from recent activity — standup prep, yesterday/today/blockers, structuring rough notes into a shareable update. |

### Communication & writing (`communication`)

| Skill | When to use |
|---|---|
| [blue-team](skills/blue-team/SKILL.md) | Developing a raw early idea — tech decision, project pitch, LinkedIn thesis, personal choice — into a sharper version that holds up before its audience, with load points, reinforcements, and a hardness grade. |
| [communication-analysis](skills/communication-analysis/SKILL.md) | Analyzing or rewriting feedback, messages, or conversations for congruence, hidden appeals, clarity, or boundaries. |
| [documentation](skills/documentation/SKILL.md) | Writing or revising technical documentation for a named reader — README, API reference, runbook, architecture doc, or onboarding guide. |
| [html-artifacts](skills/html-artifacts/SKILL.md) | Producing a self-contained HTML file instead of a markdown reply when content has spatial, comparative, or interactive structure — comparisons, diagrams, timelines, decks, throwaway editors. |
| [ki-stil](skills/ki-stil/SKILL.md) | Checking a German draft for wording that reads generic or AI-typical — counted, located style signals from a bundled scanner, an evidence-tiered verdict, and concrete rewrites; a heuristic, never an authorship verdict. |
| [problem-first-explanation](skills/problem-first-explanation/SKILL.md) | Producing explanations — technical or not — that lead with the concrete problem before the solution. |
| [red-team](skills/red-team/SKILL.md) | Attacking a finished or near-finished artefact or decision — ADR, proposal, LinkedIn post, application, career move — through a fresh-context critic, a materiality gate, stakeholder lenses, and a categorical verdict. |
| [stakeholder-update](skills/stakeholder-update/SKILL.md) | Writing a status update for readers outside the immediate working group — weekly/monthly leadership status, launch announcement, risk escalation, or the same progress retold for partners and customers. |
| [tldr](skills/tldr/SKILL.md) | Compressing something too long to read into the few facts needed to decide or act, read instead of the source — the last message and the work behind it, or a named file, PR, document, or thread. |
| [was](skills/was/SKILL.md) | Re-pitching a short message that was read but not understood, in plain German — the missing context added first instead of shortening, short active sentences, the repo's glossary terms kept verbatim. |

### Personal & knowledge (`personal`)

| Skill | When to use |
|---|---|
| [hypertrophy-training](skills/hypertrophy-training/SKILL.md) | Experienced trainee: set volume, RIR/effort, auto-regulation, diagnosing a stalled lift, training under elevated injury risk, or returning after an injury (educational). |

For agents that auto-load `AGENTS.md` (Codex CLI, opencode, Aider): the
links above are valid relative paths and may be fetched on demand. For
machine consumption prefer `skills.json`.

## Conventions for skill authors

- A skill lives in `skills/<skill-name>/` and has a `SKILL.md` at its root.
- `SKILL.md` starts with YAML frontmatter providing at minimum:
  - `name` — must match the directory name (`scripts/quick_validate.py` enforces it).
  - `category` — one of `architecture`, `refactoring`,
    `ai-ml`, `workflow`, `communication`, `personal` (the fixed list in
    `scripts/catalogue.py`; `scripts/quick_validate.py` mirrors it so the
    validator also works on skills outside this repo). Determines the
    catalogue section, the `install.sh --category` subset, and which plugin
    bundles the skill.
  - `description` — single paragraph; the first sentence becomes the
    `summary` in `skills.json` (for a router the whole description does, since
    it is the category's entire trigger surface). Keep it within the description budget:
    **≤250 chars** for most skills, **≤450 chars** for router skills, **≤400 chars**
    for the small allowlist of high-traffic skills in
    `scripts/check_descriptions.py`. Descriptions
    are always-loaded metadata that competes for a tight context budget
    (Codex CLI truncates the skill list past ~2% of context), so move
    trigger lists and feature enumerations into the SKILL.md **body** (a
    leading `## When to use` section) rather than the frontmatter. CI
    enforces this with `python3 scripts/check_descriptions.py`, which also
    caps the aggregate across all `auto` skills.
- Optional frontmatter fields:
  - `activation` — `auto` (default) or `command`. `auto` skills are
    model-triggered and their description counts toward the auto-trigger
    budget. `command` skills are user-invoked only: OpenCode exposes them as
    slash commands from the ordinary skills directory when `metadata` sets
    `opencode/slash: "true"` and `opencode/autoinvoke: "false"`; Claude loads
    them from the plugins as `/<category>:<name>`. Codex custom prompts are
    deprecated, so under codex they install
    into `~/.agents/skills/` like any skill, gated by an `agents/openai.yaml`
    sidecar (`policy.allow_implicit_invocation: false`) that keeps Codex from
    auto-triggering them. That sidecar is committed per skill, at
    `skills/<name>/agents/openai.yaml` — `install.sh` links it, it does not
    generate it. For Claude, pair `command` with
    `disable-model-invocation: true` in the same frontmatter (the runtime
    realization Claude honors; ignored elsewhere). CI enforces both with
    `scripts/quick_validate.py`.
  - `when_to_use` — trigger phrases for a **router**, as a single paragraph.
    Claude Code appends it to the description in its skill listing (joined
    with `" - "`, the two capped at 1,536 chars together), so it holds the
    situations users actually type without spending the router's ≤450-char
    description budget on them. Codex ignores the key entirely (verified with
    `codex debug prompt-input`), which is why
    `scripts/check_descriptions.py` keeps it out of the Codex-facing budgets
    and gives it Claude's combined cap instead. A router's `skills.json`
    summary appends it the same way Claude does, so the recall menu in
    `eval-suite/recall` ([fabiandistler/eval-suite](https://github.com/fabiandistler/eval-suite))
    shows what the client shows.
  - `compatibility` — runtime / language requirements in plain prose.
  - `environments` — comma-separated list of the environments the skill
    belongs to: `coding`, `chat`, or both (e.g. `environments: coding, chat`).
    `install.sh --env=coding|chat` uses this to install only the matching
    subset. A skill without the field belongs to every environment.
  - `targets` — comma-separated subset of `claude`, `codex`, `opencode`
    (e.g. `targets: codex, opencode`). `install.sh` never links the skill for
    an agent the field leaves out, and removes a link it had created there
    before. Use it when a runtime already ships an equivalent of its own. A
    skill without the field is installed for every target. Because `plugins/` is
    the Claude distribution, a skill that excludes `claude` also gets no
    plugin symlink (`scripts/check_plugins.py` knows this).
  - `metadata.version` — semver-ish string.
  - `argument-hint` — the argument a `command` skill takes, shown by Claude
    Code next to the command name (e.g. `argument-hint: "<owner>/<repo>"`).
    Other agents ignore it.
  - `license`, `allowed-tools` — Agent Skills format fields that
    `scripts/quick_validate.py` accepts. No skill here uses them yet.
- The body is plain Markdown. Avoid agent-specific vocabulary
  (slash-commands, "the Skill tool", proprietary tool names, hardcoded
  install paths, runtime error text). Prefer
  describing the workflow in terms any reader can apply.
- Cross-skill references name only registered, model-invocable skills.
  A `command` skill is user-invoked, so say suggest the user run it instead
  of invoking it. A router member is read via its router file, never invoked
  by a namespaced name; name the router and the member file to read.
  CI enforces this with `python3 scripts/check_skill_refs.py`.
- Generated files — `skills.json`, the router member tables and the
  `.claude/` mirror — are regenerated by the prek commit hooks
  (`build-manifest`, `build-routers`, `build-project-claude` in
  `.pre-commit-config.yaml`) whenever a commit touches a `SKILL.md`, an
  instruction fragment or a plugin subagent. On drift the hook rewrites
  the files and fails the commit; stage them and commit again. Without the
  hooks installed (`prek install`), or after deleting a skill (deletions
  never trigger a hook), regenerate by hand in this order:
  `python3 scripts/build_manifest.py`, `python3 scripts/build_routers.py`,
  `python3 scripts/build_project_claude.py`. CI's `--check` gates catch
  whatever slips through.
- `prek install` also installs a commit-msg hook (`scripts/check_commit_msg.py`,
  Conventional Commits subjects) and two pre-push hooks that run
  `scripts/check_all.sh --skip prek,mermaid,bats` and
  `scripts/check_all.sh --only bats`; set `PYTHON=` to a 3.11+ interpreter, or
  the push stops with exit 4.
- Shell scripts are tested with Bats: one `test/<script>.bats` suite per
  entry point (`install.sh` is split into `test/install*.bats`), run by
  `test/bats/bats-core/bin/bats test/` after `git submodule update --init`.
  The rule and its exemptions are `instructions/45-shell-scripts.md`; shared
  setup lives in `test/test_helper.bash`. The bats-core, bats-support and
  bats-assert submodule pins are bumped by hand, to release tags.
- The catalogue and plugin checks below read `skills.json`, not the
  `SKILL.md` files, so a stale manifest makes them answer from stale
  metadata — regenerate it before running them locally, and that is why
  `build_manifest.py --check` is the first CI gate. Two readers stay
  independent on purpose: `scripts/quick_validate.py` parses frontmatter
  itself, so it validates the source rather than the generator's output,
  and `install.sh` reads it in bash, so skill linking never depends on
  `python3`.
- After adding, renaming, or removing a skill, update both catalogue
  tables by hand — `README.md` and `AGENTS.md` (`## Skill catalogue`) —
  keeping their text identical and each skill under the section matching
  its `category`. CI enforces this with `python3 scripts/check_docs.py`.
- Keep the plugin in sync for **top-level** skills: add/rename/remove the
  relative symlink `plugins/<category>/skills/<skill-name>` →
  `../../../skills/<skill-name>`. A router member is a normal skill directory
  under `skills/` but gets no plugin symlink: `build_routers.py` creates
  `skills/<router>/members/<name>` and the generated member table, and the
  category plugin contains only the router. CI enforces this with
  `python3 scripts/check_plugins.py`.
- Fast loop for a docs or plugin change:
  `scripts/check_all.sh --only docs,plugins`; `--list` shows every check name.
- A reference file over 100 lines carries a `## Contents` heading with
  section links within its first 20 lines, so a partial read still shows its
  scope. CI enforces this with `python3 scripts/check_reference_tocs.py`.
- A SKILL.md or reference states no dated facts (ISO dates, "as of 2026",
  "verified 2026-09-07"): they turn false without notice. Dated provenance
  (when a version was verified, a source revision, a re-check deadline) goes
  into one paragraph per file that starts `As of 20YY-MM[-DD]`. Code spans,
  code blocks and URLs are exempt. CI enforces this with
  `python3 scripts/check_dated_claims.py`.
- No Markdown table in `skills/**/*.md` is wider than three columns, fenced
  output templates included, because skills and the answers they shape are
  read on a phone; use a nested list or a table of at most three columns. CI
  enforces this with `python3 scripts/check_table_width.py`.
- Every `references/`, `scripts/`, `assets/`, `evals/` or `members/` path a
  SKILL.md or reference names exists relative to the skill directory, and
  every relative Markdown link exists relative to the linking file — code
  spans and fenced commands included. CI enforces this with
  `python3 scripts/check_skill_paths.py`.
- A GitHub step an agent executes names the operation (list open issues,
  read an issue with comments, create a PR), then uses this canonical
  sentence, keeping the `gh` command as the fallback for agents without the
  GitHub MCP: "Use the GitHub MCP tools if the session has them; otherwise
  `gh` …". GraphQL-backed `gh` porcelain (`gh issue`, `gh pr`, `gh search`,
  `gh label`, `gh repo view`, `gh release list|view`) fails with HTTP 403 in
  Claude Code cloud sessions; REST (`gh api`, `gh run`) works. A script that
  runs headlessly cannot call MCP tools, so it uses `gh api` against the REST
  endpoint. CI enforces this with `python3 scripts/check_gh_graphql.py`.

## Scripts an agent runs

Applies to any executable an agent invokes: `scripts/` in a skill or
plugin, hook commands, CI helpers. The seven rules that hold outside
this repo too — non-interactive input, `--help`, exit codes, named
writes, secrets, installed smoke test, bounded output — are also carried
globally by `instructions/on-demand/85-agent-scripts.md`; edit both when
they change.

- Never read from an interactive prompt. Agents run non-interactive
  shells; a TTY prompt hangs the session until timeout. Take every input
  as a flag, env var, or stdin. On a missing required input, exit
  non-zero naming the flag and its allowed values.
- `--help` is the agent's only interface documentation — one usage line,
  the flags, two examples. It is also context cost: keep it under ~25
  lines.
- Data to stdout, diagnostics to stderr. Prefer JSON/TSV over
  whitespace-aligned columns.
- Distinct exit code per failure class, documented in `--help`, so the
  caller can branch without parsing prose.
- Idempotent by default: agents retry. "Create if not exists", never
  "fail on duplicate".
- One named verb per write, narrowest stable ID, `--dry-run` first;
  never hide writes in `fix`/`auto`/raw.
- Secrets from env or config, never a flag (shell history, `ps`); never
  echo them, not in `--json` errors. CI flags a skill, instruction or
  script example that passes a credential in argv with
  `python3 scripts/check_secret_argv.py`.
- Smoke-test the installed command from `/tmp`, not the source folder.
- Bound the output. Harness output is truncated past roughly 10–30k
  characters, silently. Default to a summary; offer `--output FILE` and
  `--offset` for the rest.
- Python with third-party deps: PEP 723 inline block + `uv run
  script.py`. No sibling requirements.txt, no install step. `uv add
  --script` to edit, `uv lock --script` when the run must reproduce.
- A one-off command in SKILL.md (`uvx`, `npx`) is version-pinned, or it
  is not a convention.
- Reference bundled skill scripts relative to the skill directory
  (`python3 scripts/tool.py <repo-path>`), never via a repo-root path
  (`skills/<name>/scripts/`, `members/<name>/scripts/`). The skill is
  installed elsewhere, so the target repo is always passed as an argument.
- Every auto or router skill ships eval prompts in `skills/<name>/evals.json`
  (>=3 `should_trigger`, >=1 `should_not_trigger`, optional
  `expected_behavior`; see `docs/adr/0006-skill-eval-prompts.md`). Command
  skills are exempt and may ship one. The `evals` check in
  `scripts/check_all.sh` (the list CI calls) runs `check_evals.py --strict`,
  so a missing or malformed file fails.

## Agent skills

### Issue tracker

Issues live as GitHub issues on fabiandistler/agents, managed via the `gh` CLI. See `docs/agents/issue-tracker.md`.

### Triage labels

The five canonical triage roles use their default label strings (`needs-triage`, `needs-info`, `ready-for-agent`, `ready-for-human`, `wontfix`). See `docs/agents/triage-labels.md`.

### Domain docs

Single-context: one `GLOSSARY.md` + `docs/adr/` at the repo root. See `docs/agents/domain.md`.

### Weekly skill audit

A scheduled Claude Code routine follows `docs/agents/skill-audit.md` every
week: the `repo-error-checker` subagent runs the CI checks repo-wide, and the
`skill-reviewer` subagent judges a rotating quarter of the skills (plus the
most-changed ones) against `docs/agents/skill-audit-checklist.md`. Findings
land in one rolling `skill-audit` issue; mechanical fixes in one
`claude/skill-audit-<date>` PR. Record a finding you decide to keep under the
issue's *Accepted* section so the audit stops reporting it.
