Skip to content

[BUG] Windows: shell mismatch between AI prompt generation and Inline Terminal execution #321

@F915

Description

@F915

Problem (one or two sentences)

Zoo Code correctly detects the user's configured default shell (e.g., PowerShell 7) and tells the AI to generate commands using that shell's syntax, but the Inline Terminal actually executes commands in cmd.exe. This causes PowerShell-specific commands to fail with garbled error text, and all non-ASCII output appears garbled on non-UTF-8 locales.

Context (who is affected and when)

Who is affected: All Windows users who have configured a non-cmd default shell in VSCode (PowerShell 7, git-bash, WSL, etc.), particularly those in non-UTF-8 locales (Chinese/936, Japanese/932, Korean/949).

When it happens: Whenever Zoo Code's Inline Terminal executes a command. This is the default behavior since terminalShellIntegrationDisabled defaults to true.

Not affected: macOS / Linux users (native UTF-8 shells). Windows users who have not changed their default shell from cmd.exe.

Reproduction steps

  1. Windows 11 (zh-CN locale), VSCode with Zoo Code v3.55.0
  2. Set terminal.integrated.defaultProfile.windows = PowerShell 7 (UTF-8)
  3. In Zoo Code Inline Terminal, run Write-Host "test"
  4. Observe: the command is not executed. Instead, garbled Chinese text appears where the cmd.exe error message should be
  5. Run echo 中文测试
  6. Observe: output shows garbled text instead of the expected Chinese characters

Expected result

Commands should execute in the shell that Zoo Code detects (PowerShell 7). Write-Host "test" should execute as a valid PowerShell cmdlet. Non-ASCII output should display correctly in UTF-8.

Actual result

Commands execute in cmd.exe. PowerShell cmdlets are not recognized. Non-ASCII output is decoded using the system code page (CP936) instead of UTF-8, producing garbled text.

Variations tried (optional)

  • Shell detection confirmed: getShell() correctly returns the path to pwsh.exe from VSCode settings.
  • Encoding switch ineffective: chcp 65001 && echo 中文 still produces garbled output (cmd.exe parses the command text using CP936 before chcp executes).
  • cmd /c wrapper works: cmd /c "chcp 65001 > nul && echo 中文测试" produces correct output (the new subprocess allows the code page to be switched before the internal command is parsed).

App Version

v3.55.0

API Provider (optional)

Not Applicable / Other

Model Used (optional)

No response

Zoo Code Task Links (optional)

No response

Relevant logs or errors (optional)

## Root Cause

Zoo Code has a `getShell()` function in `src/utils/shell.ts` that detects the user's configured shell from VSCode settings. It is used to generate the AI system prompt (so the AI knows which syntax to use), but it is not passed to the terminal creation code.

**Path 1: Inline Terminal (execa) — default**


// ExecaTerminalProcess.ts:43
shell: BaseTerminal.getExecaShellPath() || true,  // true → cmd.exe on Windows


Since `getExecaShellPath()` is undefined by default, `shell: true` resolves to `process.env.ComSpec` → `cmd.exe`.

**Path 2: Zoo Code terminal (secondary, when Inline Terminal is disabled)**


// Terminal.ts:21
this.terminal = terminal ?? vscode.window.createTerminal({
    cwd, name: "Roo Code", iconPath, env
})
// missing: shellPath


Without `shellPath`, `createTerminal` may fall back to cmd.exe.

## Proposed Fix

Connect the existing `getShell()` to both terminal creation paths.

### File 1: `ExecaTerminalProcess.ts`


+import { getShell } from "../../utils/shell"

- shell: BaseTerminal.getExecaShellPath() || true,
+ shell: BaseTerminal.getExecaShellPath() || getShell(),


### File 2: `Terminal.ts`


+import { getShell } from "../../utils/shell"

 this.terminal = terminal ?? vscode.window.createTerminal({
-    cwd, name: "Roo Code", iconPath, env
+    cwd, name: "Roo Code", iconPath, env, shellPath: getShell()
 })


### Safety

- `getShell()` validates against a built-in allowlist.
- Falls back to `cmd.exe` if validation fails.
- `setExecaShellPath()` callers retain priority (left side of `||` checked first).
- No regression for macOS/Linux or Windows users who have not configured a custom shell.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions