Prompt Cache Control
npx claude-code-templates@latest --mod observability/prompt-cache-control Scanned by NVIDIA SkillSpector
Automated static analysis (no LLM) · v2.12.0 · 2026-10-17
Partial analysis: some checks could not run on this component.
SkillSpector looks for patterns such as shell commands, credential access, network calls or unpinned dependencies. An observation is something worth reading in the files before you install, not a confirmed vulnerability. Components that run code locally, like hooks, MCP servers and security tooling, naturally show more of them.
- Agent Config Directory AccessAgent Snooping · README.md:100
- Agent Config Directory Access ×3Agent Snooping · hooks/prompt-cache-control.tsx:139
- MCP server referenced without pinned version: 'npx claude-code-templates'.MCP Rug Pull · README.md:94
- Skill declares no tool scope ('permissions' or 'allowed-tools') but code capabilities were detected: network.MCP Least Privilege · SKILL.md:1
Learn more about NVIDIA SkillSpector.
Content
hooks/prompt-cache-control.tsx. Options: ttl, warnSeconds, compactAtTokens, band, status, toast, idleCompact (set in user or managed settings pluginConfigs, or /config). Run claude plugin validate on the installed folder to see every event it hooks and every $ call it makes.
prompt-cache-control (Claude Cache Control)
A prompt-cache meter above the Claude Code prompt. Every request Claude makes
reports how much of its prompt the cache served, how much it wrote and how much
went uncached; this mod keeps those numbers per request and per turn, counts
down to the moment the cache lapses and tells you what to do about it: keep
going, /compact or /clear.
cache ██████████ 98% read 80k · wrote 1k · new 300 ⏱ 3:41 5m · warm: keep going
cache ░░░░░░░░░░ 0% read 0 · wrote 52k · new 300 ⏱ 4:58 5m · cache missed: model changed (…)
cache ██████████ 98% read 150k · wrote 1k · new 300 ⏱ 0:00 5m · expired: the next message rewrites 151k tokens. /compact first, or /clear if the task is done/cache opens a pane: the time left with a solid bar that shrinks as the cache runs out (green, yellow below 40% of the lifetime, red from the warning threshold), a stacked read / wrote / new bar for the last request, and a colour-coded table with one row per turn. Bars are filled cells and columns have fixed widths with no-break spaces, so the terminal and the Desktop (HTML) pane render the same.
How the countdown works
From Anthropic's prompt caching documentation:
- The cache lives 5 minutes by default, 1 hour when asked for.
- Every request that reads the cache refreshes it at no extra cost, so a conversation that keeps talking keeps the 5-minute cache warm.
- The lifetime is counted from the start of the request that wrote or read the entry; generation time counts against it.
- A prompt is
input_tokens(uncached remainder) +cache_read_input_tokens+cache_creation_input_tokens. - Writes cost 1.25x base input for 5 minutes and 2x for 1 hour; reads cost about 0.1x (less on some models). The expensive moment is an expired cache on a large context, which is when this mod suggests
/compact. /clearstarts a new conversation in the same process, so the meter and the/cachetable start over with it. A change in the prefix (model, effort or thinking settings, tool set, system prompt,CLAUDE.md) makes the next request write instead of read. The mod names the cause when it sees a miss: model changed, the cache had lapsed, or the prefix changed.
Which lifetime your account gets
The mod follows Claude Code's own rules (prompt caching: cache lifetime, Claude Code 2.1.242 or later). For the main conversation the TTL is the first match of:
| # | Source | Result |
|---|---|---|
| 1 | the mod's ttl option (5m / 1h) |
what you set |
| 2 | FORCE_PROMPT_CACHING_5M=1 |
5 minutes |
| 3 | CLAUDE_CODE_PROMPT_CACHE_TTL |
5m or 1h |
| 4 | the promptCacheTtl setting (local, project or user settings file) |
5m or 1h |
| 5 | ENABLE_PROMPT_CACHING_1H=1 |
1 hour |
| 6 | the account | 1 hour on a Claude subscription within its plan usage; 5 minutes on usage credits, an API key or a cloud provider |
The account comes from the rate-limit windows the last response reported: a five_hour or seven_day window means a subscription, and one at 100% means requests now draw on usage credits. An API key or a cloud provider reports no such window, and before the first response nothing is known, so the mod starts from 5 minutes there. Managed settings are not readable from a mod.
On top of that the mod watches the traffic, which beats rows 2 to 6: a request that hits the cache more than 5 minutes after the previous one proves the 1-hour lifetime (a later miss does not undo it, since a changed prefix looks the same), and a miss 5 to 60 minutes after the previous request, with the same model and a prompt that did not shrink, says the entry lapsed, so 5 minutes (a later hit overrules it). That covers what the mod cannot see: managed settings, a gateway that rewrites the TTL, or a subscription that ran out of plan usage mid-session. The pane header names the source in use.
Why the mod infers instead of reading it: the API names the TTL of each write (cache_creation.ephemeral_5m_input_tokens / ephemeral_1h_input_tokens) and Claude Code's status line exposes it as prompt_cache.ttl, but the mod API passes on only the four token counts. To check by hand, claude -p "hello" --output-format json and read usage.cache_creation.
Other switches read from the environment at session start:
| Variable | Effect on the meter |
|---|---|
DISABLE_PROMPT_CACHING=1 (and _HAIKU, _SONNET, _OPUS) |
the band says caching is off for that model |
Idle compaction (Claude Code 2.1.290+)
Claude Code can compact a large terminal conversation by itself while you are away, shortly before its one-hour cache lapses, so your next message reads a summary instead of rewriting the whole prompt. When that will happen, the band adds a magenta ⇣ 41:12 next to the cache countdown: the time until Claude Code compacts if nobody types. After it happens, a toast and the band say compacted while idle (240k → 30k), and the old countdown stops.
It fires at 90% of the cache lifetime (about 54 minutes) only when all of these hold (read from the 2.1.299 build, not from documentation):
| Condition | Where the mod reads it |
|---|---|
| The feature is rolled out to your account | the tengu_sunny_locket flag Claude Code caches in ~/.claude.json; mode: "off" means it never runs, and "idleCompaction": true does not turn it on |
| Auto-compact is on | DISABLE_COMPACT, DISABLE_AUTO_COMPACT, autoCompactEnabled |
| Idle compaction is not turned off | "idleCompaction": false in settings.json |
| The cache lives one hour and is still warm | the same lifetime as the main countdown |
| The prompt is at least the threshold | CLAUDE_CODE_IDLE_COMPACT_MIN_TOKENS, never below 100K, 200K when unset |
The mod reads only those two keys from ~/.claude.json (or $CLAUDE_CONFIG_DIR/.claude.json); without the cached flag it shows no idle countdown. /cache shows a line saying whether it is armed and, if not, why (for example not rolled out to this account (mode off) or waits for 200k tokens; the prompt is 80k). Two settings in the catalog set it up: environment/idle-compaction-early (from 100K) and environment/idle-compaction-off.
What it hooks
turn.step: reads each main-loop request's usage (subagents have their own prefixes and are left out)$.clock.every(1000): redraws the countdown, and only while its text changes, so an idle expired session costs nothingui.renderonAbovePrompt(the band) and onPane(/cache)session.compact: notes a compaction of the main conversation, and announces one with triggeridle$.ui.toast: once per cache entry at the warning threshold (60 s by default) and again at 10, 3, 2 and 1 seconds left, for prompts of 20k tokens or more
Options
ttl: string "auto" | "5m" | "1h" (default auto)
warnSeconds: number countdown threshold for the yellow state and the toast (default 60)
compactAtTokens: number prompt size that makes an expired cache suggest /compact (default 100000)
band: boolean row above the prompt (default true)
status: boolean entry under the prompt, "cache 98% · 3:41" (default false)
toast: boolean toasts at the threshold, 10, 3, 2 and 1 s (default true)
idleCompact: boolean idle compaction countdown and notice (default true)The 100k compactAtTokens is a judgement, not a figure from the documentation: lower it if your model's cache writes are expensive for you.
Install
npx claude-code-templates@latest --mod observability/prompt-cache-control
claudeIt is written to .claude/skills/prompt-cache-control/, which Claude Code auto-loads as prompt-cache-control@skills-dir once the workspace trust prompt is accepted. For one session with hot reload: claude --plugin-dir .claude/skills/prompt-cache-control. claude plugin validate .claude/skills/prompt-cache-control prints every event it hooks and every $ call it makes; claude plugin test .claude/skills/prompt-cache-control runs its tests.
Options are read from user settings (~/.claude/settings.json, never project settings), --settings <file> or managed settings, under the plugin's full id:
{ "pluginConfigs": { "prompt-cache-control@skills-dir": { "options": { } } } }Requirements. Mods are on by default in Claude Code 2.1.287+. Typed against Anthropic's declarations: https://github.com/anthropics/claude-code/tree/main/mods