diff --git a/src/main/ipc/handlers/git.ts b/src/main/ipc/handlers/git.ts index 6018c69f..2aeb5240 100644 --- a/src/main/ipc/handlers/git.ts +++ b/src/main/ipc/handlers/git.ts @@ -4,6 +4,7 @@ import path from 'path'; import { execFileNoThrow } from '../../utils/execFile'; import { logger } from '../../utils/logger'; import { withIpcErrorLogging, createIpcHandler, CreateHandlerOptions } from '../../utils/ipcHandler'; +import { getExpandedEnv } from '../../utils/cliDetection'; import { parseGitBranches, parseGitTags, @@ -524,9 +525,26 @@ export function registerGitHandlers(): void { ipcMain.handle('git:checkGhCli', withIpcErrorLogging( handlerOpts('checkGhCli'), async (ghPath?: string) => { - // Use custom path if provided, otherwise fall back to 'gh' (expects it in PATH) - const ghCommand = ghPath || 'gh'; - logger.debug(`Checking gh CLI at: ${ghCommand} (custom path: ${ghPath || 'none'})`, LOG_CONTEXT); + // Use custom path if provided + let ghCommand = ghPath || 'gh'; + logger.debug(`Checking gh CLI (custom path: ${ghPath || 'auto-detect'})`, LOG_CONTEXT); + + // Auto-detect gh location if no custom path provided + if (!ghPath) { + // Use platform-appropriate command: 'where' on Windows, 'which' on Unix + const command = process.platform === 'win32' ? 'where' : 'which'; + const env = getExpandedEnv(); // Expanded PATH for finding binaries + const whichResult = await execFileNoThrow(command, ['gh'], undefined, env); + + if (whichResult.exitCode === 0 && whichResult.stdout.trim()) { + // On Windows, 'where' can return multiple paths - take the first one + ghCommand = whichResult.stdout.trim().split('\n')[0]; + logger.debug(`Auto-detected gh CLI at: ${ghCommand}`, LOG_CONTEXT); + } else { + // If detection fails, fall back to 'gh' and let execFileNoThrow handle the error + logger.debug('Auto-detection failed, using default "gh" command', LOG_CONTEXT); + } + } // Check if gh is installed by running gh --version const versionResult = await execFileNoThrow(ghCommand, ['--version']); diff --git a/src/main/utils/cliDetection.ts b/src/main/utils/cliDetection.ts index 024e128f..dbf13c06 100644 --- a/src/main/utils/cliDetection.ts +++ b/src/main/utils/cliDetection.ts @@ -9,7 +9,7 @@ let cloudflaredPathCache: string | null = null; * Build an expanded PATH that includes common binary installation locations. * This is necessary because packaged Electron apps don't inherit shell environment. */ -function getExpandedEnv(): NodeJS.ProcessEnv { +export function getExpandedEnv(): NodeJS.ProcessEnv { const home = os.homedir(); const env = { ...process.env }; const isWindows = process.platform === 'win32';