Skip to content

Fix Windows npm-shim claude spawn + stop leaking env in spawn errors (#63)#66

Merged
kahliburke merged 2 commits into
mainfrom
fix/agent-spawn-error-sanitize
Jul 18, 2026
Merged

Fix Windows npm-shim claude spawn + stop leaking env in spawn errors (#63)#66
kahliburke merged 2 commits into
mainfrom
fix/agent-spawn-error-sanitize

Conversation

@kahliburke

Copy link
Copy Markdown
Owner

Fixes #63. Two commits:

1. Resolve npm .cmd/.ps1 CLI shims (91c8ab2)

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 ENOENTs even though claude --version works in the user's shell. 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 / powershell -File) as before. Benefits every CLI spawn routed through launch_argv, not just the agent.

Verified on a real Windows instance against a claude.cmd shim:

  • 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"]
  • real spawn output → 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 IOError whose text stringifies the whole setenv(cmd, env) — including the process environment (ANTHROPIC_API_KEY, …). That was surfaced verbatim via sprint(showerror, e) into the agent UI, so a user pasting Error opening agent: … into an issue leaked their credentials. backend_start now catches the spawn failure and re-raises a sanitized ErrorException built from the argv alone, with an actionable hint (Windows ENOENT → npm-shim / native-installer guidance; otherwise a PATH hint).

Tests: _which_pathext search, launch_argv PATHEXT fallback, and spawn-error sanitization (both iswin branches, asserts no secret/env in the message). 151/151 agent tests pass.

…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
kahliburke merged commit 0ded524 into main Jul 18, 2026
5 checks passed
@kahliburke
kahliburke deleted the fix/agent-spawn-error-sanitize branch July 18, 2026 02:15
kahliburke added a commit that referenced this pull request Jul 20, 2026
Managed zero-Docker Qdrant (#24), extension runtimes non-addressable at
the session resolver, Windows claude-spawn fix (#66), and extension
runtime-env fixes (#61, #65). Docs: note that extension runtimes are not
addressable sessions.
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.

Agent fails to spawn claude on Windows when the CLI is installed via npm (.ps1/.cmd shim)

1 participant