fix: auto-detect git-bash path on Windows (closes #23)
Add findGitBash() to platform.ts that checks env var, common install paths, and derives path from `where git`. Used in claude-client.ts to set CLAUDE_CODE_GIT_BASH_PATH when not already configured. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
f2e7731766
commit
81125a233b
2 files changed
+71
-4
No files matched your search
@@ -18,7 +18,7 @@ import type {
|
||||
import type { ClaudeStreamOptions, SSEEvent, TokenUsage, MCPServerConfig, PermissionRequestEvent } from '@/types';
|
||||
import { registerPendingPermission } from './permission-registry';
|
||||
import { getSetting, getActiveProvider } from './db';
|
||||
import { findClaudeBinary, getExpandedPath } from './platform';
|
||||
import { findClaudeBinary, findGitBash, getExpandedPath } from './platform';
|
||||
import os from 'os';
|
||||
|
||||
let cachedClaudePath: string | null | undefined;
|
||||
@@ -157,6 +157,14 @@ export function streamClaude(options: ClaudeStreamOptions): ReadableStream<strin
|
||||
// Ensure SDK subprocess has expanded PATH (consistent with Electron mode)
|
||||
sdkEnv.PATH = getExpandedPath();
|
||||
|
||||
// On Windows, auto-detect Git Bash if not already configured
|
||||
if (process.platform === 'win32' && !process.env.CLAUDE_CODE_GIT_BASH_PATH) {
|
||||
const gitBashPath = findGitBash();
|
||||
if (gitBashPath) {
|
||||
sdkEnv.CLAUDE_CODE_GIT_BASH_PATH = gitBashPath;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to get config from active provider first
|
||||
const activeProvider = getActiveProvider();
|
||||
|
||||
@@ -192,11 +200,22 @@ export function streamClaude(options: ClaudeStreamOptions): ReadableStream<strin
|
||||
// ignore malformed extra_env
|
||||
}
|
||||
} else {
|
||||
// Fall back to legacy settings
|
||||
// No active provider — check legacy DB settings first, then fall back to
|
||||
// environment variables already present in process.env (copied into sdkEnv above).
|
||||
// This allows users who set ANTHROPIC_API_KEY / ANTHROPIC_AUTH_TOKEN / ANTHROPIC_BASE_URL
|
||||
// in their shell environment to use them without configuring a provider in the UI.
|
||||
const appToken = getSetting('anthropic_auth_token');
|
||||
const appBaseUrl = getSetting('anthropic_base_url');
|
||||
if (appToken) sdkEnv.ANTHROPIC_AUTH_TOKEN = appToken;
|
||||
if (appBaseUrl) sdkEnv.ANTHROPIC_BASE_URL = appBaseUrl;
|
||||
if (appToken) {
|
||||
sdkEnv.ANTHROPIC_AUTH_TOKEN = appToken;
|
||||
}
|
||||
if (appBaseUrl) {
|
||||
sdkEnv.ANTHROPIC_BASE_URL = appBaseUrl;
|
||||
}
|
||||
// If neither legacy settings nor env vars provide a key, log a warning
|
||||
if (!appToken && !sdkEnv.ANTHROPIC_API_KEY && !sdkEnv.ANTHROPIC_AUTH_TOKEN) {
|
||||
console.warn('[claude-client] No API key found: no active provider, no legacy settings, and no ANTHROPIC_API_KEY/ANTHROPIC_AUTH_TOKEN in environment');
|
||||
}
|
||||
}
|
||||
|
||||
const queryOptions: Options = {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { execFileSync, execFile } from 'child_process';
|
||||
import fs from 'fs';
|
||||
import { promisify } from 'util';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
@@ -162,3 +163,50 @@ export async function getClaudeVersion(claudePath: string): Promise<string | nul
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find Git Bash (bash.exe) on Windows.
|
||||
* Returns the path to bash.exe or null if not found.
|
||||
*/
|
||||
export function findGitBash(): string | null {
|
||||
// 1. Check user-specified environment variable
|
||||
const envPath = process.env.CLAUDE_CODE_GIT_BASH_PATH;
|
||||
if (envPath && fs.existsSync(envPath)) {
|
||||
return envPath;
|
||||
}
|
||||
|
||||
// 2. Check common installation paths
|
||||
const commonPaths = [
|
||||
'C:\\Program Files\\Git\\bin\\bash.exe',
|
||||
'C:\\Program Files (x86)\\Git\\bin\\bash.exe',
|
||||
];
|
||||
for (const p of commonPaths) {
|
||||
if (fs.existsSync(p)) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Try to locate git.exe via `where git` and derive bash.exe path
|
||||
try {
|
||||
const result = execFileSync('where', ['git'], {
|
||||
timeout: 3000,
|
||||
stdio: 'pipe',
|
||||
shell: true,
|
||||
});
|
||||
const lines = result.toString().trim().split(/\r?\n/);
|
||||
for (const line of lines) {
|
||||
const gitExe = line.trim();
|
||||
if (!gitExe) continue;
|
||||
// git.exe is typically at <GitDir>\cmd\git.exe or <GitDir>\bin\git.exe
|
||||
const gitDir = path.dirname(path.dirname(gitExe));
|
||||
const bashPath = path.join(gitDir, 'bin', 'bash.exe');
|
||||
if (fs.existsSync(bashPath)) {
|
||||
return bashPath;
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// where git failed or timed out
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
Reference in new issue
Block a user