fix(browse): pass windowsHide so the daemon stops popping console windows

On Windows, `browse` leaves empty black console windows on top of whatever the
user is doing — they pop up every few minutes for as long as any browser skill
is alive, and outlive the process that created them.

Cause: `bun-polyfill.cjs` maps `Bun.spawn`/`Bun.spawnSync` onto node's
`child_process`, and node defaults `windowsHide` to **false**. Bun never creates
these windows, so nothing in the daemon's own code looks wrong — the behaviour
only appears on the node fallback path.

The one users notice is `spawnTerminalAgent()`, which launches
`bun run terminal-agent.ts` through this shim. The daemon respawns it on a
watchdog, so closing the window is not enough — a new one arrives shortly after.
Ten `bun.exe` processes were live on the machine this was diagnosed on.

Why they linger after the child exits: with the default terminal application set
to "Let Windows decide", the console is brokered through Windows Terminal via
svchost, and WT leaves the empty frame behind when its only child exits. The
frame has no child process at all, which is why it looks like a dead terminal.

Setting `windowsHide: true` on both wrappers fixes every console child routed
through the shim — the bun agent plus the `tasklist`, `git` and `powershell`
calls elsewhere in the daemon. No behaviour change on macOS or Linux, where the
option is ignored.

Not covered by this commit: `chromium.launch()` goes through playwright's own
process launcher rather than this shim, so it still creates one window per daemon
start. Worth a follow-up.
This commit is contained in:
Jake Wilk 2026-08-11 15:32:30 -04:00 committed by Garry Tan
parent f3ea49ff6e
commit d5217a5ed2
No known key found for this signature in database
GPG Key ID: C1F69E85C74EFE1D
1 changed files with 7 additions and 0 deletions

View File

@ -75,6 +75,9 @@ globalThis.Bun = {
timeout: options.timeout,
env: options.env,
cwd: options.cwd,
// Bun never shows a console window; node's spawn defaults windowsHide to
// false, so without this every console child pops a window on Windows.
windowsHide: true,
});
return {
@ -91,6 +94,10 @@ globalThis.Bun = {
stdio,
env: options.env,
cwd: options.cwd,
// See spawnSync. This is the one users notice: spawnTerminalAgent() launches
// `bun run terminal-agent.ts` through here and the daemon respawns it on a
// watchdog, so an empty console window reappears every few minutes.
windowsHide: true,
});
return {