fix(core): prefer pwsh.exe over Windows PowerShell 5.1 (#25859)#25900
fix(core): prefer pwsh.exe over Windows PowerShell 5.1 (#25859)#25900kaluchi wants to merge 5 commits into
Conversation
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request improves shell command execution on Windows by prioritizing PowerShell 7 (pwsh.exe) over the legacy Windows PowerShell 5.1. This change resolves long-standing issues with argument quoting and improves compatibility with modern shell features like '&&' and '||' operators, while maintaining backward compatibility for users without PowerShell 7 installed. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request updates the shell configuration to prefer pwsh.exe on Windows to resolve quoting issues and adds integration tests for verification. It also refactors the resolveExecutable utility to be synchronous and updates the test suite to use vi.stubEnv. Feedback indicates that the switch to synchronous I/O blocks the event loop and violates project conventions, identifies a regression in Windows executable resolution for extensionless files, and suggests using asynchronous operations with real-path resolution for better security and performance.
|
/gemini review |
|
Note this PR is non-breaking by design: Copilot CLI refuses to run without pwsh 7 (#847) and won't support 5.1 (#411, not planned). Here, 5.1 users keep working exactly as before — only users who already installed pwsh get the fix. |
506111a to
650765e
Compare
Windows PowerShell 5.1 silently strips embedded double quotes from
arguments when invoking native executables, causing commands such as
`node -e 'console.log("test")'` to fail with `ReferenceError: test is
not defined` when run via `!` in shell mode. PowerShell 7 (pwsh.exe)
uses standards-compliant argument passing and does not exhibit this
behavior.
On Windows, `getShellConfiguration` now prefers `pwsh.exe` on PATH
before falling back to `powershell.exe`. Users with PowerShell 7
installed get the fix automatically; users without it keep the
existing behavior and full cmdlet surface — no regression either way.
The pre-existing `resolveExecutable` helper is converted to sync,
matching the prevailing style in `shell-utils.ts` (the same file
already uses `spawnSync` for the PowerShell AST parser).
Fixes google-gemini#25859
Review feedback from gemini-code-assist caught a regression I
introduced: by skipping the empty extension when the input exe has
no extension, commands like `resolveExecutable('mytool')` on Windows
stopped finding extensionless binaries.
Revert the extension list to match the original async version:
always probe `['.exe', '.cmd', '.bat', '']` on Windows. The
`path.extname` optimization was saving microseconds per call at the
cost of a real correctness bug — not worth it.
Drop the test I added for that optimization.
Match the file's existing convention for Windows path literals
(see line 521: 'C:\Program Files\PowerShell\7\pwsh.exe' and
line 613: path.resolve('C:\Windows\System32')).
650765e to
4fded9b
Compare
The test uses Windows-style paths (C:\...) that break on Linux/Mac because path.delimiter splits on ":" — the colon in "C:" fractures the mocked PATH into two garbage entries. The real validation runs on the Windows CI runner where path semantics are native.
4fded9b to
1c4aa6d
Compare
|
This pull request is being closed as it has been open for 14 days without a 'help wanted' designation. We encourage you to find and contribute to existing 'help wanted' issues in our backlog! Thank you for your understanding. |
|
@scidomino please help here |
|
Gemini CLI needs this PR for the Windows users 🤩 |
|
any updates or resolution here? |
|
Sorry. Rerunning the tests. |
|
failed lint. |
|
This pull request is being closed as it has been open for 14 days without a 'help wanted' designation. We encourage you to find and contribute to existing 'help wanted' issues in our backlog! Thank you for your understanding. |
|
Thanks for the review. The auto-close bot fired again on the PR after you reopened it — same misconfigured policy. The lint failure from the main-merge is fixed and pushed to the branch (PR head won't show it until reopen). The I resolved the main conflict in favor of the sync a) the alternative has a large transitive blast radius — cascading async through the consumers of b) the previous async version was already synchronous in effect — serial c) the surrounding execution flow has large synchronous sections — command parsing ( |
|
@scidomino — the auto-close bot closed the PR again after your reopen (request-review button isn't available while it's closed). Could you reopen and add the 'help wanted' label? Lint fix and rationale for the sync conflict are in the comment above. |

Summary
Fixes #25859. Related: closes-as-effectively-same #18374; addresses the feature-request spirit of #15493, #2353, #6413.
On Windows,
run_shell_commandwith embedded double quotes (e.g.node -e 'console.log(\"test\")') fails because Windows PowerShell 5.1 silently strips\"during native-command argument passing. PowerShell 7 (pwsh.exe) uses standards-compliant argument passing (\$PSNativeCommandArgumentPassing = 'Windows'by default since 7.3) and does not exhibit this behavior.This PR makes
getShellConfigurationpreferpwsh.exefromPATHoverpowershell.exeon Windows. Users with PowerShell 7 installed get the fix; users without keep the existing behavior — no regression either way.Context
Windows PowerShell 5.1 is in legacy maintenance mode. Microsoft itself displays this banner when 5.1 starts:
```
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
Install the latest PowerShell for new features and improvements!
https://aka.ms/PSWindows
```
PS 5.1 is .NET Framework-bound, Windows-only, and lags PS 7 on shell behavior. `$PSNativeCommandArgumentPassing` (fixes native-cmd arg passing) and bash-style `&&`/`||` chain operators were added in PS 7 and cannot be backported to 5.1.
Respecting the user's environment. gemini-cli is a developer tool, and developers who work on Windows overwhelmingly install PowerShell 7 — it's the modern, cross-platform, actively-maintained runtime Microsoft recommends. Currently gemini-cli ignores the user's choice and pins Windows invocations to `powershell.exe` (5.1 on any modern Windows) regardless of whether pwsh 7 is installed. This PR follows both Microsoft's own guidance and the user's clear intent: prefer PS 7 when it's on their system, fall back to 5.1 only when it isn't.
Side benefits
PowerShell 7 also addresses other Windows-specific pain reported against gemini-cli:
These aren't explicitly targeted by the fix but improve as a natural consequence for users who have pwsh 7 installed.
Verification
Reproduce directly in each shell — same commands, different results.
Issue 1: embedded double quotes stripped (#25859)
Windows PowerShell 5.1:
```
PS C:\Users\EugenPC> node -e 'console.log("test")'
[eval]:1
console.log(test)
^
ReferenceError: test is not defined
at [eval]:1:13
...
Node.js v22.18.0
```
PowerShell 7.6.1:
```
PS C:\Users\EugenPC> node -e 'console.log("test")'
test
```
Issue 2: `&&` / `||` operators rejected (#20773, #21997, #18022)
Windows PowerShell 5.1:
```
PS C:\Users\EugenPC> echo a && echo b
At line:1 char:8
The token '&&' is not a valid statement separator in this version.
```
PowerShell 7.6.1:
```
PS C:\Users\EugenPC> echo a && echo b
a
b
```
With this PR, gemini-cli routes through `pwsh.exe` on Windows when it's installed, inheriting the correct behavior for both issues.
Behavior matrix
Only the first row changes behavior.
Tests
Root cause
PR #11157 (2025-10-16) changed the default Windows shell from `cmd.exe /d /s /c` to `powershell.exe -NoProfile -Command`. Windows PowerShell 5.1 lacks `$PSNativeCommandArgumentPassing` (introduced in PS 7.2 as experimental, default since 7.3) and has a long-standing runtime limitation: `"` inside arguments is dropped when invoking native executables. Fixable only by running through PS 7 — which is what this PR does.