From f40646ebf846c77950fbd2434868893cc4e78c0f Mon Sep 17 00:00:00 2001
From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
Date: Fri, 13 Nov 2026 18:59:36 -0800
Subject: [PATCH] perf(cli): use packaged Node for ordinary Mac commands
---
resources/darwin/bin/orca | 46 ++++++++++-
src/cli/index.ts | 1 +
.../authoring/plugin-test-node.test.ts | 33 ++++++--
src/cli/plugins/authoring/plugin-test-node.ts | 18 +++--
src/cli/profiles/profile-state.ts | 2 +
src/cli/runtime/cli-lifecycle-handlers.ts | 2 +
src/cli/runtime/client.ts | 2 +
.../runtime/packaged-cli-interpreter.test.ts | 59 ++++++++++++++
src/cli/runtime/packaged-cli-interpreter.ts | 32 ++++++++
src/cli/server/serve-service.ts | 7 +-
.../packaged-mac-cli-interpreter.test.ts | 78 +++++++++++++++++++
11 files changed, 265 insertions(+), 15 deletions(-)
create mode 100644 src/cli/runtime/packaged-cli-interpreter.test.ts
create mode 100644 src/cli/runtime/packaged-cli-interpreter.ts
create mode 100644 src/main/cli/packaged-assets/packaged-mac-cli-interpreter.test.ts
diff --git a/resources/darwin/bin/orca b/resources/darwin/bin/orca
index fd415b25ccc..accc7298f67 100755
--- a/resources/darwin/bin/orca
+++ b/resources/darwin/bin/orca
@@ -20,7 +20,6 @@ fi
CONTENTS="$APP_PATH/Contents"
ELECTRON="$CONTENTS/MacOS/Orca"
-# The unpacked entrypoint runs directly in Electron's Node mode.
CLI="$CONTENTS/Resources/app.asar.unpacked/out/cli/index.js"
export ORCA_NODE_OPTIONS="${NODE_OPTIONS-}"
@@ -28,4 +27,49 @@ export ORCA_NODE_REPL_EXTERNAL_MODULE="${NODE_REPL_EXTERNAL_MODULE-}"
unset NODE_OPTIONS
unset NODE_REPL_EXTERNAL_MODULE
+function plist_version() {
+ local file=$1 key=$2 line found=0 remaining=256
+ REPLY=
+ [ -r "$file" ] || return 1
+ while IFS= read -r line; do
+ [ "$remaining" -gt 0 ] || return 1
+ remaining=$((remaining - 1))
+ if [[ $line == *"$key"* ]]; then
+ found=1
+ line=${line#*}
+ fi
+ if [ "$found" -eq 1 ]; then
+ if [[ $line =~ ^[[:space:]]*\([0-9]{1,3}\.[0-9]{1,3}(\.[0-9]{1,3})?)\[[:space:]]*$ ]]; then
+ REPLY=${BASH_REMATCH[1]}
+ return 0
+ fi
+ [[ $line =~ ^[[:space:]]*$ ]] || return 1
+ fi
+ done < "$file"
+ return 1
+}
+
+function supports_packaged_node() {
+ local minimum current index required actual
+ plist_version "$NODE_CONTENTS/Info.plist" LSMinimumSystemVersion || return 1
+ IFS=. read -r -a minimum <<< "$REPLY"
+ plist_version /System/Library/CoreServices/SystemVersion.plist ProductVersion || return 1
+ IFS=. read -r -a current <<< "$REPLY"
+ for index in 0 1 2; do
+ required=$((10#${minimum[$index]:-0}))
+ actual=$((10#${current[$index]:-0}))
+ [ "$actual" -gt "$required" ] && return 0
+ [ "$actual" -lt "$required" ] && return 1
+ done
+ return 0
+}
+
+NODE_CONTENTS="$CONTENTS/Helpers/Orca Agents.app/Contents"
+NODE="$NODE_CONTENTS/MacOS/Orca Agents"
+if [ -x "$NODE" ] && supports_packaged_node; then
+ export ORCA_CLI_ELECTRON_EXECUTABLE="$ELECTRON"
+ unset ELECTRON_RUN_AS_NODE
+ exec "$NODE" "$CLI" "$@"
+fi
+
ELECTRON_RUN_AS_NODE=1 exec "$ELECTRON" "$CLI" "$@"
diff --git a/src/cli/index.ts b/src/cli/index.ts
index 862d3b443d1..b7d5e5c6ae6 100644
--- a/src/cli/index.ts
+++ b/src/cli/index.ts
@@ -1,4 +1,5 @@
#!/usr/bin/env node
+import './runtime/packaged-cli-interpreter'
import {
findCommandSpec,
isCommandGroup,
diff --git a/src/cli/plugins/authoring/plugin-test-node.test.ts b/src/cli/plugins/authoring/plugin-test-node.test.ts
index 9e4f174c6d7..da64d711343 100644
--- a/src/cli/plugins/authoring/plugin-test-node.test.ts
+++ b/src/cli/plugins/authoring/plugin-test-node.test.ts
@@ -1,7 +1,20 @@
-import { describe, expect, it } from 'vitest'
+import { afterEach, describe, expect, it, vi } from 'vitest'
import type { ProcessResult, ProcessSpec } from '@orca/process-host/process-spec'
import { selectPluginTestNode } from './plugin-test-node'
+const { runDefault, packaged } = vi.hoisted(() => {
+ const packaged: { path: string | null } = { path: null }
+ return { runDefault: vi.fn(), packaged }
+})
+vi.mock('@orca/process-host', () => ({ runProcess: runDefault }))
+vi.mock('../../runtime/packaged-cli-interpreter', () => ({
+ getPackagedElectronExecutable: () => packaged.path
+}))
+afterEach(() => {
+ packaged.path = null
+ vi.clearAllMocks()
+})
+
const ORCA = { execPath: '/Applications/Orca.app/Contents/MacOS/Orca', version: 'v22.9.0' }
function answering(stdout: string | Error, code = 0) {
@@ -17,9 +30,19 @@ function answering(stdout: string | Error, code = 0) {
}
describe('selectPluginTestNode', () => {
+ it('uses root Electron for the fallback child while the packaged CLI runs on Node', async () => {
+ packaged.path = '/Applications/Orca.app/Contents/MacOS/Orca'
+ runDefault.mockRejectedValue(new Error('spawn node ENOENT'))
+ expect(await selectPluginTestNode()).toMatchObject({
+ program: '/Applications/Orca.app/Contents/MacOS/Orca',
+ env: { ELECTRON_RUN_AS_NODE: '1' },
+ source: 'orca'
+ })
+ })
+
it('uses a new enough system node by the absolute path it reports, probed outside the plugin', async () => {
const probe = answering('v20.6.0 /usr/local/bin/node\n')
- const node = await selectPluginTestNode({ ...ORCA, electron: '38.0.0', run: probe.run })
+ const node = await selectPluginTestNode({ ...ORCA, electron: true, run: probe.run })
expect(node).toEqual({
program: '/usr/local/bin/node',
env: {},
@@ -32,7 +55,7 @@ describe('selectPluginTestNode', () => {
it('keeps a Windows path with spaces whole', async () => {
const probe = answering('v22.1.0 C:\\Program Files\\nodejs\\node.exe\r\n')
- const node = await selectPluginTestNode({ ...ORCA, electron: '38.0.0', run: probe.run })
+ const node = await selectPluginTestNode({ ...ORCA, electron: true, run: probe.run })
expect(node.program).toBe('C:\\Program Files\\nodejs\\node.exe')
})
@@ -42,7 +65,7 @@ describe('selectPluginTestNode', () => {
['failing', answering('', 1)],
['answering garbage', answering('nope')]
])('falls back to Orca as Node when the system node is %s', async (_reason, probe) => {
- const node = await selectPluginTestNode({ ...ORCA, electron: '38.0.0', run: probe.run })
+ const node = await selectPluginTestNode({ ...ORCA, electron: true, run: probe.run })
expect(node).toEqual({
program: ORCA.execPath,
env: { ELECTRON_RUN_AS_NODE: '1' },
@@ -53,7 +76,7 @@ describe('selectPluginTestNode', () => {
it('needs no Electron switch when the CLI itself runs on plain Node', async () => {
const probe = answering(new Error('spawn node ENOENT'))
- const node = await selectPluginTestNode({ ...ORCA, electron: undefined, run: probe.run })
+ const node = await selectPluginTestNode({ ...ORCA, electron: false, run: probe.run })
expect(node.env).toEqual({})
})
})
diff --git a/src/cli/plugins/authoring/plugin-test-node.ts b/src/cli/plugins/authoring/plugin-test-node.ts
index 7f774fdca08..0632d9b9030 100644
--- a/src/cli/plugins/authoring/plugin-test-node.ts
+++ b/src/cli/plugins/authoring/plugin-test-node.ts
@@ -1,3 +1,4 @@
+import { getPackagedElectronExecutable } from '../../runtime/packaged-cli-interpreter'
import { mkdtemp, rm } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
@@ -21,15 +22,18 @@ type Dependencies = {
/** The runtime this CLI runs on: Electron as Node in a packaged app, or Node in development. */
execPath: string
version: string
- electron: string | undefined
+ electron: boolean
}
-const defaults = (): Dependencies => ({
- run: runProcess,
- execPath: process.execPath,
- version: process.version,
- electron: process.versions.electron
-})
+const defaults = (): Dependencies => {
+ const packagedElectron = getPackagedElectronExecutable()
+ return {
+ run: runProcess,
+ execPath: packagedElectron ?? process.execPath,
+ version: process.version,
+ electron: Boolean(packagedElectron || process.versions.electron)
+ }
+}
function supports(version: string): boolean {
const [major = 0, minor = 0] = version.replace(/^v/, '').split('.').map(Number)
diff --git a/src/cli/profiles/profile-state.ts b/src/cli/profiles/profile-state.ts
index 4b1b8cb7a2d..eeab936abcc 100644
--- a/src/cli/profiles/profile-state.ts
+++ b/src/cli/profiles/profile-state.ts
@@ -1,3 +1,4 @@
+import { reenterPackagedElectron } from '../runtime/packaged-cli-interpreter'
import { z } from 'zod'
import type { CommandHandler } from '../dispatch/dispatch'
import { printResult } from '../output/command-result-output'
@@ -119,6 +120,7 @@ export const PROFILE_STATE_HANDLERS: Record = {
rejectProfileStateRemoteSelection(flags)
const selector = parseSelector(flags)
const profileId = parseProfileId(flags)
+ reenterPackagedElectron()
const userDataPath = getDefaultUserDataPath()
let result: ProfileStateRollbackResult
if (canLaunchProfileStateRecovery()) {
diff --git a/src/cli/runtime/cli-lifecycle-handlers.ts b/src/cli/runtime/cli-lifecycle-handlers.ts
index ff339c7dd90..f826dd189b0 100644
--- a/src/cli/runtime/cli-lifecycle-handlers.ts
+++ b/src/cli/runtime/cli-lifecycle-handlers.ts
@@ -1,3 +1,4 @@
+import { reenterPackagedElectron } from './packaged-cli-interpreter'
import { spawn } from 'node:child_process'
import { resolve } from 'node:path'
import type { CommandHandler } from '../dispatch/dispatch'
@@ -138,6 +139,7 @@ export const CORE_HANDLERS: Record = {
}
const port = getOptionalServePort(flags)
const pairingAddressValue = flags.get('pairing-address')
+ reenterPackagedElectron()
const exitCode = await serveOrcaApp({
json,
port,
diff --git a/src/cli/runtime/client.ts b/src/cli/runtime/client.ts
index 4c07a3fb815..c0f8f2f45cf 100644
--- a/src/cli/runtime/client.ts
+++ b/src/cli/runtime/client.ts
@@ -1,3 +1,4 @@
+import { reenterPackagedElectron } from './packaged-cli-interpreter'
import { randomUUID } from 'node:crypto'
import type { CliStatusResult, RuntimeStatus } from '../../shared/runtime-types'
import { runtimeHostConnectionState } from '../../shared/remote-runtime/host-status/runtime-host-connection-state'
@@ -307,6 +308,7 @@ export class RuntimeClient {
if (this.remote) {
return this.getCliStatus()
}
+ reenterPackagedElectron()
return openLocalOrca(
() => this.getCliStatus(),
(options) => this.call<{ requested: boolean }>('desktop.openWindowInBackground', {}, options),
diff --git a/src/cli/runtime/packaged-cli-interpreter.test.ts b/src/cli/runtime/packaged-cli-interpreter.test.ts
new file mode 100644
index 00000000000..d9fe68f1b82
--- /dev/null
+++ b/src/cli/runtime/packaged-cli-interpreter.test.ts
@@ -0,0 +1,59 @@
+import { afterEach, expect, it, vi } from 'vitest'
+import { accessSync } from 'node:fs'
+import type * as Fs from 'node:fs'
+
+vi.mock('node:fs', async (importOriginal) => ({
+ ...(await importOriginal()),
+ accessSync: vi.fn()
+}))
+
+const platform = process.platform
+const argv = process.argv
+afterEach(() => {
+ Object.defineProperty(process, 'platform', { value: platform })
+ process.argv = argv
+ vi.unstubAllEnvs()
+ vi.restoreAllMocks()
+ vi.mocked(accessSync).mockReset()
+ vi.resetModules()
+})
+
+it('consumes the shim marker before replacing a lifecycle command with root Electron', async () => {
+ Object.defineProperty(process, 'platform', { value: 'darwin' })
+ process.argv = ['/helper/node', '/app/cli.js', 'open', '--json']
+ vi.stubEnv('ORCA_CLI_ELECTRON_EXECUTABLE', '/Applications/Orca.app/Contents/MacOS/Orca')
+ vi.stubEnv('ORCA_NODE_OPTIONS', '--max-old-space-size=2048')
+ const replaced = new Error('Process replaced')
+ let invocation:
+ | { file: string; args: readonly string[] | undefined; env: NodeJS.ProcessEnv | undefined }
+ | undefined
+ vi.spyOn(process, 'execve').mockImplementation((file, args, env) => {
+ invocation = { file, args, env }
+ throw replaced
+ })
+ vi.resetModules()
+ const { reenterPackagedElectron } = await import('./packaged-cli-interpreter')
+ expect(process.env.ORCA_CLI_ELECTRON_EXECUTABLE).toBeUndefined()
+ expect(reenterPackagedElectron).toThrow(replaced)
+ expect(invocation).toMatchObject({
+ file: '/Applications/Orca.app/Contents/MacOS/Orca',
+ args: ['/Applications/Orca.app/Contents/MacOS/Orca', '/app/cli.js', 'open', '--json'],
+ env: { ELECTRON_RUN_AS_NODE: '1', ORCA_NODE_OPTIONS: '--max-old-space-size=2048' }
+ })
+ expect(invocation?.env).not.toHaveProperty('ORCA_CLI_ELECTRON_EXECUTABLE')
+})
+
+it('reports an unavailable app before attempting native process replacement', async () => {
+ Object.defineProperty(process, 'platform', { value: 'darwin' })
+ process.argv = ['/helper/node', '/app/cli.js', 'open']
+ vi.stubEnv('ORCA_CLI_ELECTRON_EXECUTABLE', '/missing/Orca')
+ vi.mocked(accessSync).mockImplementation(() => {
+ throw new Error('ENOENT')
+ })
+ vi.spyOn(process, 'execve').mockImplementation(() => {
+ throw new Error('Native replacement attempted')
+ })
+ vi.resetModules()
+ const { reenterPackagedElectron } = await import('./packaged-cli-interpreter')
+ expect(reenterPackagedElectron).toThrow('The installed Orca app is unavailable')
+})
diff --git a/src/cli/runtime/packaged-cli-interpreter.ts b/src/cli/runtime/packaged-cli-interpreter.ts
new file mode 100644
index 00000000000..44d211a04e1
--- /dev/null
+++ b/src/cli/runtime/packaged-cli-interpreter.ts
@@ -0,0 +1,32 @@
+import { isAbsolute } from 'node:path'
+import { accessSync, constants } from 'node:fs'
+import { RuntimeClientError } from './types'
+
+const electron = process.env.ORCA_CLI_ELECTRON_EXECUTABLE
+delete process.env.ORCA_CLI_ELECTRON_EXECUTABLE
+const packagedElectron =
+ process.platform === 'darwin' && electron && isAbsolute(electron) ? electron : null
+
+export function getPackagedElectronExecutable(): string | null {
+ return packagedElectron
+}
+
+/** App-owned operations retain the root app's update and process identity. */
+export function reenterPackagedElectron(): void {
+ if (!packagedElectron) {
+ return
+ }
+ try {
+ accessSync(packagedElectron, constants.X_OK)
+ accessSync(process.argv[1], constants.R_OK)
+ } catch {
+ throw new RuntimeClientError(
+ 'app_not_found',
+ 'The installed Orca app is unavailable. Reinstall Orca and try again.'
+ )
+ }
+ process.execve(packagedElectron, [packagedElectron, ...process.argv.slice(1)], {
+ ...process.env,
+ ELECTRON_RUN_AS_NODE: '1'
+ })
+}
diff --git a/src/cli/server/serve-service.ts b/src/cli/server/serve-service.ts
index d1052fe34a0..167b2aec8b1 100644
--- a/src/cli/server/serve-service.ts
+++ b/src/cli/server/serve-service.ts
@@ -1,3 +1,4 @@
+import { reenterPackagedElectron } from '../runtime/packaged-cli-interpreter'
import { existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs'
import { homedir } from 'node:os'
import { dirname } from 'node:path'
@@ -268,7 +269,7 @@ export const SERVE_SERVICE_HANDLERS: Record = {
'Use either --allow-public or --refuse-public, not both.'
)
}
- const result = await installServeService({
+ const options = {
command: optionalString(flags.get('command')),
// Validate before launchd can loop on a bad value and trip the supervisor brake.
port: getOptionalServePort(flags),
@@ -277,7 +278,9 @@ export const SERVE_SERVICE_HANDLERS: Record = {
allowPublic: flags.get('allow-public') === true,
refusePublic: flags.get('refuse-public') === true,
dryRun: flags.get('dry-run') === true
- })
+ }
+ reenterPackagedElectron()
+ const result = await installServeService(options)
emit(result, json, formatServeServiceInstall)
},
'serve service status': async ({ json }) => {
diff --git a/src/main/cli/packaged-assets/packaged-mac-cli-interpreter.test.ts b/src/main/cli/packaged-assets/packaged-mac-cli-interpreter.test.ts
new file mode 100644
index 00000000000..379b442cbd0
--- /dev/null
+++ b/src/main/cli/packaged-assets/packaged-mac-cli-interpreter.test.ts
@@ -0,0 +1,78 @@
+import { execFile } from 'node:child_process'
+import { chmod, mkdir, mkdtemp, readFile, realpath, rm, writeFile } from 'node:fs/promises'
+import { tmpdir } from 'node:os'
+import { join } from 'node:path'
+import { promisify } from 'node:util'
+import { afterEach, expect, it } from 'vitest'
+
+const run = promisify(execFile)
+let root: string | undefined
+afterEach(async () => {
+ if (root) {
+ await rm(root, { recursive: true, force: true })
+ root = undefined
+ }
+})
+
+it.skipIf(process.platform === 'win32').each([
+ ['13.5', 'node', true],
+ ['13.4', 'electron', true],
+ ['27.2', 'node', true],
+ ['unknown', 'electron', true],
+ ['13.5', 'electron', false]
+] as const)(
+ 'runs the packaged CLI on %s with %s (helper executable: %s)',
+ async (version, runtime, executable) => {
+ root = await realpath(await mkdtemp(join(tmpdir(), 'orca-mac-cli-')))
+ const contents = join(root, 'Test.app', 'Contents')
+ const bin = join(contents, 'Resources', 'bin')
+ const helper = join(contents, 'Helpers', 'Orca Agents.app', 'Contents')
+ await Promise.all([
+ mkdir(bin, { recursive: true }),
+ mkdir(join(contents, 'MacOS'), { recursive: true }),
+ mkdir(join(helper, 'MacOS'), { recursive: true })
+ ])
+ const systemVersion = join(root, 'SystemVersion.plist')
+ await writeFile(
+ systemVersion,
+ `\nProductVersion\n${version}\n\n`
+ )
+ await writeFile(
+ join(helper, 'Info.plist'),
+ '\nLSMinimumSystemVersion\n13.5\n\n'
+ )
+ const shim = await readFile(join(__dirname, '../../../../resources/darwin/bin/orca'), 'utf8')
+ const launcher = join(bin, 'orca')
+ await writeFile(
+ launcher,
+ shim.replace('/System/Library/CoreServices/SystemVersion.plist', systemVersion)
+ )
+ for (const [path, name] of [
+ [join(contents, 'MacOS', 'Orca'), 'electron'],
+ [join(helper, 'MacOS', 'Orca Agents'), 'node']
+ ]) {
+ await writeFile(
+ path,
+ `#!/bin/sh\nprintf '%s\\n' '${name}' "$@" "NODE_OPTIONS:\${NODE_OPTIONS-unset}" "ORCA_NODE_OPTIONS:\${ORCA_NODE_OPTIONS-unset}"\n`
+ )
+ await chmod(path, name === 'node' && !executable ? 0o644 : 0o755)
+ }
+ const result = await run('/bin/bash', [launcher, 'status', '--json'], {
+ env: {
+ PATH: '/usr/bin:/bin',
+ HOME: root,
+ NODE_OPTIONS: '--max-old-space-size=2048',
+ ORCA_BACKGROUND_LAUNCH: '1'
+ }
+ })
+ expect(result.stdout.split('\n')).toEqual([
+ runtime,
+ join(contents, 'Resources', 'app.asar.unpacked', 'out', 'cli', 'index.js'),
+ 'status',
+ '--json',
+ 'NODE_OPTIONS:unset',
+ 'ORCA_NODE_OPTIONS:--max-old-space-size=2048',
+ ''
+ ])
+ }
+)