feat: BROWSE_NO_AUTOSTART prevents sidebar from spawning headless browser

When set, the browse CLI refuses to start a new server and exits with
a clear error: "Server not available, run /open-gstack-browser to restart."
The sidebar agent sets this so users never get an invisible headless
browser when the headed one is closed.
This commit is contained in:
Garry Tan
2026-04-02 19:32:17 -07:00
parent 256a72a378
commit 1bc02585aa
2 changed files with 15 additions and 3 deletions
+10 -1
View File
@@ -330,12 +330,21 @@ async function ensureServer(): Promise<ServerState> {
return state;
}
// BROWSE_NO_AUTOSTART: sidebar agent sets this so the child claude never
// spawns an invisible headless browser. If the headed server is down,
// fail fast with a clear error instead of silently starting a new one.
if (process.env.BROWSE_NO_AUTOSTART === '1') {
console.error('[browse] Server not available and BROWSE_NO_AUTOSTART is set.');
console.error('[browse] The headed browser may have been closed. Run /open-gstack-browser to restart.');
process.exit(1);
}
// Guard: never silently replace a headed server with a headless one.
// Headed mode means a user-visible Chrome window is (or was) controlled.
// Silently replacing it would be confusing — tell the user to reconnect.
if (state && state.mode === 'headed' && isProcessAlive(state.pid)) {
console.error(`[browse] Headed server running (PID ${state.pid}) but not responding.`);
console.error(`[browse] Run '$B connect' to restart.`);
console.error(`[browse] Run '/open-gstack-browser' to restart.`);
process.exit(1);
}
+5 -2
View File
@@ -242,9 +242,12 @@ async function askClaude(queueEntry: any): Promise<void> {
env: {
...process.env,
BROWSE_STATE_FILE: stateFile || '',
// Connect to the existing headed browse server instead of launching a new one.
// Without this, the child claude starts a headless browser on a random port.
// Connect to the existing headed browse server, never start a new one.
// BROWSE_PORT tells the CLI which port to check.
// BROWSE_NO_AUTOSTART prevents spawning an invisible headless browser
// if the headed server is down — fail fast with a clear error instead.
BROWSE_PORT: process.env.BROWSE_PORT || '34567',
BROWSE_NO_AUTOSTART: '1',
// Pin this agent to its tab — prevents cross-tab interference
// when multiple agents run simultaneously
BROWSE_TAB: String(tid),