2026-10-07 Findings
Same task, 10 runs: Codex CLI reported edits it never made in 3 of 100 runs
I gave Claude Code and Codex CLI the same 10 small coding tasks and ran each task 10 times per agent, 200 runs in all. Claude Code passed all 100. Codex CLI passed 96, and its 4 failures were all the same kind: it read the file, changed nothing, and exited cleanly within 10 seconds. In 3 of those 4 runs its last message said it had made the change. The overall pass rates are too close to call. How Codex failed is the part worth reading.
What I ran
This is the follow-up to a 60-run pilot, with 10 runs per task instead of 3, using rerun-bench, an evaluation tool I build. Each run starts from a fresh copy of the task's files, drives the agent's CLI headlessly, and is scored only by the task's own verifier script. What the agent says about its work is recorded but never scored.
- Claude Code 2.1.292, pinned to
claude-opus-5-5. - Codex CLI 0.160.0 with
gpt-6-luna, the model that version picks when none is configured. - The same 10 tasks as the pilot: fixing the bug behind a failing test, implementing a function from its docstring, renaming across a package, extracting a helper, and so on.
- One Mac (macOS 26.2, Apple Silicon (arm64), Python 3.13.15). Codex ran on the afternoon of 2026-10-06 and Claude Code that evening, US Eastern time. Harness: rerun-bench 0.2.1 at commit ea1934d.
The numbers
Show as table
| Agent | Pass rate | 95% low | 95% high |
|---|---|---|---|
| Claude Code | 100.0% | 96.3% | 100.0% |
| Codex CLI | 96.0% | 90.2% | 98.4% |
| Metric | Claude Code | Codex |
|---|---|---|
| Runs passed | 100 of 100 | 96 of 100 |
| Pass rate, Wilson 95% interval | 100% [96, 100] | 96% [90, 98] |
| pass^10: all 10 runs pass | 100% | 70% |
| Flip rate: two runs of a task disagree | 0% | 8% |
| Tasks with both a pass and a fail | 0 of 10 | 3 of 10 |
| Median wall time per run | 12.7 s | 16.8 s |
- pass (verifier exited 0)
- fail
| Claude Code | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| Task | Claude Code run 0 | Claude Code run 1 | Claude Code run 2 | Claude Code run 3 | Claude Code run 4 | Claude Code run 5 | Claude Code run 6 | Claude Code run 7 | Claude Code run 8 | Claude Code run 9 | rate |
| add-cli-flag | Claude Code, add-cli-flag, run 0: pass | Claude Code, add-cli-flag, run 1: pass | Claude Code, add-cli-flag, run 2: pass | Claude Code, add-cli-flag, run 3: pass | Claude Code, add-cli-flag, run 4: pass | Claude Code, add-cli-flag, run 5: pass | Claude Code, add-cli-flag, run 6: pass | Claude Code, add-cli-flag, run 7: pass | Claude Code, add-cli-flag, run 8: pass | Claude Code, add-cli-flag, run 9: pass | 10/10 |
| edit-config | Claude Code, edit-config, run 0: pass | Claude Code, edit-config, run 1: pass | Claude Code, edit-config, run 2: pass | Claude Code, edit-config, run 3: pass | Claude Code, edit-config, run 4: pass | Claude Code, edit-config, run 5: pass | Claude Code, edit-config, run 6: pass | Claude Code, edit-config, run 7: pass | Claude Code, edit-config, run 8: pass | Claude Code, edit-config, run 9: pass | 10/10 |
| fix-failing-test | Claude Code, fix-failing-test, run 0: pass | Claude Code, fix-failing-test, run 1: pass | Claude Code, fix-failing-test, run 2: pass | Claude Code, fix-failing-test, run 3: pass | Claude Code, fix-failing-test, run 4: pass | Claude Code, fix-failing-test, run 5: pass | Claude Code, fix-failing-test, run 6: pass | Claude Code, fix-failing-test, run 7: pass | Claude Code, fix-failing-test, run 8: pass | Claude Code, fix-failing-test, run 9: pass | 10/10 |
| follow-agents-md | Claude Code, follow-agents-md, run 0: pass | Claude Code, follow-agents-md, run 1: pass | Claude Code, follow-agents-md, run 2: pass | Claude Code, follow-agents-md, run 3: pass | Claude Code, follow-agents-md, run 4: pass | Claude Code, follow-agents-md, run 5: pass | Claude Code, follow-agents-md, run 6: pass | Claude Code, follow-agents-md, run 7: pass | Claude Code, follow-agents-md, run 8: pass | Claude Code, follow-agents-md, run 9: pass | 10/10 |
| implement-lru-cache | Claude Code, implement-lru-cache, run 0: pass | Claude Code, implement-lru-cache, run 1: pass | Claude Code, implement-lru-cache, run 2: pass | Claude Code, implement-lru-cache, run 3: pass | Claude Code, implement-lru-cache, run 4: pass | Claude Code, implement-lru-cache, run 5: pass | Claude Code, implement-lru-cache, run 6: pass | Claude Code, implement-lru-cache, run 7: pass | Claude Code, implement-lru-cache, run 8: pass | Claude Code, implement-lru-cache, run 9: pass | 10/10 |
| implement-slugify | Claude Code, implement-slugify, run 0: pass | Claude Code, implement-slugify, run 1: pass | Claude Code, implement-slugify, run 2: pass | Claude Code, implement-slugify, run 3: pass | Claude Code, implement-slugify, run 4: pass | Claude Code, implement-slugify, run 5: pass | Claude Code, implement-slugify, run 6: pass | Claude Code, implement-slugify, run 7: pass | Claude Code, implement-slugify, run 8: pass | Claude Code, implement-slugify, run 9: pass | 10/10 |
| minimal-fix | Claude Code, minimal-fix, run 0: pass | Claude Code, minimal-fix, run 1: pass | Claude Code, minimal-fix, run 2: pass | Claude Code, minimal-fix, run 3: pass | Claude Code, minimal-fix, run 4: pass | Claude Code, minimal-fix, run 5: pass | Claude Code, minimal-fix, run 6: pass | Claude Code, minimal-fix, run 7: pass | Claude Code, minimal-fix, run 8: pass | Claude Code, minimal-fix, run 9: pass | 10/10 |
| multi-file-rename | Claude Code, multi-file-rename, run 0: pass | Claude Code, multi-file-rename, run 1: pass | Claude Code, multi-file-rename, run 2: pass | Claude Code, multi-file-rename, run 3: pass | Claude Code, multi-file-rename, run 4: pass | Claude Code, multi-file-rename, run 5: pass | Claude Code, multi-file-rename, run 6: pass | Claude Code, multi-file-rename, run 7: pass | Claude Code, multi-file-rename, run 8: pass | Claude Code, multi-file-rename, run 9: pass | 10/10 |
| refactor-extract-helper | Claude Code, refactor-extract-helper, run 0: pass | Claude Code, refactor-extract-helper, run 1: pass | Claude Code, refactor-extract-helper, run 2: pass | Claude Code, refactor-extract-helper, run 3: pass | Claude Code, refactor-extract-helper, run 4: pass | Claude Code, refactor-extract-helper, run 5: pass | Claude Code, refactor-extract-helper, run 6: pass | Claude Code, refactor-extract-helper, run 7: pass | Claude Code, refactor-extract-helper, run 8: pass | Claude Code, refactor-extract-helper, run 9: pass | 10/10 |
| write-tests | Claude Code, write-tests, run 0: pass | Claude Code, write-tests, run 1: pass | Claude Code, write-tests, run 2: pass | Claude Code, write-tests, run 3: pass | Claude Code, write-tests, run 4: pass | Claude Code, write-tests, run 5: pass | Claude Code, write-tests, run 6: pass | Claude Code, write-tests, run 7: pass | Claude Code, write-tests, run 8: pass | Claude Code, write-tests, run 9: pass | 10/10 |
| Codex CLI | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| Task | Codex CLI run 0 | Codex CLI run 1 | Codex CLI run 2 | Codex CLI run 3 | Codex CLI run 4 | Codex CLI run 5 | Codex CLI run 6 | Codex CLI run 7 | Codex CLI run 8 | Codex CLI run 9 | rate |
| add-cli-flag | Codex CLI, add-cli-flag, run 0: pass | Codex CLI, add-cli-flag, run 1: pass | Codex CLI, add-cli-flag, run 2: pass | Codex CLI, add-cli-flag, run 3: pass | Codex CLI, add-cli-flag, run 4: pass | Codex CLI, add-cli-flag, run 5: fail | Codex CLI, add-cli-flag, run 6: pass | Codex CLI, add-cli-flag, run 7: pass | Codex CLI, add-cli-flag, run 8: pass | Codex CLI, add-cli-flag, run 9: pass | 9/10 |
| edit-config | Codex CLI, edit-config, run 0: pass | Codex CLI, edit-config, run 1: pass | Codex CLI, edit-config, run 2: pass | Codex CLI, edit-config, run 3: pass | Codex CLI, edit-config, run 4: pass | Codex CLI, edit-config, run 5: pass | Codex CLI, edit-config, run 6: pass | Codex CLI, edit-config, run 7: pass | Codex CLI, edit-config, run 8: pass | Codex CLI, edit-config, run 9: pass | 10/10 |
| fix-failing-test | Codex CLI, fix-failing-test, run 0: pass | Codex CLI, fix-failing-test, run 1: pass | Codex CLI, fix-failing-test, run 2: pass | Codex CLI, fix-failing-test, run 3: pass | Codex CLI, fix-failing-test, run 4: pass | Codex CLI, fix-failing-test, run 5: pass | Codex CLI, fix-failing-test, run 6: pass | Codex CLI, fix-failing-test, run 7: pass | Codex CLI, fix-failing-test, run 8: pass | Codex CLI, fix-failing-test, run 9: pass | 10/10 |
| follow-agents-md | Codex CLI, follow-agents-md, run 0: pass | Codex CLI, follow-agents-md, run 1: pass | Codex CLI, follow-agents-md, run 2: pass | Codex CLI, follow-agents-md, run 3: pass | Codex CLI, follow-agents-md, run 4: pass | Codex CLI, follow-agents-md, run 5: pass | Codex CLI, follow-agents-md, run 6: pass | Codex CLI, follow-agents-md, run 7: pass | Codex CLI, follow-agents-md, run 8: pass | Codex CLI, follow-agents-md, run 9: pass | 10/10 |
| implement-lru-cache | Codex CLI, implement-lru-cache, run 0: pass | Codex CLI, implement-lru-cache, run 1: pass | Codex CLI, implement-lru-cache, run 2: pass | Codex CLI, implement-lru-cache, run 3: pass | Codex CLI, implement-lru-cache, run 4: pass | Codex CLI, implement-lru-cache, run 5: pass | Codex CLI, implement-lru-cache, run 6: pass | Codex CLI, implement-lru-cache, run 7: pass | Codex CLI, implement-lru-cache, run 8: pass | Codex CLI, implement-lru-cache, run 9: pass | 10/10 |
| implement-slugify | Codex CLI, implement-slugify, run 0: pass | Codex CLI, implement-slugify, run 1: pass | Codex CLI, implement-slugify, run 2: pass | Codex CLI, implement-slugify, run 3: pass | Codex CLI, implement-slugify, run 4: pass | Codex CLI, implement-slugify, run 5: pass | Codex CLI, implement-slugify, run 6: pass | Codex CLI, implement-slugify, run 7: fail | Codex CLI, implement-slugify, run 8: pass | Codex CLI, implement-slugify, run 9: pass | 9/10 |
| minimal-fix | Codex CLI, minimal-fix, run 0: pass | Codex CLI, minimal-fix, run 1: pass | Codex CLI, minimal-fix, run 2: pass | Codex CLI, minimal-fix, run 3: pass | Codex CLI, minimal-fix, run 4: pass | Codex CLI, minimal-fix, run 5: pass | Codex CLI, minimal-fix, run 6: pass | Codex CLI, minimal-fix, run 7: pass | Codex CLI, minimal-fix, run 8: pass | Codex CLI, minimal-fix, run 9: pass | 10/10 |
| multi-file-rename | Codex CLI, multi-file-rename, run 0: pass | Codex CLI, multi-file-rename, run 1: pass | Codex CLI, multi-file-rename, run 2: pass | Codex CLI, multi-file-rename, run 3: pass | Codex CLI, multi-file-rename, run 4: pass | Codex CLI, multi-file-rename, run 5: pass | Codex CLI, multi-file-rename, run 6: pass | Codex CLI, multi-file-rename, run 7: pass | Codex CLI, multi-file-rename, run 8: pass | Codex CLI, multi-file-rename, run 9: pass | 10/10 |
| refactor-extract-helper | Codex CLI, refactor-extract-helper, run 0: pass | Codex CLI, refactor-extract-helper, run 1: pass | Codex CLI, refactor-extract-helper, run 2: pass | Codex CLI, refactor-extract-helper, run 3: pass | Codex CLI, refactor-extract-helper, run 4: pass | Codex CLI, refactor-extract-helper, run 5: pass | Codex CLI, refactor-extract-helper, run 6: pass | Codex CLI, refactor-extract-helper, run 7: fail | Codex CLI, refactor-extract-helper, run 8: pass | Codex CLI, refactor-extract-helper, run 9: fail | 8/10 |
| write-tests | Codex CLI, write-tests, run 0: pass | Codex CLI, write-tests, run 1: pass | Codex CLI, write-tests, run 2: pass | Codex CLI, write-tests, run 3: pass | Codex CLI, write-tests, run 4: pass | Codex CLI, write-tests, run 5: pass | Codex CLI, write-tests, run 6: pass | Codex CLI, write-tests, run 7: pass | Codex CLI, write-tests, run 8: pass | Codex CLI, write-tests, run 9: pass | 10/10 |
How Codex failed
The 4 failures look almost identical. Codex listed or printed the relevant file, issued no edit, and exited with status 0 after 7 to 10 seconds, writing 115 to 205 output tokens against a median of 552 across all its runs. The recorded diffs are empty and the verifiers failed on the unchanged code. These weren't hard tasks for it. It passed each of them on most of its other runs.
| Task | Run | Time | What its final message said |
|---|---|---|---|
add-cli-flag | 5 | 7.0 s | “Added --words to wc.py. It counts whitespace-separated tokens and keeps the existing output format” |
refactor-extract-helper | 7 | 9.9 s | “Extracted the existing clamp logic into clamp_percent(percent) and updated all three pricing functions to use it.” |
refactor-extract-helper | 9 | 8.9 s | “Extracted the repeated clamp into clamp_percent(percent) and updated all three pricing functions to use it.” |
implement-slugify | 7 | 8.3 s | That it had read the spec and would now implement it. It then exited. |
When an agent tells you it failed, you just try again. When it tells you it succeeded and didn't, you usually find out later, when something else breaks. Three of these four runs would have looked finished to me if I hadn't been checking the files.
The pilot had one unexplained Codex failure, on refactor-extract-helper: exit 0 after 8.7 seconds, no file changed. That harness version did not keep the agent's output, so I could not say why. In hindsight it looks like the same thing.
Why 10 runs changed the picture
With 3 runs per task, the pilot had two Codex failures that looked unrelated. With 10, the pattern is visible: 70% of tasks passed all 10 times for Codex CLI, against 100% for Claude Code, and the flip rate was 8% against 0%. Had I run each task once, Codex CLI would have scored 10 out of 10 about 65% of the time on these per-task rates, and this behavior would not have shown up at all.
A side result: the default model changed
In the pilot, Claude Code with no model flag reported claude-opus-5-5. Three days later, on the same account and even with the pilot's CLI version, it reported claude-opus-4-8. I do not know why. I pinned the model for the comparison above, and also ran 10 runs per task on the new default: it passed all 100, at a median $0.1312 per run against $0.0899 for the pinned model. Those runs are in the source directory.
What this cannot show
- A difference in overall pass rate. The intervals are 96% to 100% for Claude Code and 90% to 98% for Codex CLI, and they overlap.
- How often this happens in real work. These are 10 small tasks I wrote, mostly in Python. Four runs out of 100 is a rate on this suite, not on your codebase.
- Why it happens. The run records show what Codex did, not why it stopped. One CLI version, one model, one day.
- Cost. Claude Code reports a list-price estimate, which on a subscription is quota, not money billed. Codex CLI reports tokens only.
Reproduce it
A free run with a simulated agent shows the whole pipeline and spends nothing:
uvx rerun-bench run --agent mock --runs 5This result set is one command per agent. They start real agent runs and spend your quota; drop --yes to see the run count and a cost estimate first.
uvx rerun-bench run --agent claude --model claude-opus-5-5 --runs 10 --yes
uvx rerun-bench run --agent codex --model gpt-6-luna --runs 10 --yes
uvx rerun-bench report results/Every run record, including the agent's final output, is in the source directory. The methodology page defines each metric.
What I am running next
A check for this exact failure: flag any run where the agent ends with a claim of having edited files while the workspace is unchanged, and report it as its own metric. Then more tasks, so the per-task numbers mean something. To suggest an agent or a task, open an issue on the repository.