fix: pass claude binary path to Agent SDK for packaged app

The SDK's query() function also needs to find the claude binary.
Added findClaudePath() in claude-client.ts and pass it via
pathToClaudeCodeExecutable option, fixing "Failed to create session"
in packaged builds where PATH is limited.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
7418andClaude Opus 4.6 committed 2026-02-06 22:23:18 +08:00
1 parent 2c5280cd77
commit 2e6fc2af7d
1 file changed
+53
+53
View File
@@ -14,6 +14,53 @@ import type {
} from '@anthropic-ai/claude-agent-sdk';
import type { ClaudeStreamOptions, SSEEvent, TokenUsage, MCPServerConfig, PermissionRequestEvent } from '@/types';
import { registerPendingPermission } from './permission-registry';
import { execFileSync } from 'child_process';
import os from 'os';
import path from 'path';
let cachedClaudePath: string | null | undefined;
function findClaudePath(): string | undefined {
if (cachedClaudePath !== undefined) return cachedClaudePath || undefined;
const home = os.homedir();
const candidates = [
'/usr/local/bin/claude',
'/opt/homebrew/bin/claude',
path.join(home, '.npm-global', 'bin', 'claude'),
path.join(home, '.local', 'bin', 'claude'),
path.join(home, '.claude', 'bin', 'claude'),
];
for (const p of candidates) {
try {
execFileSync(p, ['--version'], { timeout: 3000, stdio: 'pipe' });
cachedClaudePath = p;
return p;
} catch {
// not found
}
}
// Fallback: which claude
const extra = ['/usr/local/bin', '/opt/homebrew/bin', '/usr/bin', '/bin',
path.join(home, '.npm-global', 'bin'), path.join(home, '.nvm', 'current', 'bin'),
path.join(home, '.local', 'bin'), path.join(home, '.claude', 'bin')];
const current = (process.env.PATH || '').split(':');
for (const p of extra) { if (!current.includes(p)) current.push(p); }
try {
const result = execFileSync('/usr/bin/which', ['claude'], {
timeout: 3000, stdio: 'pipe',
env: { ...process.env, PATH: current.join(':') },
});
const found = result.toString().trim();
if (found) { cachedClaudePath = found; return found; }
} catch { /* not found */ }
cachedClaudePath = null;
return undefined;
}
/**
* Convert our MCPServerConfig to the SDK's McpStdioServerConfig format
@@ -92,6 +139,12 @@ export function streamClaude(options: ClaudeStreamOptions): ReadableStream<strin
permissionMode: (permissionMode as Options['permissionMode']) || 'acceptEdits',
};
// Find claude binary for packaged app where PATH is limited
const claudePath = findClaudePath();
if (claudePath) {
queryOptions.pathToClaudeCodeExecutable = claudePath;
}
if (model) {
queryOptions.model = model;
}