[BUG] VS Code extension: prompt-cache indicator restarts at full TTL when the webview processes frames late (remote window, display off)

Status Open
Reported on v2.1.288
Maintainer reply None cached
Activity 0 comments · opened Oct 3, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code (logic below is unchanged in 2.1.288)

What's Wrong?

The prompt-cache indicator in the VS Code extension's input footer (clock icon, minutes left) times the cache from when the panel's webview processes a message, not from when the API request was made. When the webview handles frames late, the indicator restarts at the full TTL even though no request was sent.

Measured case (remote window: macOS client, Linux host over Remote-SSH, extension 2.1.287, 1h cache TTL):

  • the session's last API request: 18:53:01 (transcript timestamp; usage.cache_creation.ephemeral_1h_input_tokens > 0). Nothing was sent after it; the transcript has not been written since.
  • the client's display was off 17:58–19:16. The client stayed awake, so the connection stayed up and the remote session kept working.
  • at 19:16, when the display came back on, the panel rendered the backlog in one burst and the indicator showed 60m, implying expiry about 20:16. The real expiry was 19:53.

So the indicator says the cache is warm for about 23 minutes after it has actually gone cold, and a user who continues in that window pays a full re-cache while believing it is a cheap warm turn. It also makes it look as if waking the client re-cached the conversation, which it did not.

Cause, as far as the bundled webview shows (webview/index.js, 2.1.287 and 2.1.288): the indicator's anchor resolves as receivedAt ?? Date.parse(timestamp), and receivedAt is Date.now() at the moment the webview handles a live frame (processIncomingMessage sets liveFrameReceivedAt = Date.now()). Any delay between the CLI receiving the response and the webview handling the frame (a display-off or occluded window, a remote reconnect flushing queued messages) moves the anchor forward by that delay. The transcript-replay path anchors on the message timestamp and is correct.

What Should Happen?

The indicator should time the cache from when the request was actually made (or its response reached the CLI), independent of when the panel happened to process the frame: for example a time stamped by the CLI or the extension host, not by the webview.

Error Messages/Logs

None; the indicator is wrong silently.

Steps to Reproduce

  1. Open a Remote-SSH window to a Linux host and start a session (1h cache TTL).
  2. Give it a task that runs a while; turn the client's display off before the task finishes, keeping the client itself awake.
  3. More than ~20 minutes after the task's last request, turn the display back on.
  4. The panel renders the backlog at once and the indicator shows ~60m. Compare with the last assistant timestamp in the session transcript.

Claude Model

Opus

Is this a regression?

I don't know

Claude Code Version

2.1.287 (extension); same logic in 2.1.288

Platform

Anthropic API

Operating System

macOS client, Linux remote host (Remote-SSH)

Terminal/Shell

VS Code-family editor (VSCodium) with the Claude Code extension, remote window

View original on GitHub ↗