Skip to content

Architecture

Three design decisions explain most of luvus’s behavior.

The server owns everything: panes (real PTYs), the layout, agent detection, the session snapshot. It renders the whole UI into an off-screen buffer. The client is nearly stateless. It forwards your input and paints frames. That split is why sessions survive: the thing you close (the client) was never the thing that mattered.

Named sessions preserve the same boundary instead of adding a global manager. Each running name owns one server process, startup lock, pair of sockets, snapshot, PTY tree, and orchestration ledger. Stopped names consume no CPU or memory. Shared preferences, detection manifests, skills, and module installs remain at the Luvus root.

All state mutation happens on a single thread, driven by one event loop. Slow work (git fetches, session-store scans, quality gates) runs on worker threads and posts results back as events. Single-writer state is why orchestration’s task claims and path leases are race-free by construction, with no locks to get wrong.

The server doesn’t resend the screen. It sends only the cells that changed, coalesced into same-style runs. A keystroke costs ~22 bytes on the wire, a full 40-character line ~100 bytes. This is what makes remote attach over plain SSH feel local, and keeps the local render path around a millisecond per frame.

Pure Rust, a single ~3 MB binary, single-digit-MB resident memory even with panes full of scrollback, zero idle redraws (an idle session draws nothing). Performance is treated as a feature with a budget, so changes that would make the hot path slower don’t ship.