Skip to main content

kvleak

Find out where your AI coding agent leaks prompt-cache money, and how to stop it. · 中文

CI PyPI Python Dependencies License

A 99.0% cache hit rate, and the session still leaked $82. On Claude Fable 5.1 one cache miss costs as much as 80 hits. In a 30-day audit of real Claude Code use, 2% of calls carried more than half of all uncached input. See the numbers →

Your agent probably reports a 90%+ cache hit rate, and you are still overpaying. A cache miss costs about 12× more than a hit, and the misses are rare but huge. They come from idle gaps that outlive the 5-minute TTL, from model switches, and from subagents that start cold. In real audits, about 5% of calls burn about half of all uncached input.

kvleak reads the transcripts that are already on your disk, finds every expensive miss, says why it happened, and puts a dollar figure on it.

uvx kvleak          # or: pipx run kvleak  ·  pip install kvleak

No API key, no config, no network calls, no dependencies. It reads ~/.claude/projects by default and any JSONL with token usage via --path.

 kvleak · prompt-cache leak report
 14 sessions + 18 subagents · 1,594 model calls · 10.0k min miss size

  Cache hit rate    92.1%  ██████████████████████
  Input spend       $145.09   caching already saved you $791.64
  Leaked to misses   $69.54   47.9% of input spend went to cache rebuilds and cold starts
  Recoverable        $27.00   with break-even-capped keep-alive pings alone

 Where the leak comes from
  cause                            misses  uncached    leak  share
  Idle gap outlived the cache TTL      48     10.0M  $38.40  55.2%  ████████▊
  Model switched mid-session           21      5.2M  $18.34  26.4%  ████▏
  Prefix changed within the TTL        16      2.6M  $11.14  16.0%  ██▌
  New session cold start               14      336k   $1.61   2.3%  ▎
  Subagent cold start                  18      468k  $0.054   0.1%

 What to do about it
  1. Idle gaps are your biggest leak class. Reply before the TTL ring empties, ...
  2. Switching models throws away the whole cache (KV state is per model). ...

Output from the bundled synthetic demo: python examples/make_demo.py demo && kvleak --path demo


Real numbers

30 days of interactive Claude Code sessions 97.5% hit rate, but 27.5% of input spend went to cache rebuilds
Share of that leak caused by idle gaps 82% (median gap 2.8 h; Claude Code now uses the 1 h TTL)
Cost of one miss on a 200k context $3.95 on Fable 5.1, $1.56 on Opus 5.5 (1 h TTL)
6-worker swarm, pointers + warm workers + pinned models −86% input cost in simulation

Methodology and reproduction commands: docs/benchmarks.md.

kvleak HTML report

What you get

Command What it does
kvleak Audits every session: hit rate, dollars leaked, leak broken down by cause, leakiest sessions, worst single misses, and concrete next steps.
kvleak --since 7d --html report.html A self-contained HTML report (light/dark, no JS) you can share with your team. --markdown and --json also work.
kvleak session <id> Call-by-call timeline of one session, with each miss flagged and explained.
kvleak statusline --install Adds a live cache TTL countdown to Claude Code: ◕ cache 3:41 · 182k ctx · rebuild $0.89.
kvleak breakeven 150k --idle 20m Tells you whether to keep this cache alive or let it die.
kvleak pointer build.log --status FAIL Turns a huge file into a ~60-token hand-off message for multi-agent boards.
kvleak --fail-over 15 Exits with code 2 when more than 15% of input spend leaked, so it can gate CI or nightly jobs.

Every miss gets a cause

Cause What happened Typical fix
Idle gap outlived the TTL You were away for more than 5 min (or 1 h), so the next message rebuilt everything. Watch the statusline countdown, batch work, or use capped keep-alive pings.
Prefix changed within the TTL Something near the top of the prompt changed: a timestamp, unsorted JSON, or a different tool list. Make the prefix deterministic.
Model switched mid-session KV caches are per model, so a switch always means a full-price rebuild. Pin one model per session or worker and hand off with pointers.
History compacted /compact or auto-compact rewrote the history. Compact once at a natural break, not mid-task.
Cold start / subagent cold start A fresh agent paid full price for its system prompt and tool schemas. Reuse warm workers; keep system prompts identical.

Only the avoidable part counts as leak: the context the cache already held, priced at write cost minus read cost. A new user message or new tool output would be paid for anyway, so it is not counted. Details: docs/how-it-works.md.

Live TTL countdown in Claude Code

kvleak statusline --install      # backs up settings.json; refuses to overwrite an existing statusLine without --force
◕ cache 3:41 · 182k ctx · rebuild $0.89        (green → yellow → red as the TTL drains)
○ cache cold · next msg rebuilds 182k ($0.89)

When the ring is almost empty, sending your next message now refreshes the TTL at the cost of a cache read. If you already have a statusline script, call kvleak statusline from it; it reads the same JSON on stdin.

Should I keep this cache alive?

$ kvleak breakeven 100k --model claude-sonnet-5 --idle 20m

  Cached prefix 100k on claude-sonnet-5 (5m TTL)
  Rebuild if it expires   125k tok-equiv  ($0.250)
  ...of which avoidable   115k tok-equiv  ($0.230)
  One keep-alive ping     10.0k tok-equiv  ($0.020)
  Break-even              11 pings ≈ 54m30s of idle time

  Idle 20m00s: 4 pings cost 40.0k tok-equiv  ($0.080), saving 75.0k tok-equiv  ($0.150). Keep it alive.

The rule is K_max = floor((write − read) / read): 11 pings at 0.10× reads, 24 at 0.05×, 49 at 0.025×. Past that, let the cache expire.

Running multi-agent swarms?

Multi-agent and multi-model setups multiply leaks in three ways:

  • caches never cross models
  • shared boards make every agent re-read everyone's logs, which costs O(N²)
  • one-shot subagents each pay a cold-start tax

The multi-agent cache playbook describes six layers of practice: pinned models with pointer hand-offs, a script → small model → large model funnel, warm workers with TTL batching, a slim board contract, deterministic prefixes, and deliberate compaction. It includes a contract you can paste straight into your swarm's instructions, and kvleak measures each layer.

$ kvleak pointer /tmp/build.log --status FAIL --note "3 tests failing in //pkg"
{"bytes":40211,"lines":512,"note":"3 tests failing in //pkg","path":"/tmp/build.log","sha256":"9f2c1e07a1b4c3d2","status":"FAIL","tail":[...]}

Supported logs

Source How
Claude Code (incl. subagents) automatic: ~/.claude/projects, respects $CLAUDE_CONFIG_DIR
Any JSONL with usage counters --path <dir-or-file>. Auto-detects Anthropic (cache_read_input_tokens), OpenAI (prompt_tokens_details.cached_tokens), Gemini (cachedContentTokenCount) and flat agent-framework keys (input_tokens, cache_read_tokens, created_at).

Prices for current Claude models are built in (kvleak models). For other providers, add a pricing file; see examples/pricing.json. Models without a price still get full token-level analysis.

Want your agent harness supported natively? A reader is one small function that yields Steps. See src/kvleak/sources.py and CONTRIBUTING.md.

Use it as a library

from kvleak import analyze, load

report = analyze([load("session.jsonl")])
print(report.hit_rate, report.leak_usd, report.buckets["ttl_expiry"])

FAQ

Is my data sent anywhere? No. kvleak only reads local files and makes no network calls.

I'm on a subscription, not the API. Does this matter? Yes. Cache misses use up your rate-limit headroom the same way they would cost money on the API. Read the dollar figures as relative weights.

My hit rate is 95%. Am I fine? Maybe not. Hit rate counts tokens, not dollars, and one 800k-token rebuild weighs as much as thousands of cheap hits. Look at the Leaked line instead.

How accurate is the cause detection? It follows the rules in docs/how-it-works.md. The main blind spot is very long generations: timestamps are written when a response ends, so a few TTL expiries can show up as prefix busts.

Credits

Inspired by the cache-countdown idea in olddonkey/cache-refresher and by production audits of multi-agent swarms.

MIT licensed. Contributions welcome!

Metadata

Release files for kvleak 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for kvleak 0.1.0
File Size Uploaded Provenance
kvleak-0.1.0.tar.gz 153.5 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for kvleak 0.1.0
File Interpreter ABI Platform
kvleak-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 184.7 kB

Release files / kvleak-0.1.0.tar.gz

Download URL kvleak-0.1.0.tar.gz
Size 153.5 kB
Tags Source
SHA-256 checksum
How to use checksums
2a591e1588f614f7dbb61f8b6530bc04b433759a55bd700dc77b3a43e96f8b00
BLAKE2b-256 checksum
How to use checksums
3bc5ab477e7c3c1c8819730442dfef43f709a080fa4eb8af08fea91d549960c9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.7

Release files / kvleak-0.1.0-py3-none-any.whl

Download URL kvleak-0.1.0-py3-none-any.whl
Size 31.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fd0c47d06b9c43633eb3054a7523658899b7a67cf32dc8b5b70fa2e102d2bf4b
BLAKE2b-256 checksum
How to use checksums
f38f760bfd4e11955ef4cbea610b8f8162f1ecc32595a0ae71bfb86054c84269
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.7

Security for kvleak 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page