ProjectslassoDocs

Architecture

lasso architecture: the browser and MCP clients reach the lasso binary through Cloudflare Access; lasso drives the local herdr over its socket and remote herdrs through an SSH pool, keeps state in lasso.db, and sends Web Push to the phone

lasso is one Go binary. It embeds its React frontend, keeps its state in a SQLite file, and drives herdr (the terminal multiplexer the agents actually run in) on its own machine and on every machine you can SSH to. It does not run agents itself: herdr owns the panes and the processes, and lasso orchestrates around it, including relaying messages into panes and carrying replies back over tailcat.

The pieces#

The web server. One listener serves the embedded single-page app, the /api/* routes behind it, and the agent-facing endpoints: the MCP server at /mcp, herdr's socket API as MCP tools at /herdr-mcp, and raw CDP at /cdp. chrome-devtools-mcp's tools are on /mcp too, as browser_*. Live state (the focused pane, the layout, theme and settings revisions) reaches the browser over server-sent events at /api/events. See HTTP routes.

Terminals through ttyd. The terminal column is a real terminal: lasso spawns ttyd running herdr (or herdr --remote <host> for a remote host) and reverse-proxies it, WebSocket included, at /terminal/<host>/. Each ttyd listens on its own unix socket named by lasso's PID and the host, so several lasso instances never collide, and a host keeps its terminal warm: switching back to a host re-points the proxy at a ttyd that is already running instead of spawning a new one. The terminal for a host nobody is looking at is retired after a while.

herdr over its socket. lasso talks to the local herdr server over its unix socket (-herdr-sock) to read panes and focus, follow events, and create workspaces and worktrees for new agents.

Remote hosts over SSH. For each remote host, lasso opens one SSH ControlMaster connection with the system ssh binary, so your ~/.ssh/config (ProxyJump, identities, known hosts) applies exactly as on the command line. Everything for that host rides it: the remote herdr socket forwarded to a local one, file operations over SFTP, and git commands. A remote herdr must speak the same protocol as the herdr on lasso's machine. A host whose herdr lasso cannot drive (a different version, or not running) still gets theme writes over a files-only SSH connection.

Per-tab hosts. Which host a view drives is a property of the browser tab, not of the server: each tab sends its host with every request (X-Lasso-Host or ?host=). Two tabs can sit on two machines at once, and an agent's MCP calls default to the caller's own host. See Hosts.

State in lasso.db. Agent records, New Agent defaults, the shared UI state, OAuth clients and tokens, push devices and the VAPID key, plugin approvals and the list of browsers all live in one SQLite file in ~/.lasso. Each remote host keeps its own creator settings in its own ~/.lasso/lasso.db, written with that host's sqlite3. See Files and directories.

Web Push to the phone. lasso signs Web Push messages with its VAPID key and sends them through the browser vendor's push service (Apple's, for an iPhone), which delivers them to the service worker on the device even with no tab open. See Notifications.

The shared browser. A headless Chromium on lasso's machine, started on first use and stopped when idle, optionally capped in a systemd user scope. The Browser tab streams it, and agents drive it through /cdp or through /mcp's browser_* tools, for which lasso runs one chrome-devtools-mcp process per MCP session per browser that session uses. Each browser is its own Chromium. See Shared browser.

Plugins. A plugin's tab pages are served from /plugins/<name>/ as an opaque, sandboxed origin; its MCP server runs in an isb sandbox, a container by default or a VM if you choose (or, if you trust it, on the host), and its tools are mirrored onto /mcp. See Plugins.

Background work#

Some work runs whether or not a browser is open:

  • Host refresher. Probes every host in ~/.ssh/config on an interval, so the host picker opens on warm data. Each completed probe also converges that host's theme if it drifted while the host was asleep.
  • Repo cache warmer. Keeps every reachable host's repo and branch lists fresh for the New dialog.
  • Agent reaper. Reconciles agent records against herdr's panes, marking an agent closed only after its pane has been missing from several successful listings in a row.
  • Blocked-agent watcher. Looks across the fleet for agents waiting on a human and sends notifications. It polls nothing while no device is registered.
  • SSH reaper. Cleans up SSH control masters left behind by killed herdr --remote clients.

The diagram#

The diagram above is reladraw source at docs/assets/architecture/lasso.reladraw. Edit it and run mise run diagram, which renders it to SVG inside a separate Debian incus container, since reladraw is fetched from npm at render time. See Development.