Skip to content

Keep browse daemons alive across separate CLI invocations on macOS#1140

Open
be-student wants to merge 1 commit intogarrytan:mainfrom
be-student:fix/browse-detached-daemon
Open

Keep browse daemons alive across separate CLI invocations on macOS#1140
be-student wants to merge 1 commit intogarrytan:mainfrom
be-student:fix/browse-detached-daemon

Conversation

@be-student
Copy link
Copy Markdown

@be-student be-student commented Apr 22, 2026

Summary

Keep browse daemons alive across separate CLI invocations on macOS.

Before this change, a first command like browse goto https://example.com would succeed,
but the daemon and Chromium session could still die with the launching shell. A second
invocation would then start a fresh server from about:blank, losing browse state.

Root Cause

The POSIX launch path was not putting the Bun server and its Chromium children into a
proper detached session/process group. In practice on macOS, the launched browser session
could still die when the short-lived parent shell exited. Shell hangups (SIGHUP) were
also not explicitly handled for the headless reuse case.

Fix

  • keep the POSIX path Bun-native by spawning the Bun server with detached: true
  • keep headless daemons alive on SIGHUP, matching the headless reuse intent
  • leave the Windows-specific Node launcher in place
  • replace the weak helper-only regression test with a real two-invocation lifecycle test
    against a local HTTP server

Verification

  • bun test test/browse-cli-daemon.test.ts
  • bun run build
  • manual verification:
    • browse goto https://example.com
    • separate invocation: browse url
    • confirmed it returns https://example.com/ instead of restarting at about:blank

Notes

I explicitly avoided adding a new POSIX node runtime dependency in the final structure.

The browse CLI was starting a server that looked healthy during the first
command, but the daemon and its Chromium children were still tied to the
launching shell session. A follow-up invocation would miss the prior server,
start from about:blank, and lose all persisted browse state.

This keeps the server fully Bun-native on POSIX by using a detached Bun spawn
instead of adding a new Node launch dependency, keeps headless daemons alive on
SIGHUP, and replaces the weak helper-only regression test with a real
multi-invocation lifecycle test against a local HTTP server.

Constraint: The fix must work with Bun-built CLI binaries on macOS without adding dependencies
Rejected: Keep using Bun.spawn(...).unref() without detached sessioning | daemon and Chromium still died after the launching shell exited
Rejected: POSIX Node launcher | fixed the symptom locally but added an unnecessary Node runtime dependency
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Detached launch behavior is part of browse state persistence; do not revert to parent-attached spawn without re-testing separate invocations
Tested: bun test test/browse-cli-daemon.test.ts; bun run build; manual browse goto https://example.com then separate browse url reuse check
Not-tested: Full /qa and /canary flows on macOS after prolonged idle periods
@be-student be-student force-pushed the fix/browse-detached-daemon branch from b4689d1 to 2090f3d Compare April 22, 2026 12:41
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