Skip to content

Commit 7ac0b0d

Browse files
authored
chore: use bundled CLI rather than local one (#121)
1 parent 6f89d98 commit 7ac0b0d

File tree

3 files changed

+49
-58
lines changed

3 files changed

+49
-58
lines changed

forge.config.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ function copyNativeDependency(
9797
const config: ForgeConfig = {
9898
packagerConfig: {
9999
asar: {
100-
unpack: "{**/*.node,node_modules/@recallai/**}",
100+
unpack:
101+
"{**/*.node,node_modules/@recallai/**,**/.vite/build/cli.js,**/.vite/build/yoga.wasm}",
101102
},
102103
prune: false,
103104
name: "Array",

src/main/services/agent.ts

Lines changed: 16 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
import { execSync } from "node:child_process";
21
import { randomUUID } from "node:crypto";
3-
import { existsSync } from "node:fs";
4-
import { homedir } from "node:os";
52
import { join } from "node:path";
63
import { Agent, PermissionMode } from "@posthog/agent";
7-
import { type BrowserWindow, type IpcMainInvokeEvent, ipcMain } from "electron";
4+
import {
5+
app,
6+
type BrowserWindow,
7+
type IpcMainInvokeEvent,
8+
ipcMain,
9+
} from "electron";
810

911
interface AgentStartParams {
1012
taskId: string;
@@ -29,6 +31,15 @@ export interface TaskController {
2931
currentRunId?: string;
3032
}
3133

34+
function getClaudeCliPath(): string {
35+
const appPath = app.getAppPath();
36+
const isProduction = !appPath.includes("node_modules");
37+
38+
return isProduction
39+
? join(`${appPath}.unpacked`, ".vite/build/cli.js")
40+
: join(appPath, ".vite/build/cli.js");
41+
}
42+
3243
function resolvePermissionMode(
3344
mode: AgentStartParams["permissionMode"],
3445
): PermissionMode {
@@ -43,50 +54,6 @@ function resolvePermissionMode(
4354
return (match as PermissionMode | undefined) ?? PermissionMode.ACCEPT_EDITS;
4455
}
4556

46-
function findClaudeExecutable(): string | undefined {
47-
// Common installation locations based on Claude Code docs
48-
const commonPaths = [
49-
join(homedir(), ".local", "bin", "claude"), // Native installer location
50-
join(homedir(), ".claude", "local", "claude"), // Migrated local installation
51-
join(homedir(), ".volta", "bin", "claude"), // Volta (Node version manager)
52-
join(homedir(), ".nvm", "current", "bin", "claude"), // nvm
53-
"/opt/homebrew/bin/claude", // Homebrew on Apple Silicon
54-
"/usr/local/bin/claude", // Homebrew on Intel Mac / apt on Linux
55-
"/usr/bin/claude", // System installation
56-
];
57-
58-
// Add npm global installation paths
59-
try {
60-
const npmPrefix = execSync("npm config get prefix", {
61-
encoding: "utf-8",
62-
}).trim();
63-
if (npmPrefix) {
64-
commonPaths.push(join(npmPrefix, "bin", "claude"));
65-
}
66-
} catch {
67-
// npm not available or failed, continue
68-
}
69-
70-
// Check common paths first
71-
for (const path of commonPaths) {
72-
if (existsSync(path)) {
73-
return path;
74-
}
75-
}
76-
77-
// Fall back to using 'which' if available
78-
try {
79-
const path = execSync("which claude", { encoding: "utf-8" }).trim();
80-
if (path && existsSync(path)) {
81-
return path;
82-
}
83-
} catch {
84-
// which command failed, continue
85-
}
86-
87-
return undefined;
88-
}
89-
9057
export function registerAgentIpc(
9158
taskControllers: Map<string, TaskController>,
9259
getMainWindow: () => BrowserWindow | null,
@@ -227,13 +194,6 @@ export function registerAgentIpc(
227194

228195
const mcpOverrides = {};
229196

230-
const claudePath = findClaudeExecutable();
231-
if (!claudePath) {
232-
throw new Error(
233-
"Claude Code executable not found in PATH. Please install Claude Code CLI.",
234-
);
235-
}
236-
237197
await agent.runTask(posthogTaskId, {
238198
repositoryPath: repoPath,
239199
permissionMode: resolvedPermission,
@@ -243,10 +203,10 @@ export function registerAgentIpc(
243203
queryOverrides: {
244204
abortController,
245205
...(model ? { model } : {}),
246-
pathToClaudeCodeExecutable: claudePath,
247206
stderr: forwardClaudeStderr,
248207
env: envOverrides,
249208
mcpServers: mcpOverrides,
209+
pathToClaudeCodeExecutable: getClaudeCliPath(),
250210
},
251211
});
252212

vite.main.config.mts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,38 @@ function copyAgentTemplates(): Plugin {
5858
};
5959
}
6060

61+
/**
62+
* Copy Claude executable to the build directory
63+
*/
64+
function copyClaudeExecutable(): Plugin {
65+
return {
66+
name: "copy-claude-executable",
67+
writeBundle() {
68+
const sdkDir = join(
69+
__dirname,
70+
"node_modules/@posthog/agent/node_modules/@anthropic-ai/claude-agent-sdk",
71+
);
72+
73+
const files = ["cli.js", "yoga.wasm"];
74+
75+
for (const file of files) {
76+
const src = join(sdkDir, file);
77+
const dest = join(__dirname, ".vite/build", file);
78+
copyFileSync(src, dest);
79+
}
80+
81+
console.log("Copied Claude CLI and dependencies to build directory");
82+
},
83+
};
84+
}
85+
6186
export default defineConfig({
62-
plugins: [tsconfigPaths(), fixFilenameCircularRef(), copyAgentTemplates()],
87+
plugins: [
88+
tsconfigPaths(),
89+
fixFilenameCircularRef(),
90+
copyAgentTemplates(),
91+
copyClaudeExecutable(),
92+
],
6393
resolve: {
6494
alias: {
6595
"@": path.resolve(__dirname, "./src"),

0 commit comments

Comments
 (0)