{"slug": "show-hn-claude-thermos-keeps-your-claude-session-warm-for-you", "title": "Show HN: Claude-thermos – keeps your Claude session warm for you", "summary": "A new open-source tool called claude-thermos prevents expensive prompt-cache rebuilds in Claude Code sessions by keeping the main agent's cache warm while subagents run. The tool, which runs as a local reverse proxy, targets the 5-minute TTL on Anthropic's prompt cache that causes roughly 22% of total costs on long sessions with subagents. Developer 'nchammas' released claude-thermos on GitHub, claiming it eliminates the cost of re-encoding cached conversation history.", "body_md": "**Stop paying to rebuild your Claude Code cache.** When your main agent waits on a subagent for more than 5 minutes, its prompt cache silently expires, and the next turn re-encodes your entire conversation at the write rate instead of reading it back cheap. On long sessions with many subagents that's roughly 20% of your bill. `claude-thermos`\n\nkeeps the cache warm so you never pay that tax.\n\nRun Claude Code exactly as you normally would, but through `claude-thermos`\n\nwith `uvx`\n\n:\n\n```\nuvx claude-thermos                     # instead of: claude\nuvx claude-thermos -p \"fix the bug\"    # any claude args pass straight through\n```\n\nRequires Python 3.11+ and the `claude`\n\nCLI on your `PATH`\n\n.\n\nThat's it. Warming runs automatically in the background. To disable it for a run without changing the command, set `CLAUDE_WARMER_DISABLE=1`\n\n.\n\nTuning (all optional):\n\n| Flag | Default | Meaning |\n|---|---|---|\n`--idle` |\n`270` |\nSeconds the main agent must be idle before warming kicks in |\n`--interval` |\n`270` |\nSeconds between warming cycles |\n`--max-cycles` |\n`4` |\nMax warms per idle episode (`auto` for unlimited) |\n`--subagent-window` |\n`540` |\nSeconds a subagent counts as \"still active\" |\n\nClaude Code's prompt cache uses a **5-minute TTL**. Every turn, your whole conversation history is served from cache at **0.1x** the input price instead of being re-sent at full price, as long as the cache stays alive.\n\nThe cache expires if more than 5 minutes pass between requests on the same prefix. The dominant trigger for that gap is not you thinking. It's the main agent **blocked on a subagent that runs longer than 5 minutes**. A subagent has a different system prompt and tool set, so its requests have a *different* cache prefix and never refresh the main agent's. While the subagent works, the main agent's cached history ages untouched; past 5 minutes it's gone. When the subagent returns, the main agent resumes with a byte-identical, append-only history, and finds its cache missing, forcing a full re-encode at the **1.25x** write rate.\n\nBy then the history is large, so the re-encode is expensive: individual collapses re-write 200K to 500K tokens. Measured across roughly 185 local sessions, these rebuilds accounted for about **22% of the total bill**, money spent re-encoding content that was already cached moments earlier.\n\n`claude-thermos`\n\nlaunches Claude Code behind a small local reverse proxy (it points `ANTHROPIC_BASE_URL`\n\nat a loopback port; all traffic still goes to the real Anthropic API).\n\n**Observe.** The proxy watches`/v1/messages`\n\ntraffic and groups it into sessions and*lineages*, a lineage being one cache prefix, keyed by model + tool set + system text. The first tool-bearing lineage is the**main** agent; the rest are subagents.**Detect the danger window.** When the main lineage goes idle*and*a subagent is actively running, the main prefix is at risk of expiring.**Warm.** On an interval under the 5-minute TTL, it replays the main agent's last real request as a**warm request**: identical cacheable prefix, but`max_tokens: 1`\n\nand no streaming. The single token is thrown away; the point is the prefill, which reads and refreshes the full cached prefix. Warm requests go**directly** to the API, never through the proxy, so they can't disturb real traffic.**Result.** When the subagent finishes, the main agent's cache is still warm. It pays a cheap read instead of a full rewrite.\n\nEach warm costs a cache read (0.1x); each rewrite it prevents would have cost a write (1.25x) on a much larger prefix, so the trade is heavily in your favor.\n\nEvery session writes to:\n\n```\n~/.claude-thermos/logs/<session_id>/\n├── events.jsonl    # append-only structured event stream\n└── summary.json    # rollup totals, written when the session ends\n```\n\n`events.jsonl`\n\nrecords each request/response's token usage plus every warming decision (`warm_fired`\n\n, `warm_result`\n\n, `cap_reached`\n\n, `resume_detected`\n\n, and so on). `summary.json`\n\nis the rollup you'll usually read:\n\n| Field | Meaning |\n|---|---|\n`warms_fired` |\nWarm requests sent |\n`cache_read_total` |\nTokens read back by those warms |\n`episodes` |\nIdle-with-subagent episodes that ended in a successful resume (a rewrite actually avoided) |\n`rewrite_avoided_tokens` |\nTokens that would have been re-written, summed across episodes |\n`warm_cost` |\nWhat warming cost you: `0.1 × cache_read_total` |\n`rewrite_avoided_cost` |\nWhat it saved: `1.25 × rewrite_avoided_tokens` |\n`net_savings` |\n`rewrite_avoided_cost − warm_cost` |\n\nAll three cost figures are in **base-input-token units** (token counts already weighted by their cache multiplier). To turn `net_savings`\n\ninto dollars, **multiply it by your model's price per input token**:\n\n```\ndollars saved ≈ net_savings × (input token price)\n```\n\nFor example, at an input price of $3 / 1M tokens, a `net_savings`\n\nof `1_200_000`\n\nis about `1_200_000 × $3 / 1_000_000 = $3.60`\n\nsaved that session.", "url": "https://wpnews.pro/news/show-hn-claude-thermos-keeps-your-claude-session-warm-for-you", "canonical_source": "https://github.com/izeigerman/claude-thermos", "published_at": "2026-07-23 17:06:22+00:00", "updated_at": "2026-07-23 17:22:44.962789+00:00", "lang": "en", "topics": ["artificial-intelligence", "large-language-models", "ai-tools", "developer-tools"], "entities": ["Claude Code", "Anthropic", "claude-thermos", "nchammas"], "alternates": {"html": "https://wpnews.pro/news/show-hn-claude-thermos-keeps-your-claude-session-warm-for-you", "markdown": "https://wpnews.pro/news/show-hn-claude-thermos-keeps-your-claude-session-warm-for-you.md", "text": "https://wpnews.pro/news/show-hn-claude-thermos-keeps-your-claude-session-warm-for-you.txt", "jsonld": "https://wpnews.pro/news/show-hn-claude-thermos-keeps-your-claude-session-warm-for-you.jsonld"}}