Universal Rust multiplexer for the agentic era: detachable, scriptable, and inspectable, with a tmux-compatible CLI, daemon-backed SDK, and native Ratatui integration.
Important
Released on 16 May 2026. All 90 tmux-compatible commands are implemented, but bugs are expected — this is a fresh public preview. Please file issues if you hit one.
- A tmux-style CLI for sessions, windows, panes, buffers, hooks, formats, copy mode, control mode, and common terminal workflows.
- A Rust SDK for creating sessions, splitting panes, sending typed input, reading snapshots, subscribing to pane output, waiting for text or bytes, and shutting down cleanly.
- A ratatui widget that renders pane snapshots into a
ratatui::buffer::Bufferwithout requiring async work in the draw path. - Native local runtime support: Unix PTYs and Unix sockets on Linux/macOS; ConPTY and named pipes on Windows — no WSL required.
- A small published crate set with internal implementation crates kept out of the public package surface.
From crates.io:
cargo install rmux --lockedFrom a local checkout:
cargo install --path .For Rust applications, after the public crates are published:
cargo add rmux-sdk
cargo add ratatui-rmuxrmux new-session -d -s work
rmux split-window -h -t work
rmux send-keys -t work 'echo "hello from rmux"' Enter
rmux attach-session -t workUse command help locally:
rmux list-commands
rmux new-session --help
rmux split-window --help[dependencies]
rmux-sdk = "0.1"
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }use std::time::Duration;
use rmux_sdk::{
EnsureSession, EnsureSessionPolicy, ProcessSpec, Rmux, SessionName,
TerminalSizeSpec,
};
#[tokio::main]
async fn main() -> rmux_sdk::Result<()> {
let rmux = Rmux::builder()
.default_timeout(Duration::from_secs(5))
.connect_or_start()
.await?;
let session_name = SessionName::new("work").expect("valid session name");
let session = rmux
.ensure_session(
EnsureSession::named(session_name)
.policy(EnsureSessionPolicy::CreateOrReuse)
.detached(true)
.size(TerminalSizeSpec::new(120, 32))
.process(ProcessSpec {
command: None,
environment: None,
}),
)
.await?;
let pane = session.pane(0, 0);
pane.send_text("printf 'ready\\n' && sleep 1\n").await?;
pane.wait_for_text("ready").await?;
let snapshot = pane.snapshot().await?;
println!("{}x{}", snapshot.cols, snapshot.rows);
Ok(())
}use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget};
use ratatui_rmux::{PaneState, PaneWidget};
use rmux_sdk::PaneSnapshot;
fn render(snapshot: PaneSnapshot, area: Rect, buffer: &mut Buffer) {
let state = PaneState::from_snapshot(snapshot);
PaneWidget::new(&state).render(area, buffer);
}
Three public surfaces — a rmux CLI, a rmux-sdk Rust crate, and a ratatui-rmux widget — share a single local protocol to talk to the daemon. Anything one surface can do, the others can do too.
| Crate | Role | Publication |
|---|---|---|
rmux-types |
Shared platform-neutral value types | public |
rmux-proto |
Detached IPC DTOs, framing, wire-safe errors | public |
rmux-os |
Small OS boundary helpers | public |
rmux-ipc |
Local IPC endpoints and transports | public |
rmux-sdk |
Daemon-backed Rust SDK | public |
ratatui-rmux |
Ratatui integration widget | public |
rmux-pty |
PTY allocation, resize, child process control | support crate |
rmux-core |
Sessions, panes, layouts, formats, hooks, buffers | support crate |
rmux-server |
Tokio daemon and request dispatch | support crate |
rmux-client |
Local IPC client and attach plumbing | support crate |
rmux |
CLI and hidden daemon entrypoint | public binary |
rmux-render-core |
Shared snapshot rendering core | workspace-internal |
| Platform | PTY backend | IPC backend | Default endpoint |
|---|---|---|---|
| Linux | Unix PTY | Unix socket | /tmp/rmux-{uid}/default |
| macOS | Unix PTY | Unix socket | /tmp/rmux-{uid}/default |
| Windows | ConPTY | Named pipe | per-user named pipe |
On Linux and macOS, RMUX reads .rmux.conf from the standard system and user locations:
/etc/rmux.conf~/.rmux.conf$XDG_CONFIG_HOME/rmux/rmux.conf~/.config/rmux/rmux.conf
On Windows, RMUX reads .rmux.conf as well, from the following locations:
%XDG_CONFIG_HOME%\rmux\rmux.conf%USERPROFILE%\.rmux.conf%APPDATA%\rmux\rmux.conf%RMUX_CONFIG_FILE%
The workspace is designed to be checked from source with locked dependencies:
cargo fmt --all -- --check
cargo clippy --workspace --all-targets --locked -- -D warnings
cargo test --workspace --locked --no-fail-fastAdditional local checks:
scripts/cfg-check.sh
scripts/unsafe-check.sh
scripts/no-network-in-runtime.sh
scripts/check-platform-neutrality.sh
scripts/ratatui-rmux-budget.sh
scripts/verify-package.shRelease artifact checks are driven by:
scripts/release-local.sh
scripts/package-unix.sh#![forbid(unsafe_code)] is used in the upper-level crates. OS and terminal boundary code is isolated in the lower-level runtime crates.
RMUX is dual-licensed under either:
at your option.