VS Code: support per-chat Codex app-server lifecycle instead of global window reload
Summary
Please add a VS Code lifecycle equivalent to Claude Code's extension: each Codex chat/editor panel should own the backend process/session resources it needs, and closing that panel should shut those resources down, including the local codex.exe app-server and its child processes when they are panel-scoped.
Today the OpenAI/Codex VS Code extension appears to start one shared local Codex app-server for the entire extension host. That makes a Codex reload require either a global VS Code window reload or a singleton app-server restart, both of which are operationally worse than Claude Code's per-panel lifecycle.
Why this matters
I often run multiple agents simultaneously in the same VS Code window, for example Claude Code plus ChatGPT/Codex. When only the Codex agent needs a reload, such as after an MCP server/config change, using Developer: Reload Window interrupts every active agent and extension in the window.
Claude Code's VS Code extension behaves better for this workflow: closing the Claude chat tab tears down the resources for that specific chat, including claude.exe, so I can restart only that agent without disrupting the rest of VS Code.
Environment
- OS: Windows
- VS Code extension:
openai.chatgptversion26.513.21555(openai.chatgpt-26.513.21555-win32-x64) - Claude comparison extension:
anthropic.claude-codeversion2.1.142(anthropic.claude-code-2.1.142-win32-x64) - Codex binary path observed locally:
~/.vscode/extensions/openai.chatgpt-26.513.21555-win32-x64/bin/windows-x86_64/codex.exe - Claude binary path observed locally:
~/.vscode/extensions/anthropic.claude-code-2.1.142-win32-x64/resources/native-binary/claude.exe
Observed behavior in Claude Code VS Code extension
From the installed Claude extension bundle, the panel path creates a per-panel communication/process object:
setupPanel(...)creates a newm3(...)instance for theWebviewPanel.- The panel dispose hook calls
H.shutdown(): z.onDidDispose(() => { H.shutdown(); ... })m3.shutdown()aborts active controllers, closes all channels, drains pending channel ops, and tears down the subprocess path.- The lower process transport closes stdin and sends termination (
SIGTERM, thenSIGKILLafter timeout) if the process remains alive.
Operationally, closing a Claude Code chat tab terminates the corresponding claude.exe process tree.
Observed behavior in OpenAI/Codex VS Code extension
From the installed OpenAI/Codex extension bundle:
- Activation creates a single app-server connection:
let d = new I_(t.extensionUri, l);let m = d.startCodexProcess();- That singleton
dis then passed into shared providers and the main webview provider, includingwl,R_,dR, auth/preview/fetch paths, etc. - The main provider stores one
this.codexMcpConnectionand uses it across sidebar and editor panels. registerOnDidDisposeForWebviewPanel(...)clears pending webview requests and removes the panel, but does not shut down a panel-specific app-server because there is no panel-specific app-server.- The webview message
codex-app-server-restartcurrently routes toworkbench.action.reloadWindow, which reloads the whole VS Code window instead of only Codex.
This means closing a Codex task/editor tab does not terminate codex.exe; the process remains shared by the whole extension. If Codex needs a backend reload, the current UX pushes toward a full window reload, interrupting other agents.
Requested behavior
Preferred:
- Make each Codex chat/editor panel/session own a
CodexMcpConnection/ app-server lifecycle, similar to Claude Code'sm3per-panel model. - On
WebviewPanel.onDidDispose/ custom editor dispose, gracefully shut down the backend process/session for that panel. - Ensure subprocesses are terminated as part of the panel lifecycle.
- Reopening the chat should create a fresh app-server/session without requiring
workbench.action.reloadWindow.
Acceptable fallback if a fully per-panel process model is not currently viable:
- Add an official
Restart Codex App Servercommand for the VS Code extension that restarts only the Codex app-server process and preserves the VS Code extension host/window. - Replace the current
codex-app-server-restart -> workbench.action.reloadWindowbehavior with that narrower restart path. - Avoid using full window reload for settings/config changes that only require the Codex backend to re-read config, such as WSL/MCP/app-server runtime changes.
Implementation notes from local inspection
The current singleton design makes a trivial local patch unsafe for exact parity. Killing the singleton codex.exe from a single panel's dispose hook would also kill any other Codex panel using the same CodexMcpConnection. Real parity needs the provider to route MCP requests/responses/notifications through a connection associated with the owning webview/panel/session, or needs an explicit supported app-server restart API with clear UX that it is global to Codex but not global to VS Code.
Expected outcome
A user should be able to reload/restart ChatGPT/Codex inside VS Code without reloading the entire VS Code window and without interrupting other active agents such as Claude Code.
2 Comments
Update: local investigation found a working per-tab lifecycle patch
I continued investigating this locally on Windows with the installed
openai.chatgptVS Code extension bundle (openai.chatgpt-26.513.21555-win32-x64). The original issue description is still accurate, but the root cause and the required shape of the fix are now clearer.Confirmed target behavior after local patch
After patching the installed extension bundle locally and reloading the VS Code extension host, the behavior now matches what I expected from Claude Code:
codex.exefor the Codex extension by itself.codex.exe app-serverfor that tab.codex.exeand its MCP child processes.More precise findings
In the installed/minified bundle, the local fix required all of these pieces together:
WebviewPanel.onDidDispose/ custom editor dispose, dispose the connection for that webview and call the app-server teardown path.codex.exe, because MCP server children otherwise remain orphaned.The final bug that kept the local patch from being fully correct was specific to new Codex tabs:
/extension/panel/newenterresolveCustomEditorwithconversationId == null.conversationId != null.codex.exeand MCP children, but closing the tab did not call the per-webview teardown.The final local fix was to register the dispose handler unconditionally for the custom editor panel, even when
conversationIdis null, and to capture the webview before disposal so the same webview key can be used to look up and tear down the per-tab connection.Conceptually:
And inside the dispose registration, the important detail was preserving the webview key before the panel is disposed:
The local Windows teardown hardening used a recursive process-tree cleanup rooted at the app-server PID (
Get-CimInstance Win32_Process/ descendant traversal, children first, root last), withtaskkill /PID <pid> /T /Fas a fallback.Validation performed locally
node --checkpassed on the patched installedextension.jsbundle.codex.exe, per-tab process/MCP trees on tab open, and full process-tree cleanup on tab close.Upstream suggestion
For the official extension, I think the durable fix should be a source-level version of this lifecycle ownership model:
I cannot provide a clean PR because the locally validated target was the installed/minified VSIX bundle, not a reproducible extension source package, but this should narrow down the lifecycle issue substantially.
Thanks for the suggestion, but we're unlikely to change this. It would be a big architectural change, and it wouldn't benefit most users.