Skip to content
DurkBench

The method

How we test

What we ask each app, how we keep it fair, and what every number means.

Test kit

v6

A bump means the rules changed

Models pinned

10

4 featured + 6 more

Rounds a day

24

One every hour

What we do, in five sentences

  1. 1We pay for Claude Code, Codex, and Grok Build — the same paid coding apps you type into.
  2. 2One machine in our lab runs all three, day and night — it checks its sign-ins, then starts a fresh round of checks every hour.
  3. 3In each round every app gets the exact same short job, in a brand-new empty folder, with no tools, no saved settings, and no memory of the last run.
  4. 4We time the whole thing from key press to last word, count the tokens each app reports, and check that the answer is actually right.
  5. 5Every number on this site comes from one of those runs, and we keep the raw file it came from.

We test the apps, not the hidden web APIs behind them. ChatGPT Sol and API gpt-5.6 are different products. grok-build-0.1 is API-only, so it is not on our boards.

The two checks we run

The wording never changes. We never make a prompt longer, because prompt size is part of the measurement.

What every number means

The units on the boards, in plain words.

Token
A token is a small chunk of text, roughly four letters. Models read and write text one token at a time.
Wall tok/s
Every token the model wrote, thinking included, divided by the full start-to-finish time. Higher is better. It is the only speed unit that means the same thing in all three apps, so our boards sort on it.
Stream tok/s
How fast text appears once it starts flowing. Claude counts visible answer tokens from the first word to the last. Grok does the same when its stream gives us a window. Codex sends no token stream, so its column covers the whole turn and carries a *. We show this number but never rank on it.
TTFT (time to first word)
How long you stare at a blank screen before the first visible word shows up. Thinking does not count as a word. Lower is better. Codex leaves this blank because it does not stream.
Wall time
Start to finish for the whole command, including the app booting. It is what you actually wait for. Lower is better.
Middle value (median)
For a window we report the middle sample, not the average, so one freak slow run cannot drag a whole row down.
Slots / n
How many finished checks sit behind a number. A small count moves a lot, so we always print it next to the value.

Status words like rate limit and wrong answer are spelled out on the Logs page. Test kit versions are spelled out on the Changelog.

How we keep it fair

Three different apps only compare if every run is set up the same way. These are the rules we do not bend.

Clean room
Every run starts in a new empty folder. No saved settings, no skills, no slash commands, no memory, no tools. Grok gets a throwaway home folder. If an app reaches for a tool anyway, the row fails and is labeled used tools.
Same job for everyone
Same prompts, same one-line system prompt — “Answer the user. Do not use tools. Do not add a preamble.” — and every model at the top of its own effort scale, so no app can quietly coast.
Paid sign-ins only
We run on plans we pay for, like any customer. If an API key is sitting in the environment, the run stops on purpose. A key would quietly move billing to the API and we would stop testing the paid app.
One try, fails stay in
We never retry a bad run and we never pick the nicer of two samples. Every fail is recorded once and labeled: rate limit, rate limit warning, timeout, auth, used tools, wrong answer, or parse. Dropping fails would make every tool look better than it really is.
Every round is graded
A speed round only counts if the answer is right. A plain script checks the count against the one correct answer — no human opinion, no AI judge. A fast wrong answer scores nothing, so no app can win by writing rubbish quickly.
Nothing gets blended
Write speed and the ping stay on separate boards. We never mash them into one winner score, because the trade-off is yours to make.

The models we pin

The exact names we ask for every round. If an app serves something else, we save the real name and mark the row remapped.

Featured on the boards
claude-fable-5 and claude-opus-5 in Claude Code, gpt-5.6-sol in Codex, and grok-4.6 in Grok Build. Every board leads with these four.
Also measured
claude-haiku-4-5, claude-sonnet-5, gpt-5.6-luna, gpt-5.6-terra, gpt-5.5, and grok-4.5. Same rounds, same rules. They live on the Other models page.
Effort
Every pin runs at the top of its own scale: xhigh for grok-4.6, high for everything else. grok-4.5 has no xhigh, so high is its honest ceiling.
Ping carriers
The ping rides on claude-haiku-4-5, gpt-5.6-luna, and grok-4.6. gpt-5.2 was retired on August 19, 2026 — OpenAI now refuses it on subscription accounts.

Where these numbers can mislead you

The honest caveats. We would rather you know them than quote us wrongly.

One lab, our numbers
Every number comes from one machine on a normal home connection, measured by us. Use it to compare the three apps against each other. These are not official figures from Anthropic, OpenAI, or xAI.
We time the app, not just the model
Start-up, the app’s own hidden prompt, and its network path all count. That is on purpose — it is what you wait for. It also means a quick model inside a slow app looks slow here.
Codex carries a big built-in prompt
Codex ships a large built-in agent prompt. Fresh input of roughly 9–12k tokens is that prompt, not a 250-token reply. Its CLI does not echo the model name back, so model_verified stays false on those rows.
Grok leftovers
A clean Grok 4.5 ping answered ok in 8.9s with 7987 input tokens. Its inspect output still lists a Codex plugin row and one hook. We name those leftovers on the sample. No tool ran. grok-4.5-build is the same family as grok-4.5.
We cannot see your quota
People talk about Claude and ChatGPT in 5-hour windows. SuperGrok is one weekly pool shared with Chat, Imagine, and Voice. We do not read anyone’s remaining quota from an API, so nothing here predicts when you will run out.

For the fine print

The exact command lines

You do not need these to read the boards. They are here so anyone can check our work, flag by flag. The strings are generated from the same code the tests run, so they cannot drift. Only the model flag changes from pin to pin.

Show the exact commands our lab runs

Claude Code · Ping

claude -p --model claude-haiku-4-5 --effort high --output-format stream-json --include-partial-messages --verbose --max-turns 1 --tools "" --permission-mode dontAsk --safe-mode --setting-sources "" --disable-slash-commands --system-prompt "Answer the user. Do not use tools. Do not add a preamble." --strict-mcp-config --mcp-config "{\"mcpServers\":{}}" --no-session-persistence "Reply with exactly: ok"

Claude Code · Speed

claude -p --model claude-sonnet-5 --effort high --output-format stream-json --include-partial-messages --verbose --max-turns 1 --tools "" --permission-mode dontAsk --safe-mode --setting-sources "" --disable-slash-commands --system-prompt "Answer the user. Do not use tools. Do not add a preamble." --strict-mcp-config --mcp-config "{\"mcpServers\":{}}" --no-session-persistence "Count from 1 to 120 in plain text on a single line, numbers separated by single spaces. Output nothing else."

Codex · Ping

codex --ask-for-approval never exec --sandbox read-only --skip-git-repo-check --ignore-user-config --ephemeral --disable memories --disable multi_agent -m gpt-5.6-luna -c "model_reasoning_effort=\"high\"" -c "web_search=\"disabled\"" -c features.shell_tool=false --json "Reply with exactly: ok"

Codex · Speed

codex --ask-for-approval never exec --sandbox read-only --skip-git-repo-check --ignore-user-config --ephemeral --disable memories --disable multi_agent -m gpt-5.6-terra -c "model_reasoning_effort=\"high\"" -c "web_search=\"disabled\"" -c features.shell_tool=false --json "Count from 1 to 120 in plain text on a single line, numbers separated by single spaces. Output nothing else."

Grok Build · Ping

grok --no-auto-update --no-leader -p "Reply with exactly: ok" --output-format json -m grok-4.6 --effort xhigh --cwd <temp> --tools none --disallowed-tools run_terminal_command,search_replace,web_search,web_fetch,spawn_subagent,Agent,todo_write --permission-mode dontAsk --max-turns 1 --no-subagents --disable-web-search --no-plan --verbatim

Grok Build · Speed

grok --no-auto-update --no-leader -p "Count from 1 to 120 in plain text on a single line, numbers separated by single spaces. Output nothing else." --output-format streaming-json -m grok-4.6 --effort xhigh --cwd <temp> --tools none --disallowed-tools run_terminal_command,search_replace,web_search,web_fetch,spawn_subagent,Agent,todo_write --permission-mode dontAsk --max-turns 1 --no-subagents --disable-web-search --no-plan --verbatim

One command, read flag by flag

Take the Claude speed command above and read every flag. Each one is a rule from this page, enforced in the command line itself. Codex and Grok get the same treatment through their own flags.

-p
Print mode. One prompt in, one answer out, then the app exits. No chat session.
--model claude-sonnet-5
The pin. The only part that changes from model to model — everything else is identical.
--effort high
The think setting, pinned at this model's ceiling: xhigh for grok-4.6, high for everything else.
--max-turns 1
One answer only. The app cannot take a second turn to fix a bad first one.
--tools "" and --strict-mcp-config
No tools and no plugins. If the app reaches for one anyway, the row fails and is labeled used tools.
--setting-sources "" and --disable-slash-commands
Ignore everything saved on the machine: settings, skills, commands. Every run starts from nothing.
--system-prompt "Answer the user…"
The one-line bench prompt. The same line goes to all three apps, word for word.
--output-format stream-json
The app's own typed event stream. Timings, tokens, and rate limits come from these events — never from reading the screen.
--no-session-persistence
Nothing is remembered between rounds. No memory, no history.

How to read this

Our runner never uses --bare on Claude — that path refuses the paid login. It never passes Grok --tools ""; it uses none. It never sets an API key, because a key would switch billing away from the paid app we are trying to measure.

Read next