Skip to content

Surface the desktop server switcher and allow a different server per window - #2740

Draft
bhushit wants to merge 13 commits into
get-bb:mainfrom
bhushit:feat/surface-server-switcher
Draft

Surface the desktop server switcher and allow a different server per window#2740
bhushit wants to merge 13 commits into
get-bb:mainfrom
bhushit:feat/surface-server-switcher

Conversation

@bhushit

@bhushit bhushit commented Aug 30, 2026

Copy link
Copy Markdown

What was wrong

bb desktop already lets you point the app at a remote bb server (Window ▸ Server, Window ▸ Set Server URL…), but it has three gaps:

  1. Undiscoverable — the only entry point is a native menu most users never open.
  2. One custom URL at a time — the custom target holds a single URL; setting a new one replaces it.
  3. App-global + hijacking — the target is global, so all windows are forced onto the same server, and switching a window to a remote replaces its content. If that remote needs sign-in, you can get stranded on its gate page with no in-app way back.

Refs #1451 (multiple desktop servers / remote handoff) and #483 (the original remote-session request the switcher shipped from).

What changed

All behind a new remoteUi experiment (default off):

  • Surface the switcher in-app — a sidebar-footer indicator + popover, and a Connection settings page, so switching/adding servers no longer requires the native menu.
  • User-curated server list — replace the single custom URL with an add/remove allowlist (server-target.ts, v2 schema + migration); auto-discovered getbb Connect machines list alongside.
  • A different server per window — selecting a remote opens it in its own window (openRemoteServerWindow), leaving This Mac in place; closing the window returns you. Per-window Connect session; auth failure falls through to load the server so its gate can prompt sign-in instead of a fatal error — you can never be stranded.
  • Security parity with the native menu — every server-target mutation (switch and edit) is gated to the builtin/This-Mac origin (isBuiltinServerOrigin), and the switcher only renders on the This Mac window. A remote or compromised page can neither drive nor display it.
  • Custom getbb origins authenticate through Connect (fixes the existing custom-path sign-in dead-end).

New BbDesktopApi members are experimental_-prefixed with docs/api_to_audit.md entries. No HOST_DAEMON_PROTOCOL_VERSION change (no server↔daemon wire touched).

How you verified

  • pnpm exec turbo run typecheck test lint green across @bb/app, @bb/desktop, @bb/desktop-contract, @bb/domain (0 errors).
  • Unit tests added: builtin-only origin guard (getbb/remote origins rejected for switching), v1→v2 migration, switcher hidden when not on This Mac, Connection add/remove + disabled-on-remote.
  • Manual (dev desktop): opened a remote in its own window, closed it to return, confirmed a remote page can't render or drive the switcher, and This Mac switching works.

Refs #1451

AGENT GENERATED

Bhushit Agarwal and others added 13 commits August 30, 2026 10:46
…om Connect URLs

The server target was reachable only from the native "Window > Server"
menu, and BbDesktopApi exposed nothing about it, so the renderer could
neither read nor change which bb server the app targets. Selecting a
custom URL also skipped authenticateConnectTarget, so a pasted
getbb.app origin loaded without a session cookie and hit a sign-in
wall, while the same server picked from the Connect list authenticated.

Expose the target over four experimental_ BbDesktopApi members backed by
a new server-target IPC module, add a Settings > Connection section that
lists the selectable servers and edits the custom URL, and route custom
targets on a getbb.app host through the same Connect authentication the
Connect-list entries use.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…bar indicator

Add a `remoteUi` experiment (default off) that gates both Settings > Connection
and a new sidebar footer pill showing which server the UI renders from. The pill
reuses the Connection section's server list and switch actions through a shared
useServerTarget hook, and derives its status dot from the existing websocket
connection state rather than inventing one.

The native Server menu appended a "no Connect servers" line whenever the Connect
sync was skipped, even when This Mac plus a custom server were already listed,
which read as a contradiction. Show that line only when nothing beyond the
builtin server is selectable, and surface the same guidance as quiet muted text
in the Connection section instead. Rewrite the skip labels and section copy in
plain language.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replace the single custom server URL with a list the user manages, and make
bb Connect a removable default. This Mac is now the trust root: switching
between already-trusted servers stays available to remote pages, but only a
local frame may add a server, remove one, or untrust bb Connect, so a hostile
remote page can never grow the set of servers the app will load.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Collapse the sidebar server indicator into an icon-only footer action
with a status dot, and rebuild the Connection settings on the plugin
marketplace card layout so bb Connect is a removable default entry.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Selecting a remote server now opens (or focuses) a dedicated window while
the This Mac window stays put, so closing the remote window is always the
way back and the app can never be stranded. Remote windows get their own
loading and error views, best-effort Connect auth with per-URL renewal
refcounting, and Cmd-N duplicates the focused window's server. Startup
always boots the builtin server; per-window persistence across restart is
deferred. An in-flight guard keeps rapid repeat selections from spawning
duplicate windows.

With switching no longer needed from a remote page, all server-target IPC
(switch, add, remove, trust) is now accepted only from the builtin origin,
matching the native menu; isTrustedSwitchOrigin is gone and the renderer
disables switching in remote windows.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The sidebar indicator gated on the remoteUi flag of whichever server the
window happened to be viewing, so a remote server with the experiment on
would render this app's switcher inside its window — wired to the local
preload, listing the local catalog, and inert under the builtin-only
mutation guard. Gate the indicator and the Connection settings tab on
canManageServers instead, which main derives from the window's sender
origin, so remote windows show no switcher at all: you view that server
and close the window to return.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant