fix: restrict terminal childProcess.spawn to local-only environments#10538
Draft
shanevcantwell wants to merge 1 commit intocontinuedev:mainfrom
Draft
fix: restrict terminal childProcess.spawn to local-only environments#10538shanevcantwell wants to merge 1 commit intocontinuedev:mainfrom
shanevcantwell wants to merge 1 commit intocontinuedev:mainfrom
Conversation
childProcess.spawn executes on the extension host machine. With extensionKind: ["ui", "workspace"], the extension host almost always runs locally. For any remote workspace (SSH, WSL, Dev Container, Codespaces, tunnel), spawning locally either runs commands on the wrong machine or fails with ENOENT when the local shell doesn't exist in the extension host context. Replace ENABLED_FOR_REMOTES (which listed all remote types) with LOCAL_ONLY (just "" and "local"). All remote types now fall through to ide.runCommand() which delegates to VS Code's integrated terminal and executes in the correct remote environment. The isWindowsHostWithRemote guard is removed as it is now redundant — the platform-agnostic check handles all cases. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This was referenced Feb 15, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
childProcess.spawn()inrunTerminalCommandexecutes on the extension host machine. WithextensionKind: ["ui", "workspace"], the extension host almost always runs locally. For any remote workspace, spawning locally either runs commands on the wrong machine or fails with ENOENT.ENABLED_FOR_REMOTES(which listed all remote types as eligible for local spawn) withLOCAL_ONLY = ["", "local"]. All remote types now delegate toide.runCommand(), which routes through VS Code's integrated terminal in the correct remote environment.isWindowsHostWithRemoteguard, which is now redundant — it was a Windows-specific patch for a platform-agnostic problem.Fixes #10462
Note:
VsCodeIde.runCommand()has pre-existing bugs that prevent it from working on remotes (sendText(command, false)never presses Enter,createTerminal()creates local terminals from UI-side extensions). These are tracked and fixed separately in #10542. This PR is intentionally scoped to only therunTerminalCommand.tsrouting change.Context
The
ENABLED_FOR_REMOTESlist was introduced in 1500281 (May 2025) to bring streaming output, background process support, and color to remote environments. The intent was sound —childProcess.spawnprovides much better output capture than theide.runCommand()fallback. However, the approach assumed the extension would be running on the remote side, when in practiceextensionKind: ["ui", "workspace"]almost always places the extension host locally.This created a structural contradiction: remote types were listed as "enabled" for local spawn, then a
isWindowsHostWithRemoteguard was added (PR #10391) to undo that for Windows hosts specifically. Non-Windows hosts (Linux→SSH, Mac→Dev Container, etc.) remained broken — commands either ran on the wrong machine silently or failed withspawn /bin/sh ENOENTas reported in #10462.The correct fix is to recognize the actual invariant:
childProcess.spawn()runs on the extension host, so it's only valid when there is no remote workspace. All remotes should delegate toide.runCommand()regardless of host platform.This does mean remote environments lose streaming output capture —
ide.runCommand()executes the command correctly but returns no stdout/stderr. That's a real gap, but it's strictly better than ENOENT or running on the wrong machine. Improving output capture for remote terminals is tracked separately in #10542.What changes
isWindowsHostWithRemote→ide.runCommand()ide.runCommand()(correct machine)ide.runCommand()(correct container)ide.runCommand()(correct machine)No regressions. Every scenario either stays the same or gets fixed.
Test plan
cd core && npx vitest run— 1649 tests pass, 0 failureside.runCommand()delegation