Repository navigation
Description
Feature hasn't been suggested before.
- I have verified this feature I'm about to request hasn't been suggested before.
Describe the enhancement you want to request
Problem
I run OpenCode servers on a mixed fleet (Windows + WSL, macOS laptop, several Linux hosts, a cloud VPS) and want one web UI that shows and controls sessions across all of them.
Today's multi-server support is client-side federation: every browser maintains its own server list and connects to every server independently. Server identity is tied to a URL, and there is no enrollment, no presence, and no session index shared between clients. A mesh VPN doesn't close the gap — configuration stays O(N x M) (every client device joins the VPN and configures all N servers), and it still provides no shared index, no presence, and no stable application-level identity.
Related: #43727, #43030, #40843, #41152; #19949 / #15752 asked for multi-server-in-one-UI (closed "not planned").
Proposal
An optional hub-and-node control plane on top of standalone servers — centralized discovery, decentralized execution. Standalone opencode serve is unaffected.
flowchart LR
USER("Client Browser"):::NODE
subgraph VPS["Cloud Server"]
HUB(("☁️ Hub Server")):::NODE
GATE(["🔒 Auth"]):::NODE
HUB <--> GATE
end
subgraph LANA["Home"]
NA(["🖥️ PC"]):::NODE
NB(["💻 WSL"]):::NODE
end
subgraph LANB["Office"]
NC(["🗄️ Server"]):::NODE
end
subgraph ROAM["Hotspot"]
ND(["💻 Laptop"]):::NODE
end
NA -->|WebSocket| HUB
NB -->|WebSocket| HUB
NC -->|WebSocket| HUB
ND -->|WebSocket| HUB
GATE <--> USER
style VPS fill:#0001,stroke:gray,stroke-width:1px,stroke-dasharray:6 4,opacity:0.6;
style LANA fill:#0001,stroke:#FA08,stroke-width:1px,stroke-dasharray:6 4;
style LANB fill:#0001,stroke:#AF08,stroke-width:1px,stroke-dasharray:6 4;
style ROAM fill:#0001,stroke:#0AF8,stroke-width:1px,stroke-dasharray:6 4;
classDef NODE fill:#0008,stroke:white,color:white;
- Enrollment:
opencode join <hub-url>(interactive browser approval, or--tokenfor headless). The node gets a permanent ID independent of hostname/IP/URL and authenticates with a node-generated keypair thereafter. - Presence: each node keeps one outbound persistent connection (NAT/firewall-friendly); nodes remain visible while offline.
- Session index: nodes advertise lightweight session metadata via sequenced events with snapshot fallback — same shape as the existing
/sync/history+/global/eventreconciliation. The hub holds an index, never the authoritative session data. - Access: the hub relays authenticated client traffic to nodes over multiplexed streams (nodes themselves authenticate by keypair, not through the client auth layer). Direct client-node transport is a possible later optimization.
Nodes stay authoritative for projects, tools, execution, and session contents. Configuration concentrates to O(N + M): a node enrolls once, a client only needs the hub URL.
Non-goals for now: no session DB migration to the hub, no filesystem sync, no distributed execution, no P2P requirement, no multi-user ACLs committed (the design stays open to them).
Relationship to the experimental control-plane (WorkspaceAdapter)
There is real overlap here, and the indexing/relay parts of this proposal would conflict with it if built independently: control-plane/workspace.ts already proxies requests to remote OpenCode servers (runInWorkspace over a Target.remote { url, headers }), reconciles session events by posting per-session sequence state to /sync/history and following /global/event via SSE with reconnect backoff, and tracks per-workspace connection status.
The scopes differ in ways that look complementary rather than competing. Workspaces are project-scoped — adapters register per projectID and every workspace carries one — while a node is machine-scoped and owns many projects. A workspace's identity is minted by the controlling instance and its remote is addressed by URL, which requires inbound reachability; a node's identity is minted at enrollment, URL-independent, and connects outbound only.
That suggests a concrete compatibility path: the hub becomes the connectivity substrate underneath the existing machinery. An enrolled node surfaces as an ordinary Target.remote — its target() resolving to a hub relay URL plus auth headers — so the existing proxying and /sync/history + /global/event reconciliation are reused rather than duplicated. I'd value maintainer input on whether that layering matches the intended direction of the control-plane work.
Planned first step
I plan to start with node identity + enrollment only: the opencode join flow, a permanent node ID, and keypair authentication — opt-in, with no change to standalone opencode serve or the control-plane code. Presence, session indexing, and relayed access would follow as separate increments built on the sync machinery above.
I have fuller design notes (enrollment token format, re-enrollment/revocation, epoch-based reconciliation, relay multiplexing, trust model, deployment behind an SSO proxy) and will post them if there's interest. Also open to prototyping out of tree first if working code is preferred before an in-tree abstraction.
This proposal and its architecture originate from me. Claude Fable 5 (Anthropic) and ChatGPT Sol 5.6 (OpenAI) assisted with drafting, research, and design review; I have reviewed and take responsibility for all content and claims.
Activity
AlexanderWagnerDev commentedon Nov 9, 2026
I would really like to see this feature reconsidered, as it would solve a real limitation for people running OpenCode across multiple machines.
My current setup includes Windows and Linux machines, a home lab behind NAT/firewalls without incoming port access, and a remote server where I would like to host a centralized web interface using Docker.
OpenCode's existing remote pairing and OpenTunnel functionality already solves the connectivity problem. I can access individual OpenCode instances through their
*.opentunnel.xyzURLs without SSH, VPNs, or opening inbound ports.The missing piece is centralized, server-side management of these instances.
Currently, adding remote servers to one OpenCode client does not make those connections available in another browser or through the remote web interface.
For my use case, even a much smaller implementation than the originally proposed hub architecture would be extremely useful:
Each OpenCode instance should continue running and executing commands on its own machine. The central server would only handle discovery, authentication, and API routing.
This would also make the feature usable on native Windows installations, where SSH-based orchestration is not necessarily desirable.
I understand that the original proposal involves a more comprehensive hub-and-node architecture. However, could a smaller, optional implementation based on registering existing remote OpenCode endpoints be considered instead?
It could potentially reuse the existing OpenCode server API and OpenTunnel connectivity without introducing a completely new node enrollment protocol.
For users managing several machines, having one persistent, browser-accessible dashboard would be a substantial improvement over maintaining separate client-side server lists.
I would love to see this revisited, even if the initial implementation only supports manually registered remote servers.