Skip to content

fix: make spawn() work when host is an Electron main process#1508

Open
Copilot wants to merge 3 commits into
mainfrom
copilot/fix-cli-spawn-in-electron
Open

fix: make spawn() work when host is an Electron main process#1508
Copilot wants to merge 3 commits into
mainfrom
copilot/fix-cli-spawn-in-electron

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 29, 2026

In an Electron main process, process.execPath is the Electron binary. Spawning the bundled .js CLI with it fails two ways: bare spawn triggers single-instance lock → clean exit → misleading CLI server exited unexpectedly with code 0; with ELECTRON_RUN_AS_NODE=1 alone, process.versions.electron is still set in the child, Commander picks Electron argv parsing, and --headless is misclassified as a positional arg → error: too many arguments.

Changes

  • applyElectronSpawnEnv(env, isJsFile) (client.ts) — new @internal helper; when process.versions.electron !== undefined and the CLI is a .js file, injects ELECTRON_RUN_AS_NODE=1 and COPILOT_CLI_RUN_AS_NODE=1 via ??= (caller values are never overwritten). No-ops in all non-Electron hosts.

  • getNodeExecPath(override?) — accepts an optional path override; exported @internal for testability.

  • CopilotClientOptions.nodeExecPath?: string (types.ts) — escape hatch for Electron apps that bundle a real Node binary, bypassing the env-var injection entirely:

    const client = new CopilotClient({
        nodeExecPath: process.env.MY_APP_NODE_PATH ?? "node",
    });
  • startCLIServer() — wired to call applyElectronSpawnEnv before spawn and pass options.nodeExecPath to getNodeExecPath.

  • 6 new unit tests covering injection, no-overwrite, non-.js skip, non-Electron no-op, override, and option storage.

  • README — new "Electron usage" section documenting both failure modes and both fixes.

  • CHANGELOG[Unreleased] Fixed entry.

Copilot AI and others added 2 commits May 29, 2026 22:05
Co-authored-by: friggeri <106686+friggeri@users.noreply.github.com>
Co-authored-by: friggeri <106686+friggeri@users.noreply.github.com>
Copilot AI requested a review from friggeri May 29, 2026 22:08
@friggeri friggeri marked this pull request as ready for review May 29, 2026 22:21
@friggeri friggeri requested a review from a team as a code owner May 29, 2026 22:21
Copilot AI review requested due to automatic review settings May 29, 2026 22:21
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a startup failure when the Node.js SDK is hosted inside an Electron main process, where process.execPath points at the Electron binary and spawning the bundled .js CLI either silently exits (single-instance lock) or trips Commander's Electron argv parsing on --headless.

Changes:

  • New @internal helper applyElectronSpawnEnv() injects ELECTRON_RUN_AS_NODE=1 and COPILOT_CLI_RUN_AS_NODE=1 (via ??=) for .js CLIs when process.versions.electron is defined, and getNodeExecPath() now accepts an optional override.
  • New public CopilotClientOptions.nodeExecPath escape hatch for apps that bundle a real Node binary; wired through to the .js spawn branch in startCLIServer().
  • Documentation (README "Electron Usage" section, CHANGELOG Unreleased entry) and 6 unit tests covering injection, no-overwrite, non-.js, non-Electron, override, and option storage.
Show a summary per file
File Description
nodejs/src/client.ts Adds applyElectronSpawnEnv, extends getNodeExecPath with override, stores nodeExecPath option, and uses both in the .js spawn branch.
nodejs/src/types.ts Adds nodeExecPath?: string to CopilotClientOptions with JSDoc explaining the Electron use case.
nodejs/test/client.test.ts New Electron spawn environment describe block exercising helper behavior and option storage.
nodejs/README.md New "Electron Usage" section documenting failure modes, automatic fix, and nodeExecPath escape hatch.
CHANGELOG.md Adds an [Unreleased] entry describing the fix and new option.

Copilot's findings

  • Files reviewed: 5/5 changed files
  • Comments generated: 1

Comment thread CHANGELOG.md Outdated
Comment on lines +8 to +31
## [Unreleased]

### Fixed: CLI server spawn in Electron main process (Node.js SDK)

`CopilotClient.start()` previously threw `CLI server exited unexpectedly with
code 0` when the host was an Electron main process. The root cause was that
`process.execPath` resolves to the Electron binary rather than a Node
executable, so spawning the bundled `.js` CLI failed silently (bare spawn) or
with a Commander argv-parsing error (`ELECTRON_RUN_AS_NODE=1` alone).

The SDK now detects `process.versions.electron` at spawn time and automatically
injects `ELECTRON_RUN_AS_NODE=1` and `COPILOT_CLI_RUN_AS_NODE=1` into the
child process environment. No code changes are required in existing Electron
apps.

A new `nodeExecPath` option on `CopilotClientOptions` lets apps that bundle a
real Node binary point the SDK at it directly, bypassing the auto-injected
env-vars entirely:

```ts
const client = new CopilotClient({
nodeExecPath: process.env.MY_APP_NODE_PATH ?? "node",
});
```
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 9480efeb: removed the manual [Unreleased] CHANGELOG entry so release notes remain generator-managed.

Co-authored-by: friggeri <106686+friggeri@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants