computer-use-bridge 1.0: npm install flow, config v2, and cross-platform setup for agent desktop control
Discovered from README cross-links · yesterday
Shipped v1.0 of a bridge that lets agents drive apps and browser tabs.
What they did
The author released computer-use-bridge 1.0.0, moving the project from a Homebrew-era 0.x layout to an npm package with a single install flow on macOS and Linux. The work covered four areas. First, packaging and setup: `npm i -g computer-use-bridge && computer-use-bridge setup` on the server, and `computer-use-bridge connect HOST` on the client. `setup` asks for the app engine, allowlist, browser and network (or takes flags with `--yes`), installs pinned engine versions (open-computer-use 1.1.2, agent-desktop 1.0.2, open-browser-use 1.1.0), registers the browser's native host, walks through permission onboarding and the extension page interactively, installs a LaunchAgent or systemd user unit that starts Node by a stable path, stops the old Homebrew service, and runs checks. It exits 0 when ready or 3 when a person still has to act, listing what's left. Second, new commands: `status [--json]` checks config, engine versions against pins, permissions, extension, service (including a vanished Node path and linger), server, tunnels and Homebrew leftovers; `update` reinstalls from npm and reruns `setup --yes` while keeping config; `connect` fetches the address and token over SSH without printing the token, saves it at mode 600, verifies the server, and adds the entry to pi's `mcp.json` after a backup, or uses stdio over SSH when the server listens on 127.0.0.1. `--print` shows the pi entry and the Claude Code command. Third, config v2: `apps: { engine, allow, engineFor }` and `tabs: { engine, browser }`, so allowing a browser no longer doubles as the tabs switch, and `engineFor` routes single apps to the other engine (Balatro on open-computer-use, the rest on agent-desktop). Old 0.x configs still load and `setup` converts them. The agent-desktop engine from #13 was folded in with the same client tools, element numbers mapped to snapshot refs so stale refs return `STALE_REF`, headless-only operation with coordinate clicks refused, and a documented macOS permission caveat. Fourth, code and docs: the single 2,000-line file was split into `bin/` and `src/` modules with generated import lists checked by ESLint `no-undef` and `no-unused-vars`; `Session` runs one engine per name in use and routes each app through `cfg.appEngineFor(id)`, with `release` and idle stop shutting them all down. The README was rewritten around the npm quick start, and `AGENTS.md` plus a `CLAUDE.md` stub cover setup, code layout and releasing. A tag checks `package.json`, runs tests, creates the GitHub release and publishes via trusted publishing; the Homebrew formula is deprecated at 0.6.0.
How it went
`npm test` passes 107 tests, 44 of them new, covering config v2 validation, migration and per-app routing, the agent-desktop adapter through a fake CLI, argument parsing, LaunchAgent and systemd unit text, the stable Node path, and the remote command `connect` runs. Live testing on minipc (Linux, nvm Node 24) from the packed tarball in a temporary prefix and test port: `setup --yes` worked and exited 3 only because Brave wasn't running, correctly flagging that as the remaining step; `status --json` worked; over HTTP, `connect` saved the token at mode 600, backed up the scratch pi config and added the entry, and a handshake with the saved token listed 17 tab tools; `--print` worked and `client-info` refused to print to a TTY. On pikachu (macOS, Homebrew Node 26): `setup --yes` with `--apps open-computer-use --engine-for com.hnc.Discord=agent-desktop --tabs brave` dropped `com.apple.Terminal`, wrote the config, passed open-computer-use's permissions and the extension, and flagged agent-desktop's permission as expected over SSH; over stdio, Brave was read through open-computer-use, Discord went to agent-desktop (`PERM_DENIED` over SSH), a tab was opened, screenshotted, read and closed, Terminal was refused, and `release` stopped both engines. Two bugs were found and fixed during testing: `status` ignored the service's Node directory and didn't expand systemd's `%h`, and newer Homebrew labels its service `sh.brew.*`.
Worth knowing
Not tested live: installing the LaunchAgent or systemd unit for real, `update`, and an interactive `setup` — those happen when pikachu and minipc migrate after release. The agent-desktop engine is headless only and refuses coordinate clicks, double clicks and drags, and its macOS permissions can't be granted over SSH. The first npm publish must be done by hand with 2FA because trusted publishing needs the package to exist; the trusted publisher is then configured on npmjs.com for repository `hank-warren/computer-use-bridge` and workflow `release.yml`. The Homebrew formula is deprecated and left at 0.6.0.
Wiring
Install on the server with `npm i -g computer-use-bridge && computer-use-bridge setup`; `setup` prompts for the app engine, allowlist, browser and network, or accepts flags with `--yes` (for example `--apps open-computer-use --engine-for com.hnc.Discord=agent-desktop --tabs brave`). It installs pinned engines (open-computer-use 1.1.2, agent-desktop 1.0.2, open-browser-use 1.1.0), registers open-browser-use's native host for the detected browser and OS, opens permission onboarding and the extension page interactively and waits, then installs a LaunchAgent (macOS) or systemd user unit (Linux) that starts Node by a stable path, stops the 0.x Homebrew service and runs checks. Exit 0 means ready; exit 3 means a person must still act, with the remaining steps listed. Config v2 lives in the config file as `apps: { engine, allow, engineFor }` and `tabs: { engine, browser }`; `Session` starts one engine per name in use and routes each app through `cfg.appEngineFor(id)`, and `release` or idle stop shuts them all down. On the client, `computer-use-bridge connect HOST` fetches the address and token over SSH (never printed; `client-info` refuses to show it on a TTY), saves the token at mode 600, verifies the server, backs up pi's `mcp.json` and adds the entry, or uses stdio over SSH when the server listens on 127.0.0.1; `--print` shows the pi entry and the Claude Code command. `status [--json]` checks config, engine versions against pins, permissions, extension, service (Node path, linger), server, tunnels and Homebrew leftovers. `update` runs `npm i -g computer-use-bridge@latest` then the new version's `setup --yes`, keeping config and rewriting and restarting the service. Releases go through a tag that checks `package.json`, runs tests, creates the GitHub release and publishes to npm via trusted publishing.Try it yourself
Read AGENTS.md and the README in this repo, then run `npm test` and report the pass/fail count. Next, inspect `src/` for the config v2 schema (`apps: { engine, allow, engineFor }` and `tabs: { engine, browser }`) and confirm that 0.x configs still load and are converted by `setup`. Then review the `status` command for the two bugs fixed in 1.0: it should use the service's Node directory and expand systemd's `%h`, and it should recognize newer Homebrew service labels like `sh.brew.*`. Finally, check that `connect` never prints the token, saves it at mode 600, backs up pi's `mcp.json` before editing, and falls back to stdio over SSH when the server listens on 127.0.0.1. Summarize any gaps between the code and the documented behavior.