The receipt nobody printed

You got comped.
The question is how badly.

Every coding session on your machine already wrote down what it burned โ€” and which model burned it. Nobody reads it, because it's four gigabytes of JSONL in four different shapes. comped reads all of it, works out what you're running on its own, and tells you what your last 30 days would have cost at API list price.

$ rote play run https://play.modiqo.ai/rajkaria/comped

No flags. No plan to type. Needs python3 and nothing else โ€” no API key, no sign-in, no upload, and no network calls at all.

The comped card: total spent at list price, the multiplier against your plan, spend per model, the providers detected, cache-read share, and the top repeated asks with what each repeat cost.
One card. Rendered from the synthetic logs bundled with the Play, so the numbers are small โ€” on a real month they are not.

New

You don't tell it what you use. It already knows.

Asking which AI you run makes no sense โ€” your logs say so on every line. Each usage record carries the model id the harness sent, and that id names the provider behind it. So it reads, then it decides.

comped ยท price_ledger
$ rote play run .../comped
โ†’ ~/.claude/projects        98 sessions
โ†’ ~/.codex/sessions         12 sessions
โ†’ ~/.pi/agent/sessions      not installed
โ†’ opencode storage          not installed
 
detected  Claude 90%  ยท  Kimi 10%
models    claude-opus-5, claude-fable-5, kimi-k2.6
plan      Claude Max 20ร— โ€” assumed, not typed
 
$2,584.71 comped ยท 13.1ร—

1The harnesses

Claude Code โ€” subagent transcripts included โ€” Codex, Pi and OpenCode. A directory that isn't there is a shrug, not an error, and the card names what it didn't find so you know what wasn't counted.

2The provider

Read off the model id once gateway and region prefixes are stripped, so us.anthropic.claude-opus-5 and claude-opus-5 are one provider, not two. Point Claude Code at Moonshot or Z.ai and the ids give that away too โ€” which is exactly the point.

3The tier

The one thing no log records: a Pro session and a Max session are the same bytes. So instead of asking, it prices every plan at once and marks the one it assumed โ€” always the least flattering one, the smallest multiplier you could honestly claim.

ClaudeGPTCodexKimiGLMDeepSeekGeminiGrokQwenMiniMaxMistralLlama ClaudeGPTCodexKimiGLMDeepSeekGeminiGrokQwenMiniMaxMistralLlama

Kimi, GLM, DeepSeek, Qwen and MiniMax are priced from the same bundled table as Claude and GPT. A provider that doesn't sell a subscription is named on the card, its spend stays in the total, and nothing pretends to cover it. Paying for one anyway? plan=usd:29.

Every plan, priced at once

This is the shape of what the card does โ€” drag the month, read your own row. The real one uses your actual token counts instead of a slider, and highlights the row it assumed.

$2,584
  1. Claude Pro$20/mo129ร—
  2. Claude Max 5ร—$100/mo26ร—
  3. Claude Max 20ร—$200/mo13ร—
  4. ChatGPT Plus$20/mo129ร—
  5. ChatGPT Pro$200/mo13ร—

Nothing here leaves your browser. It's arithmetic, not a service.

How it gets the number

No estimates, no sampling, no telemetry. It reads the same files your agent already wrote and does the arithmetic you'd do by hand if you had a spare weekend.

  1. It reads every harness you have. Claude Code โ€” including the subagent transcripts hiding in subdirectories โ€” plus Codex, Pi and OpenCode. Each one is a separate step, so a harness you don't use is a shrug, not an error.
  2. It throws away the duplicates. Claude Code writes one line per content block, so roughly four in ten usage lines are the same API call again. Price those and your number is fiction. They're collapsed on (message.id, requestId). Codex is the opposite problem: cumulative counters that have to be differenced.
  3. It prices what's left. Uncached input, cache writes, cache reads and output, each at its own rate, in exact decimal arithmetic โ€” from a bundled price table that names its source, its upstream checksum and the date it was taken. A model the table doesn't know is reported with its token count and never priced by guess.
  4. Then it reads you back to yourself. The jobs you've asked three or more times across different days, what each repeat cost, and โ€” for the darker version โ€” the mistakes your agent keeps making and what recovering from them cost.

Three Plays, one honest parser

Same core underneath. Pick the one that matches the question you're actually asking.

rajkaria/comped

What did it cost me?

The card. List-price total, the multiplier against every plan you could be on, which providers you actually used, cache-read share, spend per model, what moved since your last run, and the asks you keep repeating with a price on each.

rote play run https://play.modiqo.ai/rajkaria/comped
rajkaria/session-ledger

Just give me the data

The deduplicated ledger under everything else: usage records, the messages that started each turn, every tool call and whether it failed. Nothing priced, nothing judged. If you're writing a session Play, read this instead of re-parsing the logs.

rote play run https://play.modiqo.ai/rajkaria/session-ledger
rajkaria/wrong-turns

Where did it go wrong?

The mistakes your agent makes on repeat โ€” tool errors, the message where you corrected it, reverts โ€” grouped by signature, priced by what recovery cost, each with a drafted rule for your CLAUDE.md. It writes the draft. It never edits your files.

rote play run https://play.modiqo.ai/rajkaria/wrong-turns

New to rote? Two minutes to install, then any of the above.

What it looks at, exactly

Short version below. The long version is in the docs, field by field, including every number the card can show you.

Tokens

Per API call: uncached input, cache writes, cache reads, output and reasoning tokens, with the model and the session they belong to. Reasoning bills as output, because that's how you're charged.

Turns

The message that started each turn, so cost can be attributed to what you asked rather than to a wall of API calls. Messages your harness generated are labelled as such and kept out of the totals that claim to be yours.

Tools

Every tool call, its one-line summary, and whether it errored. That's what makes "your agent has failed the same way 14 times" a fact rather than a feeling.

Never

Prompt text beyond a 120-character truncation plus a hash. File contents. Your credentials โ€” it refuses to open the files that hold them. Which AI you're on comes from the model ids in the logs, never from your account.

The boring, important part

A tool that reads your logs is asking for a lot of trust. Here's the exact shape of what it does, and how you can check rather than believe.

None of that is a promise you have to take on faith. The test suite fails the build if the core imports urllib, http, socket, requests or ssl; if any module except the PNG renderer so much as mentions subprocess; or if any line of source references a credential path. Read that test โ€” it's 20 lines.

Is the number real?

It's a list-price equivalent, and the card says so on its face. That distinction matters, so here it is plainly.

It is not a bill

You're on a subscription. You paid what you paid. This is what the same tokens would have cost at the API's published rates โ€” the number that tells you whether your plan is a bargain or a rounding error.

Every figure shows its working

Each run writes comped-explain.txt: one line per model with the token counts, the rate each was multiplied by, the plan it inferred and every rung of the ladder. If a number looks wrong, you can find out why in about ten seconds.

Checked against someone else's maths

Continuous integration compares our Claude Code token totals, per model, against ccusage โ€” an independent tool with its own parser. Same logs, same dedup, same totals.

Unknown models stay unknown

If the bundled table has no rate for a model, it appears under "unpriced" with its token count and no dollar figure. A guessed price would make the headline number worse, not better.

Go and find out

Try it on the synthetic logs bundled with the Play first, if you'd rather not point a stranger's code at your own on the first date.

$ rote play run https://play.modiqo.ai/rajkaria/comped claude_dir=resources/fixtures/claude codex_dir=resources/fixtures/codex
$ rote play run https://play.modiqo.ai/rajkaria/comped

Then post your multiplier. Everyone thinks theirs is the bad one.