11import { spawn } from 'child_process'
2+ import * as fs from 'fs'
23import * as os from 'os'
34import * as path from 'path'
45
@@ -12,6 +13,75 @@ import type { CodebuffToolOutput } from '../../../common/src/tools/list'
1213
1314const COMMAND_OUTPUT_LIMIT = 50_000
1415
16+ // Common locations where Git Bash might be installed on Windows
17+ const GIT_BASH_COMMON_PATHS = [
18+ 'C:\\Program Files\\Git\\bin\\bash.exe' ,
19+ 'C:\\Program Files (x86)\\Git\\bin\\bash.exe' ,
20+ 'C:\\Git\\bin\\bash.exe' ,
21+ ]
22+
23+ /**
24+ * Find bash executable on Windows.
25+ * Priority:
26+ * 1. CODEBUFF_GIT_BASH_PATH environment variable
27+ * 2. bash.exe in PATH (e.g., inside WSL or Git Bash terminal)
28+ * 3. Common Git Bash installation locations
29+ */
30+ function findWindowsBash ( env : NodeJS . ProcessEnv ) : string | null {
31+ // Check for user-specified path via environment variable
32+ const customPath = env . CODEBUFF_GIT_BASH_PATH
33+ if ( customPath && fs . existsSync ( customPath ) ) {
34+ return customPath
35+ }
36+
37+ // Check if bash.exe is in PATH (works inside WSL or Git Bash)
38+ const pathEnv = env . PATH || env . Path || ''
39+ const pathDirs = pathEnv . split ( path . delimiter )
40+
41+ for ( const dir of pathDirs ) {
42+ const bashPath = path . join ( dir , 'bash.exe' )
43+ if ( fs . existsSync ( bashPath ) ) {
44+ return bashPath
45+ }
46+ // Also check for just 'bash' (for WSL)
47+ const bashPathNoExt = path . join ( dir , 'bash' )
48+ if ( fs . existsSync ( bashPathNoExt ) ) {
49+ return bashPathNoExt
50+ }
51+ }
52+
53+ // Check common Git Bash installation locations
54+ for ( const commonPath of GIT_BASH_COMMON_PATHS ) {
55+ if ( fs . existsSync ( commonPath ) ) {
56+ return commonPath
57+ }
58+ }
59+
60+ return null
61+ }
62+
63+ /**
64+ * Create an error message for Windows users when bash is not available.
65+ */
66+ function createWindowsBashNotFoundError ( ) : Error {
67+ return new Error (
68+ `Bash is required but was not found on this Windows system.
69+
70+ To fix this, you have several options:
71+
72+ 1. Install Git for Windows (includes bash.exe):
73+ Download from: https://git-scm.com/download/win
74+
75+ 2. Use WSL (Windows Subsystem for Linux):
76+ Run in PowerShell (Admin): wsl --install
77+ Then run Codebuff inside WSL.
78+
79+ 3. Set a custom bash path:
80+ Set the CODEBUFF_GIT_BASH_PATH environment variable to your bash.exe location.
81+ Example: set CODEBUFF_GIT_BASH_PATH=C:\\path\\to\\bash.exe` ,
82+ )
83+ }
84+
1585export function runTerminalCommand ( {
1686 command,
1787 process_type,
@@ -31,18 +101,33 @@ export function runTerminalCommand({
31101
32102 return new Promise ( ( resolve , reject ) => {
33103 const isWindows = os . platform ( ) === 'win32'
34- const shell = isWindows ? 'cmd.exe' : 'bash'
35- const shellArgs = isWindows ? [ '/c' ] : [ '-c' ]
104+ const processEnv = {
105+ ...getSystemProcessEnv ( ) ,
106+ ...( env ?? { } ) ,
107+ } as NodeJS . ProcessEnv
108+
109+ let shell : string
110+ let shellArgs : string [ ]
111+
112+ if ( isWindows ) {
113+ const bashPath = findWindowsBash ( processEnv )
114+ if ( ! bashPath ) {
115+ reject ( createWindowsBashNotFoundError ( ) )
116+ return
117+ }
118+ shell = bashPath
119+ shellArgs = [ '-c' ]
120+ } else {
121+ shell = 'bash'
122+ shellArgs = [ '-c' ]
123+ }
36124
37125 // Resolve cwd to absolute path
38126 const resolvedCwd = path . resolve ( cwd )
39127
40128 const childProcess = spawn ( shell , [ ...shellArgs , command ] , {
41129 cwd : resolvedCwd ,
42- env : {
43- ...getSystemProcessEnv ( ) ,
44- ...( env ?? { } ) ,
45- } as NodeJS . ProcessEnv ,
130+ env : processEnv ,
46131 stdio : 'pipe' ,
47132 } )
48133
0 commit comments