Skip to content

fix(discovery): spawn PowerShell install commands natively on Windows#2750

Merged
wpfleger96 merged 2 commits into
mainfrom
duncan/powershell-native-install
Jul 24, 2026
Merged

fix(discovery): spawn PowerShell install commands natively on Windows#2750
wpfleger96 merged 2 commits into
mainfrom
duncan/powershell-native-install

Conversation

@wpfleger96

Copy link
Copy Markdown
Member

Problem

On Windows, install_shell_command wraps every install command in Git Bash -l -c, including the Windows-specific powershell.exe … irm https://chatgpt.com/codex/install.ps1 | iex command. A Git Bash login shell prepends its POSIX dirs (C:\Program Files\Git\usr\bin) to PATH, so when Codex's install.ps1 shells out to bare tar -xzf C:\…, it resolves Git's GNU tar (/usr/bin/tar) instead of Windows bundled bsdtar. GNU tar parses C: as a remote host:

tar (child): Cannot connect to C: resolve failed
gzip: stdin: unexpected end of file
/usr/bin/tar: Child returned status 128
/usr/bin/tar: Error is not recoverable: exiting now
Downloaded Codex package archive did not contain the expected package layout.

Claude's installer doesn't hit the same failure because it doesn't shell out to tar.

Solution

On Windows, detect powershell.exe install commands and spawn them natively (Command::new("powershell.exe")) instead of routing them through Git Bash. The discriminator is a case-insensitive prefix check on the first whitespace-delimited token — minimal and precise.

The native spawn preserves everything install_shell_command provides that applies:

  • NPM_CONFIG_* / COREPACK env strip + managed npm prefix env
  • PATH composed from managed Buzz dirs + inherited process PATH (no POSIX login-shell dirs)
  • CREATE_NO_WINDOW so no console flash
  • stdin null, piped-drain in run_install_command
  • The retry/backoff/annotate logic is fully shared

The -Command body is split correctly at the boundary (case-insensitive) and passed as a single argument to preserve pipes and spaces inside the installer script call.

Non-PowerShell commands (e.g. npm install -g … adapter steps) continue through the existing Git Bash path unchanged.

Tests

6 unit tests:

  1. is_powershell_command detection (positive + negative)
  2. Routing: PowerShell → native spawn on Windows, non-PowerShell → Git Bash
  3. Unix: non-Windows path returns the shell command unchanged (compile-time cfg)
  4. -Command body preservation (no bash args in native spawn; body is single arg)

Full just desktop-tauri-test suite: 1627/1627 passing. Windows CI will validate end-to-end.

Codex's CLI installer (powershell.exe … irm … | iex) was routed through
Git Bash (-l -c), which prepends POSIX dirs to PATH. Inside the
PowerShell script, bare `tar` resolved to Git's GNU tar (/usr/bin/tar)
instead of Windows bsdtar. GNU tar parses the drive letter in C:\… as a
remote host → "Cannot connect to C: resolve failed" → empty extraction →
"did not contain the expected package layout".

Add is_powershell_command() to detect commands beginning with
powershell.exe (case-insensitive) and install_powershell_command() to
spawn them natively without the Git Bash wrapper. -Command body is
located by a case-insensitive substring search and passed as a single
argument so pipes and spaces inside the script are preserved exactly.
build_install_command() routes on this predicate; non-PowerShell commands
(npm install -g … adapter steps) keep the existing Git Bash path unchanged.

All env cleanup (NPM_CONFIG_*, COREPACK_HOME), PATH composition
(managed Buzz dirs + inherited), and CREATE_NO_WINDOW are preserved.
No login-shell PATH is composed for the native spawn because
login_shell_path() is always None on Windows and POSIX-shaped entries
must not reach native children.

Tests: is_powershell_command detection, build_install_command routing
(PS→powershell.exe, non-PS→bash on Windows; always shell on Unix),
-Command body preservation (flags forwarded, pipe in single arg).

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
@wpfleger96
wpfleger96 requested a review from a team as a code owner July 24, 2026 19:56
…shared helpers

- install_powershell_command: find -Command on token boundary (not substring),
  strip one outer double-quote pair from the body (catalog serialization artifact),
  so PowerShell receives the bare pipeline instead of a string expression
- Extract apply_npm_env / apply_no_window to eliminate duplication between
  install_shell_command and install_powershell_command
- Replace loose contains-checks with exact argv assertions in three tests:
  test_powershell_command_argv_exact, test_powershell_command_token_boundary_not_substring,
  test_powershell_command_claude_catalog_dequoted

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
@wpfleger96
wpfleger96 merged commit f3981db into main Jul 24, 2026
45 of 47 checks passed
@wpfleger96
wpfleger96 deleted the duncan/powershell-native-install branch July 24, 2026 21:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant