Skip to content

Commit 0047371

Browse files
benvinegarclaude
andauthored
fix: detect $bunfs virtual paths for daemon autostart in Bun binaries (#86)
* fix: detect $bunfs virtual paths for daemon autostart in Bun binaries The previous fix (PR #84) assumed argv[0] was the real binary and execPath was the embedded Bun runtime, but it's the opposite: Bun compiled binaries report argv as ["bun", "/$bunfs/root/<name>", ...] with execPath pointing to the real binary on disk. The old code matched the $bunfs virtual path against SCRIPT_ENTRYPOINT_PATTERN (because it contains "/"), spawning `bun /$bunfs/root/hunk mcp serve` — a path that doesn't exist outside the binary. Fix: detect the /$bunfs/ prefix in argv[1] and use execPath directly. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * style: format daemon launcher test Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent e36f63c commit 0047371

2 files changed

Lines changed: 19 additions & 20 deletions

File tree

src/mcp/daemonLauncher.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,31 +10,33 @@ export interface DaemonLaunchCommand {
1010
args: string[];
1111
}
1212

13+
/** Detect Bun's virtual filesystem prefix used inside compiled single-file executables. */
14+
const BUNFS_PREFIX = "/$bunfs/";
15+
1316
/** Resolve how the current Hunk process should launch a sibling `hunk mcp serve` daemon. */
1417
export function resolveDaemonLaunchCommand(
1518
argv = process.argv,
1619
execPath = process.execPath,
1720
): DaemonLaunchCommand {
1821
const entrypoint = argv[1];
1922

20-
// Running from source or a JS wrapper (bun src/main.tsx, node bin/hunk.cjs):
21-
// reuse the runtime + script entrypoint.
22-
if (entrypoint && !entrypoint.startsWith("-") && SCRIPT_ENTRYPOINT_PATTERN.test(entrypoint)) {
23+
// Bun-compiled single-file executables report argv as
24+
// ["bun", "/$bunfs/root/<name>", ...userArgs]
25+
// with execPath pointing to the real binary on disk.
26+
// Detect the virtual $bunfs path and use execPath directly.
27+
if (entrypoint && entrypoint.startsWith(BUNFS_PREFIX)) {
2328
return {
2429
command: execPath,
25-
args: [entrypoint, "mcp", "serve"],
30+
args: ["mcp", "serve"],
2631
};
2732
}
2833

29-
// Bun-compiled single-file executables set process.execPath to the Bun
30-
// runtime embedded inside the binary, not the binary itself. When
31-
// argv[0] differs from execPath, it is the actual compiled binary the
32-
// user invoked — use that to spawn the daemon.
33-
const invokedBinary = argv[0];
34-
if (invokedBinary && invokedBinary !== execPath) {
34+
// Running from source or a JS wrapper (bun src/main.tsx, node bin/hunk.cjs):
35+
// reuse the runtime + script entrypoint.
36+
if (entrypoint && !entrypoint.startsWith("-") && SCRIPT_ENTRYPOINT_PATTERN.test(entrypoint)) {
3537
return {
36-
command: invokedBinary,
37-
args: ["mcp", "serve"],
38+
command: execPath,
39+
args: [entrypoint, "mcp", "serve"],
3840
};
3941
}
4042

test/daemon-launcher.test.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,13 @@ describe("MCP daemon launcher", () => {
2626
});
2727
});
2828

29-
test("uses argv[0] for Bun-compiled binaries where execPath is the embedded runtime", () => {
30-
// In Bun single-file executables, process.execPath is the Bun runtime
31-
// inside the binary, while argv[0] is the actual compiled binary path.
29+
test("uses execPath for Bun-compiled binaries where argv contains $bunfs virtual paths", () => {
30+
// In Bun single-file executables, argv is ["bun", "/$bunfs/root/<name>", ...userArgs]
31+
// and execPath is the real binary on disk.
3232
expect(
3333
resolveDaemonLaunchCommand(
34-
[
35-
"/usr/local/lib/node_modules/hunkdiff/node_modules/hunkdiff-darwin-arm64/bin/hunk",
36-
"show",
37-
],
38-
"/usr/local/lib/node_modules/hunkdiff/node_modules/hunkdiff-darwin-arm64/bin/hunk___bun",
34+
["bun", "/$bunfs/root/hunk", "show"],
35+
"/usr/local/lib/node_modules/hunkdiff/node_modules/hunkdiff-darwin-arm64/bin/hunk",
3936
),
4037
).toEqual({
4138
command: "/usr/local/lib/node_modules/hunkdiff/node_modules/hunkdiff-darwin-arm64/bin/hunk",

0 commit comments

Comments
 (0)