Skip to content

feat: add macOS-only native no-activate launch option#724

Open
2c67cc18 wants to merge 3 commits intovercel-labs:mainfrom
2c67cc18:codex/2026-03-11-native-no-activate
Open

feat: add macOS-only native no-activate launch option#724
2c67cc18 wants to merge 3 commits intovercel-labs:mainfrom
2c67cc18:codex/2026-03-11-native-no-activate

Conversation

@2c67cc18
Copy link

@2c67cc18 2c67cc18 commented Mar 11, 2026

Add a macOS-only --no-activate / AGENT_BROWSER_NO_ACTIVATE option for native headed Chrome launches.

On macOS native Chrome launches, --no-activate now uses open -g to start the browser without intentionally foregrounding it, captures the DevTools websocket URL from redirected stderr, and keeps a PID-based fallback so close can still terminate the browser if Browser.close does not complete.

This is scoped intentionally:

  • macOS only
  • native Chrome only
  • headed only
  • opt-in only

Several alternatives were considered and not chosen:

  • Fixed --remote-debugging-port=<port> for PID lookup.
    This worked, but it introduces a real port-allocation race: the port must be released before Chrome can bind it, so another process can theoretically claim it in between.

  • Using --user-data-dir as the process identity.
    This is not reliably unique when persistent profiles are reused, so PID lookup can become ambiguous.

  • Dropping PID ownership and relying only on Browser.close.
    This would reduce code, but it weakens lifecycle control compared with the normal native path, which already prefers owning the browser process and having a fallback kill path.

  • A macOS-native launcher via AppKit / NSWorkspace (for example through Rust Objective-C bindings).
    That may be a cleaner long-term macOS integration path, but it would require introducing new platform-specific code and dependencies. This change stays within the existing dependency/tooling model and keeps the implementation narrower.

  • Extending Playwright / non-native behavior.
    That was intentionally left out of scope. This change is only for the native Chrome path.

Given those tradeoffs, the final implementation uses:

  • open -g for macOS no-activate launch
  • redirected stderr for the DevTools handshake
  • a launch marker argument for PID reacquisition
  • PID-based fallback termination to stay aligned with native lifecycle expectations

Validation:

  • cargo check
  • cargo test no_activate
  • cargo test e2e_no_activate_launch_and_interact -- --ignored --test-threads=1
  • cargo test e2e_no_activate_close_kills_stopped_pid -- --ignored --test-threads=1
  • local machine test:
    • cargo run -- --native --headed --no-activate open example.com

One test tradeoff remains open: e2e_no_activate_close_kills_stopped_pid currently takes about 30 seconds because it intentionally stops the browser process and therefore waits through the existing CdpClient::send_command timeout before the PID fallback executes. That proves the real production path, but it is slow. It is still unclear whether the better tradeoff is to keep that full-path e2e as-is or add a narrower test-specific close helper with a shorter timeout.

@vercel
Copy link
Contributor

vercel bot commented Mar 11, 2026

@2c67cc18 is attempting to deploy a commit to the Vercel Labs Team on Vercel.

A member of the Team first needs to authorize it.

@2c67cc18 2c67cc18 force-pushed the codex/2026-03-11-native-no-activate branch from 2b47ba7 to 128193c Compare March 11, 2026 16:54
Co-authored-by: OpenAI Codex <codex@openai.com>
@2c67cc18 2c67cc18 force-pushed the codex/2026-03-11-native-no-activate branch from 128193c to c252d71 Compare March 11, 2026 17:33
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.

1 participant