[macOS] Preserve direct process invocation across first-launch self-extraction

Author: francipCreated Sep 3, 2026Updated Sep 3, 2026

Summary

The first direct process invocation of a packaged macOS application does not have the same observable process behavior as later invocations. After installing the expanded application, the self-extractor starts it through detached open -n and immediately returns. That path cannot preserve a shell caller's argument vector, working context, standard streams, signal relationship, or application exit result.

This prevents Electrobun applications that expose a CLI or hybrid GUI/CLI surface from treating the packaged executable as a normal process on first use.

Current behavior

The extractor deliberately builds open -n APPBUNDLE_PATH, spawns it without waiting, completes the progress UI, and returns:

https://github.com/blackboardsh/electrobun/blob/61b514f2b787d40c8ecdc87c482d8b97c6a33d7b/package/src/extractor/main.zig#L8367-L8391

The source comments explain why -n is required for the current GUI flow: the extractor is still a live instance of the replaced bundle identity. That makes sense for Finder-style application activation, but it is not a transparent handoff for a direct executable invocation.

The ordinary launcher path is synchronous and inherits standard I/O, forwards selected signals, waits, and returns the child result, although generic argument forwarding is still tracked by #483 and the launcher currently overrides the child working directory:

https://github.com/blackboardsh/electrobun/blob/61b514f2b787d40c8ecdc87c482d8b97c6a33d7b/package/src/launcher/main.zig#L663-L710

Expected behavior

Electrobun should provide a documented process-preserving first-launch path for applications that support direct command-line invocation. This may be an explicit build/runtime mode; the existing detached Finder/GUI behavior does not need to change.

For a process-preserving launch:

  • each caller argument reaches the installed application as the same argument-vector element after launcher-owned controls are consumed;
  • caller working directory and environment are preserved or changed only by a documented policy;
  • stdin, stdout, and stderr remain distinct inherited descriptors;
  • relevant signals reach the installed application;
  • the initial process waits and returns the installed application's exit result; and
  • first and later direct launches satisfy the same contract.

Reproduction

  1. Build a never-launched stable macOS application whose main process reports a non-sensitive argv/cwd fixture, writes distinct payloads to stdout and stderr, and exits with status 23.
  2. Invoke its packaged executable directly from a shell with distinct arguments, redirected standard streams, and a known working directory.
  3. Observe the first invocation, then invoke the installed application the same way a second time.
  4. Compare arguments, working directory, both output streams, signal handling, waiting behavior, and final status.

The first invocation currently returns after the detached open request rather than behaving as the application process.

Related issues

  • #483 tracks ordinary launcher argv forwarding and should remain the canonical argv issue.
  • #359 tracks the broader macOS first-launch self-extraction architecture and bundle mutation.

This issue is limited to process-handoff parity; it does not require a particular shell, terminal emulator, or application framework above Electrobun.