codex-claude-loop — the gated Claude × Codex build loop
Claude is the principal orchestrator; it rarely types product code. Codex CLI does the
hands-on implementation from persistent threads. The whole thing is bash around
codex exec — no framework, no MCP, no daemon.
The cycle (one brief)
Claude writes a brief → Codex authors a plan (persistent thread) → back to Claude
→ Claude APPROVES the plan (loop until tight) → Codex implements (same thread)
→ Claude REVIEWS the diff against the plan (loop until clean) → cl_release
The persistent thread is the trick: the plan Codex authored carries into
implementation, so it implements its own approved plan with full context. The approved
plan text is also sent with the implementation instruction, so if a human edited and
re-approved the plan file, the file wins over what the thread drafted.
How to run it
source ${CLAUDE_PLUGIN_ROOT}/skills/codex-claude-loop/lib/codex-claude-loop.sh then use
the phase functions, or call bash lib/codex-claude-loop.sh <phase> … directly. Config
via env (CL_REPO, CL_IMPL_MODEL, CL_PLAN_MODEL, CL_REVIEW_MODEL, CL_SANDBOX,
CL_LOCK_TIMEOUT).
- First run:
cl_doctor (codex/jq/git/sha256 present, the four codex capabilities
the loop needs, repo + schema resolve).
- Codex plans:
cl_plan <slug> <brief.md> → writes <slug>.plan.md, opens a
persistent thread, stores its id.
- Claude approves the plan (judgment — YOU read it): read
<slug>.plan.md. If tight,
cl_record_verdict <slug> plan approve "why". If not, re-brief and re-plan. Loop until
the plan holds. Prompt yourself to refute it, not rubber-stamp it.
- Codex implements:
cl_impl <slug> → resumes the thread, writes code, runs tests,
holds the writer lock, and records a success marker only if codex exited clean.
- Optional same-session follow-up:
cl_prompt <slug> "<additional request>" queues
behind the lane's writer lock, resumes the exact stored thread, and prints Codex's
response. It requires a successful implementation and makes re-review mandatory.
- Claude reviews the diff:
cl_review_human <slug> (rich review you read) — or
inspect git diff <base> yourself. Judge it against the plan. Approve
(cl_record_verdict <slug> review approve "why") or send the blocking items back into
the same thread with cl_revise <slug> "…" and re-review. Loop until clean.
- Release:
cl_release <slug> confirms both gates still hold for the tree as it is
right now, and refuses otherwise. Then changelog, tag, merge, deploy (honor the
project's own deploy gate).
cl_status shows where every slug stands. cl_wave <slug> <brief.md> advances one step
per call and returns 3 when it is your turn, 0 when both gates hold — re-run it
after each judgment rather than expecting it to block.
Autonomous fallback (no orchestrator to gate)
When there is no Claude brain available to judge (e.g. usage cap spent), cl_codex_gate <slug> stands in a Codex adversarial reviewer that emits a parseable verdict
(schemas/verdict.schema.json, defaults to revise unless confident). Use it to keep the
loop moving unattended — but a real orchestrator review is the standard.
Rails (load-bearing)
- One writer.
cl_impl, cl_revise, and cl_prompt share one lock; don't bypass it.
Two Codex processes writing the same tree = corruption.
- Never review a tree that is being written. Both review paths refuse while the lock
is held. To genuinely overlap review and implementation, give each lane its own
worktree and its own
CL_REPO.
- Gates must refute, not rubber-stamp. A gate that always approves is worse than no
gate. Blocking items need concrete fixes, and
approve with a non-empty blocking list
is downgraded on disk.
- A revise round is not closed by a matching sentence. Every item you send back with
cl_revise is kept and handed to the next review, which is told to judge it on intent.
When you review, do the same: ask what the item was trying to prevent, then check the
code prevents it. A change that satisfies the wording and misses the point stays blocking.
- Approvals are bound to what they judged. Editing the plan voids its approval;
changing the tree voids the review approval. If a re-approval is refused, read the
reason rather than deleting state to make it pass.
- The plugin guards git publication. Normal Claude Code Bash calls for
git commit,
push, merge, and tag are refused while a successful implementation is not covered
by both current approvals. The standalone skill install has no hook; neither path binds
a human terminal or deliberately wrapped git commands.
- Verify model variants before architecting on them. Set
CL_IMPL_MODEL /
CL_REVIEW_MODEL only to models you have actually confirmed behave as you assume.
- Tail the log within a minute of launching any lane. A bad flag makes
codex exec
die into its jsonl while you believe a lane is running.
- First run =
cl_selfreview: have Codex adversarially tear apart THIS harness before
you trust it.
- Honor the repo's own rules (branch protection, deploy gates, secrets never printed).
State
~/.codex-claude-loop/<repo>-<hash of its path>/ — plans, verdicts, thread ids, base
SHAs, JSONL logs. Outside the repo so it never pollutes a tree Codex is writing, and keyed
by path so two repos with the same basename never share approvals. Override with
CL_STATE.
1---2name: codex-claude-loop3description: Use when driving a gated build loop where Claude orchestrates and Codex CLI implements — Claude plans and judges, Codex plans/implements from a persistent thread, with approve-the-plan and review-the-diff gates that refuse to be skipped. For delegating serious multi-file work to Codex instead of one-shot prompts.4---56# codex-claude-loop — the gated Claude × Codex build loop78Claude is the principal orchestrator; it rarely types product code. Codex CLI does the9hands-on implementation from **persistent threads**. The whole thing is bash around10`codex exec` — no framework, no MCP, no daemon.1112## The cycle (one brief)1314```15Claude writes a brief → Codex authors a plan (persistent thread) → back to Claude16 → Claude APPROVES the plan (loop until tight) → Codex implements (same thread)17 → Claude REVIEWS the diff against the plan (loop until clean) → cl_release18```1920**The persistent thread is the trick:** the plan Codex authored carries into21implementation, so it implements *its own approved plan* with full context. The approved22plan text is also sent with the implementation instruction, so if a human edited and23re-approved the plan file, the file wins over what the thread drafted.2425## How to run it2627`source ${CLAUDE_PLUGIN_ROOT}/skills/codex-claude-loop/lib/codex-claude-loop.sh` then use28the phase functions, or call `bash lib/codex-claude-loop.sh <phase> …` directly. Config29via env (`CL_REPO`, `CL_IMPL_MODEL`, `CL_PLAN_MODEL`, `CL_REVIEW_MODEL`, `CL_SANDBOX`,30`CL_LOCK_TIMEOUT`).31320. **First run:** `cl_doctor` (codex/jq/git/sha256 present, the four codex capabilities33 the loop needs, repo + schema resolve).341. **Codex plans:** `cl_plan <slug> <brief.md>` → writes `<slug>.plan.md`, opens a35 persistent thread, stores its id.362. **Claude approves the plan** (judgment — YOU read it): read `<slug>.plan.md`. If tight,37 `cl_record_verdict <slug> plan approve "why"`. If not, re-brief and re-plan. Loop until38 the plan holds. Prompt yourself to *refute* it, not rubber-stamp it.393. **Codex implements:** `cl_impl <slug>` → resumes the thread, writes code, runs tests,40 holds the writer lock, and records a success marker only if codex exited clean.414. **Optional same-session follow-up:** `cl_prompt <slug> "<additional request>"` queues42 behind the lane's writer lock, resumes the exact stored thread, and prints Codex's43 response. It requires a successful implementation and makes re-review mandatory.445. **Claude reviews the diff:** `cl_review_human <slug>` (rich review you read) — or45 inspect `git diff <base>` yourself. Judge it *against the plan*. Approve46 (`cl_record_verdict <slug> review approve "why"`) or send the blocking items back into47 the same thread with `cl_revise <slug> "…"` and re-review. Loop until clean.486. **Release:** `cl_release <slug>` confirms both gates still hold for the tree as it is49 right now, and refuses otherwise. Then changelog, tag, merge, deploy (honor the50 project's own deploy gate).5152`cl_status` shows where every slug stands. `cl_wave <slug> <brief.md>` advances one step53per call and returns **3** when it is your turn, **0** when both gates hold — re-run it54after each judgment rather than expecting it to block.5556## Autonomous fallback (no orchestrator to gate)5758When there is no Claude brain available to judge (e.g. usage cap spent), `cl_codex_gate59<slug>` stands in a **Codex adversarial reviewer** that emits a parseable verdict60(`schemas/verdict.schema.json`, defaults to `revise` unless confident). Use it to keep the61loop moving unattended — but a real orchestrator review is the standard.6263## Rails (load-bearing)6465- **One writer.** `cl_impl`, `cl_revise`, and `cl_prompt` share one lock; don't bypass it.66 Two Codex processes writing the same tree = corruption.67- **Never review a tree that is being written.** Both review paths refuse while the lock68 is held. To genuinely overlap review and implementation, give each lane its own69 worktree and its own `CL_REPO`.70- **Gates must refute, not rubber-stamp.** A gate that always approves is worse than no71 gate. Blocking items need concrete fixes, and `approve` with a non-empty blocking list72 is downgraded on disk.73- **A revise round is not closed by a matching sentence.** Every item you send back with74 `cl_revise` is kept and handed to the next review, which is told to judge it on intent.75 When you review, do the same: ask what the item was trying to prevent, then check the76 code prevents it. A change that satisfies the wording and misses the point stays blocking.77- **Approvals are bound to what they judged.** Editing the plan voids its approval;78 changing the tree voids the review approval. If a re-approval is refused, read the79 reason rather than deleting state to make it pass.80- **The plugin guards git publication.** Normal Claude Code Bash calls for `git commit`,81 `push`, `merge`, and `tag` are refused while a successful implementation is not covered82 by both current approvals. The standalone skill install has no hook; neither path binds83 a human terminal or deliberately wrapped git commands.84- **Verify model variants before architecting on them.** Set `CL_IMPL_MODEL` /85 `CL_REVIEW_MODEL` only to models you have actually confirmed behave as you assume.86- **Tail the log within a minute of launching any lane.** A bad flag makes `codex exec`87 die into its jsonl while you believe a lane is running.88- **First run = `cl_selfreview`:** have Codex adversarially tear apart THIS harness before89 you trust it.90- Honor the repo's own rules (branch protection, deploy gates, secrets never printed).9192## State9394`~/.codex-claude-loop/<repo>-<hash of its path>/` — plans, verdicts, thread ids, base95SHAs, JSONL logs. Outside the repo so it never pollutes a tree Codex is writing, and keyed96by path so two repos with the same basename never share approvals. Override with97`CL_STATE`.