Skip to content

feat: shell integration-based terminal output capture for remote environments#10786

Open
shanevcantwell wants to merge 1 commit intocontinuedev:mainfrom
shanevcantwell:fix/vscode-runcommand-remote
Open

feat: shell integration-based terminal output capture for remote environments#10786
shanevcantwell wants to merge 1 commit intocontinuedev:mainfrom
shanevcantwell:fix/vscode-runcommand-remote

Conversation

@shanevcantwell
Copy link
Contributor

@shanevcantwell shanevcantwell commented Feb 24, 2026

Summary

  • When the extension host runs on Windows with a remote workspace (SSH, WSL, Dev Container), childProcess.spawn executes locally instead of on the remote. The existing fallback used ide.runCommand (sendText) with no output capture, returning a hardcoded "Command failed" status.
  • Adds a new runCommandWithOutput IDE method using VS Code's Shell Integration API (1.93+) to execute commands on remote terminals with full stdout capture and ANSI color preservation.
  • When shell integration is unavailable, runCommandWithOutput falls back to sendText internally and the caller reports "Command completed" — no double-execution.

How it works

  1. Creates an invisible terminal (not shown to user)
  2. Waits for shell integration to activate via onDidChangeTerminalShellIntegration (10s timeout)
  3. Executes via shellIntegration.executeCommand(command)
  4. Reads output via execution.read() async iterable
  5. Strips only VS Code's internal OSC 633 markers; preserves ANSI color codes for UnifiedTerminal's AnsiRenderer
  6. Disposes terminal after capture
  7. If shell integration is unavailable: shows terminal, sends command via sendText, returns empty string (command still executes, just without output capture)

Files changed (10)

File Change
core/index.d.ts Add runCommandWithOutput to IDE interface
core/config/types.ts Add to global IDE type
core/protocol/ide.ts Add protocol type
core/protocol/messenger/messageIde.ts Add proxy method
core/protocol/messenger/reverseMessageIde.ts Add listener
extensions/vscode/src/extension/VsCodeMessenger.ts Add handler
extensions/vscode/src/VsCodeIde.ts runCommandWithOutput() + waitForShellIntegration() implementation
core/tools/implementations/runTerminalCommand.ts Use new method in remote fallback path
core/tools/implementations/runTerminalCommand.vitest.ts Update mocks and assertions
core/util/filesystem.ts Add stub for FileSystemIde

Test plan

  • SSH remote: pwd, echo, Python scripts with ANSI output — green "Command completed" with captured output and rendered colors
  • WSL remote: Same commands — working, ~5s initial delay due to shell integration startup on WSL terminals
  • Native Windows (no regression): Local childProcess.spawn path completely unaffected — no changes to that code path
  • Shell integration unavailable: Falls back to sendText internally, reports "Command completed" without double-executing
  • Unit tests: 36/37 pass (1 pre-existing failure unrelated to this change)

Related issues

🤖 Generated with Claude Code

@shanevcantwell shanevcantwell requested a review from a team as a code owner February 24, 2026 12:15
@shanevcantwell shanevcantwell requested review from sestinj and removed request for a team February 24, 2026 12:15
@dosubot dosubot bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Feb 24, 2026
@haystack-code-reviewer-pr-hook

Try Haystack Code Reviewer

Want AI-powered code review for this PR? Get instant analysis, interactive visualizations, and actionable insights.

Review this PR with Haystack

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 10 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="core/tools/implementations/runTerminalCommand.vitest.ts">

<violation number="1" location="core/tools/implementations/runTerminalCommand.vitest.ts:273">
P0: Fallback on empty output causes commands to execute twice in remote environments</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@shanevcantwell
Copy link
Contributor Author

Better now in ssh and wsl-Ubuntu remote. Containers, JetBrains, linux mint, macos use the same code path. Thanks for the patience while I got to the core of the issue.

…environments

When the extension host runs on Windows with a remote workspace (SSH, WSL,
Dev Container), childProcess.spawn executes locally instead of on the remote.
The existing fallback used ide.runCommand (sendText) which had no output
capture, returning a hardcoded "Command failed" status.

This adds a new runCommandWithOutput IDE method that uses VS Code's Shell
Integration API (1.93+) to execute commands on remote terminals with full
output capture. The method creates an invisible terminal, waits for shell
integration to activate, executes via shellIntegration.executeCommand(),
and reads output via the async iterable read() API. ANSI color codes are
preserved for rendering by the UnifiedTerminal component; only VS Code's
internal OSC 633 shell integration markers are stripped.

Falls back gracefully to sendText when shell integration is unavailable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L This PR changes 100-499 lines, ignoring generated files.

Projects

Status: Todo

1 participant