[BUG] VS Code: the 600-message webview trim leaves orphan empty "Thinking" rows, shrinks agent "Tool calls (N)" to 0, and counts background-agent rows against the main feed

Status Open
Reported on v2.1.284
Maintainer reply None cached
Activity 0 comments · opened Sep 29, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

The VS Code webview keeps at most 600 messages and trims to 500 when it goes over. That is a reasonable memory protection and this report does not ask to remove it. The problem is how the trimming looks to the user. One mechanism, three visible effects:

  1. Orphan empty "Thinking" rows. The trim removes completed tool-call rows first and keeps thinking-only rows, text and TodoWrite. The older part of the feed then shows runs of empty "Thinking" / "Thought for 0s" rows with no tool calls between them. The feed looks corrupted, not trimmed. The transcript on disk is complete: in one examined 65-second window, the .jsonl has all 17 tool_use and 16 tool_result records, and none of them are shown. The thinking blocks themselves were empty in the transcript (signature only, as is normal for models that omit thinking text), so they render as a bare label.
  1. Agent card "Tool calls (N)" shrinks and drops to 0. The card counts tool_use blocks in the same trimmed messages array, not in the agent's transcript. Observed on screen: a running agent's open card went from "Tool calls (5)" to "Tool calls (3)" while I watched, the two oldest calls disappearing; a finished background agent that ran for 63 minutes shows "Tool calls (0)". "Open transcript" for the same agent loads the transcript from disk and shows the calls, so the card and the transcript disagree. Modeled on one agent's transcript (268 real calls), the card value would go 89, 112, 21, 5, 14, 7, 1, 0 over the session.
  1. Background-agent rows count against the main feed's cap. Every SDK message, including subagent messages, goes through the same append-and-trim path; nothing excludes rows by parent tool-use id. Agent rows are also rendered in the main feed in normal view. In my session agents produced 91% of the messages over 14 minutes and held 59-80% of the 500-600 slots, so the main conversation's history aged out 4.6-11.3 times faster than it would without agents (depending on the interval).

What Should Happen?

  1. When messages are dropped, show a marker such as "N earlier messages hidden, full history is in the session transcript", ideally with a way to load them.
  2. Trim whole API messages, or drop a thinking-only row together with the tool-call row it belongs to (same message id), so no bare "Thinking" rows are left behind.
  3. On the agent card, show "showing N of M tool calls", with M from the agent's usage counter (task_progress) or from its transcript, instead of the length of an array that is being trimmed.
  4. Give subagent rows their own cap or separate storage, so busy background agents cannot evict the main conversation.
  5. Optionally expose or document the cap.

Error Messages/Logs

Steps to Reproduce

Clean session (verified):

  1. Open a new session in the VS Code extension panel, normal view (claudeCode.focusView = false).
  2. Send: Make 50 no-op Bash calls that run true, in batches of 10, with a short progress line after each batch.
  3. Then send: make 100 more empty bash. Continue with more batches if needed; it takes a couple of hundred calls in total to pass 600 messages.
  4. Scroll up: the Bash rows of the earliest calls are gone, while the progress lines and thinking rows remain. The most recent calls are shown normally.
  5. The session .jsonl still contains every tool_use and tool_result.

Agent card (observed in a long session):

  1. Start a background subagent that makes many tool calls while the session is past the cap.
  2. Open its card in the agent map and keep it open: "Tool calls (N)" decreases as older calls are trimmed.
  3. After the agent finishes and more messages arrive, its card shows "Tool calls (0)". "Open transcript" still shows the calls.

Claude Model

Not sure / Multiple models

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.284 (Claude Code)

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

Other

Additional Information

Environment: Claude Code VS Code extension 2.1.284 (win32-x64), chat panel (not the integrated terminal), normal view (claudeCode.focusView = false). Windows 10 Home 10.0.19045. Reproduced with Opus 5.5 and Sonnet 5; the trim is in the webview and does not depend on the model.

Code pointers (webview/index.js, 2.1.284; minified names change between releases, so search by string):

  • Cap constants: search gh1=600,uh1=500 (cap 600, trim target 500, fh1 = 100 most recent messages protected from the first pass).
  • Trim: function ih1 with helpers Vg and NI0; search protectRecentFromToolPass. Pass 1 removes, oldest first and outside the protected tail, messages whose blocks are all completed tool_use with a result, plus their tool_result messages (TodoWrite, Agent, Task and Skill excluded). Pass 2 removes any non-pending messages. Pass 3 removes the oldest.
  • Live call site: w71(k61(...),...,{protectRecentFromToolPass:!0}) right after lw( in the incoming-message handler, run for every message, including those with parent_tool_use_id. Tab reopen: M71(, same rule without the protected tail.
  • Row label: IC1 (search Thought for ): an empty thinking block renders a static label.
  • Agent card: the function that renders "Tool calls (" counts i35(ne($.messages.value, zp(X))), i.e. tool_use blocks of the trimmed array filtered by sdkParentToolUseId ?? parentToolUseId. The transcript view uses get_subagent_transcript (from disk). A separate counter KH0 ("N tools", from task_progress usage) does not depend on the array.

Screenshots: clean-session repro on Sonnet 5.5 (the first 50 Bash calls have no rows left, only the progress lines; the latest calls are shown normally); a finished background agent that ran for 41 minutes (525k tokens) whose card shows "Tool calls (2)". Some content is redacted.

Not confirmed: the live DOM was not captured (e.g. counting rows in the webview dev tools); the percentages and the modeled card values above come from replaying the trim rule on the session transcript. The JetBrains panel appears to share this webview (the 2.1.281 changelog mentions "the VS Code and JetBrains panels"), so it is likely affected too; not verified.

Related: #24733 (tool calls disappearing in the panel during streaming, older version, no cap identified), #29017 and #95656 (reopened conversations render only part of the history), #79042 (large resumed sessions show truncated history), #80649 (empty signature-only thinking blocks). #98118 is a separate issue: nested agents attached to the wrong parent in a small session far below this cap.

<img width="427" height="266" alt="Image" src="https://github.com/user-attachments/assets/ccf5c861-dbc3-484d-8694-a835baa62267" />
<img width="1640" height="1243" alt="Image" src="https://github.com/user-attachments/assets/606daf5b-e541-4d57-a6fa-e76dd799bbe8" />

View original on GitHub ↗