From a2372858084ee8d3ac624305809ca5b5c1ba5cf4 Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Mon, 23 Mar 2026 22:04:19 +0700 Subject: [PATCH] fix(desktop): resolve to Helper app for daemon child processes on macOS When packaged, Electron's process.execPath points to the main app binary which inherits the full app entitlements and UI lifecycle. Resolve to the Helper binary instead so daemon child processes run without inheriting the main app's entitlement/UI baggage. --- packages/desktop/src/daemon/runtime-paths.ts | 26 +++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/packages/desktop/src/daemon/runtime-paths.ts b/packages/desktop/src/daemon/runtime-paths.ts index 5f6a4ea5c..18c09e9a6 100644 --- a/packages/desktop/src/daemon/runtime-paths.ts +++ b/packages/desktop/src/daemon/runtime-paths.ts @@ -168,6 +168,30 @@ export function resolveCliEntrypoint(): NodeEntrypointSpec { }; } +function resolveNodeExecPath(): string { + if (app.isPackaged && process.platform === "darwin") { + const marker = ".app/Contents/MacOS/"; + const markerIndex = process.execPath.indexOf(marker); + if (markerIndex !== -1) { + const bundleRoot = process.execPath.substring(0, markerIndex + ".app".length); + const name = path.basename(process.execPath); + const helperPath = path.join( + bundleRoot, + "Contents", + "Frameworks", + `${name} Helper.app`, + "Contents", + "MacOS", + `${name} Helper`, + ); + if (existsSync(helperPath)) { + return helperPath; + } + } + } + return process.execPath; +} + export function createNodeEntrypointInvocation(input: { entrypoint: NodeEntrypointSpec; argvMode: NodeEntrypointArgvMode; @@ -175,7 +199,7 @@ export function createNodeEntrypointInvocation(input: { baseEnv: NodeJS.ProcessEnv; }): NodeEntrypointInvocation { return createSharedNodeEntrypointInvocation({ - execPath: process.execPath, + execPath: resolveNodeExecPath(), isPackaged: app.isPackaged, packagedRunnerPath: app.isPackaged ? assertPathExists({