feat(cli): add Bun compiled binary runtime asset management

Introduce runtime path abstraction for Bun-compiled binaries that extracts
assets to ~/.happy/runtime/{version} instead of using project paths. This
enables proper distribution of CLI as a self-contained binary with embedded
tools (ripgrep, difftastic) and scripts that are extracted at runtime.
This commit is contained in:
weishu
2025-12-20 16:44:58 +08:00
parent 80725a2d34
commit f0493ce68d
11 changed files with 276 additions and 25 deletions
+2 -2
View File
@@ -6,12 +6,12 @@ import { randomUUID } from "node:crypto";
import { logger } from "@/ui/logger";
import { claudeCheckSession } from "./utils/claudeCheckSession";
import { getProjectPath } from "./utils/path";
import { projectPath } from "@/projectPath";
import { runtimePath } from "@/projectPath";
import { systemPrompt } from "./utils/systemPrompt";
// Get Claude CLI path from project root
export const claudeCliPath = resolve(join(projectPath(), 'scripts', 'claude_local_launcher.cjs'))
export const claudeCliPath = resolve(join(runtimePath(), 'scripts', 'claude_local_launcher.cjs'))
export async function claudeLocal(opts: {
abort: AbortSignal,
+3 -3
View File
@@ -2,7 +2,7 @@ import { EnhancedMode, PermissionMode } from "./loop";
import { query, type QueryOptions as Options, type SDKMessage, type SDKSystemMessage, AbortError, SDKUserMessage } from '@/claude/sdk'
import { claudeCheckSession } from "./utils/claudeCheckSession";
import { join, resolve } from 'node:path';
import { projectPath } from "@/projectPath";
import { runtimePath } from "@/projectPath";
import { parseSpecialCommand } from "@/parsers/specialCommands";
import { logger } from "@/lib";
import { PushableAsyncIterable } from "@/utils/PushableAsyncIterable";
@@ -122,7 +122,7 @@ export async function claudeRemote(opts: {
executable: 'node',
abort: opts.signal,
pathToClaudeCodeExecutable: (() => {
return resolve(join(projectPath(), 'scripts', 'claude_remote_launcher.cjs'));
return resolve(join(runtimePath(), 'scripts', 'claude_remote_launcher.cjs'));
})(),
}
@@ -232,4 +232,4 @@ export async function claudeRemote(opts: {
} finally {
updateThinking(false);
}
}
}
+3 -3
View File
@@ -18,7 +18,7 @@ import { notifyDaemonSessionStarted } from '@/daemon/controlClient';
import { initialMachineMetadata } from '@/daemon/run';
import { startHappyServer } from '@/claude/utils/startHappyServer';
import { registerKillSessionHandler } from './registerKillSessionHandler';
import { projectPath } from '../projectPath';
import { runtimePath } from '../projectPath';
import { resolve } from 'node:path';
export interface StartOptions {
@@ -76,8 +76,8 @@ export async function runClaude(options: StartOptions = {}): Promise<void> {
machineId: machineId,
homeDir: os.homedir(),
happyHomeDir: configuration.happyHomeDir,
happyLibDir: projectPath(),
happyToolsDir: resolve(projectPath(), 'tools', 'unpacked'),
happyLibDir: runtimePath(),
happyToolsDir: resolve(runtimePath(), 'tools', 'unpacked'),
startedFromDaemon: options.startedBy === 'daemon',
hostPid: process.pid,
startedBy: options.startedBy || 'terminal',