From a77df300c83cde3582fb24bdcf5e5f7feb2a966e Mon Sep 17 00:00:00 2001 From: Xyntexx <21282105+Xyntexx@users.noreply.github.com> Date: Tue, 14 Oct 2025 14:26:27 +0300 Subject: [PATCH] Fix Windows subprocess CLI detection (WinError 193) On Windows, npm creates both 'claude' (a bash script) and 'claude.cmd' (a batch file). The SDK was using shutil.which('claude'), which returns the bash script that cannot be executed as a Win32 application, causing OSError: [WinError 193] %1 is not a valid Win32 application. This fix: - Uses 'claude.cmd' on Windows and 'claude' on other platforms - Updates fallback location paths to include .cmd extension on Windows - Adds common Windows npm installation path (AppData/Roaming/npm) Tested on Windows 11 with Python 3.12 and claude-agent-sdk 0.1.3 Co-Authored-By: Claude --- .../_internal/transport/subprocess_cli.py | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/claude_agent_sdk/_internal/transport/subprocess_cli.py b/src/claude_agent_sdk/_internal/transport/subprocess_cli.py index 8cdff4e9..8142c6f7 100644 --- a/src/claude_agent_sdk/_internal/transport/subprocess_cli.py +++ b/src/claude_agent_sdk/_internal/transport/subprocess_cli.py @@ -60,16 +60,29 @@ def __init__( def _find_cli(self) -> str: """Find Claude Code CLI binary.""" - if cli := shutil.which("claude"): + # On Windows, npm creates both 'claude' (bash script) and 'claude.cmd' (batch file) + # We need to use 'claude.cmd' for proper execution on Windows + search_name = "claude.cmd" if sys.platform == "win32" else "claude" + + if cli := shutil.which(search_name): return cli - locations = [ - Path.home() / ".npm-global/bin/claude", - Path("/usr/local/bin/claude"), - Path.home() / ".local/bin/claude", - Path.home() / "node_modules/.bin/claude", - Path.home() / ".yarn/bin/claude", - ] + # Fallback locations to check manually + if sys.platform == "win32": + locations = [ + Path.home() / "AppData/Roaming/npm/claude.cmd", + Path.home() / ".npm-global/bin/claude.cmd", + Path.home() / "node_modules/.bin/claude.cmd", + Path.home() / ".yarn/bin/claude.cmd", + ] + else: + locations = [ + Path.home() / ".npm-global/bin/claude", + Path("/usr/local/bin/claude"), + Path.home() / ".local/bin/claude", + Path.home() / "node_modules/.bin/claude", + Path.home() / ".yarn/bin/claude", + ] for path in locations: if path.exists() and path.is_file():