Skip to content

[BUG] IDE extension: retained editor selection is never invalidated when the document closes, and leaks into new conversations #91155

Description

@3meyc-ua

Preflight Checklist

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

What's Wrong?

The IDE extension's current-file/selection chip in the chat input keeps showing a file that is no longer open in the editor, and that stale value leaks into brand-new conversations.

The retained selection lives in extension-host module state and is only ever invalidated under two conditions. From extension.js (v2.1.251):

function XT0($) { return $ === 0 ? "clear" : "retain" }
window.onDidChangeActiveTextEditor(async (X) => {
  if (!X) {
    if (XT0(window.visibleTextEditors.length) === "retain") return;
    RU.bump(); yz = void 0; tM = void 0; Q.fire(void 0); return;
  }
  ...
})

workspace.onDidCloseTextDocument((X) => {
  if (!xU(X.uri.scheme)) J.fire({ filePath: X.fileName, uri: X.uri.toString() });
  if (X.uri.toString() !== tM) return;
  RU.bump(); yz = void 0; tM = void 0; Q.fire(void 0);
})

So the cached selection yz clears only when (a) the active editor becomes undefined at a moment when visibleTextEditors.length === 0, or (b) onDidCloseTextDocument fires with a URI matching the retained one.

Neither reliably happens in normal use:

  • Clicking into the Claude tab fires onDidChangeActiveTextEditor(undefined) and takes the "retain" branch. That part is intentional and correct — you don't want to lose your selection by focusing the chat.
  • But there is no expiry or revalidation afterwards. If the document is later closed while the active editor is already undefined, condition (a) never re-evaluates, and condition (b) depends on the host actually disposing the TextDocument — which VS Code/Cursor defer while anything still holds a reference (language servers commonly do). The result is a cached selection that outlives the editor indefinitely.

The leak into new conversations follows from the same state being the source of truth for a fresh tab. The host answers get_current_selection straight from that retained value:

if ($.request.type === "get_current_selection")
  return { type: "get_current_selection_response", selection: this.getCurrentSelection() };

and the webview re-applies it to the active session on every visibility change:

G2(() => {
  let G = this.comms.connection.value?.isVisible.value;
  if (G && Z === !1) _z(() => {
    this.activeSession.value?.applySelectionUpdate(this.context.currentSelection.value)
  });
  Z = G
})

with the include toggle re-initialising to on (let [M, _] = Y1(!0)useState(true), not persisted). So "New Conversation" / ⇧⌘Esc is not inheriting from the previous conversation — both conversations are reading one stale host-level value, and each new one re-enables sending it.

Net effect: a file the user closed long ago is silently attached to every prompt of every new conversation, and the only remedy is a window reload or an unnoticed per-conversation click.

What Should Happen?

The retained selection should be invalidated when the editor it refers to is no longer open. Concretely, any of:

  1. Revalidate on read — before answering get_current_selection (and before re-applying on visibility change), confirm the retained URI is still among window.visibleTextEditors / window.tabGroups, and drop it if not. This fixes the case where onDidCloseTextDocument never fires.
  2. Re-evaluate the "retain" decision on onDidChangeVisibleTextEditors, not only on onDidChangeActiveTextEditor, so closing the last editor while focus is in the chat still clears.
  3. Don't seed a brand-new conversation from a selection the user never made in that conversation, or at least default includeSelection to off when the retained selection predates the conversation.

Related: #24726 requests a persistent setting to disable auto-attach entirely. That's a separate ask — this report is that the existing behaviour is incorrect even for users who want auto-attach, because the attached file is simply wrong.

Steps to Reproduce

  1. In Cursor (or VS Code), open the Claude Code extension panel and open some source file in an editor tab. The chip in the chat input shows that filename.
  2. Click into the Claude Code tab so no text editor is active.
  3. Close the file's editor tab, leaving no text editor visible (e.g. only webview tabs such as Simple Browser and the Claude tabs remain).
  4. Observe the chip still shows the closed file, with tooltip Showing Claude your current file selection (<filename>).
  5. Press ⇧⌘Esc (Claude Code: Open in New Tab) or run Claude Code: New Conversation.
  6. The brand-new conversation shows the same closed file in the chip, toggled on, and sends it as context.

Workaround: Developer: Reload Window resets the host-side cache. Reopening and re-closing the file also clears it when the close event fires.

Is this a regression?

No / Not sure

Claude Code Version

2.1.251 (Claude Code)

Platform

IDE extension (VS Code / Cursor)

Operating System

macOS 26.5 (arm64)

Additional Context

  • Extension: anthropic.claude-code-2.1.251-darwin-arm64
  • Host: Cursor 3.18.9 (arm64), extension engines.vscode: ^1.94.0
  • Code references are from the shipped extension.js and webview/index.js in that extension build; identifiers are minified, so names like XT0, yz, tM will differ across builds.
  • There is no setting to work around this: the extension contributes 15 claudeCode.* settings and none affects selection attachment.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:idebugSomething isn't workinghas reproHas detailed reproduction stepsplatform:macosIssue specifically occurs on macOSplatform:vscodeIssue specifically occurs in VS Code

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions