From d3cdd489be78ed8d328600ebd8c36567dd11f474 Mon Sep 17 00:00:00 2001 From: Austin Liu <193228693+Dingding-leo@users.noreply.github.com> Date: Thu, 23 Jul 2026 23:36:28 +0930 Subject: [PATCH] fix(cli): resolve claude.cmd on Windows in omniroute launch (#8246) (#8283) spawn('claude') without shell:true cannot resolve the .cmd shim that npm installs on Windows, causing ENOENT and a misleading 'not found in PATH' error. Use claude.cmd + shell:true + windowsHide on win32, matching the pattern already used in launch-codex.mjs. Co-authored-by: Austin Liu --- bin/cli/commands/launch.mjs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/bin/cli/commands/launch.mjs b/bin/cli/commands/launch.mjs index 2280819b5f..b737786541 100644 --- a/bin/cli/commands/launch.mjs +++ b/bin/cli/commands/launch.mjs @@ -106,10 +106,10 @@ export async function runLaunchCommand(opts = {}, claudeArgs = []) { if (!res.ok) throw new Error(`status ${res.status}`); } catch { console.error( - (t("launch.notRunning") || "OmniRoute is not reachable at {port}. Start it with 'omniroute serve'.").replace( - "{port}", - baseUrl - ) + ( + t("launch.notRunning") || + "OmniRoute is not reachable at {port}. Start it with 'omniroute serve'." + ).replace("{port}", baseUrl) ); return 1; } @@ -120,7 +120,14 @@ export async function runLaunchCommand(opts = {}, claudeArgs = []) { const env = buildClaudeEnv(process.env, baseUrl, authToken, { configDir }); return await new Promise((resolve) => { - const child = spawn("claude", claudeArgs, { env, stdio: "inherit" }); + // #8246: on Windows, npm installs claude as a .cmd shim — spawn() without + // shell:true cannot resolve PATHEXT shims and fails with ENOENT. + const claudeCommand = process.platform === "win32" ? "claude.cmd" : "claude"; + const child = spawn(claudeCommand, claudeArgs, { + env, + stdio: "inherit", + ...(process.platform === "win32" ? { shell: true, windowsHide: true } : {}), + }); child.on("error", (err) => { if (err && err.code === "ENOENT") { console.error(t("launch.notFound") || "The 'claude' CLI was not found in PATH."); @@ -142,7 +149,10 @@ export function registerLaunch(program) { ) .option("--port ", t("serve.port") || "Proxy port", "20128") .option("--remote ", "Remote OmniRoute base URL (overrides --port and the active context)") - .option("--profile ", "Claude Code profile to use (CLAUDE_CONFIG_DIR ~/.claude/profiles/)") + .option( + "--profile ", + "Claude Code profile to use (CLAUDE_CONFIG_DIR ~/.claude/profiles/)" + ) .option("--token ", t("launch.token") || "Token Claude sends (ANTHROPIC_AUTH_TOKEN)") .option("--api-key ", "Alias for --token (OmniRoute access token / API key)") .allowUnknownOption(true)