TTL is not observable truth
The display is the last assistant record plus an assumed TTL. It is not a live Claude Code cache API.
A copyable, reversible, agent-executable setup: refresh a TTL estimate every 60 seconds and request checks with /loop 50m. Actual cadence can change through cron rounding, jitter, and busy-turn delays.
The display is the last assistant record plus an assumed TTL. It is not a live Claude Code cache API.
The installer multiplexes the original command, makes a backup, and supports rollback.
/loop belongs to the current Claude Code session and is not a persistent scheduler.
They are related, but not interchangeable.
Anthropic's API docs confirm a default 5-minute TTL and an extra-cost 1-hour option. They do not prove that every Claude Max or Claude Code session uses one hour.
The script finds the last type: assistant record near the transcript tail and adds a configurable TTL. Treat it as a heuristic.
50m is a requested value, not a strict interval. The heartbeat remains useful for missed completion notifications, but cannot guarantee a run before an assumed one-hour cache expiry.
The claim that Max uses one hour and overage falls back to five minutes lacks a stable public specification. Keep it contested and never infer account state automatically.
Prefer giving agent-setup.md to an agent. The manual path follows.
tmp="$(mktemp -d)"
cd "$tmp"
curl -fsSLO https://claude-code-cache-heartbeat.pages.dev/assets/ttl_statusline.py
curl -fsSLO https://claude-code-cache-heartbeat.pages.dev/assets/statusline_mux.py
curl -fsSLO https://claude-code-cache-heartbeat.pages.dev/assets/install_statusline.pypython3 install_statusline.py --checkThis reports the plan without modifying files or printing the existing command body.
python3 install_statusline.py --apply
python3 install_statusline.py --verifyThe installer backs up ~/.claude/settings.json, preserves an existing command through a mux, and sets refreshInterval: 60.
statusLine object should change. Preserve hooks, permissions, plugins, and project settings./bin/sh only to re-execute the pre-install command with its existing semantics. Status JSON is stdin data, not interpolated command text. Stop if that command's origin is not trusted. --verify checks the mux-config hash and requires mode 0600 on settings, config, receipt, and backups.{
"statusLine": {
"type": "command",
"command": "python3 ~/.claude/claude-cache-heartbeat/statusline_mux.py",
"refreshInterval": 60
}
}Existing keys such as padding and hideVimModeIndicator are preserved.
# 5-minute heuristic
export CLAUDE_CACHE_TTL_SECONDS=300
# 1-hour heuristic (default)
export CLAUDE_CACHE_TTL_SECONDS=3600This only changes the display heuristic; it does not alter server-side cache policy.
python3 install_statusline.py --uninstallrefreshInterval: 60 is required: official docs state event-driven updates can go quiet while idle. Without a timer, a time-based segment freezes.Use it for a long-running task in the current session when completion notifications may be missed.
/loop 50m Cache/heartbeat check-in. If a background task is running, do a quick non-blocking peek at its progress and report anything notable. Stop this loop once the task is done, or after 3 consecutive checks with no completion and no new progress. Otherwise reply "ok".Read process state or new output. Do not turn the heartbeat itself into another long wait.
Stop immediately when complete; also stop after three observed checks with neither completion nor new progress. Rounding, jitter, and busy-turn delay mean this is not a fixed 150 minutes.
/loop is session-scoped. Unexpired tasks can return with --resume/--continue; recurring tasks fire once more and delete themselves seven days after creation. Use a durable scheduler across sessions, restarts, or longer periods.| Check | Expected |
|---|---|
python3 install_statusline.py --verify | Settings, mux, TTL script, and receipt pass |
| Send a message and observe | A dim ttl~ HH:MM segment appears |
| Wait 60 to 120 seconds | The time-based segment is timer-refreshed |
| Short TTL test | Temporarily set CLAUDE_CACHE_TTL_SECONDS=60; the segment becomes a red block after expiry |
| Original statusline | Existing model, quota, git, or other segments remain |
| After heartbeat creation | Confirm Claude's actual cron cadence and job ID; do not assume strict 50m |
| Heartbeat | The loop stops after completion or three observed no-progress checks; recurring tasks last at most seven days |
Discovery entry, claim boundaries, and resource map.
The complete Markdown guide.
Execution contract: inspect, check, backup, apply, verify, rollback.
Machine-readable files, versions, and claim status.
refreshInterval./loop syntax, cron rounding, jitter, session scope, and seven-day expiry.Sources checked on 2026-08-06. Claude Code and cache behavior can change; an executing agent should re-check official docs.