Why is Claude Code so expensive all of a sudden

Your usage did not change. Your token economics did.

The short answer: a coding agent bills you for the entire conversation on every single turn, so cost grows with how long your sessions run, not how many messages you send. When a bill jumps without your habits changing, it is almost always one of three things. Your prompt cache stopped hitting, so context you used to pay 0.1x for is now billing at full input price. Your sessions got longer, so the same work resends a bigger transcript more times. Or an expensive model is doing work a cheaper one could have done, at five times the input rate and five times the output rate.

Those three causes are all measurable, and none of them show up in a monthly total. You need per-request numbers: model, input tokens, cache-read tokens, cache-write tokens, output tokens. Once you have those four token columns per call, the answer is usually obvious within about ten minutes of looking.

Cost scales with context, and context only ever grows

The Messages API is stateless. Every turn ships the full history back up: system prompt, tool definitions, every file the agent read, every diff it produced, every test output it looked at. Turn 40 in a session is not one message, it is turn 1 through turn 39 plus your new instruction. That is why a single long refactor session can cost more than a whole day of short, scoped ones.

Two things make this worse than it sounds. Output tokens are billed at five times the input rate on every current Claude model, and outputs become inputs on the next turn. And when a model reads a large file into context, it stays there. A 3000-line file read once at turn 5 is still being billed at turn 40, thirty-five more times, unless something clears it.

The current models take a 1M token context window. Bigger windows are useful and they also remove the wall that used to force you to start a fresh session. Nothing stops a long run from filling it now.

Broken prompt caching is the most common single cause

Prompt caching is what makes agentic coding affordable at all. A cache read costs roughly 0.1x the base input price; a cache write costs 1.25x for the five-minute TTL. Two requests against the same prefix already beat paying full price twice. When it works, most of your transcript bills at a tenth of list.

It is a prefix match on exact bytes. The prompt renders in a fixed order (tools, then system, then messages), and any byte that changes anywhere in the prefix invalidates everything after it. That is a sharp cliff, not a gradual degradation: a cache that was serving 90 percent of your tokens can go to serving zero because one string moved. Common culprits:

  • A timestamp or session ID interpolated into the system prompt. It changes every request, so nothing downstream ever matches.
  • Tools added, removed, or reordered mid-session. Tools render at position zero, so a changed tool list invalidates the whole request.
  • Switching models mid-session. Caches are scoped per model, so the new model starts cold.
  • Non-deterministic serialization, such as JSON dumped without sorted keys or a set iterated in arbitrary order.
  • Long single turns. A cache breakpoint looks back at most 20 content blocks, so a turn with 30 tool-call and tool-result pairs can silently miss the previous entry.
  • Idle gaps. The default cache TTL is five minutes. Come back from lunch and your first request pays full price plus a fresh write.

The diagnostic is one field. If cache_read_input_tokens is zero across repeated requests that share a prefix, caching is not working and you are paying list price on your entire transcript. Also worth knowing: input_tokens reports only the uncached remainder. If your agent ran for two hours and input_tokens says 4000, the rest went through cache. Add all three fields to get real prompt size.

Thinking and effort multiply whatever context you already have

On Claude Opus 5, thinking is on by default. Omitting the thinking parameter runs adaptive thinking; on Opus 4.8 and 4.7 the same omission meant no thinking at all. If you carried a request shape forward from an older model, you are now paying for reasoning tokens you did not previously buy, and max_tokens caps thinking plus response text together, so tight limits can truncate mid-answer.

Effort is the other lever. It runs low, medium, high, xhigh, max, and defaults to high. Higher effort means more thinking and more tool calls per turn. Opus 5 in particular is strong at low and medium, so an effort setting inherited from a previous model is frequently just spend with no quality return. Subagents compound this: each one re-establishes context, explores, reports back, and then the coordinator reads the report, so a task that fans out to six subagents can cost several times what the same task costs done directly.

How to find where the money actually went

  • Get per-request records, not daily totals. You want model, input, cache-read, cache-write, output, and which process made the call.
  • Sort by cost descending. In practice a handful of calls usually account for most of a bad day.
  • Check cache_read_input_tokens on the expensive ones. Zero means a cache miss, and cache misses are the cheapest problem to fix.
  • Check the model column. Look for the most expensive model handling file reads, greps, commit messages, and formatting.
  • Check output tokens against value delivered. Output bills at five times input, so a verbose narration habit shows up on the bill.
  • Compare cost per session against session length. If they track linearly and steeply, your sessions are simply too long.

Two free tools do the reading part well. ccusage parses Claude Code local JSONL logs and gives you a clean breakdown with no setup; claude-code-usage-monitor watches burn rate live. If all you need is an answer to what happened last Tuesday, either is a good first stop, and I would rather you use one of them than buy anything.

Reading the bill and changing the bill are different problems. Log readers do the first one very well. They cannot decline a call.

Where Probe0 fits

I built Probe0 because I kept diagnosing the same three causes and then having no way to act on them. It is a local proxy on your machine, not a hosted service, and there is no Probe0 server for your requests to travel to. You install one proxy and one certificate, and every coding agent CLI on the machine routes through it: Claude Code, Codex, Cursor. There is no per-tool configuration.

Recording gives you the ledger described above, including which process made each call, so you can tell an editor plugin apart from a terminal session. Model Tiering sends the cheap work to a cheap model first. Exact Cache and Semantic Cache stop identical and near-identical calls from going out twice; the semantic one keeps a strict similarity floor and refuses to match anything carrying tool calls, because a wrong hit there corrupts a run rather than just being wrong. Request Coalescing collapses simultaneous identical calls into one upstream. Local Routing sends work to a model already running in Ollama or LM Studio and retries weak answers on the cloud. Spend Guard sets a hard cap per run and per day: it warns, then pauses. Every module is switchable on its own and reports what it saved, so you can turn one on and judge it.

The honest limits: it is macOS only and in private beta. It is a single-developer tool, not a team gateway with multi-user auth and shared dashboards. Provider coverage is what coding agents actually call, not a catalog of a hundred providers. If you need team-wide governance or a hosted analytics product, look at the hosted gateways instead.

What I would change first

Before adding any tooling, three changes cost nothing. Keep the system prompt byte-stable and put anything dynamic later in the message list rather than in the prefix. Stop starting long sessions you do not need, and scope work so a session ends before it accumulates a transcript you will pay for on every subsequent turn. And set effort deliberately per kind of work rather than accepting the default everywhere, because the default is high and a lot of coding work does not need it.

If you do those and the bill is still surprising, the cause is in the per-request data. It always is.

Related