enabled
scoped
Warming on
Global master switch. Per-surface, per-project and per-session settings can override it (ccw or the dashboard).
Reference / schema 2
The configuration surface of Cache Warm v0.5.2, generated from scripts/lib.mjs and the plugin manifest. Defaults below are the values the code ships with.
01 Resolution
Each session resolves every setting from the first scope that defines it. Values that are unset simply inherit. Two scopes can never accidentally change each other's surfaces: inside a Claude Code session, an unscoped ccw change applies to that session's surface only.
# what this session actually uses, and where each value comes from
ccw config --session
# the same, for one scope
ccw config --desktop
ccw config --project
# every scope that currently holds a setting
ccw scopes
CLAUDE_CODE_ENTRYPOINT maps to cli; anything containing desktop to desktop; VS Code, JetBrains, Cursor and Windsurf entrypoints to ide. sdk-* runs — claude -p and the Agent SDK — are headless and are never registered or warmed.
02 Settings
The first five are scoped. The rest make sense once per machine and can only be set at the global scope. Values are stored as JSON in ~/.claude-cache-warm/config.json; only explicitly set values are persisted.
enabled
scoped
Global master switch. Per-surface, per-project and per-session settings can override it (ccw or the dashboard).
warmWhen
scoped
background-work: only while a subagent, background task or scheduled task is pending (recommended). always: any idle session.
intervalMinutes
scoped
Counted from the conversation's last request. auto = 50 on a 1-hour cache, 4 on a 5-minute cache. Otherwise 1 to 59, shorter than the cache TTL.
maxIdleMinutes
scoped
Stop pinging once nobody has typed and no real work has happened for this long. 0 = never stop.
minContextTokens
scoped
Small contexts are cheap to rebuild; do not warm them.
dashboardPort
global only
Local port for ccw dashboard.
statusline
global only
auto: add the cache segment to your status line (creating one if you have none). wrap-only: only add it to an existing status line. off: remove it and restore your original status line exactly.
statuslineSegments
global only
Comma-separated, in order. Available: model, folder, branch, pr, warm, context, cache, fill, limits, cost. cost is a list-price estimate, so it is off by default.
03 Plugin tab
/plugin are a real scope.Claude Code passes plugin-tab values to hooks as CLAUDE_PLUGIN_OPTION_*. The SessionStart hook snapshots them, so the CLI, status line and dashboard can see them too. Editing a value in the tab makes it win over the override it would otherwise sit behind; untouched tab values never undo edits made with ccw or the dashboard. Edits apply immediately through the ConfigChange hook, and sleeping timers pick them up within a minute.
The tab exposes one extra convenience option that is not a stored setting:
desktopModeplugin tab onlysame-as-cli: follow the settings above. off / background-work / always: override them for sessions in the Claude desktop app only.
04 Status line
Configure with ccw set statuslineSegments model,folder,warm, the plugin tab, or the dashboard's Global tab. Parts without data are omitted. Long lines wrap onto the next row at part boundaries. The segment wraps your existing status line — it never replaces it.
model
Model name, with the effort level when Claude Code reports it.
on by defaultfolder
Project folder, plus the subfolder you are in when it differs.
on by defaultbranch
Current git branch, read from .git without spawning a process.
on by defaultpr
Open pull request number and review state.
on by defaultwarm
Warming state, next-ping countdown and pending background jobs.
on by defaultcontext
Tokens currently in the context window.
on by defaultcache
Tokens the last request read from the cache, and the percentage.
on by defaultfill
Context-window usage as an amount and a percentage.
on by defaultlimits
5-hour and 7-day subscription usage, when available.
on by defaultcost
List-price cost estimate. Opt-in: misleading on a subscription.
opt-in# default order
ccw set statuslineSegments model,folder,branch,pr,warm,context,cache,fill,limits
# the segment itself: auto (default), wrap-only, off
ccw statusline auto
ccw statusline wrap-only
ccw statusline off # restores every original exactly
05 States
One function — computeStatus() — is the single source of truth. The waker acts on it; the CLI, status line and dashboard only display it. These are the states the code can return.
warming
Eligible and waiting; nextPingAt is set and the waker will exit 2 when it is due.
busy
A turn is in progress, so the conversation is refreshing its own cache. Nothing fires mid-turn.
no-work
The default background-work policy is on and nothing is pending in the background.
off
Warming is switched off at some scope that applies to this session.
small-context
The context is below minContextTokens; rebuilding it is cheap.
idle-cap
Nobody has been active for longer than maxIdleMinutes, and no background work is running.
ping-cap
The session already used its pings for this idle stretch (ceil(idle cap / interval) + 1, hard cap 24).
suspended
The last two verifiable pings missed the cache. Warming resumes when someone is active again.
expired
The cache TTL already elapsed. A ping now would be the expensive rewrite, so none is sent.
ended
The session ended or its process is gone.
06 Commands
ccw CLI.| In Claude Code | Shell | What it does |
|---|---|---|
/cache-warm:on [scope] | ccw on [scope] | Switch warming on. |
/cache-warm:off [scope] | ccw off [scope] | Switch warming off. |
/cache-warm:status | ccw status [--all] [--json] | Sessions, what each waits on, next-ping countdown, per-ping and cold-return estimates. |
/cache-warm:config … | ccw config [scope] | Effective settings and the scope each value comes from. |
/cache-warm:dashboard | ccw dashboard [--no-open] | Start the loopback dashboard and open it. |
/cache-warm:statusline | ccw statusline install | auto | off | Install, configure or restore the status line segment. |
/cache-warm:test | ccw test | Self-test this session: one verified ping a minute after the turn, settings restored. |
| ccw when <background-work|always> [scope] | Choose the warming policy. |
| ccw interval <minutes|auto> [scope] | Set the ping interval; auto follows the session's cache TTL. |
| ccw set <key> <value> [scope] | Set any scoped key; global-only keys always write to global. |
| ccw unset <key> [scope] | Drop one key at that scope so it inherits again. |
| ccw reset [scope] | Drop every setting at one scope. |
| ccw scopes | List every scope that currently holds settings. |
| ccw doctor | Health checks, including verified pings per surface. |
| ccw events [n] | The most recent entries from the local event log. |
bin/ccw is on the Bash tool's PATH. From a plain terminal, run node scripts/ccw.mjs <command>, or install the plugin's bin yourself.
07 Scopes
ccw interval 30 --global # every session
ccw when always --desktop # every Desktop-app session
ccw off --cli # every CLI session
ccw interval 20 --project # this folder and everything below it
ccw set maxIdleMinutes 600 --session # just this session
ccw config --session # effective values and their sources
ccw reset --desktop # that scope inherits everything again
ccw unset intervalMinutes --project # drop one key at one scope
Run inside Claude Code, ccw off in the Desktop app turns off Desktop sessions, not your CLI ones. Changing every surface at once needs --global. From a plain terminal, unscoped means global.
session, project, cli, desktop, ide — for example /cache-warm:off desktop or /cache-warm:on session.
08 Cost
The plugin estimates each ping and each avoided rebuild from list prices in its own source. It is an estimate, not a bill — on a subscription the same tokens come out of usage limits.
tokens × input price × cache-read multiplier
Cache reads are 0.1× base input price, except Fable and Mythos 5.1 at 0.025×.
tokens × input price × write multiplier
Cache writes are 1.25× for a 5-minute cache and 2× for a 1-hour cache.
For the worked example on the overview — 800K tokens on Opus 5 with a 1-hour cache — the estimator reports roughly $0.40 per ping and $8.00 per cold rebuild, a break-even of about 18 pings. With a 180-minute idle cap, warming cannot continue indefinitely; with maxIdleMinutes at 0 a hard cap of 24 pings per idle stretch still applies.
09 Limits
auto uses 4m on a 5m cache and 50m on a 1h cache. A fixed interval that is too long produces a warning in ccw status.maxIdleMinutes with no human activity and no real work. 0 means no time cap.ceil(maxIdleMinutes / interval) + 1 pings since the last activity. While background work is running, the idle cap and that formula do not apply, but the hard cap of 24 pings since activity still does.claude -p and Agent SDK sessions are never registered.Source of truth: scripts/lib.mjs. State files and the HTTP API are documented in docs/CONTRACT.md.