| name | codex-review |
| description | Get a second opinion on the current change or a plan from a different model (Codex), and
enforce its verdict mechanically. Codex returns a structured JSON verdict โ findings
scored by priority (0 critical, 1 important, 2 minor, 3 nit) against sev.schema.json โ and
a gate script turns that into a pass/fail exit code, so a critical or important finding
gets fixed or escalated rather than re-argued by the model that wrote the code. Infra
failures (rate limit, model reject, empty output) are their own outcome and never count as
a clean pass. Use after writing tests, before a deploy or merge, or to review a plan before
execution. Triggers on `/codex-review`, `/codex-review --plan <file>`,
`/codex-review --base <ref>`, "run a codex review", "get an external review of this diff",
"codex-review this before I ship".
|
| user_invocable | true |
/codex-review โ cross-model external review, mechanically gated
Codex is the judge; the diff is the defendant. This session does not get to overrule a
CRITICAL/IMPORTANT verdict.
Before you run: should you, and how hard?
This tool assumes the review is warranted now. If that isn't obvious, run /review first โ
the orchestrator decides whether to review at all, at which gate, and sets the round budget, then
dispatches here. Quick self-gate if you skip it:
- Plan/spec exists but little/no code โ review the plan (
--plan), defer the diff review until
after build. Don't diff-review an empty tree.
- Trivial / docs-only / tests-only / mechanical rename โ don't review. Reviewing noise erodes
the signal of a real finding.
- Just applied a trivial/mechanical fix โ don't re-review; re-review only substantive change.
Before reading any findings, pre-commit the fix bar: you will fix CRITICAL/IMPORTANT (a
core-user-journey break, data loss, security, a privacy/cost leak) and file MINOR/NIT as issues
rather than fixing them in-loop. Deciding the bar up front is what stops "one more round" creep.
The five disciplines
- Structured verdict โ Codex emits JSON against
sev.schema.json, not prose. The gate is
computed from priority, never eyeballed.
- Don't re-judge the verdict โ
codex-review.sh decides pass/fail via exit code. For BLOCK
items you fix or escalate; you do not argue Codex out of a CRITICAL/IMPORTANT. That
would forfeit the cross-vendor independence this skill exists for.
- Infra โ clean โ a rate-limit / model-reject / empty-output run exits
2 (INFRA), never 0.
Never treat it as a pass or feed it into a fix loop.
- Judge immutability โ
codex-review.sh + sev.schema.json are committed and must not be
edited during a review cycle. Edit source; never edit the gate that judges it. The reverse is
enforced too: the gate fingerprints the working tree + HEAD before and after, so a reviewer that
edited your code is INFRA (exit 2), never a verdict.
- Verification must be executed, not asserted โ the reviewer runs
workspace-write so it can
actually run your typechecker and tests, and is told to prove findings by running them and never
to restate test counts from commit messages. Read its notes: if it claims a pass without naming
a command it ran, distrust it. See "Why #5 exists" below โ this was learned the hard way.
Usage
.claude/skills/codex-review/codex-review.sh
.claude/skills/codex-review/codex-review.sh --base origin/main
.claude/skills/codex-review/codex-review.sh --staged
.claude/skills/codex-review/codex-review.sh --worktree
.claude/skills/codex-review/codex-review.sh --plan docs/superpowers/plans/<f>.md \
--focus "auth clone forge risk; persist-tail drift; array-index targeting"
.claude/skills/codex-review/codex-review.sh --base origin/main --block-at 2
Exit codes: 0 CLEAN (pass) ยท 1 FINDINGS (blocking items exist) ยท 2 INFRA (did not run
cleanly) ยท 3 USAGE. Raw verdict JSON is written to --out (default /tmp/codex-review.json).
How to drive it (the bounded loop)
Run as a capped loop; the script decides each gate, not your judgment.
- Review. Run the script for the right target (
--plan before execution; --base/--staged
after TDD, before deploy/merge).
- Branch on the exit code:
- 0 CLEAN โ done. Note "Codex-reviewed: clean" in the lane summary and proceed to the
existing gates (
npm run typecheck, npm run test, deploy.sh).
- 1 FINDINGS โ read
/tmp/codex-review.json. For each BLOCK item (priority โค block_at):
- CRITICAL (0) / IMPORTANT (1): fix it. Do not write a rebuttal. If you genuinely believe
Codex is wrong, that's a human call โ escalate with
AskUserQuestion (quote the finding +
your reasoning), don't silently override.
- MINOR (2) / NIT (3) (advisory at the default threshold): use judgment โ fix, or note as
a deliberate skip in the lane summary.
Then re-review (back to step 1).
- 2 INFRA โ do not proceed and do not loop on it. Retry once; if it persists, surface the
tail (rate limit?
codex login expired? model gone?) and stop. An unrun review is not a pass.
- Round budget: set it from risk, extend only on convergence, backstop at 6.
Don't default to "loop until clean." Set an initial budget (via
/review, or: standard diff
1, elevated/multi-file 2, high-risk auth/privacy/cost/data-loss 2โ3).
- Converging (round N's findings are the same blocking items, fewer/less severe) โ you may
extend by +1 with a one-line justification in the lane summary.
- DEEPENING (round 2+ surfaces new, lower-severity findings rather than confirming the
round-1 fixes) โ stop. Do not open another round. New lower-severity findings each round is
a scope call for the human, not a convergence problem โ escalate the residual.
- Hard backstop 6, absolute. If round 6 still returns blocking CRITICAL/IMPORTANT, stop and
escalate โ more rounds past the cap degrade more than they fix.
Don't re-run on an unchanged diff. If the only remaining findings are ones the human has already
reviewed and accepted as residuals, that's the terminal state โ record them as human-accepted
and proceed.
Notes
- workspace-write, not read-only. Codex runs
-s workspace-write so it can execute your
typechecker and test suite; it is told not to edit, and the gate enforces that with a
before/after tree+HEAD fingerprint (a mutation โ INFRA exit 2). All fixes are still yours.
Override with CODEX_REVIEW_SANDBOX=read-only โ but note that mode cannot run Vitest at all,
because Vite must write a temp config file next to vitest.config.ts to load a TS config, so the
reviewer silently drops back to static-only.
Why #5 exists
This gate ran -s read-only until 2026-07-15. Two things were wrong with that, and together they
made the reviewer look like it was verifying while it was not:
- Read-only can't run Vitest (the temp-config write above) โ a flaw in the mode choice itself.
- On Ubuntu 24.04,
kernel.apparmor_restrict_unprivileged_userns=1 blocks unprivileged user
namespaces. Codex sandboxes with bubblewrap, which needs them, so every command it tried died
(bwrap: loopback: Failed RTM_NEWADDR). It could not run anything.
It reported verification anyway โ "TypeScript type-checking passed" without ever running the
typechecker, and once a precise test count that turned out to be copied from the diff's own commit
message. It was reading the author's claims and handing them back as evidence.
The cost, on one real lane: 17 rounds of apparent convergence while a bug that made publishing
permanently impossible sat in the diff untouched. A multi-agent review later found it, plus nine
more, in a single pass โ and once the sandbox was fixed, the same Codex found six of them in one
round, because it could finally execute.
Two lessons worth keeping:
- A reviewer that cannot execute is a static reviewer wearing a verification badge, and its
reassurance is worse than none, because it reads as evidence. Check the host once:
unshare -U -r echo ok must print ok (fix: kernel.apparmor_restrict_unprivileged_userns=0).
- Clean โ correct. A single-reviewer pass reads the diff in isolation and is structurally blind
to bugs that only appear when you trace call paths across the codebase. Before a non-trivial PR,
run a multi-reviewer pass as well.
- Keep this skill's files out of the diff you're reviewing โ if the gate itself needs to change,
do it in a separate, self-reviewed commit, never mid-cycle.
- Pairs with, does not replace, the deterministic gates: Codex reviews correctness/security;
typecheck + test + test:security + deploy.sh remain the last word.