diff --git a/WINDOWS.md b/WINDOWS.md index 9d0414ddc..c8c4a0d0c 100644 --- a/WINDOWS.md +++ b/WINDOWS.md @@ -79,34 +79,60 @@ Codebuff checks GitHub for the latest release on first run. This fails when: --- +### Issue: "Bash is required but was not found" Error + +**Symptom**: +``` +Bash is required but was not found on this Windows system. +``` + +**Cause**: +Codebuff requires bash for command execution. This error appears when: +- Git for Windows is not installed +- You're not running inside WSL +- bash.exe is not in your PATH + +**Solutions**: + +1. **Install Git for Windows** (recommended): + - Download from https://git-scm.com/download/win + - This installs `bash.exe` which Codebuff will automatically detect + - Works in PowerShell, CMD, or Git Bash terminals + +2. **Use WSL (Windows Subsystem for Linux)**: + - Provides full Linux environment with native bash + - Install: `wsl --install` in PowerShell (Admin) + - Run codebuff inside WSL for best compatibility + +3. **Set custom bash path** (advanced): + - If bash.exe is installed in a non-standard location: + ```powershell + set CODEBUFF_GIT_BASH_PATH=C:\path\to\bash.exe + ``` + +**Reference**: Issue [#274](https://github.com/CodebuffAI/codebuff/issues/274) + +--- + ### Issue: Git Commands Fail on Windows **Symptom**: Git operations (commit, rebase, complex commands) fail with syntax errors or unexpected behavior. **Cause**: -Codebuff uses Windows `cmd.exe` for command execution, which: -- Does not support bash syntax (HEREDOC, process substitution) -- Has limited quote escaping compared to bash -- Cannot execute complex git commands that work in Git Bash +Complex git commands may have issues with Windows path handling or shell escaping. **Solutions**: -1. **Install Git for Windows** (if not already installed): +1. **Ensure Git for Windows is installed**: - Download from https://git-scm.com/download/win - - Ensures git commands are available in PATH - -2. **Use Git Bash terminal** instead of PowerShell: - - Git Bash provides better compatibility with bash-style commands - - Launch Git Bash and run `codebuff` from there + - Codebuff uses bash.exe from Git for Windows for command execution -3. **Or use WSL (Windows Subsystem for Linux)**: +2. **Use WSL for complex operations**: - Provides full Linux environment with native bash - Install: `wsl --install` in PowerShell (Admin) - Run codebuff inside WSL for best compatibility -**Note**: Even when running in Git Bash, Codebuff spawns commands using `cmd.exe`. Using WSL provides the most reliable experience for git operations. - **Reference**: Issue [#274](https://github.com/CodebuffAI/codebuff/issues/274) --- diff --git a/sdk/src/run-state.ts b/sdk/src/run-state.ts index 14676ea34..12b896af7 100644 --- a/sdk/src/run-state.ts +++ b/sdk/src/run-state.ts @@ -502,7 +502,7 @@ export async function initialSessionState( shellConfigFiles: {}, systemInfo: { platform: process.platform, - shell: process.platform === 'win32' ? 'cmd.exe' : 'bash', + shell: 'bash', nodeVersion: process.version, arch: process.arch, homedir: os.homedir(), diff --git a/sdk/src/tools/run-terminal-command.ts b/sdk/src/tools/run-terminal-command.ts index dd2c974b9..87b819f28 100644 --- a/sdk/src/tools/run-terminal-command.ts +++ b/sdk/src/tools/run-terminal-command.ts @@ -1,4 +1,5 @@ import { spawn } from 'child_process' +import * as fs from 'fs' import * as os from 'os' import * as path from 'path' @@ -12,6 +13,75 @@ import type { CodebuffToolOutput } from '../../../common/src/tools/list' const COMMAND_OUTPUT_LIMIT = 50_000 +// Common locations where Git Bash might be installed on Windows +const GIT_BASH_COMMON_PATHS = [ + 'C:\\Program Files\\Git\\bin\\bash.exe', + 'C:\\Program Files (x86)\\Git\\bin\\bash.exe', + 'C:\\Git\\bin\\bash.exe', +] + +/** + * Find bash executable on Windows. + * Priority: + * 1. CODEBUFF_GIT_BASH_PATH environment variable + * 2. bash.exe in PATH (e.g., inside WSL or Git Bash terminal) + * 3. Common Git Bash installation locations + */ +function findWindowsBash(env: NodeJS.ProcessEnv): string | null { + // Check for user-specified path via environment variable + const customPath = env.CODEBUFF_GIT_BASH_PATH + if (customPath && fs.existsSync(customPath)) { + return customPath + } + + // Check if bash.exe is in PATH (works inside WSL or Git Bash) + const pathEnv = env.PATH || env.Path || '' + const pathDirs = pathEnv.split(path.delimiter) + + for (const dir of pathDirs) { + const bashPath = path.join(dir, 'bash.exe') + if (fs.existsSync(bashPath)) { + return bashPath + } + // Also check for just 'bash' (for WSL) + const bashPathNoExt = path.join(dir, 'bash') + if (fs.existsSync(bashPathNoExt)) { + return bashPathNoExt + } + } + + // Check common Git Bash installation locations + for (const commonPath of GIT_BASH_COMMON_PATHS) { + if (fs.existsSync(commonPath)) { + return commonPath + } + } + + return null +} + +/** + * Create an error message for Windows users when bash is not available. + */ +function createWindowsBashNotFoundError(): Error { + return new Error( + `Bash is required but was not found on this Windows system. + +To fix this, you have several options: + +1. Install Git for Windows (includes bash.exe): + Download from: https://git-scm.com/download/win + +2. Use WSL (Windows Subsystem for Linux): + Run in PowerShell (Admin): wsl --install + Then run Codebuff inside WSL. + +3. Set a custom bash path: + Set the CODEBUFF_GIT_BASH_PATH environment variable to your bash.exe location. + Example: set CODEBUFF_GIT_BASH_PATH=C:\\path\\to\\bash.exe`, + ) +} + export function runTerminalCommand({ command, process_type, @@ -31,18 +101,33 @@ export function runTerminalCommand({ return new Promise((resolve, reject) => { const isWindows = os.platform() === 'win32' - const shell = isWindows ? 'cmd.exe' : 'bash' - const shellArgs = isWindows ? ['/c'] : ['-c'] + const processEnv = { + ...getSystemProcessEnv(), + ...(env ?? {}), + } as NodeJS.ProcessEnv + + let shell: string + let shellArgs: string[] + + if (isWindows) { + const bashPath = findWindowsBash(processEnv) + if (!bashPath) { + reject(createWindowsBashNotFoundError()) + return + } + shell = bashPath + shellArgs = ['-c'] + } else { + shell = 'bash' + shellArgs = ['-c'] + } // Resolve cwd to absolute path const resolvedCwd = path.resolve(cwd) const childProcess = spawn(shell, [...shellArgs, command], { cwd: resolvedCwd, - env: { - ...getSystemProcessEnv(), - ...(env ?? {}), - } as NodeJS.ProcessEnv, + env: processEnv, stdio: 'pipe', })