Claude
Skills
Sign in
Back

cross-model-review

Included with Lifetime
$97 forever

Use this skill for cross-model code reviews where a different AI model reviews code written by the current model. Activates on mentions of cross-model review, peer review, second opinion, review my code, review this PR, review changes, independent review, unbiased review, different model review, cross-check code, or code review.

Code Review

What this skill does


# Cross-Model Code Review

Cross-model validation: the authoring model writes code, a different model reviews it. Different architectures, different training distributions, no self-approval bias.

**Core insight:** Single-model self-review is systematically biased. The same blind spots that let bugs through during writing let them through during review. Cross-model review catches different bug classes because the reviewer has fundamentally different failure modes.

**How to read this skill:** patterns and decision trees below are guidelines. Pick what fits, blend when needed. The rules marked ⚠️ are different: they're real CLI behaviors (`yield_time_ms`, the `--` separator, scope flags), not procedural ceremony. Audited sessions show 366+ orphaned `claude -p` processes per session and ~7 minutes wasted per spiral when ⚠️ rules are skipped. Treat them as facts about the tool, not opinions about workflow.

## Direction & Pre-Flight

Identify the host first. The host runs the _other_ model's CLI as a subprocess.

| Current host | You invoke   | Direction                     |
| ------------ | ------------ | ----------------------------- |
| Claude Code  | `codex` CLI  | Claude writes → Codex reviews |
| Codex        | `claude` CLI | Codex writes → Claude reviews |

Confirm the reviewer is reachable before the real call:

| Host   | Verify command                                                                                                                      | Notes                             |
| ------ | ----------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- |
| Claude | `codex --version`                                                                                                                   | One-shot, no special flags        |
| Codex  | `printf 'say ok\n' \| env -u ANTHROPIC_API_KEY claude -p --output-format text --no-session-persistence` with `yield_time_ms: 30000` | Sanity ping only, see Rules 1 & 4 |

**User defaults are authoritative.** Both CLIs read configured defaults (`~/.codex/config.toml`, `~/.claude/settings.json`). Never specify `--model`, `-m`, or `-c model=`. The only sanctioned override is reasoning effort, and only for spec review (see Effort Override Policy below).

---

## ⚠️ Codex → Claude: Four Non-Negotiable Rules

Rules 1–3 cause the overwhelming majority of cross-model review failures. They're not workflow preferences; they're how the `claude -p` shell tool behaves under Codex. Rule 4 doesn't break the review; it silently bills it to the wrong account. Get all four right on the first call.

### Rule 1: `yield_time_ms: 300000` on EVERY call

Codex's shell tool yields output back to the model after `yield_time_ms` elapses (default `1000` = 1 second). A real `claude -p` review takes 30 seconds to 5+ minutes. The default yields empty output + `Process running with session ID NNNN` before Claude has even started, and the model misreads this as failure.

**The rule:** every `claude -p` call uses `yield_time_ms: 300000` (5 minutes). Initial call, every reaping call, every sanity ping beyond a one-line `say ok`. No exceptions.

```json
{ "cmd": "claude -p --allowedTools \"Read,Glob,Grep,Bash(git *)\" -- \"PROMPT\"", "yield_time_ms": 300000 }
```

**Common cognitive trap:** "My prompt is short, I only need 30s." Wrong. Claude session setup, network, and model compute dominate; prompt length barely factors in. Always 300000.

**Consistency rule:** once you're at 300000, stay at 300000. Reverting to 1000 between calls in the same session creates a fresh wave of orphans on top of any still running.

### Rule 2: `Process running with session ID NNNN` is NOT an error: REAP, never retry

When Codex returns `Process running with session ID NNNN`, the process is alive and computing in the background. The yield fired before completion. **This is normal output, not failure.**

```dot
digraph reap {
    rankdir=TB;
    node [shape=box];

    "Initial call" [style=filled, fillcolor="#e8e8ff"];
    "Process running ID 84814" [style=filled, fillcolor="#fff8e0"];
    "WRONG: re-invoke claude -p" [style=filled, fillcolor="#ffe8e8"];
    "RIGHT: reap session_id 84814" [style=filled, fillcolor="#e8ffe8"];
    "Process exited code 0" [style=filled, fillcolor="#e8ffe8"];
    "New orphan ID 84815" [style=filled, fillcolor="#ffe8e8"];

    "Initial call" -> "Process running ID 84814";
    "Process running ID 84814" -> "WRONG: re-invoke claude -p" [label="retry"];
    "Process running ID 84814" -> "RIGHT: reap session_id 84814" [label="reap"];
    "WRONG: re-invoke claude -p" -> "New orphan ID 84815" [label="spawns new process"];
    "RIGHT: reap session_id 84814" -> "Process exited code 0" [label="loop until exit"];
}
```

**Wrong** (each retry spawns a fresh process; original keeps running):

```json
{"cmd": "claude -p --allowedTools '...' -- 'PROMPT'", "yield_time_ms": 300000}
→ "Process running with session ID 84814"
{"cmd": "claude -p --allowedTools '...' -- 'PROMPT'", "yield_time_ms": 300000}
→ "Process running with session ID 84815"   // 84814 still alive, orphaned
{"cmd": "claude -p --allowedTools '...' -- 'PROMPT'", "yield_time_ms": 300000}
→ "Process running with session ID 84816"   // 84814 + 84815 both still alive
... 8 more retries ... 11+ orphans, ~7 minutes wall time
```

**Right** (reap the existing session by ID until exit):

```json
{"cmd": "claude -p --allowedTools '...' -- 'PROMPT'", "yield_time_ms": 300000}
→ "Process running with session ID 84814"
{"session_id": 84814, "yield_time_ms": 300000}        // reap, do NOT re-invoke claude -p
→ "Process running with session ID 84814"             // still computing
{"session_id": 84814, "yield_time_ms": 300000}        // keep reaping
→ "Process exited with code 0"                        // done, parse the output
```

**Reaping rules:**

- Do NOT re-invoke `claude -p` (creates a new process)
- Do NOT change flags, prompts, or tools (reaping is a different operation entirely)
- DO call `{"session_id": NNNN, "yield_time_ms": 300000}` repeatedly
- Stop only when `Process exited with code X` appears

### Rule 3: Variadic flags require the `--` separator

The `claude` CLI has flags that take `<value...>` and greedily consume every following argument until the next flag. If your prompt follows one of these without a `--` separator, the prompt gets swallowed as a flag value, the prompt arg goes missing, and Claude errors with `Input must be provided either through stdin or as a prompt argument when using --print` or hangs waiting on stdin.

**Variadic flags:** `--allowedTools` / `--allowed-tools`, `--disallowedTools` / `--disallowed-tools`, `--tools`, `--add-dir`, `--betas`, `--file`, `--mcp-config`, `--plugin-dir`.

**Required form** (default to this, works regardless of flag order):

```bash
claude -p --allowedTools "Read,Glob,Grep,Bash(git *)" -- "PROMPT"
```

**Two fallback shapes** (use only if `--` won't work in your context):

| Shape               | Example                                                        |
| ------------------- | -------------------------------------------------------------- |
| Prompt before flags | `claude -p "PROMPT" --allowedTools "Read,Bash(git *)"`         |
| Stdin pipe          | `echo "PROMPT" \| claude -p --allowedTools "Read,Bash(git *)"` |

The `codex` CLI does not have this issue, its flags are non-variadic.

### Rule 4: Strip `ANTHROPIC_API_KEY` so the review bills to your subscription

Codex — and most shells that touch the Anthropic API — export `ANTHROPIC_API_KEY` into the environment. Child `claude -p` calls inherit it, and Claude Code's auth precedence ranks the API key **above** your Pro/Max subscription OAuth. Interactive `claude` prompts once before using a stray key and remembers your choice; `-p` (non-interactive) mode uses the key **silently, on every call**. The review still works — it just bills per-token against the 

Related in Code Review