cantrips
AGENTS.md3 starsChanged 4 months agoMITView on GitHub
cantrips is a multi-harness (Claude Code + Codex) plugin of curated agent skills: the core engineering loop (/grilling → /spec → /tickets → /implement + /tdd → /simplify → /review-gate → /commit → /compound) plus its supporting skills. A feature's spec and tickets are disposable working material under a gitignored .scratch/, deleted once the feature closes (docs/agents/cantrips-loop.md); what survives is the skills, git history, the decision records in docs/adr/, and the deferred ideas in IDEAS.md. The plugin also ships a…
- Reads credentials
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,774 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository26 other files it gives its agents.
- mod/CLAUDE.mdCLAUDE.md
- sync-upstreamSkill
- afkSkill
- codebase-designSkill
- commitSkill
- compound-refreshSkill
- compoundSkill
- deputySkill
- diagnosing-bugsSkill
- grillingSkill
- handoffSkill
- implementSkill
- improve-codebase-architectureSkill
- prototypeSkill
- questionnaireSkill
- researchSkill
- review-gateSkill
- setup-cantrips-loopSkill
- setup-git-guardrailsSkill
- simplifySkill
- specSkill
- tddSkill
- teachSkill
- ticketsSkill
- wait-whatSkill
- writing-for-agentsSkill
The file
Show its rules and text
We split this AGENTS.md into the rules it gives an agent
13 rules. About 0 are common, 5 are distinctive, and 8 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈5
Distinctive · estimate
This author's own choices. Worth a look.
8
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 45
Write against the /writing-for-agents standard (skills/writing-for-agents/SKILL.md): predictability, leading words, checkable completion …
- Very specific: line 60
Every skill carries an agents/openai.yaml sidecar (interface.display_name, interface.short_description, policy.allow_implicit_invocation): …
- Very specific: line 70
Every step that dispatches a general-purpose sub-agent asks for a background dispatch and carries the parenthetical "(Claude Code: do not …
- Distinctive: line 90
Run each scenario against the unedited skill too: a pass line it already meets proves nothing about the edit.
- Very specific: line 105
every skill directory carries its agents/openai.yaml sidecar.
- Distinctive: line 107
When editing plugin metadata, edit BOTH manifests, and both catalog files for the description.
- Very specific: line 115
Commit messages follow Conventional Commits.
- Very specific: line 121
Never hand-edit the plugin.json versions or the release manifest.
- Distinctive: line 129
Create a git branch, stage files, or commit work yourself unless the user expressly told you so.
- Very specific: line 130
Commit secrets, tokens, .env files, dumps, or credentials.
- Distinctive: line 131
Put user-specific paths or personal conventions inside the plugin (see distributability above).
- Distinctive: line 140
Start by inspecting existing patterns: read a neighboring skill before writing a new one.
- Very specific: line 141
Before editing a file, check IDEAS.md's Adopt when triggers for one naming it, and propose each entry that fires as a related change, for …
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
AGENTS.md
Project overview
cantrips is a multi-harness (Claude Code + Codex) plugin of curated agent skills: the core engineering loop (/grilling → /spec → /tickets → /implement + /tdd → /simplify → /review-gate → /commit → /compound) plus its supporting skills.
A feature's spec and tickets are disposable working material under a gitignored .scratch/, deleted once the feature closes (docs/agents/cantrips-loop.md); what survives is the skills, git history, the decision records in docs/adr/, and the deferred ideas in IDEAS.md.
The plugin also ships a Claude Code mod, the loop panel under mod/: a pane beside the chat that shows the loop's stage, the feature's spec and ticket board, and a band chip that opens it.
The repository is the plugin: the manifests, the skills tree, the mod, and the catalog files that publish it all sit at the root, and an install copies the whole checkout.
Everything else here (docs/, this file) therefore rides along into an install; keep it small and keep nothing secret in it.
There is no build
This repository is content, not code: no dependencies, no package manager, no build, no lint step, and no tests but those of the scripts skills ship, such as skills/review-gate/scripts/findings.test.ts over the script /review-gate reports through, and those of the mod.
mise run test runs every such file and the mod's pure core under node --test, with node 22.18 or later on PATH and nothing else installed, then the mod's mounted scenarios.
Nothing needs installing to work on it, and nothing gates an edit: the tests are there to run when you touch a script or the mod, never a step an edit must pass.
The one mechanical convention is .editorconfig (LF, UTF-8, two-space indent, trailing newline, 100-column guide).
What tooling exists is convenience: mise.toml wraps the scripts in scripts/, mise run dev:sync-install mirroring the working tree over the local installs (Claude Code and Codex CLI) so unreleased edits are usable from other projects, mise run dev:fork-diff reporting how far a fork has drifted from its upstream without ever asserting — it defines no expected state and exits zero whatever it finds — mise run dev:mod-preview starting the mod's preview session, and mise run dev:mod-shot rendering that session's pane to an image (uv fetches its Python libraries on the first run).
Consequently the invariants below are honored by hand. Nothing fails when one drifts, so check them yourself whenever you touch the files they cover.
Repository structure
skills/<skill>/SKILL.md: the one shared skills tree; both harnesses auto-discover it.agents/<role>.md: the plugin agent definitions, one per role a skill dispatches, which Claude Code loads ascantrips:<role>(a subfolder joins the name with a colon); a definition is distributable like a skill, and a role's brief lives in its body and nowhere else. A definition's description says who summons the role, the user through the skill that dispatches it or by name, or the skill alone where the role takes only the message it composes, since no frontmatter field keeps a plugin agent out of automatic delegation and a description that reads as an open offer gets it dispatched unasked. A skill's ownagents/openai.yamlis unrelated: that is the skill's Codex sidecar, and defines no agent.mod/: the loop panel mod, its pure core tested fromtests/mod/;mod/CLAUDE.mdholds its layout, reach boundary, style, tests and preview session, so read it before editing either folder or runningmise run dev:mod-preview..claude-plugin/plugin.json+.codex-plugin/plugin.json: the dual manifests; shared fields must stay identical, and thehooksandtypesfields are Claude-only..claude-plugin/marketplace.json+.agents/plugins/marketplace.json: the catalog files that publish this repo as an installable plugin (Claude Code takes a stringsource, Codex CLI the object form; both point at./).FORKS.md: the fork divergence ledger — every upstream skill listed, forks with how they deliberately differ and a reason that stays true of the fork as it stands, the rest marked not ported;/sync-upstreamand human readers both consult it.docs/agents/cantrips-loop.md: the per-repo loop config — what the six storage verbs translate to here, and which knowledge stores are enabled (docs/adr/on,docs/solutions/off). Storage-touching skills read it instead ofskills/setup-cantrips-loop/defaults.md;/setup-cantrips-looprewrites it..scratch/<feature>/: the spec and tickets of a feature in flight, gitignored and disposable — deleted when the feature closes, which is the human's act..scratch/sync/is not feature material butdev:fork-diff's cache of upstream files, outliving any one feature and safe to delete wholesale.docs/adr/: durable decision records with supersession chains, written only through/compound's user gate and read back by/spec.docs/research/: primary-source research notes, written by/research.scripts/: repository tooling — the bodiesmise.toml's tasks wrap, kept in files so a task definition reads as what it runs. Rootscripts/maintains this repository, unlike thescripts/directories inside skill folders, which are shipped assets an installed skill invokes; no skill in the plugin's tree may reference anything here.mise.tomlruns these directly, so stage anything added here withgit add --chmod=+x— a plain add records mode 100644 and the task then fails on a fresh Unix checkout.
How to add or revise a skill
- Write against the
/writing-for-agentsstandard (skills/writing-for-agents/SKILL.md): predictability, leading words, checkable completion criteria, progressive disclosure, positive phrasing, no no-ops, prune sediment. Forks prune rather than pad: a fork carries no restatement upstream lacks. Running longer than upstream is not a violation of that: a fork may add rules upstream has no counterpart for. A skill is guidance for an adaptive agent, not a program: state the intent and the guardrails the agent cannot infer — when to stop, when to ask, what done proves — and leave enumerable edge cases to its judgement. A skill's argument is the user speaking: read it as you read any request, and match a word as a flag only where the argument-hint declares it one, as/review-gate's--fix. A rule set that grows a clause per reviewed case is the symptom; hold such a file to a line budget and cut before adding. - Frontmatter:
name,description(trigger-rich for model-invoked skills; one human-facing line +disable-model-invocation: truefor user-invoked ones),argument-hintwhere an argument is meaningful,version(per-skill semver; bumped per the versioning section below), and for forkssourcerecording upstream provenance, e.g.source: mattpocock/skills@1.2.3 (to-spec).versionandsourceare unofficial keys the loaders ignore. Changing a fork's body beyond its upstream text is a divergence: record it in FORKS.md in the same edit, so/sync-upstreampreserves it instead of merging upstream's wording back. README.md describes each skill's behaviour in prose; where an edit changes what one of its sentences claims, edit README in the same change. A passage carried byte-identical stays that way even where a quality pass finds a real improvement in it: skip the finding and name the reason, since the edit trades a permanent sync divergence for a redundancy upstream chose. Where a divergence already sits in carried text and house formatting is all it buys — a reflow, a restructure, a reordering, a gloss — restore upstream's bytes on sight, and delete the bullet that recorded it in the same edit; a/sync-upstreamrun instead surfaces both — restore and bullet deletion — as one audit finding, deferred to the spec its close names. Where the edit pruned a genuine no-op instead, keep it, and record it in FORKS.md like any other divergence. Where a fork keeps a pruned passage's substance inline, check the inline copy against the whole passage it replaces, since a clause dropped there reads as the passage to every later record. Where a fork needs a name for something upstream already names, take upstream's name. Every skill carries anagents/openai.yamlsidecar (interface.display_name,interface.short_description,policy.allow_implicit_invocation):falsefor user-invoked skills — Codex CLI ignoresdisable-model-invocation, so the sidecar is what stops auto-firing there — andtruefor model-invoked ones, stating the intent explicitly rather than leaning on Codex defaults. The sidecar'sallow_implicit_invocationis always the logical inverse of the SKILL.mddisable-model-invocation; a skill shipped without a sidecar auto-fires in Codex whatever its frontmatter says. - Pipeline skills end with a flow pointer naming the next step(s) of the loop and marking a user-invoked target
(user-invoked); keep those pointers consistent when renaming or inserting skills. Author each closing from flow-pointers.md: every closing carries its format clause and its deputy step word for word, a closing whose first rendered step naming a skill can be/review-gatecarries its compact hint the same way, and a gate that puts a decision to the user carries its routing clause the same way, the copies staying identical across skills as rule 5 asks for its own clause. The format rides in the closing because an agent closing a skill skips a read whose target holds only presentation. An agent cannot observe its own context level, so the compact hint conditions on the rendered step alone and is addressed to the user, who can. - A sibling reference file that declares what it extends or replaces must cover every path the parent skill can take — the
inlinepass included, since it reaches none of the sections a main-path declaration names. A declaration that names only the main path leaves the other paths running the parent's own rules, which is how a mode degrades silently at one level while reading correct at the others. The inverse costs as much: a brief written for a dispatched carrier holds lines addressed to one, so a fallback that runs the pass inline names what travels rather than reusing the whole prompt. A lens finder's definition says "You edit nothing" — right for a finder, and in the parent context it forbids the fixes/simplify's next step tells that same context to apply. - Every step that dispatches a general-purpose sub-agent asks for a background dispatch and carries the parenthetical "(Claude Code: do not use
run_in_background: false)". A blocking dispatch freezes the session for as long as the agent runs, which degrades the user experience and is invisible from inside the skill. A step that tiers a general-purpose dispatch carries the "Model selection" paragraph/specholds for its rereader, changing only the noun for the dispatch it tiers, and the tier where that dispatch wants another — a top tier reads "the platform's most capable model" and drops the sentence naming a Claude Code class, since the top class is renamed faster than a skill is revised. A step that dispatches a definition fromagents/names it by its scoped name, passes no model of its own — a per-dispatch model outranks the frontmatter pin — and carries the fallback clause, changing only the link: "Where the harness loads no plugin agent definitions, read<role>.md, skip its frontmatter, paste its body into a general-purpose dispatch run in the background, and apply the model its frontmatter names where the dispatch primitive exposes a selector." The parenthetical and the model paragraph stay off such a step, since the definition pins both; a definition's frontmatter may name a model alias, while a body, like a skill's, still names no class. These three are the only harness-specific settings a skill body may name, and each clause stays identical across skills so a reader meets one clause, not five. - Distributability rule: the plugin must be installable by anybody — no user-specific paths, names, or personal conventions inside skill bodies. Personalization belongs in the user's own global CLAUDE.md.
- Cross-skill references use this repo's names (
/spec,/commit,/compound…), never upstream names. In docs and prose, skill names always carry the/prefix, whatever the invocation mode. - Markdown intended for agents (SKILL.md files and their references, AGENTS.md, specs) goes one sentence per line, and is exempt from the 100-column guide. Text carried from an upstream is the exception rule 2 already covers: its line breaks stay upstream's, however long its lines run, since reflowing re-creates the whole paragraph as a diff at every sync. Human-facing docs (README.md, WHY.md, NOTICE.md, IDEAS.md) wrap at ~100 columns instead.
- A gate branches on what the agent can observe in what it holds, never on how that material was produced.
"Working from a spec that folded in the standing decisions" is observable; "arriving from
/implement" and "working from a spec" are provenance, and an agent that got there another way matches neither branch and invents the behavior. Where a gate has a second branch, both branch on the one test, so the pair partitions every route into the skill. - Two settled sentences point at the loop config, and a skill takes the one its own use calls for: the verb form where it speaks a storage verb, the store form where it only gates a knowledge-store read.
The store form states the fallback outright — the store is off — where the verb form sends the reader to defaults.md for it, so a skill that speaks no verb and takes the verb form buys a load it cannot act on.
Copy the wording from a skill that already carries the form —
/specfor the verb form;/diagnosing-bugsfor the store form, swapping only which store or stores it names as off — as rule 5 asks for its own clause. - Prove a skill edit by probing what it makes an agent produce: pose a hypothetical finished-work scenario to a fresh agent holding only the revised skill and how it was invoked, ask for its next response, and grade that against a pass line written beforehand, from a scenario that leaves the behaviour under test for the skill to decide.
Run each scenario against the unedited skill too: a pass line it already meets proves nothing about the edit.
Keep the probe oblivious: its prompt poses the scenario and asks for the response, with as few cues as simulating it takes — never that it is a test, what changed, or what gets graded — since an agent that knows it is examined deliberates harder than a real run and passes where a real run fails.
The probe is oblivious to this project too, so run it through the
claudeCLI rather than as a sub-agent, on Opus at medium effort unless the user names another:claude -pfrom a temp directory outside this repo holding a copy of the skill, with--setting-sources projectto keep the installed plugin and the user's instructions out (--barewould too, but reads no OAuth login), the skill's body inlined in the prompt the way a harness loads it, and whatever the scenario says already happened made true beforehand —--session-idpins the session a skill script keys its state on, and--resumeon it probes a behaviour that spans replies, turn by turn; the prompt opens on the scenario, never on the skill's slash command, which print mode runs. A probe registers none of the skill's frontmatter hooks, since the body is inlined rather than loaded, so what a hook does is proven by the script's tests. An agent definition is proven on the mirrored install instead —mise run dev:sync-install, then a scratch session on the harness, its transcript dissected the same way — since a probe inlines a body and loads no plugin agent. Dissect the transcript (--output-format stream-json --verbose) as well as the answer: every call, read, resent input and token spent is behaviour the skill caused, and a skill that reaches the right answer the long way still fails. A gate run over skill prose reviews wording, and wording always yields another finding.
Dual-manifest and catalog sync
The plugin has two plugin.json manifests (Claude Code + Codex CLI; the Codex schema is a superset of the shared fields, while hooks and types are Claude-only, so the Codex manifest carries neither) and two catalog files, because neither harness reads the other's.
Shared metadata is duplicated by necessity, and keeping the copies honest is a manual duty:
- the shared plugin.json fields (
name,version,description,author,homepage,repository,license,keywords) stay identical between the two manifests; - both catalog files publish exactly one plugin, named after the manifests, sourced at
./, and described in the manifests' own words; - every skill directory carries its
agents/openai.yamlsidecar.
When editing plugin metadata, edit BOTH manifests, and both catalog files for the description.
Versioning and releases
release-please (.github/workflows/release-please.yml, release-please-config.json, .release-please-manifest.json) maintains a rolling release PR from Conventional Commits; merging it bumps the version, updates CHANGELOG.md, tags vX.Y.Z, and creates a GitHub Release.
There is one release unit, and no version file to maintain: .release-please-manifest.json is the version of record, mirrored via extra-files into both plugin.json manifests.
The simple release type would also write a version.txt, but it only updates that file when it already exists, so leaving it absent costs one skipped-file warning in the workflow log and nothing else.
- Commit messages follow Conventional Commits.
feat/fixtrigger releases;chore/refactor/docsdo not. Anything user-facing (skills, manifests) must befeatorfix. - Plain semver: a breaking change bumps major,
featbumps minor,fixbumps patch. - Per-skill
versionfrontmatter is bumped by hand when a skill changes; the plugin version is release-please's job. One bump per skill per release, sized to the largest change in it — successive edits to one unreleased change are one change, not three. Never hand-edit the plugin.json versions or the release manifest.
Boundaries
These govern your own conduct here, not what a skill may instruct its own users to do.
Never:
- Create a git branch, stage files, or commit work yourself unless the user expressly told you so.
- Commit secrets, tokens,
.envfiles, dumps, or credentials. - Put user-specific paths or personal conventions inside the plugin (see distributability above).
- Reintroduce a build step, a dependency, or a check script without asking; their absence is deliberate.
Ask first before:
- Renaming a skill (it touches the flow pointers, the README roster, and any spec naming it).
Preferred agent behavior
- Start by inspecting existing patterns: read a neighboring skill before writing a new one.
- Before editing a file, check IDEAS.md's
Adopt whentriggers for one naming it, and propose each entry that fires as a related change, for the user to include or leave. - CLAUDE.md here is a committed relative symlink to AGENTS.md; edit AGENTS.md, never the symlink.
- Propose updates to this file when you notice a pattern or introduce changes that deserve to be documented for future sessions.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

