Coding agents
Three are configured here: Claude Code, opencode and Codex. All three read the same
AGENTS.md files, so which one you use is your preference. CodeRabbit reviews pull requests as a
GitHub App and needs nothing in the tree.
Install any of them from its own documentation (Claude Code, opencode, Codex) and sign in with your own account — nothing in this repository carries a credential, and none of them needs configuring beyond that to pick up everything below.
How work moves
Agents do not stage, commit or push until you run /land-pr; /fix-ci and /resolve-review
push their own fixes afterwards, which is why neither loops back through it. Reading the diff
yourself is the review that matters — the gates prove the tree is consistent, not that the change is
right.
pnpm run format && pnpm run check is the floor, not the whole ask. Name the thing your change could
actually break: the test file that covers it rather than "run the tests", a request against the
endpoint you added, a query confirming the row was written, the logs after the change.
Slash commands
| Command | Does |
|---|---|
/land-pr | Validate, regenerate, branch, commit, push, and open the PR |
/fix-ci | Read every failing check in one pass, fix in dependency order, push once |
/resolve-review | Fetch review threads, decide each, reply and resolve |
Each lives in .claude/skills/<name>/SKILL.md. opencode
reads .claude/skills/ alongside its own — opencode debug skill prints every skill with the path it resolved from — so no skill needs a second copy for it.
A typed /name is the exception: opencode resolves that from .opencode/commands/ only, so each
of these three has a file there whose entire body is @.claude/skills/<name>/SKILL.md. opencode
inlines a referenced file into the prompt, which is what makes
a pointer enough where a copy used to be needed.
Codex shares no directory with the other two: it
scans .agents/skills/ and never .claude/skills/,
and it has no repo-level slash commands at all —
~/.codex/prompts/ is personal and uncommitted,
and OpenAI's own guidance for sharing one is to make it a skill. So the four skills that drive a
contribution — these three and /gh-stack — are copied to .agents/skills/<name>/, and
check:instructions fails if a half goes missing or the two drift. CODEX_SKILLS in that script is
the list; add a name and the copy when Codex should have another.
The knowledge packs are deliberately not mirrored: react-best-practices alone is fifty files, and a
Codex session that needs them is working in webapp/, whose AGENTS.md names them by path. The
mirror also costs one duplicate skill name warning per skill in opencode's log, since opencode
reads both directories and sees the same name twice.
disable-model-invocation makes these three typed-only in Claude Code. opencode and Codex both
ignore the field, so there they are ordinary skills the model can reach on its own.
Instructions live in AGENTS.md, once
| File | Covers |
|---|---|
AGENTS.md | The repository — layout, quality gates, generated artefacts, migrations, changesets |
webapp/AGENTS.md | The SPA — component conventions, linting traps, drawers, motion, vocabulary |
server/AGENTS.md | The Spring Boot server — build traps, the four test tiers, API and security conventions |
The two tools reach them differently, and neither difference is visible from the file:
- opencode reads
AGENTS.mdnatively and takes the nested ones from theinstructionsglobs inopencode.json. Those load unconditionally, so an opencode session carries all three. - Codex reads
AGENTS.mdfrom the repository root down to the directory you launched it in, and stops there. Start it inwebapp/to get the SPA guide; started at the root it has only the root file. - Claude Code reads
CLAUDE.mdand neverAGENTS.md. EachAGENTS.mdtherefore has aCLAUDE.mdbeside it holding one line —@AGENTS.md— which imports it. An import resolves against the file holding it, so the same line means a different file in each directory, and Claude loads a nested one the first time it reads a file anywhere in that tree. That is what keeps the webapp guide out of a server-only session.
pnpm run check:instructions fails on an AGENTS.md no CLAUDE.md imports, an @ reference
resolving to nothing, an instructions entry matching no file, a typed-only skill with no opencode
command, a Codex mirror that has drifted, two agent files with one body, and any committed symlink
among them. Each failure explains itself. Bodies are compared exactly, so a copy is caught when it is
made rather than after it drifts.
Adding a tree, or a skill
Write <dir>/AGENTS.md, add <dir>/CLAUDE.md containing @AGENTS.md, and give it its own
opencode.json instructions entry unless */AGENTS.md already matches. Then run the gate. A skill
is a directory under .claude/skills/; it needs a file in .opencode/commands/ only if you mark it
disable-model-invocation.
To confirm a file actually loaded, /context in Claude Code lists it under Memory files once you
have opened a file in that tree. The other two have no equivalent view — opencode debug config
echoes the patterns you configured rather than the files they matched — so there the gate is the
check.
When an agent ignores an instruction
Confirm the instruction reached it before rewriting the instruction. An AGENTS.md in a tree the
agent has not opened yet has not loaded.