Skip to content

feat: add CacheTimer widget (continues #307)#466

Open
zachthedev wants to merge 7 commits into
sirmalloc:mainfrom
zachthedev:feat-cache-timer
Open

feat: add CacheTimer widget (continues #307)#466
zachthedev wants to merge 7 commits into
sirmalloc:mainfrom
zachthedev:feat-cache-timer

Conversation

@zachthedev

@zachthedev zachthedev commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Continues #307 by @tuansondinh: his three commits, unchanged, rebased onto current main, with follow-up commits to match the project conventions and round out the widget.

What it does

A cache-timer widget (Session category) showing the time left on the prompt cache TTL, read straight from transcript_path (no hooks, no external deps): 🔥 HOT while a turn is in flight, a 🟢/🟡/🔴 m:ss countdown as it drains, ❄️ COLD once expired.

Follow-up commits on top of #307

  • Empty-state convention: renders n/a gated behind a (h)ide when empty toggle instead of returning null when there is no transcript or assistant turn yet, matching the Cache / origin widgets so it stays visible unless opted out.
  • Robustness: a malformed assistant timestamp is treated as no-data, never NaN:NaN.
  • Customizable glyphs: the five state icons are editable via the shared (g)lyph editor as named symbol slots (like the git and compaction widgets), so nerd-font / ASCII users can swap them for symbols that respect the widget color.
  • Configurable TTL: a (t)tl keybind cycles 5m/1h, and any positive ttlSeconds can be set in settings.json. Anthropic''s ephemeral cache defaults to 5 minutes, but Claude Code also writes 1-hour cache_control breakpoints, so this lets the countdown track whichever tier you care about. Default stays 5 minutes.
  • Tests: sandboxed CacheTimer.test.ts covering preview, empty-state, HOT, the countdown buckets, COLD, the timestamp guard, custom/blanked glyphs, and the TTL cycle + annotation.

bun run lint clean; bun test green (1609). Credit to @tuansondinh for the original widget.

Tuan Son and others added 5 commits June 17, 2026 19:25
Reads ~/.claude/state/cache-timer-{session_id}.json written by the
claude-cache-countdown hooks and displays live cache state:
  🔥 HOT  — agent active, cache being refreshed
  🟢 4:52 — countdown with green/yellow/red urgency colors
  ❄️ COLD — cache expired

Widget type: 'cache-timer', category: Session

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Instead of reading ~/.claude/state/cache-timer-{session_id}.json
(which required the claude-cache-countdown hooks to be installed),
the widget now reads the last assistant message timestamp directly
from the transcript_path provided by Claude Code.

No hooks, no external scripts — works out of the box with ccstatusline alone.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When Claude is processing a request, the transcript's last entry is a
user message (the assistant response hasn't been written yet). The
previous code only searched for assistant timestamps, so it would use
the prior turn's timestamp — never showing HOT during active work.

Now detects the pending user message and displays 🔥 HOT immediately.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Builds on the widget from sirmalloc#307 and aligns it with the empty-state convention the Cache widgets follow: instead of returning null when there is no transcript or no assistant turn yet, render n/a gated behind a new (h)ide when empty toggle, so the widget stays visible unless the user opts out.

Also guard a malformed assistant timestamp so it can never reach the countdown as NaN, and document that a trailing user-role entry (a prompt or a tool result) is what drives the HOT state.
Sandboxed widget tests using temp transcript files: preview, n/a versus hidden empty-state, HOT during an in-flight turn, the green/yellow/red countdown buckets and COLD, the malformed-timestamp guard, and the hide-when-empty keybind and editor wiring.
@zachthedev zachthedev marked this pull request as draft June 18, 2026 02:27
The five state icons (HOT, fresh, draining, urgent, cold) become editable glyphs via the shared (g)lyph editor, declared as named SymbolSlots the same way the other symbol-aware widgets do, so nerd-font and ASCII users can replace the emoji with symbols that respect the widget color. A blanked glyph collapses its trailing space.

The cache TTL is now configurable: a (t)tl keybind cycles 5m/1h and any positive ttlSeconds can be set in settings.json, matching Claude Code writing both 5-minute and 1-hour cache breakpoints. The 5-minute default and existing output are unchanged.
Adds cases for per-state glyph overrides (custom and blanked), the preview reflecting a custom glyph, a 1-hour TTL extending the countdown window, malformed-TTL fallback, the (t)tl cycle, and the editor TTL annotation; updates the keybind assertion for the new (t) and (g) binds.
@zachthedev zachthedev marked this pull request as ready for review June 18, 2026 02:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant