Five coding agents, five formats, one table

Dmitriy Solodukha · · updated · 4 min read

Claude Code, Codex, OpenCode, Gemini CLI and DeepSeek Harness each record their work differently, and three of the differences give a believable wrong number.

This post compares how five coding agents — Claude Code, Codex, OpenCode, Gemini CLI and DeepSeek Harness — write down what they did: where the record lives, its format, how it counts cached tokens, whether it states a cost, and where it names the model. Then it shows the one table Caprock turns all five into, so their numbers can be added up.

Update, 2026-10-20: Caprock now reads a sixth, Hermes Agent, from its own SQLite database, and carries Hermes's cost figure through as it does OpenCode's.

A reader looked at Caprock and guessed what it does underneath: "parsing JSON, and sweating to build a coherent image out of huge and heavy JSON files." He was right, and it is the part of the product nobody sees. None of the five writes its record the same way, none promises to keep its format as it is, and Claude Code deletes its record after 30 days.

How each agent records its work

How each agent records its work, read on one machine, 1 October 2026
AgentWhere it livesFormatCached tokensReports its costModel named in
Claude Code~/.claude/projectsJSON linesbeside fresh inputnoeach reply
Codex~/.codex/sessionsJSON linesinside inputnobase instructions, 96 of 100
OpenCodeits SQLite databaseSQL rowsown columnyeseach session
Gemini CLIa telemetry file, if askedOTel logreads, no writesnoeach response
DeepSeek Harnesssession.v3.jsonl.zstdJSON lines, zstdbeside fresh inputnoeach reply
"Cached tokens" is how the cached part of a prompt is counted; OTel is OpenTelemetry. Codex also writes token counts as running totals. Caprock reads Gemini CLI from a telemetry file it asks for when it starts a session. (As of 2026-10-20: Gemini CLI does keep its own session history, under ~/.gemini/tmp/<project_hash>/chats/; Caprock does not read it.)

Three ways to get a believable wrong answer

Reading the files is not the hard part. The obvious reading of each can give you a number that looks right and is not.

Cached tokens counted twice. Claude Code reports fresh input and cache reads side by side. Codex reports the whole prompt as input, with the cached part as a subset of it. Treat the two the same way and every cached Codex token is billed twice — once at full price.

Tokens counted twice. Codex writes both a running total and a per-turn figure, and often writes the same sample twice in a row. Summing the per-turn figure on one real session gave 261,111 tokens; the true count was 137,739.

The model in the wrong place. Codex names the model in a turn context in 4 transcripts out of 100. In the other 96 it is inside the session's base instructions. Read only the obvious field and most of your Codex work has no model, so no price.

None of these mistakes raises a parsing error.

A wrong number can sit on a dashboard looking perfectly ordinary.

One table

Caprock reads all five as they are written and turns each into the same rows: one per turn, tool call or lifecycle event, with the same columns whichever agent produced it — agent, model, fresh input, cache read, cache write, output, cost, the folder the work touched.

That table is yours to take out. On my machine, on 1 October:

$ caprock export > record.tsv
$ wc -l record.tsv
  305162 record.tsv

Three hundred thousand rows from four agents, in about five seconds, as TSV, CSV or JSON lines. It reads the database without writing to it, works with Caprock stopped, and leaves out prompts and replies unless you ask for them. Here is one reply from each agent in it:

One reply from each agent, from the same export — four replies of different sizes, not a cost comparison
AgentModeltokens_intokens_outcache_readcost_usd
Claude Codeclaude-opus-5-521,073308,787$0.198
Codexgpt-6-astra4,65611655,552$0.108
OpenCodedeepseek-v4-pro26,9831,5155,120$0.057
DeepSeek Harnessdeepseek-v4-pro128823121,472$0.0012
Columns 3, 8–11 and 14 of the export, cost rounded. Gemini CLI has no row: Caprock records only the Gemini sessions it starts, and the record held none.

Look at the tokens_in column. Claude Code's fresh input is 2 tokens, because almost everything came from the cache; Codex's is 4,656 because the cached part has already been taken out of it. In the files they came from, those two numbers mean different things. Here they mean the same thing.

Four of the five report tokens and no cost, so Caprock prices them from a dated table of each provider's list prices. OpenCode computes its own cost, and that figure is kept as it is — two arithmetics over the same tokens would give one session two totals.

Why this is the part worth having

When a vendor changes its format, the table stays the same. The work of noticing is done once here, instead of by everyone trying to count what their agents cost.

The columns are documented in the schema. It is plain SQLite on your disk, with network features off by default.

Sources

Figures read on 2026-10-01 by Caprock v0.62.0 on one machine, mine. A reading, not a live feed; yours will differ.

Your turn

Run it on your own history: who is waiting on you, who is stuck, what each pull request cost. Free, open source, local by default.

Download for Mac

Notarized by Apple. One file for Apple silicon and Intel, macOS 13 or later.

Or run it yourself:

curl -fsSL https://caprock.dev/mac.sh | sh

Paste in Terminal: it installs Caprock and opens it.Or with Homebrew: brew install --cask dspv/tap/caprock-app