From f97ce5ada158875809441e38c6a82058f2b84993 Mon Sep 17 00:00:00 2001 From: Vaclav Synacek Date: Tue, 3 Feb 2026 19:58:40 +0100 Subject: [PATCH] better bash detection on unix - also try PATH --- packages/coding-agent/src/utils/shell.ts | 34 +++++++++++++++++++----- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/packages/coding-agent/src/utils/shell.ts b/packages/coding-agent/src/utils/shell.ts index f8d2d7a1..8f43b0b5 100644 --- a/packages/coding-agent/src/utils/shell.ts +++ b/packages/coding-agent/src/utils/shell.ts @@ -7,14 +7,31 @@ import { SettingsManager } from "../core/settings-manager.js"; let cachedShellConfig: { shell: string; args: string[] } | null = null; /** - * Find bash executable on PATH (Windows) + * Find bash executable on PATH (cross-platform) */ function findBashOnPath(): string | null { + if (process.platform === "win32") { + // Windows: Use 'where' and verify file exists (where can return non-existent paths) + try { + const result = spawnSync("where", ["bash.exe"], { encoding: "utf-8", timeout: 5000 }); + if (result.status === 0 && result.stdout) { + const firstMatch = result.stdout.trim().split(/\r?\n/)[0]; + if (firstMatch && existsSync(firstMatch)) { + return firstMatch; + } + } + } catch { + // Ignore errors + } + return null; + } + + // Unix: Use 'which' and trust its output (handles Termux and special filesystems) try { - const result = spawnSync("where", ["bash.exe"], { encoding: "utf-8", timeout: 5000 }); + const result = spawnSync("which", ["bash"], { encoding: "utf-8", timeout: 5000 }); if (result.status === 0 && result.stdout) { const firstMatch = result.stdout.trim().split(/\r?\n/)[0]; - if (firstMatch && existsSync(firstMatch)) { + if (firstMatch) { return firstMatch; } } @@ -29,8 +46,7 @@ function findBashOnPath(): string | null { * Resolution order: * 1. User-specified shellPath in settings.json * 2. On Windows: Git Bash in known locations, then bash on PATH - * 3. On Unix: /bin/bash - * 4. Fallback: sh + * 3. On Unix: /bin/bash, then bash on PATH, then fallback to sh */ export function getShellConfig(): { shell: string; args: string[] } { if (cachedShellConfig) { @@ -86,12 +102,18 @@ export function getShellConfig(): { shell: string; args: string[] } { ); } - // Unix: prefer bash over sh + // Unix: try /bin/bash, then bash on PATH, then fallback to sh if (existsSync("/bin/bash")) { cachedShellConfig = { shell: "/bin/bash", args: ["-c"] }; return cachedShellConfig; } + const bashOnPath = findBashOnPath(); + if (bashOnPath) { + cachedShellConfig = { shell: bashOnPath, args: ["-c"] }; + return cachedShellConfig; + } + cachedShellConfig = { shell: "sh", args: ["-c"] }; return cachedShellConfig; }