Skip to content

fix(shell): default to PowerShell on native Windows without the wrapper#49

Open
MilkClouds wants to merge 1 commit into
subinium:mainfrom
MilkClouds:fix/windows-default-shell
Open

fix(shell): default to PowerShell on native Windows without the wrapper#49
MilkClouds wants to merge 1 commit into
subinium:mainfrom
MilkClouds:fix/windows-default-shell

Conversation

@MilkClouds

Copy link
Copy Markdown
Contributor

Problem

Running the bare agf binary on Windows — without agf setup having installed the wrapper — crashes on any Resume / New Session / Open:

PS C:\...> agf
Error: program not found

Cause

deliver_command is designed to exec the chosen action directly when no wrapper is present (the wrapper is only strictly needed to persist a bare cd). But from_env returned Posix whenever AGF_SHELL was unset — on every OS. So on native Windows it generated cd '...' && claude and exec'd it via sh -c; Windows has no sh, so the spawn failed with Rust's Windows ErrorKind::NotFound, whose message is literally program not found. POSIX hosts were unaffected (sh exists), so the intended no-wrapper behavior already worked everywhere except native Windows.

Why default_shell

With AGF_SHELL absent there was no shell decision at all — just a blanket POSIX assumption. Fixing the crash means making that case an OS-aware choice (native Windows → PowerShell; Git Bash / MSYS2 / Cygwin → POSIX; else POSIX), which requires reading MSYSTEM/SHELL and must be unit-testable without mutating process-global env. So it's factored into a small pure function default_shell(is_windows, msystem, shell), kept separate from from_name (an explicit user-supplied token) to avoid conflating "told us" with "inferred."

Fix

from_env honors AGF_SHELL when set, else defers to default_shell. On Windows a present SHELL signals a POSIX layer (native shells don't export it); its basename is classified through from_name so the powershell/pwsh names stay in one place and any other shell is POSIX. The wrapper still sets AGF_SHELL=powershell, so the installed path is unchanged — this only fixes the no-wrapper fallback.

no-wrapper, native Windows before after
Resume / New / Open crash (program not found) works
Cd (dir change only) warns, doesn't persist warns, doesn't persist¹

¹ Persisting a bare cd still requires the wrapper (a child process can't change the parent shell's directory) — unchanged, and this path already hints to run agf setup.

Tests

Pure unit tests for default_shell: native Windows → PowerShell, MSYSTEM/unix SHELL → POSIX, PowerShell-only-for-pwsh, and basename-not-path-substring matching.

Running the bare `agf` binary on Windows (no `agf setup`) crashed with
`Error: program not found`. With `AGF_SHELL` unset, `from_env` assumed
POSIX on every OS, so resume/new/open generated `cd ... && claude` and
the delivery path tried to exec it via `sh -c`. Windows has no `sh`, so
the spawn failed with Rust's "program not found" io error.

Infer the default shell from the OS when `AGF_SHELL` is absent: POSIX off
Windows or under a Git Bash / MSYS2 layer (`MSYSTEM`); otherwise native
Windows, which needs PowerShell. A present `SHELL` is a POSIX-layer signal
(native Windows shells don't export it, e.g. Cygwin), so its basename is
classified through `from_name` — keeping the powershell/pwsh names in one
place and treating any non-PowerShell shell as POSIX. The wrapper still
sets `AGF_SHELL` explicitly, so the installed path is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@MilkClouds MilkClouds force-pushed the fix/windows-default-shell branch from 6a3a4f8 to e4a4b83 Compare May 31, 2026 06:46
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