# Shared SSE stream keeps every v2 window synced
*anomalyco/opencode@dev · informative · 6 markers*

> **Default.** OpenCode v2 runs one HTTP server on port `4096`; the TUI, desktop, and web clients all connect to that same backend rather than each owning its own.
>
> **Trigger.** Every client opens one Server-Sent Events stream and reads the same global event feed, so an action taken in any window is published once and fanned out to all of them.
>
> **Surprise.** The desktop app forks exactly one sidecar server per Electron instance, so opening more windows reuses the backend instead of multiplying it.

**Author:** Fernando Ramirez · **Updated:** 2026-06-27T23:21:03.580Z

## Markers
1. **Start the one shared backend** — `packages/cli/src/commands/handlers/serve.ts:37–44`
   `serve` binds a single HTTP server via `HttpRouter.serve(createRoutes(password), ...)` over `NodeHttpServer.layer`. `listen` defaults to port `4096` and walks upward if it's taken. This one process owns the routes, database, and event service that every client shares; there is no per-client backend.
2. **TUI attaches and subscribes** — `packages/tui/src/context/sdk.tsx:88–100`
   The TUI builds a `createOpencodeClient` from `@opencode-ai/sdk/v2` pointed at the server `baseUrl`, then calls `sdk.global.event()` to open the SSE stream. When workspaces are enabled it follows with `sdk.sync.start()` so its view of state tracks the shared server.
3. **Desktop forks one local server** — `packages/desktop/src/main/server.ts:60–67`
   `spawnLocalServer` uses `utilityProcess.fork(sidecar, ...)` to start a single sidecar server process, then connects to `http://${hostname}:${port}`. One sidecar is spawned per Electron instance, so additional desktop windows reuse the same backend instead of starting new ones.
4. **Web points at the same server** — `packages/app/src/entry.tsx:159–166`
   The web entry builds a `ServerConnection.Http` whose `url` comes from `getCurrentUrl()`, which defaults to `http://localhost:4096`. The browser client talks to the identical HTTP server the TUI and desktop use, so all three share one backend.
5. **Each client opens one event stream** — `packages/server/src/handlers/event.ts:23–39`
   The `event.subscribe` handler acquires `EventV2.allBounded(events, subscriberCapacity)` — a bounded live feed of every server event — and pipes it out as `text/event-stream` with a 15-second heartbeat. Every connected client (TUI, desktop, web) reads from this same broadcast feed.
6. **Every event fans out to all clients** — `packages/core/src/event.ts:406–417`
   `notify` delivers each published event to local listeners, the type-specific pubsub, and `PubSub.publish(pubsub.all, event)` — the global channel that backs every SSE subscriber. Because there is one server and one `pubsub.all`, a single action lands in every open window without per-window polling.

---
Interactive view: https://app.principal-ade.com/trail/790d358f-1d4a-4c57-b927-32a4317de340
JSON: https://app.principal-ade.com/api/trails/by-id/790d358f-1d4a-4c57-b927-32a4317de340
Authored at `ae53163ca` (dev).
To open a trail or tour locally in the interactive viewer, see https://app.principal-ade.com for the Principal CLI quickstart.
