The cache is 96% efficient across all my tokens and 86% in the session you are sitting in
Two widely shared posts disagree about whether your CLAUDE.md should grow or shrink, and neither of them is arguing about cost. I went looking for the cost answer in my own data: 63,880 billed Claude Code API requests, 3,031 transcripts, one month. The aggregate cache hit rate is 96.59%. The median session is 86.41%. That gap is the whole story, and it is not a rounding difference.
TL;DR - cache reads cost 0.1x base input, writes cost 2x, and Claude Code writes 100% of them on the 2x tier. Weighted across every token I was billed for, reads dominate. Inside a typical session, writes carry 76% of the cache-input cost. Compressing your CLAUDE.md moves neither number, and no field in the transcript can tell you what your file costs.
Where the numbers come from
Every Claude Code turn writes a usage block into a session transcript under ~/.claude/projects/. Four fields carry the money:
| Field | What it is | Multiplier | Opus 5 list |
|---|---|---|---|
cache_read_input_tokens | prefix served from cache | 0.1x | $0.50 / MTok |
cache_creation_input_tokens | prefix written to cache | 1.25x or 2x | $6.25 or $10 / MTok |
input_tokens | never cached, full price | 1x | $5 / MTok |
output_tokens | what the model generated | 5x | $25 / MTok |
Multipliers and prices read off Anthropic's prompt caching docs on 2026-08-30. Those four ratios are identical for every model in Anthropic's published table, from Haiku 3.5 to Fable 5, which is why I can weight a mixed-model corpus without knowing which model served which request.
Every aggregate figure in this post comes from one run of one script at 2026-08-30 01:57 ICT, on Claude Code 2.1.251. The two worked examples further down are direct reads of individual transcript records, and the benchmark numbers I quote from other people are theirs; everything else is that single run. That distinction matters more than it sounds. Five Claude sessions were writing to this corpus while I measured it, so a table assembled from runs taken twenty minutes apart is a table of two different corpora, and I built one of those before an external reviewer caught it. The population is 63,880 billed API requests, messages timestamped 2026-07-30 to 2026-08-29, mostly Opus 5 at 70.5% of requests, then Sonnet 5 at 10.4%, Haiku 4.5 at 7.0%, Opus 4.7 at 6.7% and Fable 5 at 5.0%.
Three file counts appear in this post and they are three different things, so here they are together rather than scattered: 3,081 .jsonl files exist under ~/.claude/projects; 3,031 of them contain at least one usage block; 3,030 of those contain at least one input token, which is the set the per-session distribution runs over. The gaps are empty and aborted sessions. A post that keeps insisting on denominators should not make you hunt for its own.
cache read 17,806,573,770
cache create 627,959,582 (1h tier 627,969,243 / 5m tier 0)
uncached input 751,304
output 57,418,061
Cache-served share of input tokens = read / (read + create + uncached) = 96.59%.
Add those two cache-write figures up and they do not agree, which a reader is entitled to notice in a post about arithmetic. The 1-hour tier reads 9,661 tokens larger than the scalar it is supposedly a subset of. That is one record out of 63,880: a multi-iteration message where cache_creation_input_tokens reads 0 while the cache_creation dict reads 9,661. It is 0.0015% of the writes and moves nothing at this scale, but the scalar and the dict genuinely disagree on that row, and since this post is about to tell you to trust the dict over the scalar, it would be poor form to quietly reconcile them. Every percentage here uses the scalar for the total and the dict for the tier split, which is why the tier split is the more reliable of the two.
Two other sessions recomputed this independently the same night, from the same raw transcripts but with different scripts and different aggregation rules, and got 96.5% and 96.51% against my 96.59%. Be precise about what that shows: the corpus was being written to the whole time, so those are three measurements of a moving target, taken at three moments, with three toolchains, landing inside 0.09 points. It says the quantity is stable. It is not three people checking each other's arithmetic.
I had a 97.8% figure on file from a week earlier and it does not reproduce. It was not invented. It was a subset presented as a corpus: main-session transcripts only, last seven days. Restrict my own corpus to main sessions and it climbs to 97.16%, and narrowing the window takes it the rest of the way. That is a more useful result than a refutation, because the same defect turns up three more times below, twice in my own instrument.
Transcript records are not API requests
You cannot sum the usage blocks in a transcript. I mean that literally, and it is the first thing that goes wrong.
Claude Code writes one transcript record per content block. A turn that thinks, writes a sentence and calls two tools produces four records, chained by parentUuid, and every one carries the full usage block for the single API request behind them:
msg_011CeBgf7aRm9YY1p9UAbaSx -> 4 records
blocks=['thinking'] read=0 create=88,611
blocks=['text'] read=0 create=88,611
blocks=['tool_use'] read=0 create=88,611
blocks=['tool_use'] read=0 create=88,611
88,611 tokens, billed once, written down four times. Across the corpus that is 136,003 records for 63,880 real requests: 2.13x. It is not a clean scale factor either, because the inflation is not uniform. Turns with many tool calls duplicate more than turns that only talk, and those are not the same turns in cache terms. Sum records instead of requests and the ratio itself moves, 96.59% down to 95.88%.
Deduplicating on message.id is safe for the cache fields, and I checked rather than assuming: across 72,123 repeated ids, zero carry a conflicting cache_read, cache_creation or input_tokens value.
output_tokens is a different story, and it cost me a number. 15,616 of those repeated ids carry a larger output count on a later record than on the first one, with the cache fields byte-identical:
msg_011CeXXEpy9ivbUiyW6QnapY
read=14,779 create=72,333 fresh=2 out=1 iterations=0 <- preliminary
read=14,779 create=72,333 fresh=2 out=151 iterations=1 <- final
A first-wins dedup keeps the preliminary record and throws away the real output count. Mine did, on the first pass, and it undercounted my output tokens by 36%, which moved output's share of the total bill from 8.6% down to 6.5%. Keep the largest.
This is not new, which I only found out afterwards. ArkNill's Claude Code bug analysis filed it in April 2026 as Bug 8, described as preliminary and final entries carrying identical cache_read_input_tokens and cache_creation_input_tokens, measured across 532 transcript files at 2.37x average inflation and 4.42x worst case. That is exactly the pattern above, and it is still open as issue #41346.
The second instrument bug is smaller, and it is the reason I nearly missed the first. The obvious glob for these files, ~/.claude/projects/*/*.jsonl, is not recursive. It sees 1,702 of 3,081 files, or 55.2%, and what it misses sits two levels deeper, where subagent transcripts live. Every one of those 15,616 preliminary records is in a subagent transcript, so my first duplicate check ran on the non-recursive glob, found zero conflicts, and told me the coast was clear. Two of the three sessions measuring this hit the same glob.
A subset presented as a corpus, four times now, in four disguises. That is the failure mode of this whole topic, and it is why the number matters less than the denominator printed next to it.
Every cache write bills at 2x, not 1.25x
This is the part I got wrong the first time, in a note other people were reading.
A cache entry has a lifetime and the lifetime sets the write price. Anthropic charges 1.25x base input for a five-minute entry and 2x for a one-hour one. Almost everything published about Claude Code cost assumes 1.25x, mine included, because five minutes is the documented API default.
cache_creation_input_tokens is a single number and cannot tell you which tier you paid for. The dict beside it, message.usage.cache_creation, can:
ephemeral_5m_input_tokens 0
ephemeral_1h_input_tokens 627,969,243
Every cache write in the corpus is on the one-hour tier. Not most of them. All. What that does to the effective input bill, same raw counts, two weightings:
| Weighting | Cache reads | Cache writes |
|---|---|---|
| Writes at 1.25x, the common assumption | 69.4% | 30.6% |
| Writes at 2x, what actually bills | 58.6% | 41.3% |
The write share is understated by 35.2% relative when you assume the wrong tier. That percentage is of the input bill; on the total bill including output it comes out differently, and quietly swapping the two is its own small industry. One plausible unchecked constant, and a cost model looks exactly like a measured one while being wrong.
Two qualifiers, because this is a default and not a law of physics. Claude Code 2.1.243 added promptCacheTtl and subagentPromptCacheTtl settings, so API-key and cloud-provider users can run the main conversation on a one-hour cache while subagents sit at five minutes. Neither setting appears anywhere in my configuration, checked 2026-08-30, so what I measured is default behaviour. Set promptCacheTtl to five minutes and you pay 1.25x and the whole split above moves. Separately, ArkNill documented a bug where DISABLE_TELEMETRY=1 silently downgraded the cache from the 1h tier to 5m, fixed in v2.1.108 and community-verified, which is worth knowing if you are reading a measurement taken before April 2026.
And a consequence worth more than the arithmetic. A one-hour cache entry does not expire while you make coffee. If you have read anywhere that a five-minute break costs you a rebuild, including in my own post on the caching mechanics, that advice was written against the API default rather than against what Claude Code actually does.
cache_creation_input_tokens cannot distinguish a 1.25x write from a 2x one. If a cost breakdown does not say which dict field it read, it assumed one.
The aggregate belongs to 25 sessions
Here is the finding I did not go looking for.
96.59% is token-weighted. It answers "across every token I was billed for, what share was a cache read". That is a legitimate question and it is not the question you are living in. Per session, the same corpus looks like this:
| Cache-served share of input tokens | Value |
|---|---|
| Token-weighted across all sessions | 96.59% |
| Median session | 86.41% |
| 25th percentile session | 76.33% |
| 75th percentile session | 92.60% |
| Sessions at or above 95% | 426 of 3,030, or 14.1% |
The two diverge for one reason: the top 25 of 3,030 sessions, 0.8% of them, carry half of all my input tokens. Long sessions have excellent hit rates and they dominate any token-weighted average. The session you are actually sitting in, on a median day, does not.
That inverts the cost picture rather than softening it. Cost per input token at a hit rate h is h x 0.1 + (1 - h) x 2.0, counting cache input only and leaving output out of it:
| Hit rate | Cost per input token | Writes as share of cache-input cost |
|---|---|---|
| 96.59% (token-weighted) | 0.165 | 41.4% |
| 86.41% (median session) | 0.358 | 75.9% |
| 76.33% (p25 session) | 0.550 | 86.1% |
In the aggregate, reads carry it. In a typical session, writes carry three quarters, and the median session costs 2.17x per input token what the aggregate suggests. Both columns are cache input only. Fold output back in and the shares move again, which is the point of saying which bill you mean every time.
The same shape shows up in somebody else's instrument. ArkNill ran a proxy between Claude Code and the API, logging the cache fields off each response rather than reading transcripts, and reported 86.4% overall cache read alongside 95 to 99.8% for stable sessions in the same table. Be careful with that, because this article is partly about numbers quoted past their scope: it is a benchmark of 7 scripted scenarios on v2.1.90 in April 2026, not a corpus, and the figures are not comparable to mine. What transfers is the shape. Measure whole sessions including their cold start and you land in the eighties; measure the warm middle and you land in the high nineties. Two instruments, same split.
So if you have ever compared a published cache-efficiency figure against your own usage and felt they disagreed, this is probably why. The published figures are token-weighted, or measured on the warm part. Your bill is a pile of ordinary sessions with cold starts in them.
What this cannot tell you about your CLAUDE.md
Now the part I have to state before anyone quotes the rest back at me.
cache_creation_input_tokens reports how many tokens were written. It never reports which ones. No field anywhere in the transcript attributes a cache write to your CLAUDE.md rather than to the system prompt, the tool definitions, an MCP server's schemas, or the growing conversation. I re-read the whole usage schema looking for one.
Every number on this page would be identical if every CLAUDE.md on my machine were empty. That is not a flaw in the measurement, it is the boundary of it, and it means "what does my CLAUDE.md cost" is not answerable from this data by me or by anyone.
Three sessions measured the always-loaded prefix's share of session cost the same night, carefully, in parallel:
26.4% 31.7% 64.8%
Three defensible methods, a 2.5x spread, no agreement. The 64.8% is mine, and it runs high because I could only measure sessions containing an observable cold cache build, which skews short. The others picked different denominators. Nobody was careless. The quantity is simply not pinned down by the fields on offer, and in a post that has spent four sections on denominators I will not print a percentage whose denominator I cannot define.
The API does have a surface that would answer it. The cache-diagnosis-2026-04-07 beta returns a diagnostics object on the response. Claude Code does not write it to the transcript, so it is out of reach from the outside.
What survives, and it is enough to answer the original question:
- Your CLAUDE.md sits in the static prefix. That is documented mechanism, not something I measured.
- 98.26% of my requests carry a non-zero
cache_read_input_tokens, so on almost every turn that prefix is being served from cache at 0.1x rather than rebuilt. That is a statement about requests, not about how many of the tokens on any given request were prefix. - The expensive half of the bill is cache writes, and what drives writes is cache stability, not file length. Switching models mid-session, changing your tool set, and
/clearall force rebuilds. A long file does not.
So compressing CLAUDE.md aims at the cheap side of a price pair, and the thing that would actually move your bill sits on a different axis. I cannot tell you the size of the saving, and neither can anyone who has published a figure for it.
Subagents are the expensive cache citizens
Splitting the same corpus by whether a request came from a main session or a subagent sidechain:
| Billed requests | Cache-served | Writes as share of input bill | |
|---|---|---|---|
| Main sessions | 43,793 | 97.16% | 36.9% |
| Subagent sidechains | 20,087 | 92.65% | 61.3% |
A subagent spends most of its bill writing cache rather than reading it. That follows from what a subagent is: a fresh context that pays for its own prefix and then does one short piece of work, so it never amortises the write the way a long session does. Nearly two thirds of a sidechain's input cost is setup.
Both populations bill at the same 2x multiplier here, since neither TTL setting is configured on this machine, so the gap is a real difference in cache behaviour rather than an artefact of mixed pricing.
Which makes the useful lever fan-out width, not file length. Three small subagents each pay a full prefix write. One medium subagent pays it once. I already bundle related lookups into a single agent for context reasons, and the cache arithmetic points the same way from the money side.
Both named posts, read properly
Two posts get cited whenever this comes up, on opposite sides. I opened both, and neither is arguing about cost.
Tyler Folkman's "Your CLAUDE.md should grow, not shrink", 2025-10-12, is an accuracy argument. His case is a context that collapsed from 18,282 tokens to 122 with accuracy falling from 66.7% to 57.1%, and he argues for appending itemised entries instead of letting the model rewrite the file. Nothing I measured touches that claim. Most of the post sits behind a paywall, so the introduction is all I read and all I will characterise.
Johnathen Chilcher's "Compress Your CLAUDE.md", 2026-02-24, is signal-to-noise, not money either. Then he did the thing almost nobody does: he built a benchmark against his own advice and published the retraction. 540 runs in phase one, 1,188 across both phases. His own accounting of how his claims held up:
- "60-70% character reduction" came out as 5-13% actual token savings in API calls. His words: "You're saving 60% of a small slice, not 60% of the whole pie."
- "Claude doesn't need markdown decoration" was wrong for smaller models. Compressed instructions scored lower for Haiku and Sonnet. Only Opus was indifferent.
- The large-compressed profile triggered a significant 18.8% quality drop on a bug-fix task, p=0.018.
- An empty CLAUDE.md scored highest overall at 92.15 composite, and across his ten profiles token count correlated with quality at r = -0.95.
- His cost verdict: "at typical API rates, that's cents per run, not dollars."
So one side of this argument conceded, with data, six months ago. I am not refereeing a live fight. I turned up after it ended and measured the thing neither side reached for.
Two qualifiers on that benchmark, both dropped every time it gets cited. Instructions did help where the model was weak: his workflow profile gave Opus +5.80 on instruction-following tasks and lifted its worst run from 61.4 to 83.5. "Guardrails, not boosters" is his phrase, and raising a floor is worth something even when the average does not move. And it ran on Haiku 4.5, Sonnet 4.6 and Opus 4.6 in March 2026. If you are on Opus 5, that is a different model family and nobody has re-run it.
What I do with mine
I keep a long always-loaded surface: 102,912 bytes over 1,432 lines across 18 files, project and global combined, measured 2026-08-30. I have deliberately not converted that to tokens, because I have no tokenizer count for it and a bytes-per-token guess is exactly the kind of number this post is arguing against. I am not trimming it for cost, and I would not have trimmed it for cost before I measured any of this.
What I actually do:
- Trim for attention, on a schedule, never for the bill. Stale beats long. A rule describing behaviour the model no longer has is worse than no rule, and it costs exactly the same to carry. I have written up rules that quietly expired when the model changed underneath them, and what happens when instructions pile up until nothing is load-bearing.
- Protect cache stability instead of file length. One model per session, tool set decided up front, compaction rather than
/clear. Those move the 41.3% side of the bill, and they are the only things here that touch a typical session's 76%. - Bundle subagent work. 92.65% against 97.16% is the price of a fresh prefix, paid per spawn.
- Push detail out of the always-loaded layer and behind a lookup. Not to save tokens. So that what stays loaded is short enough to still mean something, which is a knowledge-architecture question rather than a cost one, and it pairs with the patterns I keep in CLAUDE.md patterns and the rules layer.
- Re-derive the number before quoting it. The one I was carrying was a week old, drawn from six sessions, and off by more than a point. Provenance is not verification.
If you want the mechanics, the prefix-matching rules and the things that silently break your cache are in the caching post. One level up, context management covers what to load and when.
Run it on your own transcripts. The fields are in ~/.claude/projects/**/*.jsonl and the measurement is four sums. Walk the directory recursively, deduplicate on message.id, keep the largest output_tokens for each id, read cache_creation rather than the scalar next to it, and report the per-session distribution alongside the aggregate. Skip any one of those five and you get a confident number that is wrong in the direction you were hoping for, which is how a fair share of my worst Claude Code failures have started, and part of why the tool can feel like it got worse when what actually changed was the measurement.
The full setup this came out of is in the guide.


![Claude Code Hooks Fail in Runs: 76% vs 18% [2026]](/_next/image?url=%2Fblog%2Fclaude-code-hooks-fail-in-runs-hero.webp&w=3840&q=75)
