[BUG] VS Code: a session picked from History in a new tab opens in the sidebar instead, if the sidebar has had it open
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?
With claudeCode.preferredLocation set to panel, and a session open in the secondary (right) sidebar, I open a new editor tab (Cmd+Shift+Esc), click Session history in that tab, and choose a past session. It doesn't open in the new tab. The right sidebar switches to it, so the conversation I was working in there leaves the screen, and the new tab stays empty.
This happens to any session the sidebar has shown earlier in the window, and it also breaks the workaround in #93199 (open a new tab before choosing from History). Additional Information traces the cause.
What Should Happen?
A session chosen from History in an editor tab should open in that tab, and the sidebar should let go of it if it isn't showing it. If it has to stay in the sidebar, for example because a turn is running there, the extension should say so rather than switch the sidebar without warning.
Error Messages/Logs
None shown.
Steps to Reproduce
I saw the symptom in normal use. These steps are reconstructed from the code path in Additional Information, and I haven't run them as written.
- Set
claudeCode.preferredLocationtopanel. - In the right sidebar, open session A from Session history. A must be a real session with messages, not a blank chat.
- In the same sidebar, open session B from Session history.
- Press Cmd+Shift+Esc to open a new Claude editor tab.
- In that tab, click Session history and choose session A.
- The sidebar switches from B to A, and the new tab stays empty.
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.296 (VS Code extension), VS Code 1.141.0
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Other (the VS Code extension's own panel)
Additional Information
Technical analysis. This comes from reading the bundled extension.js and webview/index.js in 2.1.296. The bundle is minified, so I name class methods and message types, which keep their names. Minified function names differ between builds.
The picker's choice goes through the path that focuses a tab already showing the session (added in 2.1.260, per #93199). That path counts every session the sidebar has a Claude process on as already open, including sessions the sidebar isn't showing.
- The picker, in the tab's webview. Choosing a session calls
focusTabShowing(session, { includeSidebarChat: true }). WithincludeSidebarChat,tabOpenElsewhere()checkskeysShownElsewhere(), which isopenSessionIds(sessions in editor tabs) plussidebarSessionIds. A is insidebarSessionIds, so the picker doesn't load A into the current tab. It callsopenInEditor(A), which sends anopen_in_editorrequest. - The extension host.
open_in_editorrunsclaude-vscode.editor.openwith A,fullEditor = trueandprogrammatic: "honor-preferred-location". BecausepreferredLocationispanel, the target ispanel, so it callscreatePanel(A, …). createPanel. No editor tab has A (sessionPanels), so it checkssidebarHoldsSession(A). That returns true, socreatePanelreturnsshowSessionInSidebar(A), which callsactivateInSidebar(A)and reveals the sidebar view. The sidebar webview makes A its active session, B leaves the screen, and the tab stays empty.- Why the sidebar holds A.
sidebarHoldsSessionis true if the session is the one the sidebar shows, or if the sidebar has a channel on it (hasChannelOnSession, which counts pending channels too).sidebarSessionIdsis built the same way, fromsessionIdsWithChannels()plus the shown session. When a surface's active session changes, the webview callsendUnusedProcess()on the others, and that ends only blank chats.isUnusedBlankChat()requires no transcript on disk, no title and no prompt or reply. So a real session keeps its Claude process, and its channel, until the sidebar webview is torn down. Every real session opened in the sidebar during the window's life keeps routing back to the sidebar.
createPanel makes the same check on every other route to a session:
vscode://anthropic.claude-code/open?session=…, which runsclaude-vscode.primaryEditor.open- session list rows, through
open_in_editor new_conversation_tabrequests that carry a session ID
Possible fix. Send a session to the sidebar only when the sidebar is showing it (shownSessionId). If the sidebar has it only as a background channel, end that process, as endUnusedProcess() does for blank chats, and open the session in the tab. If a turn is running in that background session and it can't move, say so rather than switch the sidebar.