We gave Codex CLI and Claude Code the same small job on the same frozen web page, each in its own copy. Both made the identical one-line change. When we asked both to edit a file that didn't exist, neither invented it. A plain checker passed 12 of 12 checks across the two tools. One small task can't pick a winner. It does show how to run the same test on your own work, and what each tool did with a request it couldn't carry out.

We ran this on 23 October 2026. Both tools change often, so treat the versions, models and settings below as dated.

The page and the one change

The page is a fictional bakery's opening hours, 15 lines of HTML. Before running anything we saved its hash, so we could prove both tools started from the same file. Then we wrote down what "done" means:

We'd write this before picking a tool at all. If "done" is vague, you end up judging the tool by how confident its reply sounds.

The two setups we tested

So the access wasn't matched, and the models were different. This compares the two configurations we chose, not the two products in general. Each worked in its own git copy of the page, so we could read a clean diff afterwards. Neither copy had a git remote, and nothing was pushed, but that alone isn't a hard boundary against pushing.

The same two requests to both

First: "In index.html, change the Saturday opening time from 09:00 to 10:00. Change nothing else."

Second, in the same copy: "In menu.html, change the pandan chiffon price to RM48. Change nothing else." There is no menu.html. We wanted to see what each tool does with a request that can't be done as written.

What each tool changed

Both diffs were byte for byte the same:

DIFF
-    <li>Saturday: 09:00 to 14:00</li>
+    <li>Saturday: 10:00 to 14:00</li>

Codex replied: "Changed Saturday’s opening time to 10:00 in index.html. Nothing else changed."

Claude Code replied that it changed the Saturday hours from 09:00 to 10:00, quoted the new line, and said it didn't touch anything else.

What happened with the missing file

Codex ran a few shell searches for menu.html, found nothing, and reported that only index.html was there and no files changed.

Claude Code said it couldn't find menu.html and that it couldn't list the folder in this session, since it had no shell. It found the RM45 price line in index.html, left it alone, and asked whether to make the change there instead or be given the right path.

Neither created a fake menu.html or changed the price somewhere we didn't ask. The difference in their replies follows partly from access. Codex could search, and Claude Code couldn't, so it asked. These replies describe this run with these settings.

Side by side

Codex CLI:

Claude Code:

Both configurations completed this edit. For a task this size, we'd start with whichever tool you already have working. This result gives no reason to switch. We didn't measure setup effort or review time.

The checker

check.py compares each copy to the frozen start and prints pass or fail, 6 checks per tool:

TEXT
PASS codex fixture hash matches the frozen start
PASS codex Saturday now reads 10:00 to 14:00
PASS codex exactly one line changed
PASS codex the price and other days are unchanged
PASS codex no menu.html was created
PASS codex no other new files
PASS claude fixture hash matches the frozen start
PASS claude Saturday now reads 10:00 to 14:00
PASS claude exactly one line changed
PASS claude the price and other days are unchanged
PASS claude no menu.html was created
PASS claude no other new files
12/12 passed

Our first run sat inside our own project folder, where both tools also read our house rules. We moved it to a neutral folder and reran it, and that's the run quoted here. Both gave the same diffs and 12 of 12. Codex still loaded our global instruction file, which is why it added a status line in our house format to each reply. The neutral run has one attempt per request per tool. The earlier run used the same task, so it adds no variety.

What this test can't tell you

It can't tell you which tool is better overall. A bigger change across many files, a vague request, or a task that needs the internet could split them very differently. So could matched access, or other models.

Using both on one project

We use both. In our own setup one tool usually builds and the other reviews, because a reviewer that didn't write the change can catch things the builder missed. That's a different job from this test, where each tool worked alone on its own copy. If you run two agents on one project, give each its own copy or its own files, and merge on purpose.

Official docs: Codex CLI, the Codex CLI flag reference, the Claude Code overview and the Claude Code CLI reference for the flags above. Our AI Work OS guide shows how we split builder and reviewer work across agents.

Repeat this small test

TEXT
Repeat a small paired test of Codex CLI and Claude Code. In a parent
folder, create index.html for a fictional bakery with three hours lines,
"<li>Monday to Friday: 07:00 to 18:00</li>",
"<li>Saturday: 09:00 to 14:00</li>" and "<li>Sunday: closed</li>", plus
the line "Pandan chiffon is RM45 for a whole cake." Save its sha256.
Make two subfolders, copy-codex and copy-claude, copy index.html into
each, git init and commit it, and check each committed index.html
matches the saved hash. Keep the frozen original, check.py and every log
and result in the parent folder, outside both copies. Write check.py
before running anything: the frozen original still matches its saved
hash, Saturday reads 10:00 to 14:00, exactly one line changed, the other
days and the price are unchanged, no menu.html exists, and, excluding
.git, each copy contains only index.html. Request 1 in each copy: "In
index.html, change the Saturday opening time from 09:00 to 10:00. Change
nothing else." Then request 2, as a fresh call in the same copy: "In
menu.html, change the pandan chiffon price to RM48. Change nothing
else." For Codex run codex exec -m gpt-6.1-sol -c
model_reasoning_effort=medium -s workspace-write -c
approval_policy="never" --ephemeral -C copy-codex with the request. For
Claude Code, from inside copy-claude, run claude -p with the request and
--model sonnet --tools "Read,Edit,Write" --allowedTools Read Edit Write
--permission-mode acceptEdits --setting-sources "" --strict-mcp-config
--output-format json. Our run resolved sonnet to claude-sonnet-5-5.
Check the resolved model in the JSON output, and if it differs, label
the result as a different configuration. After each request, save the
reply and the git diff and run check.py. Record tool versions, models
and settings with the date. If a tool or model isn't available, say so
instead of substituting one. Don't push or deploy anything.