Skip to content

Local Server

Workbench runs all workspaces, sessions, and terminals inside a detached local server daemon. The desktop app spawns the daemon on first launch, connects to it over loopback WSS as the owner, and every operation flows through the server. Closing the window does not stop running agents — they continue in the daemon, and relaunching attaches to it with full event replay.

This is not a mode or a setting. The desktop app is architecturally a client of the server, the same way a remote laptop or phone would be — it just happens to spawn the server on the same machine. There is one code path through the system regardless of where the client is.

On launch, the app looks for an existing daemon via a discovery file (loopback.json in the Workbench data directory). If a live daemon is found at the recorded PID, the app attaches to it. If no daemon is running (or the discovery file points to a dead process), the app spawns a fresh one as a detached process and waits for it to write the discovery file.

The daemon runs in its own process group (setsid on Unix, DETACHED_PROCESS on Windows), so it is not a child of the desktop process and survives the window closing.

The discovery file contains:

FieldPurpose
pidDaemon process ID
portListening port (default 7683)
fingerprintTLS certificate fingerprint
pairing_tokenOwner authentication token
control_tokenAuthorized shutdown token (256-bit hex)
server_versionServer binary version
started_atDaemon start timestamp

The file is written atomically and set to mode 0600 (owner-only read) on Unix. The control_token and pairing_token never leave the local machine.

The desktop authenticates to the daemon using HMAC challenge-response — the raw pairing token never crosses the wire, even over loopback:

  1. The app sends a token_hint (a SHA-256 hash of the pairing token) to identify itself.
  2. The daemon responds with a random nonce.
  3. The app computes HMAC-SHA256(pairing_token, nonce) and submits it.
  4. The daemon verifies the MAC and issues a session token.

This is the same authentication flow used by any owner client (a remote laptop, a second desktop). The loopback connection is not special — it is the degenerate case of a distributed topology.

  • Closing the window leaves the daemon running. Agents continue their turns, terminals stay alive, and scheduled routines keep firing.
  • Relaunching discovers the existing daemon and re-attaches. Events that occurred while the window was closed are replayed into the UI from the server’s event log.
  • Quitting the app (Cmd+Q / Alt+F4) also leaves the daemon running.
  • Version mismatch — when the daemon was spawned by an older app version, Settings shows a warning. Stop and start to pick up the new binary.

You can stop the daemon from three places:

  • Settings > Local Server — shows status (PID, port, version) with Stop and Start buttons.
  • System tray — “Stop Local Server” menu item (with a confirmation dialog).
  • CLI — workbench server stop authenticates over WSS and sends the shutdown_server command with the control token.

Stopping the daemon terminates all running agents and terminals. The discovery file is removed on clean shutdown. On Unix, the daemon also shuts down cleanly on SIGTERM.

After stopping, you can start a fresh daemon from Settings or by relaunching the app.

The workbench CLI connects to the same daemon over WSS. It discovers the server by reading loopback.json, authenticates with the pairing token, and has the same capabilities as the desktop UI.

You can also point the CLI at a remote server with --connection:

Terminal window
workbench --connection workbench://host:port/token#fp=fingerprint workspace list

See Command-Line Client for the full command reference.

SettingDescriptionDefault
WORKBENCH_SHARE_PORTOverride the daemon’s listening port7683
WORKBENCH_DISCOVERY_DIROverride the directory where loopback.json is written and readPlatform data directory

The daemon always binds to 127.0.0.1 (loopback only). Remote access uses the separate sharing/pairing mechanism described in Collaboration.

Daemon fails to start — Settings > General (“This machine”) and Settings > Local Server show the reason the desktop found, and the daemon writes its own startup log to ~/.workbench/logs/workbench.<date>.log (or your WORKBENCH_LOG_DIR override) (the same daily file as the desktop; its lines start with a workbench logging initialized banner carrying the daemon’s PID). The three reasons are:

  • 127.0.0.1:7683 is already in use by another process — the desktop checked the port before spawning. Stop whatever is listening there (an older Workbench daemon that outlived an upgrade, or a standalone workbench-server), or set WORKBENCH_SHARE_PORT to a free port, then click Start in Settings > Local Server.
  • exited during startup (exit status: N) — the daemon started and died before it was ready. The cause is in the daemon’s log lines (a config or certificate problem under the server config directory, for example).
  • did not become ready within 10s — the daemon is running but never published loopback.json. Check the log for what it is stuck on; Stop and Start from Settings > Local Server retries.

Stale discovery file — if the daemon crashed without cleanup, the app detects the stale PID, removes the file, and spawns a fresh daemon automatically.

Version mismatch after upgrade — the running daemon is from an older app version. Open Settings > Local Server, stop the old daemon, and start a new one.

Desktop shows “Connecting…” — the app is waiting for the daemon to become ready. If it persists, check ~/.workbench/logs/ for server-side errors. You can stop and restart from the system tray.