DEV Community

Marcus Maciel
Marcus Maciel

Posted on

I Parsed My Local Claude Code JSONL Logs to Find Out Why My Token Quota Evaporates So Fast

If you use Claude Code daily, you have probably experienced at least one of these two moments:

  1. On a Pro or Max subscription: Your 5-hour usage window suddenly hits the limit after 45 minutes of what felt like normal coding.
  2. On API billing: You pause for 6 minutes to grab coffee or review a diff, type "looks good, commit it", and that single 4-word prompt quietly costs $1.40.

I wanted to know where the tokens were actually going. Since Claude Code stores raw session transcripts locally as .jsonl files inside ~/.claude/projects, I wrote a parser to inspect every turn, tool call, subagent spawn, and cache event across my sessions.

What I found completely changed how I use Claude Code, and led me to build an open-source, in-process plugin to stop the leaks automatically.

Here are the 3 silent token killers hiding in your .jsonl logs, and how you can audit your own machine in 30 seconds.

Killer #1: The 5-Minute Prompt-Cache Cliff

Anthropic's prompt caching is the only reason large context windows (200k to 500k tokens) are affordable. When your prompt cache is warm, reading your existing conversation prefix costs 0.10x (a 90% discount).

Look at what happens to a 300,000-token context on Claude Opus 4.6 when that cache expires:

Turn State Token Multiplier Cost of 1 Turn (300k ctx)
Warm Cache Read (cache_read_input_tokens) 0.10x $0.45
Cold 5m Cache Rewrite (cache_creation_input_tokens) 1.25x $5.63
Cold 1h Cache Rewrite (cache_creation_input_tokens) 2.00x $9.00

Here is the catch most developers miss:

  • Stepping away past the TTL: On standard API keys (and subagents), the cache TTL is 5 minutes (60 minutes on subscriptions). If your context is at 300k tokens and you pause for 6 minutes to test your app in the browser, your very next prompt forces a 100% full cache rewrite at 12.5x the warm-read price.
  • The opusplan / Model-Switch Trap: Prompt caches are strictly isolated per model. If you build a 250k context in Opus and switch to Sonnet mid-session (or use opusplan), the new model starts with a completely cold cache and pays the full creation fee for your entire history.

Killer #2: The Turn-5 "Compound Interest" Effect

Claude is stateless. Every single turn re-sends the entire conversation history up to that point.

That means a noisy tool output at Turn 5 is not a one-time expense. You pay for it again at Turn 6, Turn 7, Turn 8, all the way to Turn 45:

  • Reading package-lock.json or pnpm-lock.yaml once: +40,000 tokens re-read on every future turn.
  • Running vitest or pytest where 280 passing tests print above 1 failure: +9,000 tokens of green checkmarks permanently sitting in your prefix.
  • Calling an unpaginated MCP server (like GitHub MCP or a docs server) that dumps a 15,000-token raw JSON blob into the chat.

Killer #3: Fixed Overhead Before You Even Type "Hello"

Even on Turn 1, your context isn't empty. Every installed MCP server injects its full JSON schema and tool descriptions into the system prompt, alongside your CLAUDE.md files and engine reminders. If you have 6 MCP servers enabled and a 400-line CLAUDE.md, you are paying a heavy fixed tax on every single session.

How I Fixed It: Meet CATO (Claude Adaptive Token Optimizer)

Existing tools only solved parts of the puzzle: ccusage gives great post-mortem tables after your money is gone, and RTK compresses bash output via an external CLI wrapper.

I wanted something that runs 100% inside Claude Code's native process (zero Python, zero external processes per hook, zero network calls, zero telemetry) and protects the entire session lifecycle.

So I built CATO:

GitHub logo marcusaguiarmaciel-cmd / cato-plugin

Cut Claude Code token costs by 35-80% with prompt-cache TTL tracking, pre-read structural indexing, noisy CLI pruning, and multi-session subagent ledger. Zero Python, 100% local.

CATO: Claude Adaptive Token Optimizer

XERJ Corpus Hub contributor Sponsor CATO Release Claude Code Tests

Português

A Claude Code plugin that cuts token cost with context and prompt-cache control, automatic compaction, compression of noisy output and efficient code navigation. It runs entirely inside Claude Code, with no Python and no external process per hook, and integrates with Serena, Graphify, ast-grep and GitHub MCP.

100% Local & Offline: Zero network calls, zero telemetry, and zero external npm dependencies.

CATO /cato and /cato-doctor terminal preview

Quick Start (30-Second Cost & Cache Audit)

Requires Claude Code 2.1.290 or newer (claude update).

  1. Install CATO:
    /plugin install cato --marketplace marcusaguiarmaciel-cmd/cato-plugin
    
  2. Audit your past sessions (instant, read-only):
    /cato-import
    /cato
    
    Reads your existing local .jsonl transcripts and shows your real 30-day token spend, cache misses by cause (idle TTL expiration, model switches, subagents), and context-band breakdown.
  3. Check your setup for token leaks:
    /cato-doctor
    

Language

Reports, warnings and the status line come in English, Portuguese or Spanish. CATO picks the language…




(If you're reading this on your phone or want to test it on your machine later, **drop a ⭐ Star on the GitHub card above* to bookmark it. It also really helps other Claude Code devs discover the project!)*

What CATO Does Automatically

  1. 30-Second Retroactive Audit (/cato-import + /cato):
    Right after installing, run /cato-import. It scans your historical .jsonl transcripts in ~/.claude/projects (without double-counting forked sessions) and breaks down your real cost, context bands (<100k to >400k), and every cache miss by exact cause (idle pauses past TTL, model switches, post-compaction rebuilds, and subagent misses). If you also use RTK, CATO automatically pulls and includes your rtk gain savings.

  2. Live Cache Countdown & Expensive-Prompt Guard:
    Displays your live context size, next-turn dollar cost, and a countdown timer until your prompt cache expires right in the status bar. If your cache expired while your context is huge and rewriting it would cost >= $1.00, CATO holds your prompt once and shows you the exact cost of continuing vs. running /compact or /clear. (Send again and it goes right through).

  3. BM25 Sandbox for Huge MCP Responses:
    When an MCP server returns more than 6,000 tokens, CATO intercepts it, indexes it locally into ~/.cato/sandbox/#sbx_xxxxxxxx using an in-memory BM25 ranker, and gives Claude a compact head/tail preview plus a local search_sandbox tool.

  4. Git-Aware Heavy Read Blocking & Shell Compression:
    Blocks accidental reads of lockfiles, minified bundles, and node_modules/dist/build (checking git check-ignore first so tracked folders like src/build/ are never blocked), and compresses noisy test/linter output while keeping 100% of error lines.

  5. PageRank Repo Map & /cato-doctor:
    Builds a symbol dependency map ranked by Personalized PageRank + TF-IDF (mcp__cato__repo_map), integrates with Serena MCP, Graphify, ast-grep, and GitHub MCP, and includes /cato-doctor to flag CLAUDE.md bloat and TTL mismatches.

Try the 30-Second Audit on Your Machine

If you have Claude Code >= 2.1.290, run these commands inside Claude Code:

/plugin marketplace add marcusaguiarmaciel-cmd/cato-plugin
/plugin install cato@cato
/reload-plugins
/cato-import
/cato
/cato-doctor
Enter fullscreen mode Exit fullscreen mode

And if you want a clean, privacy-safe summary of your last 30 days (with zero project names or file paths), run /cato-share:

⚡ CATO · Token & Cache Audit (30d)
────────────────────────────────────
  • Actual cost: $0.98 across 23 calls
  • Context: avg 84.5k · max 98.7k
  • Cache misses: 0× ($0.00) · 0× pause · 0× model
  • CATO saved: 0 tokens (≈ $0.00) · 0 prompts held
  • github.com/marcusaguiarmaciel-cmd/cato-plugin
Enter fullscreen mode Exit fullscreen mode

Let's Compare Notes! 👇

Run /cato-import and /cato-share on your machine and paste your 30-day audit block in the comments below (or in our GitHub Community Showcase thread). I'm super curious to see what your Idle vs. Model-Switch cache miss ratio looks like!

And if you find CATO useful, leaving a ⭐ on marcusaguiarmaciel-cmd/cato-plugin means the world and helps keep this project growing. ❤️

Top comments (0)