One more Claude Code edit won't end a Codex review that keeps returning CHANGES REQUIRED. Each speculative patch gives the reviewer new code to comment on, so every pass comes back with new comments. Sort the finding before anyone touches the code.
How to make Codex review Claude Code's commits covers the hooks, the worktrees and the loop itself. This one starts after setup, with a loop that runs and won't reach ACCEPT.
Sort every finding into one of five classes
My reviewer answers every line of the brief and every house rule with met, not met or not checkable. A finding outside that list needs a concrete failure: the input or steps, plus what goes wrong.
Each finding gets a class and a response before Claude Code sees another edit request:
| Finding class | Response |
|---|---|
| Brief or house-rule violation | Fix it, or ask a person when the requirement itself is disputed |
| Failure outside the brief | Block only with concrete reproduction details |
| Reviewer preference | Move to follow-ups unless a written rule requires it |
| Unverifiable claim | Ask for evidence before patching anything |
| Missing, duplicate or malformed verdict | Operational failure: rerun on purpose and don't count it as a review round |
When the review itself breaks
A crash, an empty final message, or a missing, duplicate or malformed verdict leaves no saved verdict, and with no saved verdict my gate refuses the merge.
review.sh exits 0 for a saved ACCEPT, 2 for a saved CHANGES REQUIRED and 1 when nothing was saved. Exit 1 says nothing about the code, so Claude Code has nothing to fix. The gate doesn't retry on its own. Read the log, then rerun the review on purpose. What the gate does when a review crashes or returns no verdict covers that case.
A blocker needs a failure you can reproduce
In my setup, a finding stands when it comes with a reproducible failure. Without one, it goes to follow-ups. The rule exists because a reviewer can be wrong, and tests only check what they test.
For a blocker, ask Codex for three things:
- The input or steps that trigger it
- The expected behavior
- The actual behavior
With those, Claude Code fixes a demonstrated failure. Without them, it patches toward a review that grows with every pass.
Tests get the same treatment. In the weakened-test example, add(2, 3) returns 6 and the weakened assertion accepts it, so the suite passes with the bug in place. A new test should fail on the old behavior. A loosened assertion with no stated reason can draw CHANGES REQUIRED, and a review can miss it too, so a passing review doesn't guarantee correct code.
Brief violations and reviewer preferences
A brief violation is a required change. A preference is a technically plausible alternative to code that already meets the brief. The per-line check keeps Codex anchored to that difference: once every brief line and house rule is met, a remaining comment needs a reproducible failure to block.
In a made-up example, Codex suggests renaming get_rows to fetch_rows. Every brief line is met, nothing fails and no house rule covers the name, so the comment goes to follow-ups. If a house rule did set the naming pattern, the same comment would be a not met line, and Claude Code would fix it in this round.
Later rounds get a narrower packet
Early rounds can raise anything relevant. Later rounds raise only merge blockers, and smaller points go on the follow-ups list.
Every round reviews the current commit. My verdicts are saved under the exact commit that was reviewed, so a new commit needs a new review, and an ACCEPT for an old commit can't cover changed code (why the verdict is saved under the commit hash). The narrowing happens in the packet Codex gets for each later round:
- The unresolved findings
- What changed since the previous review
- The exact current commit and its diff
A compact prompt for that packet:
Review the current commit. Recheck the unresolved findings and the changes since the previous review. Do not reopen settled preferences or unrelated code. A new blocker outside that scope needs concrete reproduction details.
A new blocker stays valid in any round when Codex identifies the failure and reproduces it, so narrowing doesn't hide regressions.
Pick a hard stop before round one
Write the cap down before the first round. Tell Codex which round it's in, so it knows when the later-round rules apply.
If the last allowed round returns CHANGES REQUIRED, stop sending fixes. The verdict stays CHANGES REQUIRED and the merge stays blocked, because a cap never turns the result into acceptance. A person then picks the next step: change the approach, split the change, or allow another round on purpose. Non-blockers wait in follow-ups and don't hold up the merge.
Count only substantive rounds, so a rerun after an operational failure leaves the count alone. A new commit doesn't reset the count for the same change, or every fix would buy a fresh set of rounds.
What the official Codex plugin already covers
OpenAI publishes a Codex plugin for Claude Code with an optional review gate. The gate is a Stop hook: when a targeted Codex review of Claude Code's response finds issues, it blocks the stop so Claude Code can address them.
The stop-gate prompt limits the review to the previous Claude Code turn that produced edits, requires blocking claims to be grounded in repository context or inspected tool output, and returns ALLOW or BLOCK. The prompt behind /codex:adversarial-review asks for material findings and excludes style feedback, naming feedback, low-value cleanup and speculative concerns without evidence. Both prompts already apply the evidence bar from the sections above. The README warns that the gate can create a long-running loop between Claude Code and Codex, can drain usage limits quickly, and should be on only while you're monitoring the session.
The documentation leaves the stopping policy to you: a cap on substantive rounds, how to resolve a disputed brief, how to narrow later rounds across repeated fix commits and where non-blockers go.
Disputed requirements and scope go to a person
When Claude Code and Codex read an acceptance criterion two ways, each round repeats the disagreement in a new commit. The loop is missing product intent that nobody wrote down, and extra passes can't supply it.
Keep the unresolved verdict and send the owner of the change one short question. Scope questions and anything a user will see go the same way. Codex supplies the evidence, the owner chooses the requirement, Claude Code implements that decision, and Codex reviews against it.
The loop ends in one of two states: an ACCEPT for the current commit, or a recorded blocked verdict plus a human decision about the next step.
Run these rules on your own repository
The Two Engines Kit has the review prompts, round rules and commit-specific verdict records. Built on information gathered since the first Codex and Claude CLIs.
If you want the loop set up for you instead, I set up Codex to review your Claude Code commits before they merge. The review setup is written from scratch for your repository, its stack and its conventions, and the first review runs on one of your real branches. Nothing is copied from a template or from the Two Engines Kit.
Top comments (0)