the transparent terminal multiplexer
Your terminal emulator talks directly to the shell. mpx just owns the PTY and forwards bytes. It is not in the way. It has no opinions about your escape sequences, your scrollback, or your font.
curl -fsSL https://mpx.capocasa.dev/install | sh
the loop
Start a session, work inside it, leave with Ctrl-G. Attach again later, from the same terminal or a different one, and the session is exactly where you left it, scrollback included.
every client is the same client
mpx is primaryless: every attached client sees the same output and every client can type. Detach a client and it stops seeing new bytes. Attach again and ttty, the side cache, hands back the current screen plus scrollback. Try it: type a command, switch who is typing, detach and reattach a pane.
Both panes are attached to session demo. Detached panes show
what they missed when you attach them again, because attach serves the full model:
ttty scrollback plus the live screen.
negative space
architecture
ghostty, kitty, alacritty mpx the session your terminal emulator daemon zsh, htop, vim ┌──────────────────────┐ ┌──────────────┐ ┌────────────┐ │ scrollback, font, │ bytes │ │ bytes │ │ │ mouse, clipboard │<-------->│ owns the │<-------->│ PTY │ │ rendering: all yours │ verbatim │ PTY master │ verbatim │ │ └──────────────────────┘ └──────┬───────┘ └────────────┘ │ watches, never in the data path ┌──────┴───────┐ │ ttty │ │ side cache. │ │ read on │ │ attach only │ └──────────────┘
day one
mpx newmpx or mpx main does the same. No name: the directory's name, with a counter on collision. Rerunning on an active session just attaches.mpx attachmpx new main also attaches if it exists.mpx lsmpx killmpx k main works too: any unambiguous command prefix is accepted. mpx n, mpx a, mpx l.-l host:port-p overrides the port.--log$XDG_DATA_HOME/mpx/mpx-YYYY.log. Without it, mpx logs nothing. Unknown flags are errors, not guesses.elsewhere
Run the daemon on the host where the work happens, attach from anywhere that can reach the TCP port. No SSH involvement, no SSH dependency. Over wireguard recommended, the traffic is otherwise unencrypted.
Session names gate TCP access, but that is convenience, not a security boundary. Keep the listener on a private interface and put real authentication in front if you need it.