Lawrence Huibuilds AI · writes in public
01Home02Projects03Writings04About05Resume07Email
Essay24 July 2026 · 6 min read

One Claude Session Cost Me $1,880. It Was Reading Four Novels to Write One Tweet.

1.48 billion tokens in one week, 99.6% of them the model re-reading conversations I never closed. Transcript forensics, the cache math nobody does, and the fix that took my bill from $600 a day to $125. Compression tools would have saved almost nothing.

AI codingcostcontexttoolingClaude Code

On Monday I hit my Claude weekly limit with two days still on the clock. The week before that had been fine. Nothing about my workflow felt different, which is exactly the situation where you should stop guessing and go read the data.

Claude Code writes a full transcript of every session to ~/.claude/projects, one JSONL line per API message, each with a complete usage block: input tokens, cache writes, cache reads, output. Nobody looks at these files. They are the whole answer.

I wrote a script to aggregate them. Last week against the week before:

Prior week Spike week
Estimated cost (API-equivalent) $991 $4,199
Sessions 164 833
Cache writes 27M tokens 183M tokens
Cache reads 403M tokens 1.29B tokens

In absolute terms, the spike week pushed 1.48 billion tokens through the API. At roughly 100K tokens to a novel, the model read fifteen thousand novels' worth of context to assist one developer for one week. And 99.6% of those tokens were input: only 5.5M were the model actually saying anything. The rest was re-reading.

My first suspects were the background systems. I run a second-brain wiki that syncs through scheduled Sonnet calls, plus a memory plugin that observes every session with Haiku. Both are the kind of thing that sounds expensive. Together they were under 5% of the bill, and their share actually fell during the spike week. Tool output, the thing every compression startup wants to shrink for me, was a rounding error.

The real answer was four rows in the per-session breakdown. Four sessions, alive for 98 to 133 hours each, accounted for roughly $3,150 of the $4,199. One session, a social-media watch loop, cost $1,880 on its own. That is 45% of a week's usage from a single conversation. That one session processed about 400 million tokens to emit 384 thousand: a read-to-write ratio of a thousand to one. Per turn it read roughly 400K tokens, four novels, to produce 470 tokens, one long tweet.

The mechanics of a marathon session

Nothing about those sessions looked expensive from the inside. Each individual message was ordinary. The cost hides in two compounding mechanics.

First, context accumulation. A conversation is an append-only log, and the model re-reads all of it on every turn. The watch-loop session averaged 400K tokens of context per API call by the end. At that size, even a turn that says "nothing new, checking again" pays for the entire history. Late-session turns cost more than a dollar each. The output of those turns averaged 470 tokens. I was paying for a novel to receive a sentence.

Second, cache churn. Anthropic's prompt cache makes re-read context cheap, at a tenth of input price, but the cache has a TTL. My usage is bursty. I work from my phone through remote-control sessions, so a session gets a flurry of turns, then hours of silence. Every silence longer than the TTL evicts the cache, and the next turn re-writes the full context at cache-write pricing, which is the most expensive token class there is. That one session logged 72.7M tokens of cache writes. Its context was rewritten to cache, in full, dozens of times.

You can see this signature directly in the data without reading a single transcript: the ratio of cache reads to cache writes. Mine fell from 17:1 in a normal week to 7:1 in the spike week. A falling ratio means contexts are being rebuilt instead of served.

There was also a third finding worth naming because I suspect others are making it right now. The watch loop ran on an in-session scheduler: a recurring job created inside a live session that re-fires a prompt every hour. Those jobs execute inside the session that created them. Every firing appends to the same conversation. An hourly schedule inside a session is a machine for manufacturing exactly the 400K-token context that empties your limit.

Why I didn't reach for compression

I wrote about the token-compression tool landscape last month, and I maintain one of those tools myself. So the obvious move was to deploy compression. The data said no. Headroom, the most mature tool in that space, claims 15-20% savings on coding agents by shrinking tool outputs and JSON. My tool outputs were noise. Over 80% of the spike was conversation history being re-read and re-cached. You cannot compress your way out of a conversation you refuse to end.

The correct unit of optimization is the session lifetime.

The fix: handoff, kill, cold start

The reason I never closed those sessions is that closing one felt like losing state. The conversation held the decisions, the open items, the context. So the fix is to make state survive death, then kill freely.

  1. Handoff notes. A session that has finished a work chunk writes HANDOFF-<date>.md to the repo: status, decisions with reasons, open items, next step. For the sessions already dead, I generated the notes from their transcripts with a digest script and a single Haiku call each. Cost: about a penny per project.

  2. Auto-injection. A SessionStart hook finds the newest handoff in the project and injects it into every fresh session's context. It also fires on /clear, which turns /clear into a one-keystroke reset: same session, same phone thread, context drops from hundreds of thousands of tokens to about fifteen thousand, and the handoff is already loaded.

  3. A ceiling for the sessions I forget. "autoCompactWindow": 200000 in settings caps any neglected session at 200K before auto-compaction, instead of letting it ride toward the model's full window. On a 1M-context model the default ceiling is not your friend.

  4. Daily recycling for always-on sessions. The phone workflow needs sessions alive around the clock, so each project now lives in a named tmux session, and a launchd job at 4am digests yesterday's transcript, writes a fresh handoff, kills the session, and respawns it clean with a morning briefing. Same reachability, one-day-old context at worst.

The watch loop itself became the degenerate case: it should never have been a persistent conversation at all. It is now a state file on disk and a fresh scan-and-draft session I trigger on demand. Each run costs pennies against the $300 per day the loop version averaged.

The tooling

The audit script and the handoff machinery are now a small open-source Claude Code plugin called debloat: /usage-audit tells you where your usage went and flags marathon sessions, /handoff writes the note, the hook loads it back, and the always-on recycling recipe is in the docs. The audit runs entirely on your local transcripts. No network, no API key, thirty seconds to find out whether you have a $1,880 session of your own.

Numbers to close on. The spike week averaged $600 a day with a $1,639 peak. The first full day after the fix, under a comparable workload, came to $125, below my pre-incident baseline. Per turn, late in the marathon: over $1. Per turn after the reset, same project, same work: about five cents. The model did not get cheaper. The conversation got shorter.