Skip to content
ahian-leePublic

About

Measure replay, idle-cache, re-read, and retry waste in Claude Code transcripts

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

Repository files navigation

looptax

Measure the agent loop's invisible taxes — from transcripts you already have.

Coding agents re-send their entire conversation on every model call. Prompt caching makes that affordable — until it silently doesn't: caches expire while you grab lunch, compacted context gets re-read back in, the same file is re-fetched twenty times, and your usage limits drain in ways no dashboard explains (anthropics/claude-code#16157, #38335 — thousands of users report drain they cannot attribute).

looptax is an offline analyzer that reads agent transcripts (Claude Code session JSONL) and quantifies four cost mechanisms that no accounting tool reports:

Tax Question it answers
Replay What share of everything the model processed was re-sent history? How many times was the average token (re)processed?
Idle How much did resuming sessions after cache TTL expiry cost, versus the counterfactual where the cache survived?
Amnesia How many tokens were spent re-reading files the context already had — including content thrown away by compaction?
Retry How often did mid-session API errors force re-processing?

Zero API calls, zero cost, local-only: it parses files on your disk and never uploads anything.

Findings (author's corpus)

Snapshot from 2026-07-27: 95 real Claude Code transcript files (87 conversation streams, 2,444 API requests, ~308M processed input tokens). Reproduce the method with one command against your own transcripts — see Usage.

  1. 96.2% of all input tokens the model processed were re-sent cached content. Only ~0.01% of processed input was genuinely new (uncached) text. The agent loop processed ~34x more input than the peak context size — i.e. the average context token was paid for (mostly at the cheap cache-read rate) roughly thirty-four times.
  2. The loop reads ~250 input tokens for every token it writes (input:output = 252:1). Agent cost intuition built on chat usage ("output is what's expensive") inverts: at this ratio, input-side handling — cache hygiene, context size — dominates spend.
  3. 1.3% of requests caused 22% of all cache writes. Requests that resumed a session after a 5-minute-to-1-hour idle gap (31 of 2,444) accounted for over a fifth of total cache-write volume — the single most concentrated waste mechanism found, and one no per-request dashboard surfaces.
  4. 9.5% of file Reads were redundant re-reads of a file already read in the same conversation.

Numbers above are from looptax report --format md on the author's machine (single-user corpus; see Limitations).

Install

pip install "git+https://github.com/ahian-lee/looptax.git"

Or from source:

git clone https://github.com/ahian-lee/looptax
cd looptax
pip install .

Usage

# Analyze your entire Claude Code history (~/.claude/projects)
looptax report

# Analyze specific files or directories
looptax report path/to/session.jsonl path/to/project-dir

# Machine-readable / markdown output
looptax report --format json
looptax report --format md

Sample output (truncated):

looptax report
============================================================
corpus: 95 files, 87 streams, 2444 requests (3039 duplicate records ignored)

[1] replay tax - history re-transmission
    input processed               307,772,990 tokens
      cache reads                 295,925,133  (96.2%)
    ...

How it measures

  • Usage comes from provider-reported fields, not tokenizer guesses: every request's input_tokens, cache_read_input_tokens, and cache_creation_input_tokens (with the 5m/1h TTL split) are read from the transcript. Requests split across multiple JSONL records are deduplicated by request id — usage counted once, tool calls collected from all records.
  • Idle tax classifies each request by the gap since the previous request in the same conversation stream (<5m / 5m–1h / ≥1h). Cache writes after a ≥5m gap are candidate TTL-expiry rewrites; the primary estimate is capped at the previous request's cached footprint (only content demonstrably in cache can have expired), with the uncapped number reported as an upper bound. The counterfactual prices those tokens at the 0.1x cache-read rate instead of the 1.25x/2x write premium.
  • Amnesia tax detects repeat Read calls per file per stream and sizes the waste from the repeat reads' actual tool_result payloads (chars/4, labeled an estimate). Compaction ROI is only reported when the corpus contains compaction events — zero events is reported as no data, never as "no waste".
  • Costs use a dated Anthropic price snapshot with documented cache multipliers (read 0.1x, 5m write 1.25x, 1h write 2.0x). Tokens from models the snapshot cannot price are surfaced as a warning — never silently costed at $0.

What looptax is not

The tracking layer is well served; use these tools for it, not looptax:

  • ccusage and CodeBurn — daily/session cost accounting across agent CLIs (how much you spent).
  • llmprof and contextspy — live proxies that decompose the context window of traffic you route through them.
  • tokenscope — per-session context treemaps for Claude Code.

looptax is the measurement layer: it answers why the spend happened — mechanisms (TTL expiry, re-transmission, re-reads) that only appear when you analyze whole conversations offline, across their real timestamps — and ships with a reproducible method and corpus-level findings rather than only code.

Limitations

  • Findings above are a single-user corpus (n=1, 95 files). They are the first published data point for these mechanisms, not a population estimate. Run it on your own corpus; if you'd like to contribute anonymized aggregate numbers (the JSON report contains no message content), open an issue.
  • Dollar totals are API-equivalent estimates at dated Anthropic list prices, not the amount a Claude Pro/Max subscriber was billed. Provider, geography, negotiated discounts, and temporary promotions can change actual spend.
  • The idle-tax estimate cannot distinguish TTL expiry from harness-side prefix invalidation; the cap against the prior cached footprint bounds, but does not eliminate, attribution error. Both bounds are always shown.
  • Re-read waste uses a chars/4 token approximation (provider tokenizers are not public); usage-field metrics (replay, idle) do not use approximations.
  • Compaction ROI requires a corpus containing compaction events; current Claude Code versions summarize without emitting compact_boundary markers, so this chapter reports honestly when it has no data.
  • One ingest format today (Claude Code JSONL). The ingest/ package is adapter-structured; SWE-agent/OpenHands trajectory support is the next milestone.

Development

pip install -e ".[dev]"
pytest

Test names state the failure they prevent (e.g. test_idle_estimate_capped_by_previously_cached_footprint, test_unknown_model_not_silently_priced_at_zero) — the test suite is specifically hostile to bugs that would make results look better than reality.

License

MIT

About

Measure replay, idle-cache, re-read, and retry waste in Claude Code transcripts

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages