Agent-readable wiki
RMUX Mental Model Wiki
RMUX is a universal Rust terminal multiplexer for the agentic era: a tmux-compatible CLI and daemon that lets humans and AI agents detach, inspect, script, and orchestrate persistent terminal sessions on Linux, macOS, and Windows — no WSL required. What makes it worth studying is its layered crate architecture, which separates pure domain model from IPC transport, PTY management, and public SDK into independently testable boundaries.
Pages
- The Mental Model: One Daemon, Many SurfacesRMUX has exactly one moving part at runtime: a single-socket daemon (Unix socket or Windows Named Pipe) that owns all session/window/pane state. Every other surface — CLI, SDK, ratatui widget, AI agent — sends typed request frames to that daemon and reads typed response frames back. The binary doubles as that daemon via a hidden re-exec path (`--__internal-daemon`), so no separate install is needed. The key invariant: if the daemon is not running, the CLI auto-starts it on first command; if it is already running, every subsequent client reuses the same socket without negotiation.
- Daemon Lifecycle: Start, Attach, and Re-ExecWhen a tmux-style command (e.g. `new-session -d`) finds no running daemon, `rmux-client`'s `auto_start` module re-execs the current binary with the hidden flag `--__internal-daemon` plus an optional socket path and config-forwarding flags. `src/main.rs` detects this flag and branches into `run_hidden_daemon`, which builds a `DaemonConfig`, binds a `ServerDaemon`, and blocks on `server.wait()`. On Unix this runs a single-thread Tokio runtime; on Windows it uses a multi-thread runtime with a floor of 4 workers. The socket path defaults to a per-user directory derived from `$RMUX_TMPDIR` or `/tmp`; the `$RMUX` env var lets nested clients detect they are already inside a session and short-circuit.
- Crate Map: Dependency Direction & Ownership RulesRMUX is a Cargo workspace of 12 crates arranged in strict layers. Foundation layer (no OS/network deps): `rmux-types` (TerminalSize newtype), `rmux-proto` (request/response frame contracts, codec, identity newtypes), `rmux-core` (pure in-memory domain model — sessions, windows, panes, layout, grid, scrollback). OS integration layer: `rmux-os` (host, signals, process, terminal helpers), `rmux-ipc` (socket/pipe endpoint naming and byte transport only — deliberately carries no protocol), `rmux-pty` (PTY allocation and child-process management across Linux/macOS/Windows ConPTY). Runtime layer: `rmux-server` (Tokio async daemon, owns pane I/O and all handlers), `rmux-client` (blocking RPC client, auto-start logic, attach mode). Public surface layer: `rmux-sdk` (async facade, must NOT depend on rmux-client/rmux-core/rmux-server/rmux-pty), `rmux-render-core` (pure-data snapshot projection, wasm32-compatible), `ratatui-rmux` (PaneDriver + PaneState + PaneWidget, depends only on rmux-sdk). Root binary `rmux` links rmux-server and Tokio directly only to host the hidden daemon re-exec path.
- IPC Transport & Protocol Framing`rmux-ipc` owns endpoint naming and raw byte transport only (Unix sockets on Linux/macOS, Named Pipes on Windows with a per-user mutex) — it knows nothing about request shapes. `rmux-proto` owns the typed frame contracts: `Request` and `Response` enums covering all 90 tmux-compatible commands plus SDK-only extensions (session leases, pane output subscriptions, snapshot refs, SDK wait IDs). The codec layer in `rmux-proto::codec` length-frames and encodes requests; `rmux-client::connection` drives this over the blocking stream from `rmux-ipc`. The key boundary invariant: `rmux-ipc` must remain protocol-agnostic so it can be swapped or extended without touching the request/response contracts in `rmux-proto`.
- Core Domain Model: Sessions, Panes, Grid, and Scrollback`rmux-core` is the pure in-memory domain: no OS calls, no Tokio, no network. It models the full tmux object graph — sessions own windows, windows own panes, panes own a terminal grid plus scrollback. The grid module handles VT/ANSI state (cursor, SGR attributes, alternate screen, scroll regions, wide/combining characters). Parser traces under `crates/rmux-core/tests/parser_traces/` are golden-file tests that pin exact VT sequence handling (e.g. `alternate_screen_roundtrip.trace`, `unicode_wide_cjk.trace`, `sgr_256_and_rgb.trace`). The `command_parser` module translates tmux-syntax command strings; `formats` implements tmux-format string evaluation; `hooks` tracks registered hook callbacks. Safe-change rule: any logic that belongs in this crate must be pure and deterministic — if it requires I/O, it belongs in `rmux-server` or `rmux-os`.
- Safe-Change Guide: SDK, Ratatui Integration & Failure ModesThe public SDK boundary (`rmux-sdk`) is intentionally isolated: it must never import `rmux-client`, `rmux-core`, `rmux-server`, or `rmux-pty` as normal dependencies. It re-exports identity newtypes from `rmux-proto` so callers never import internal crates. `ratatui-rmux` goes one step further — three building blocks only: `PaneDriver` (async I/O and state mutation, reaches RMUX only through `rmux-sdk`), `PaneState` (deterministic sync projection, no I/O), `PaneWidget` (sync ratatui widget, no clock/time deps). `rmux-render-core` is wasm32-compatible for the same reason. Key failure modes to anticipate: (1) daemon not running — `auto_start` re-execs but the socket write race can fail if the binary path is wrong (override via `RMUX_INTERNAL_BINARY_PATH`); (2) stale Unix socket — `rmux-server` detects and removes it on bind; (3) nested session confusion — `$RMUX` env var guards against re-attaching inside an existing session; (4) Windows ConPTY path — requires at least Windows 10 1903; older builds fall back to an error, not a silent hang.
Complete Markdown
The complete agent-readable Markdown files are published separately from this HTML page.