# Claude Code prompt-cache TTL indicator and approximate 50-minute heartbeat

Status: public operational guide; evidence confidence **medium**; the Claude Code plan-specific TTL claim is **contested**.

## Scope

This guide configures two independent mechanisms:

1. A Claude Code statusline segment that estimates a cache-expiry time from the last assistant transcript record.
2. A session-scoped `/loop 50m ...` heartbeat request that checks long-running background work without blocking. The requested cadence is not an exact interval.

The first is an indicator, not cache control. The second is primarily a reliability fallback for missed completion notifications.

## Evidence boundary

- Official Claude Code statusline documentation confirms that a command receives session JSON on stdin and that `refreshInterval` re-runs it on a fixed timer. Idle event-driven updates can go quiet.
- Official scheduled-task documentation confirms `/loop 5m check the deploy` syntax, a minimum one-minute interval, cron conversion/rounding, deterministic jitter, session scope, and seven-day recurring-task expiry.
- Official Claude Platform prompt-caching documentation confirms an API default of five minutes and an optional, extra-cost one-hour duration.
- No cited stable official document proves that every Claude Max or Claude Code session uses a one-hour TTL, or that usage overage automatically changes it to five minutes.

Therefore, the default `3600` seconds in this implementation is a configurable heuristic inherited from the source note. It must be described as an assumption.

## Files

- `assets/ttl_statusline.py`: reads status JSON, tail-scans the transcript, and prints a TTL estimate.
- `assets/statusline_mux.py`: runs the pre-existing statusline command with the same stdin and appends the TTL segment.
- `assets/install_statusline.py`: check/apply/verify/uninstall workflow with exact backup and rollback receipt.
- `assets/heartbeat-prompt.txt`: requested `/loop 50m` command plus its post-creation verification contract.

## Safe installation

```bash
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.py
python3 install_statusline.py --check
python3 install_statusline.py --apply
python3 install_statusline.py --verify
```

The installer:

- parses rather than text-edits `~/.claude/settings.json`;
- refuses malformed or unsupported statusLine shapes;
- creates a timestamped, no-clobber backup before writing;
- copies scripts under `~/.claude/claude-cache-heartbeat/`;
- preserves an existing command via a local mux;
- preserves unrelated statusLine keys and all unrelated settings;
- sets `refreshInterval` to `60`;
- writes a rollback receipt and records the executable mux-config hash;
- requires mode `0600` for settings, mux config, receipt, and backups;
- atomically replaces settings.

The mux uses `/bin/sh` only to preserve the already-configured local statusline command. Claude status JSON is passed to that command via stdin, not interpolated into shell command text. Treat the pre-install command as trusted local configuration; stop rather than preserve it if its origin is not trusted.

Rollback:

```bash
python3 install_statusline.py --uninstall
```

## Display behavior

The script reads `transcript_path` from statusline JSON. It reads the last 256 KiB of JSONL first, then expands to 4 MiB. It parses each record and accepts only `type == "assistant"` with a valid timestamp.

Default assumed TTL: `3600` seconds. Override only the display assumption:

```bash
export CLAUDE_CACHE_TTL_SECONDS=300
```

This environment variable does not alter server cache behavior.

## Heartbeat

```text
/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".
```

`50m` is a request, not a strict guarantee. Claude converts intervals to cron and may round intervals that do not map to a clean step. Recurring tasks that run more often than hourly receive deterministic jitter of up to half the interval, and a task due during a busy turn waits until that turn ends. Consequently:

- do not claim that the heartbeat will run exactly every 50 minutes;
- do not use it as proof that a one-hour cache will be refreshed before expiry;
- after creation, read Claude's confirmation and list scheduled tasks to record the actual schedule and job ID;
- count observed checks, not elapsed minutes, for the three-check stop condition.

Rules:

- Read only immediately available status or newly appended output.
- Never wait synchronously for the task.
- Stop immediately when the task is complete.
- Stop after three consecutive checks with neither completion nor new progress.
- Do not claim persistence outside the current Claude Code session.
- Unexpired tasks can return with `--resume` or `--continue`; recurring tasks fire once more and delete themselves seven days after creation.

## Verification

1. `python3 install_statusline.py --verify` returns PASS.
2. Existing statusline content remains visible.
3. A new assistant reply produces a dim `ttl~ HH:MM` segment.
4. With `CLAUDE_CACHE_TTL_SECONDS=60`, the segment becomes a red `TTL estimate expired` block after a timer refresh.
5. Claude's creation confirmation and scheduled-task list expose the actual cron cadence and job ID; the guide does not assume strict `50m` timing.
6. `/loop` stops under either stop condition and recurring-task seven-day expiry is understood.
7. `python3 install_statusline.py --uninstall` restores the exact previous `statusLine` object.

## Sources

- <https://code.claude.com/docs/en/statusline>
- <https://code.claude.com/docs/en/scheduled-tasks>
- <https://platform.claude.com/docs/en/build-with-claude/prompt-caching>
- <https://www.threads.com/@cyh.289/post/DW2N1nAk3st/>
- <https://zhuanlan.zhihu.com/p/2027075927192913321>

Checked: 2026-08-06.
