Skip to content

Architecture overview

AgentMux is a desktop application built around a small set of long-running processes that exchange events over named pipes and a local websocket. Understanding the topology is enough to navigate the rest of the docs.

┌──────────────────┐ named pipe ┌──────────────────┐
│ agentmux- │ ◀────────────────────────▶│ agentmux-cef │
│ launcher.exe │ │ (the "host") │
│ (≈325 KB shim) │ │ │
└────────┬─────────┘ └────────┬─────────┘
│ spawns │ embeds
│ ▼
│ ┌──────────────────┐
│ │ Chromium │
│ │ (CEF renderer) │
│ └────────┬─────────┘
│ │ JS bridge
│ ▼
│ ┌──────────────────┐
│ │ SolidJS app │
│ │ (the frontend) │
│ └────────┬─────────┘
│ │ websocket
▼ ▼
┌─────────────────────────────────────────────────────────┐
│ agentmux-srv │
│ (sidecar) │
│ • RPC engine (websocket) • SQLite persistence │
│ • saga coordinator • event bus │
└─────────────────────────────────────────────────────────┘
ProcessRoleCrate
launcherSets DLL search path; spawns the host from runtime/; tracks WRR (Window Reality Reconciliation) via Win32 hooks; durable event log for OS-level facts.agentmux-launcher
hostEmbeds Chromium via CEF; owns the OS window, the browser panes, the JS bridge, and IPC fan-out to the renderer.agentmux-cef
sidecarApp-domain server: workspaces, tabs, blocks, layouts, agents, identity. Persists to SQLite. Auto-spawned by the host on a dynamic port; users never run it directly.agentmux-srv
rendererA Chromium renderer process running the SolidJS frontend JS for one browser context. Not a singleton — every OS window gets its own renderer, and every browser pane inside a window adds another. Stateless — projects what the sidecar/host expose, dispatches user actions back through them.frontend/

A fifth crate — agentmux-common — provides shared utilities (path resolution, runtime mode detection) that all the above consume.

The four processes above plus the Chromium subprocesses that the host transparently spawns (GPU, network, storage, …) are collectively one instance — a process tree rooted at one launcher. A baseline single-window dev session runs as launcher + sidecar + host + 1 renderer = 4 processes; opening more windows or browser panes spawns additional renderers. Multiple instances (different versions, dev + portable) run side-by-side without colliding — see Multi-instance & dev mode.

Each process owns one concern, end-to-end:

  • The launcher is the only process that survives an OS-level Win32 surprise (a window minimize event, a monitor disconnection, a focus theft). Its WRR layer reconciles AgentMux’s own model against what Win32 actually thinks is happening.
  • The host is the only process with a CEF context. Browser panes, drag/drop, OS focus, and renderer crashes all live or die in the host. Crashing the host kills the user-facing window; the launcher restarts it.
  • The sidecar is the only process that owns durable state. Closing the host doesn’t lose data — when the host comes back, it reads from the sidecar.
  • The renderer is intentionally state-poor. It’s the projection of what the other processes hold; restarting the renderer (e.g. on hot reload) doesn’t lose anything.

This split is what makes multi-instance work cleanly. Two AgentMux portables running side-by-side each have their own host, their own sidecar, and their own data dir — they share nothing except the launcher binary on disk.

EdgeMechanismWhat flows
launcher ↔ hostNamed pipe IPCOS-level facts (window position, monitor topology, lifecycle)
host ↔ sidecarLocal websocket (dynamic port)RPC commands, event subscriptions, shell-integration env passing
host ↔ rendererCEF JS bridgePer-frame UI events (clicks, focus, resizes), pane lifecycle
renderer ↔ sidecarLocal websocket (re-uses host’s connection)Frontend dispatches reach the sidecar through the host’s bridge

Every cross-process edge has its own event format, its own ack semantics, and its own persistence strategy. None of them are “just” a function call.

This is where the reducer stack lives. Briefly:

  • Layer 1 — launcher reducer owns process / OS / monitor / pool state. Single-writer; durable JSONL event log.
  • Layer 2 — host reducer (in flight) owns CEF-side coordination: pending window creations, active drag, lifecycle.
  • Layer 3 — srv reducer owns the app domain: workspaces, tabs, blocks, layouts, agents.
  • Layer 4 — frontend slices project the above into per-pane Solid signals via per-slice reducer modules.

The full layout, slice list, and migration plan are in the reducer stack page.

Every running instance resolves its paths through agentmux-common::DataPaths (source). Resolution happens once in the launcher and is propagated to host + sidecar via the AGENTMUX_*_DIR env vars, so all three processes always agree.

ModeInstance dir
Installed~/.agentmux/versions/<version>/
Portable~/.agentmux/versions/<version>/ (same as installed — multi-instance is keyed on version, not on which folder you ran the binary from)
Dev (task dev)~/.agentmux/dev/<branch>/ (one dir per checked-out branch — different branches don’t collide)

Inside each data dir: data/ (SQLite), config/ (settings), logs/ (rotated host + sidecar + launcher logs), cef-cache/, agents/, runtime/ (lock + IPC).

Account-wide state — cookies, OAuth tokens, dictionary downloads — lives at ~/.agentmux/shared/, version-independent. The launcher’s own config.toml (saga retention etc.) lives directly at ~/.agentmux/config.toml.

See Multi-instance & dev mode for the full layout, log discovery story, and per-instance vs shared boundary.

If you’re new, read in this order:

  1. You’re here. This page.
  2. Multi-instance & dev mode — gets you to a running AgentMux you can poke at.
  3. Reducer stack — explains how state actually flows through the four processes.
  4. Pane Types — the user-visible building blocks.
  5. The Agent App API reference when you’re ready to drive AgentMux from an agent.