Summary
On native Windows, every Claude Code launch with the agentbridge plugin installed opens visible empty console windows that stay on screen for the daemon's lifetime. Closing them kills the daemon. Two spawn sites lack windowsHide: true; adding it at both sites fully resolves the problem (verified end to end on a real pair).
Related to the #231 Windows-support tracking issue (this is a concrete blocker in the "Runtime / launcher on Windows" category, but it isn't in that issue's blocker list yet).
Environment
- agentbridge v0.1.30 (commit
55120e8), installed as Claude Code plugin (marketplace)
- Claude Code 2.1.210, Windows 11 (26200), Windows Terminal as default terminal app
- Bun 1.3.11, codex-cli 0.144.4 (npm global install)
Symptom
- Launch Claude Code normally (any project).
- The plugin MCP bridge starts and eagerly ensures the daemon:
MCP server ready (push delivery) — ensuring AgentBridge daemon... → Launching detached daemon on control port 4502.
- One or two empty terminal windows appear and remain open:
- the daemon's own console (bun,
detached: true without windowsHide), and
- a window titled
C:\WINDOWS\system32\cmd.exe hosting cmd.exe /c codex app-server --listen ws://127.0.0.1:4500.
- Closing either window kills the corresponding process (daemon / app-server).
The second window exists because on Windows, Bun/Node resolves the npm codex shim (codex.cmd) and wraps it in cmd.exe /c; since the parent daemon is detached/windowless, the cmd child gets a fresh visible console.
Root cause — two spawn sites lack windowsHide: true
Site 1: daemon launch (plugins/agentbridge/server/bridge-server.js, launch()):
const daemonProc = spawn(process.execPath, ["run", DAEMON_PATH], {
cwd: process.cwd(),
env: { ... },
detached: true,
stdio: "ignore" // ← no windowsHide → visible console on win32
});
Site 2: codex app-server spawn (plugins/agentbridge/server/daemon.js, ~line 1057):
this.proc = spawn("codex", ["app-server", "--listen", listen], {
stdio: ["pipe", "pipe", "pipe"] // ← no windowsHide → visible cmd.exe wrapper console
});
Note: the bridge launches the daemon from the npm package copy of daemon.js (via AGENTBRIDGE_DAEMON_ENTRY), so patching only the plugin-cache copy of daemon.js has no effect — worth keeping in mind for where the fix lands.
Fix (verified)
Add windowsHide: true to both spawn option objects. windowsHide is a no-op on POSIX, so no platform branching is needed.
After patching both sites and restarting the daemon, all three processes run without any window (checked MainWindowHandle == 0 for the bun daemon, the cmd.exe wrapper, and codex.exe), and a full Claude→Codex→Claude round trip over the bridge still works.
The same treatment probably also applies to other spawn sites in dist/ used by the abg CLI launchers (retry loops there flash multiple console windows when daemon startup fails), but I've only verified the two plugin-path sites above.
Incidental observation (for #231)
While debugging this I also hit Codex error: ENOENT: no such file or directory, uv_spawn 'codex' from the daemon on Windows: the npm global bin dir contains only the codex sh-shim and codex.cmd, no codex.exe, so a shell-less spawn can't resolve it depending on runtime/version. Workaround was putting the platform package's vendor bin dir (which contains a real codex.exe) on PATH. Happy to file that separately if useful.
Thanks for the great tool — the bidirectional pair works nicely on Windows once these are patched. 🙌
Summary
On native Windows, every Claude Code launch with the agentbridge plugin installed opens visible empty console windows that stay on screen for the daemon's lifetime. Closing them kills the daemon. Two spawn sites lack
windowsHide: true; adding it at both sites fully resolves the problem (verified end to end on a real pair).Related to the #231 Windows-support tracking issue (this is a concrete blocker in the "Runtime / launcher on Windows" category, but it isn't in that issue's blocker list yet).
Environment
55120e8), installed as Claude Code plugin (marketplace)Symptom
MCP server ready (push delivery) — ensuring AgentBridge daemon...→Launching detached daemon on control port 4502.detached: truewithoutwindowsHide), andC:\WINDOWS\system32\cmd.exehostingcmd.exe /c codex app-server --listen ws://127.0.0.1:4500.The second window exists because on Windows, Bun/Node resolves the npm
codexshim (codex.cmd) and wraps it incmd.exe /c; since the parent daemon is detached/windowless, the cmd child gets a fresh visible console.Root cause — two spawn sites lack
windowsHide: trueSite 1: daemon launch (
plugins/agentbridge/server/bridge-server.js,launch()):Site 2: codex app-server spawn (
plugins/agentbridge/server/daemon.js, ~line 1057):Note: the bridge launches the daemon from the npm package copy of
daemon.js(viaAGENTBRIDGE_DAEMON_ENTRY), so patching only the plugin-cache copy ofdaemon.jshas no effect — worth keeping in mind for where the fix lands.Fix (verified)
Add
windowsHide: trueto both spawn option objects.windowsHideis a no-op on POSIX, so no platform branching is needed.After patching both sites and restarting the daemon, all three processes run without any window (checked
MainWindowHandle == 0for the bun daemon, thecmd.exewrapper, andcodex.exe), and a full Claude→Codex→Claude round trip over the bridge still works.The same treatment probably also applies to other spawn sites in
dist/used by theabgCLI launchers (retry loops there flash multiple console windows when daemon startup fails), but I've only verified the two plugin-path sites above.Incidental observation (for #231)
While debugging this I also hit
Codex error: ENOENT: no such file or directory, uv_spawn 'codex'from the daemon on Windows: the npm global bin dir contains only thecodexsh-shim andcodex.cmd, nocodex.exe, so a shell-less spawn can't resolve it depending on runtime/version. Workaround was putting the platform package's vendorbindir (which contains a realcodex.exe) onPATH. Happy to file that separately if useful.Thanks for the great tool — the bidirectional pair works nicely on Windows once these are patched. 🙌