Show HN: Claude-thermos – keeps your Claude session warm for you

s0ck_r4w3 pts0 comments

GitHub - izeigerman/claude-thermos: Keeps your Claude session warm for you · GitHub

/" data-turbo-transient="true" />

Skip to content

Search or jump to...

Search code, repositories, users, issues, pull requests...

-->

Search

Clear

Search syntax tips

Provide feedback

--><br>We read every piece of feedback, and take your input very seriously.

Include my email address so I can be contacted

Cancel

Submit feedback

Saved searches

Use saved searches to filter your results more quickly

-->

Name

Query

To see all available qualifiers, see our documentation.

Cancel

Create saved search

Sign in

/;ref_cta:Sign up;ref_loc:header logged out"}"<br>Sign up

Appearance settings

Resetting focus

You signed in with another tab or window. Reload to refresh your session.<br>You signed out in another tab or window. Reload to refresh your session.<br>You switched accounts on another tab or window. Reload to refresh your session.

Dismiss alert

{{ message }}

izeigerman

claude-thermos

Public

Notifications<br>You must be signed in to change notification settings

Fork

Star

main

BranchesTags

Go to file

CodeOpen more actions menu

Folders and files<br>NameNameLast commit message<br>Last commit date<br>Latest commit

History<br>40 Commits<br>40 Commits

.github/workflows

.github/workflows

src/claude_thermos

src/claude_thermos

tests

tests

.gitignore

.gitignore

LICENSE

LICENSE

Makefile

Makefile

README.md

README.md

pyproject.toml

pyproject.toml

uv.lock

uv.lock

View all files

Repository files navigation

claude-thermos

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 keeps the cache warm so you never pay that tax.

Use

Run Claude Code exactly as you normally would, but through claude-thermos with uvx:

uvx claude-thermos # instead of: claude<br>uvx claude-thermos -p "fix the bug" # any claude args pass straight through

Requires Python 3.11+ and the claude CLI on your PATH.

That's it. Warming runs automatically in the background. To disable it for a run without changing the command, set CLAUDE_WARMER_DISABLE=1.

Tuning (all optional):

Flag<br>Default<br>Meaning

--idle<br>270<br>Seconds the main agent must be idle before warming kicks in

--interval<br>270<br>Seconds between warming cycles

--max-cycles<br>Max warms per idle episode (auto for unlimited)

--subagent-window<br>540<br>Seconds a subagent counts as "still active"

Why your cache keeps expiring

Claude 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.

The 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.

By 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.

How it works

claude-thermos launches Claude Code behind a small local reverse proxy (it points ANTHROPIC_BASE_URL at a loopback port; all traffic still goes to the real Anthropic API).

Observe. The proxy watches /v1/messages traffic 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 and 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.

Each 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...

claude cache main thermos agent subagent

Related Articles