Fix Windows npm-shim claude spawn + stop leaking env in spawn errors (#63)#66
Merged
Conversation
…nment A failed `claude` spawn raises an IOError whose text stringifies the whole `setenv(cmd, env)` — including the process environment (ANTHROPIC_API_KEY and any other secrets). That was surfaced verbatim via `sprint(showerror, e)` into the agent UI / error output, so a user pasting 'Error opening agent: …' into an issue leaked their credentials (#63). backend_start now catches the spawn failure and re-raises a sanitized ErrorException built from the argv alone (no env), with an actionable hint: on Windows an ENOENT points at the npm `.cmd`/`.ps1` shim situation and the native CLI installer; elsewhere it's a PATH hint. Non-ENOENT failures report the libuv error code only, never the command/env. Addresses the secret-leak half of #63; the Windows shim-resolution gap (Sys.which not resolving the shim) is tracked separately.
On Windows, Sys.which resolves a bare command name only as `.exe` — it ignores PATHEXT, so an npm-installed CLI that ships `.cmd`/`.ps1` shims (Claude Code, gemini, …) is invisible to it and to Base.run, which then fails with ENOENT even though `claude --version` works in the user's shell (#63). launch_argv now falls back to a PATH × PATHEXT search (_which_pathext) when Sys.which returns nothing, so the shim is found and wrapped through its interpreter (cmd.exe /d /c or powershell -File) as before. Every CLI spawn routed through launch_argv (claude/gemini/codex mcp commands, the agent backend) benefits, not just the agent. Verified on a real Windows instance: Sys.which("claude")=nothing while _which_pathext resolves the .cmd, launch_argv wraps it, and the wrapped command spawns and passes args through. Combined with the spawn-error sanitization, this is the full fix for #63.
kahliburke
added a commit
that referenced
this pull request
Jul 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #63. Two commits:
1. Resolve npm
.cmd/.ps1CLI shims (91c8ab2)On Windows,
Sys.whichresolves a bare command name only as.exe— it ignores PATHEXT. So an npm-installed CLI that ships.cmd/.ps1shims (Claude Code, gemini, …) is invisible to it and toBase.run, which ENOENTs even thoughclaude --versionworks in the user's shell.launch_argvnow falls back to aPATH×PATHEXTsearch (_which_pathext) whenSys.whichreturns nothing, so the shim is found and wrapped through its interpreter (cmd.exe /d /c/powershell -File) as before. Benefits every CLI spawn routed throughlaunch_argv, not just the agent.Verified on a real Windows instance against a
claude.cmdshim:Sys.which("claude")→nothing(the gap)_which_pathext("claude")→…\claude.cmd(the fix)launch_argv(["claude","-p","--foo"])→["cmd.exe","/d","/c","…\claude.cmd","-p","--foo"]fake-claude-cmd -p --foo(spawns, args passed through)2. Sanitize spawn failures so they never leak the environment (
dd0e45a)A failed spawn raises an
IOErrorwhose text stringifies the wholesetenv(cmd, env)— including the process environment (ANTHROPIC_API_KEY, …). That was surfaced verbatim viasprint(showerror, e)into the agent UI, so a user pastingError opening agent: …into an issue leaked their credentials.backend_startnow catches the spawn failure and re-raises a sanitizedErrorExceptionbuilt from the argv alone, with an actionable hint (Windows ENOENT → npm-shim / native-installer guidance; otherwise a PATH hint).Tests:
_which_pathextsearch,launch_argvPATHEXT fallback, and spawn-error sanitization (bothiswinbranches, asserts no secret/env in the message). 151/151 agent tests pass.