Skip to content

fix(browser-control): bind the daemon on the main thread so sessions can start - #236

Open
SandroHub013 wants to merge 1 commit into
live-mainfrom
fix/browser-control-bun-webview
Open

fix(browser-control): bind the daemon on the main thread so sessions can start#236
SandroHub013 wants to merge 1 commit into
live-mainfrom
fix/browser-control-bun-webview

Conversation

@SandroHub013

@SandroHub013 SandroHub013 commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Issue for this PR

Closes #235

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Bun.WebView's chrome backend — the backend on every platform except macOS — throws
Bun.WebView with backend "chrome" is only available on the main thread when it is constructed off
the main thread. It throws at construction, so pointing it at an already-running Chrome through a
DevTools URL does not avoid it either.

The compiled binary hosts the browser-control daemon in-process, and nikcli runs sessions on a
worker thread, so that daemon bound its socket on a worker. list worked because it creates no
view; every start failed because it creates one. macOS was unaffected — it defaults to the
webkit backend — which is why the report was Windows-only.

The daemon no longer hosts itself on a worker. It delegates binding to the host's main thread via
setMainThreadDaemonHost(), and the worker then speaks to it over the same socket as any other
client, so views are created on a thread that is allowed to have them. nikcli registers that hook
over the RPC channel the TUI worker already has. With no host registered, ensureDaemon now fails
with a message naming the constraint instead of binding a daemon that cannot start a session.

createWebView() carries the same check, so any other caller gets an error with a fix in it rather
than Bun's bare message.

How did you verify your code works?

First reproduced it, on Windows 11 / Bun 1.4.0, by hosting the daemon on a worker and calling
start:

{"ok":false,"error":"Bun.WebView with backend \"chrome\" is only available on the main thread"}

Then, with hosting delegated to the main thread and the session driven from a worker through the
same Rpc util the nikcli wiring uses:

plan: delegate
main thread hosts daemon
worker start result: {"name":"page-1","url":"data:text/html,<title>via-worker</title>","status":"running", ...}
  • bun test in packages/browser-control: 10 pass, including the new test/worker-hosting.test.ts,
    which covers the hosting rule and drives a main-thread-hosted daemon from a worker
  • bun typecheck at the repo root: 35/35 packages
  • bun src/cli.ts start --url https://example.com --viewport 1024x768, plus list and shutdown,
    behave as before — the CLI spawns its own daemon process, which was always on a main thread
  • Built the binary from this branch (script/build.ts --single) and confirmed it boots. Its TUI
    smoke fails locally with EPERM: mkdir under the harness's synthetic HOME, but a binary built
    from live-main in the same tree fails identically, so that is a local build issue and not this
    change.

To confirm by hand: run start from a compiled binary's TUI on Windows or Linux. It returned the
WebView error before and returns session info now.

Screenshots / recordings

Not a UI change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Note for reviewers

The nikcli half touches the TUI worker/thread wiring (7 and 11 lines). If the delegation hook
belongs somewhere other than the existing Rpc.emit channel, say so and I will move it.

@github-actions github-actions Bot added size/M PR touches 74 lines area/cli and removed size/M PR touches 74 lines labels Aug 20, 2026
@github-actions

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@github-actions

Copy link
Copy Markdown

lgtm

@SandroHub013

Copy link
Copy Markdown
Collaborator Author

/nikcli review this

@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown

Unable to connect. Is the computer able to access the url?

github run

@nikomatt69

nikomatt69 commented Aug 20, 2026

Copy link
Copy Markdown
Owner

⚠️ CI Validation Failed

@nikomatt69 — validation failed on this commit.

Detail Value
Failed step Unknown step
Autofix status ⏭️ Autofix skipped
Run View full logs

Failure Summary

(no summary available)

Please inspect the full Actions logs for complete output. Do not share this comment publicly — it may contain redacted paths.

…can start

Bun.WebView's chrome backend - the backend everywhere except macOS - throws
"only available on the main thread" when constructed off the main thread, and
it throws at construction, so connecting to a running Chrome over a DevTools
URL does not dodge it either.

The compiled binary hosts the daemon in-process, and nikcli runs sessions on a
worker thread, so that daemon bound its socket on a worker. It answered `list`
(no view) and failed every `start` (which creates one). macOS was unaffected:
it defaults to the webkit backend.

The daemon now refuses to host on a worker and delegates binding to the host's
main thread via setMainThreadDaemonHost(); the worker then talks to it over the
same socket as any other client. nikcli wires that through the RPC channel the
TUI worker already has. createWebView() also names the constraint now, instead
of surfacing Bun's message with no caller and no fix in it.

Fixes #235
@SandroHub013
SandroHub013 force-pushed the fix/browser-control-bun-webview branch from e842b81 to 6efa91c Compare August 21, 2026 00:02
@github-actions github-actions Bot added the size/M PR touches 74 lines label Aug 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/cli size/M PR touches 74 lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

browser-control start fails on Windows: Bun.WebView only available on main thread

2 participants