Skip to main content

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

CommandDoes
/land-prValidate, regenerate, branch, commit, push, and open the PR
/fix-ciRead every failing check in one pass, fix in dependency order, push once
/resolve-reviewFetch review threads, decide each, reply and resolve

Each lives in .claude/skills/<name>/SKILL.md. opencode reads .claude/skills/ alongside its ownopencode 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

FileCovers
AGENTS.mdThe repository — layout, quality gates, generated artefacts, migrations, changesets
webapp/AGENTS.mdThe SPA — component conventions, linting traps, drawers, motion, vocabulary
server/AGENTS.mdThe 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.md natively and takes the nested ones from the instructions globs in opencode.json. Those load unconditionally, so an opencode session carries all three.
  • Codex reads AGENTS.md from the repository root down to the directory you launched it in, and stops there. Start it in webapp/ to get the SPA guide; started at the root it has only the root file.
  • Claude Code reads CLAUDE.md and never AGENTS.md. Each AGENTS.md therefore has a CLAUDE.md beside 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.