All articles
platform engineering · intermediate ·

Cross-model code review: using Codex from inside Claude Code

How a Claude Code plugin wraps the Codex App Server to delegate reviews and rescue tasks to GPT-5.5 models — and what the forwarder subagent, background job system, and review gate patterns reveal about multi-model orchestration.

claude-codecode-reviewcodexcoding-agentspatternsplugins

Claude Code and Codex are built by different companies, run on different model families, and have different strengths. The pragmatic question is not which one to use. It is how to use them together.

The Codex plugin for Claude Code answers this question with a bridge architecture. It wraps the Codex App Server through the local codex binary and exposes six slash commands inside Claude Code. Claude handles orchestration, conversation, and context management. Codex handles the delegated work — reviews, investigations, fixes — on GPT-5.5 models. Neither tool is subordinated. Each does what it is better at.

The bridge architecture

The plugin does not reimplement Codex. It delegates through the user’s local Codex CLI and App Server — the same binaries, the same authentication, the same configuration files. If Codex is already installed and logged in, the plugin picks up the existing setup. If it is not, /codex:setup detects the gap and offers to install it.

The architecture is a three-layer stack. At the top, Claude Code slash commands parse user input, estimate review scope, and route execution (foreground or background). In the middle, a shared Node.js script — codex-companion.mjs — handles all Codex interaction: building prompts, calling the App Server, tracking progress, and managing job state. At the bottom, the Codex App Server executes the actual work on GPT models.

Plugin commands and their Codex targets
CommandWhat it doesCodex sandboxModel
/codex:reviewNative read-only review of uncommitted or branch changesread-onlyDefault or configured
/codex:adversarial-reviewSteerable challenge review with custom focus textread-onlyDefault or configured
/codex:rescueDelegates diagnosis, investigation, or fixesworkspace-write (default)User-selectable
/codex:statusShows running and recent Codex jobsN/AN/A
/codex:resultShows final stored output for a finished jobN/AN/A
/codex:cancelCancels an active background jobN/AN/A

Two kinds of review

The plugin offers two review modes, and the difference matters more than the interface suggests.

/codex:review maps directly to Codex’s built-in reviewer — the same code path as running /review inside Codex. It accepts a diff target (working tree or branch) and returns findings. It does not accept custom focus text or steering instructions. The output is predictable because the prompt is not custom — it is Codex’s own review contract.

/codex:adversarial-review is a different animal. It loads a hand-written XML prompt template that positions Codex as a skeptic:

plugins/codex/prompts/adversarial-review.md markdown
<role>
You are Codex performing an adversarial software review.
Your job is to break confidence in the change, not to validate it.
</role>

<task>
Review the provided repository context as if you are trying to find
the strongest reasons this change should not ship yet.
</task>

<operating_stance>
Default to skepticism.
Assume the change can fail in subtle, high-cost, or user-visible ways
until the evidence says otherwise.
Do not give credit for good intent, partial fixes, or likely follow-up work.
</operating_stance>

The template defines an attack surface priority list — auth boundaries, data loss, rollback safety, race conditions, observability gaps — and a finding bar that requires each issue to answer four questions: what can go wrong, why the code path is vulnerable, what the likely impact is, and what concrete change would reduce the risk.

Critically, the adversarial review uses a JSON output schema. Codex must return structured findings with file paths, line ranges, confidence scores, and a top-line needs-attention or approve verdict. The plugin parses this, validates it against the schema, and renders it. This is cross-model structured communication: one model family produces machine-verifiable output that the other model’s tooling consumes.

The forwarder subagent

The most interesting design decision in the plugin is what the codex-rescue subagent is not allowed to do.

When /codex:rescue runs, it routes through a custom subagent defined in agents/codex-rescue.md. This subagent has exactly one job: invoke node codex-companion.mjs task and return the stdout unchanged. It is not the implementer. It is not the orchestrator. It is a forwarding wrapper.

The constraints are explicit and enumerable. The subagent must not inspect the repository, read files, grep for patterns, monitor progress, poll status, fetch results, cancel jobs, summarize output, or do any follow-up work. It may use the gpt-5-4-prompting skill to tighten the user’s prompt before forwarding, but even that is narrow — the skill rewrites the prompt text, not the surrounding workflow.

This pattern generalizes beyond this plugin. When building a subagent whose job is to delegate to an external system, make it a forwarder, not an orchestrator. Orchestrators accumulate context, make decisions, and create handoff points where information degrades. Forwarders take a prompt in and pass output back. The only state they carry is the routing decision.

Background jobs as infrastructure

Codex reviews and rescue tasks can run for minutes. The plugin treats this as a first-class concern with a complete background job system.

Jobs have a lifecycle: queued, running, completed, cancelled. Each job gets a unique ID, a log file, a JSON state file, and a summary entry in a repository-level index. The codex-companion.mjs script includes dedicated subcommands for status, result, and cancel — each with JSON output modes for programmatic consumption.

The worker model is deliberately simple. Background tasks spawn as detached Node.js child processes running codex-companion.mjs task-worker. The worker reads the stored job request, executes the Codex App Server call, writes progress updates to the log file, and updates the job state on completion. The parent Claude Code session never blocks on background work — it receives a job ID and a confirmation that work started.

Two design details stand out. First, the plugin supports resume. codex-companion.mjs task --resume-last finds the most recent completed task thread for the current session and continues it. This means follow-up instructions like “apply the top fix” or “dig deeper into the race condition” work without restating context — Codex already has the thread history. Second, cancellation is thorough: it sends an interrupt to the Codex App Server, terminates the worker process tree, and writes a terminal state. There is no orphaned work.

The review gate

The plugin includes an optional Stop hook called the review gate. When enabled, every time Claude attempts to stop, the hook runs a targeted Codex review of the most recent Claude turn. If the review finds issues, the stop is blocked so Claude can address them before the session ends.

The gate is implemented as a Node.js script registered in hooks.json under the Stop event. It reads the previous Claude response, constructs a compact review prompt, and calls the Codex App Server with a strict output contract: the first line must be exactly ALLOW: <reason> or BLOCK: <reason>. The hook script parses this and signals whether to proceed.

plugins/codex/prompts/stop-review-gate.md markdown
<task>
Run a stop-gate review of the previous Claude turn.
Only review the work from the previous Claude turn.
Only review it if Claude actually did code changes in that turn.
Pure status, setup, or reporting output does not count as reviewable work.
</task>

<default_follow_through_policy>
Use ALLOW if the previous turn did not make code changes or
if you do not see a blocking issue.
</default_follow_through_policy>

The gate defaults to permissive. If the previous turn was not an edit-producing turn, the review returns ALLOW immediately without further investigation. This keeps the gate cheap for conversation turns while still catching introduced issues on implementation turns.

What this pattern reveals

The Codex plugin is not the only example of cross-model orchestration, but its architecture makes the pattern explicit. Three design choices are worth extracting because they apply to any bridge between coding agents.

Delegate through local tooling, not cloud APIs. The plugin calls the Codex CLI and App Server, not the OpenAI API directly. This means it inherits the user’s existing authentication, configuration, and rate limits. There is no API key management, no separate billing, and no divergence between plugin behavior and direct Codex usage.

Separate orchestration from execution. Claude Code handles conversation, context, and routing. Codex handles the actual review or implementation work. The subagent in between is a forwarder, not a decision-maker. This separation means each component has a clear responsibility and a narrow failure mode.

Make job state observable. Every background job has an ID, a log file, a status, and queryable results. The status command shows progress. The result command shows output. The cancel command cleans up. This turns “fire and forget” into “fire and monitor” — the difference between a bridge and a black box.

The broader trajectory is clear. As coding agents proliferate, the tools that win will not be the ones with the best isolated performance. They will be the ones with the best bridges — the cleanest ways to delegate work across model families, share state between tools, and give the user visibility into where work is happening and why.


Takeaways

Cross-model orchestration is infrastructure, not a feature

The plugin does not debate which model is better. It wires them together — Claude for conversation and routing, Codex for delegated work — with clean handoffs and observable state at every boundary.

Forwarder subagents beat orchestrator subagents

The codex-rescue subagent is deliberately thin. It does not inspect the repo, summarize output, or do follow-up work. It forwards a prompt and returns results. This prevents context waste and keeps handoff boundaries clean.

Background jobs need lifecycle management

The plugin tracks every job from queued through running to completed or cancelled, with IDs, log files, and session-scoped visibility. Long-running cross-model work needs observable state, not fire-and-forget.

Structured output contracts make cross-model communication reliable

The adversarial review requires a JSON schema with file paths, line ranges, and confidence scores. Claude Code parses and validates this. Machine-verifiable output is the right contract between different model families.

Delegate through local tooling, not cloud APIs

The plugin calls the Codex CLI, not the OpenAI API. It inherits existing auth, config, and rate limits. There is no secondary login, no API key management, and no behavioral divergence from direct Codex usage.