TL;DR
Rmux is a from-scratch Rust rewrite of the terminal multiplexer idea, built specifically for the agentic era. It hit Show HN on May 21, 2026, posted by author shideneyu with the tagline “A programmable terminal multiplexer with a Playwright-style SDK” — and the framing landed. The pitch in one sentence: drop-in tmux compatibility (90 commands, your keybindings work), plus a typed async Rust SDK on the same daemon so agents and scripts can drive any CLI or TUI app the way Playwright drives a browser.
Key facts:
- v0.2.0 released May 18, 2026 (3 days before Show HN), MIT/Apache-2.0 dual-licensed
- 90 tmux-compatible CLI commands implemented —
new-session,split-window,send-keys,attach-session, etc. - Typed Rust SDK (
rmux-sdkon crates.io) with stable pane IDs, structured snapshots, locator-style waits - Native on Linux, macOS, and Windows — uses Unix PTYs on *nix, real ConPTY on Windows (no WSL required)
ratatui-rmuxwidget for embedding live panes inside Ratatui TUI apps#![forbid(unsafe_code)]in upper-level crates, OS boundary code isolated in runtime crates- Single daemon behind both surfaces — anything the CLI can do, the SDK can do, and vice versa
- Limitations: fresh public preview, “bugs are expected” per the README, scriptable plugin/scripting system not yet broken out, no Lua/scripting parity with tmux configs
If you’ve ever written a flaky tmux send-keys + tmux capture-pane | grep loop to babysit a long-running tool from a script — or had an SSH session die and lose a Claude Code or Codex run — Rmux is the most principled fix shipped in 2026 so far.
What changed as of September 2026: the facts above describe the v0.2.0 launch (May 2026). Four months later Rmux is at v0.10.0 (released August 4, 2026; ~2,600 GitHub stars) and several of the launch-day limitations are gone. The two biggest: official Python (
pip install librmux, 0.6.x) and TypeScript (npm install @rmux/sdk, 0.6.x) SDKs now exist alongside the Rust one, and the tmux-compatible surface has been expanded to track tmux 3.7b (list sorting,run-shellpositional args,scroll-to-mouse, popup rendering, key tables, control-mode notifications). Also new since launch: Web Share (browser-shared panes/sessions with hybrid post-quantum end-to-end encryption), anrmux claudelauncher that runs Claude Code with tmux teammate mode plus an installable Claude Code skill (rmux claude install-skill),send-keys --wait-text/--wait-pane-exitflags for shell automation, recoverable pane output streams (Pane::recover_output()/surface_stream()) in the SDK, signed and independently verifiable release artifacts, Nix/Homebrew/WinGet/Scoop/Chocolatey/APT/DNF packages, Linux aarch64 builds, and a long list of Windows ConPTY fixes (Ctrl-C/Ctrl-D, multiline bracketed paste, UTF-8 clipboard). The wire protocol was bumped to version 3 in 0.8.0 — restart old daemons after upgrading. Still true: it’s pre-1.0, dual MIT/Apache-2.0, and the daemon protocol is local-only. Sections below are kept as written at launch, with version notes where the facts moved.
What Rmux Actually Is
The author, shideneyu on GitHub and HN, explained the origin in the Show HN thread:
“RMUX started from a frustration: I’ve used tmux for years and got tired of scraping output with grep and sleeps to automate anything. So I rebuilt the multiplexer from scratch in Rust, with a programmable layer on top.”
That’s the core insight. Tmux is wonderful for humans and brittle for machines. The moment you try to automate — wait for a build to finish, send input only after a prompt appears, scrape a value out of top — you end up writing sleep 3 && capture-pane -p | tail -n 20 | grep ... and praying.
Rmux’s answer is two parallel surfaces on top of one daemon:
1. The CLI surface (rmux binary): looks and acts like tmux. All 90 of the most-used tmux commands are implemented, your muscle memory works, your .tmux.conf-style keybindings carry over. You can drop it in.
2. The SDK surface (rmux-sdk crate): a typed async Rust API that talks to the same daemon over a local socket. Sessions and panes are first-class objects with stable IDs. You get wait_for_text("ready") instead of sleep && grep. Structured PaneSnapshot objects (rows, cols, attributes) instead of raw escape-sequence soup. This is the “Playwright for terminals” part.
Both surfaces talk to a hidden daemon that owns the PTYs, sessions, layouts, hooks, and buffers. Detach your human terminal — your SDK script keeps driving. Kill your SDK script — your human session is still attachable.
Install
For the impatient, on macOS or Linux:
curl -fsSL https://rmux.io/install.sh | sh
As of September 2026 the package managers have caught up too: brew install rmux (macOS), winget install rmux or choco install rmux (Windows), nix profile install github:Helvesec/rmux, plus APT and DNF repos documented at rmux.io/docs/get-started.
Windows PowerShell:
irm https://rmux.io/install.ps1 | iex
From crates.io:
cargo install rmux --locked
Verify with rmux --version — it reported 0.2.0 at launch; a fresh install in September 2026 reports 0.10.0. SHA256 checksums for the prebuilt binaries have been published since the v0.2.0 GitHub Release, which is the right thing to do but still a rarity for a v0.2 launch (since 0.9.1 the artifacts are also signed and independently verifiable).
A first session feels exactly like tmux:
rmux 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 work
If you’ve never used tmux: that creates a detached session called work, splits it horizontally, sends a command into the right pane, then attaches your terminal so you can see both panes side by side. Press Ctrl+B D (the default prefix, like tmux) to detach again — the session keeps running, the process keeps running, you can re-attach from another terminal or another SSH connection later.
The SDK Is the Whole Point
The CLI is table stakes. The SDK is why you’d switch.
Add it to a Cargo project:
[dependencies]
rmux-sdk = "0.10" # was "0.2" at launch; the SDK crate tracks the daemon version
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
Not a Rust shop? Since launch the same daemon API has shipped for Python and TypeScript:
pip install librmux # Python SDK (0.6.x as of September 2026)
npm install @rmux/sdk # TypeScript SDK (0.6.x as of September 2026)
Here’s the canonical “wait for output, then capture state” pattern, adapted from the README:
use std::time::Duration;
use rmux_sdk::{
EnsureSession, EnsureSessionPolicy, 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)),
)
.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(())
}
Read that carefully. The interesting lines are:
connect_or_start()— connects to a running daemon if one exists, starts one if not. No more “did Itmux start-serveryet?” race conditions.EnsureSessionPolicy::CreateOrReuse— idempotent session bootstrap. Re-run the script, get the same session.pane.wait_for_text("ready").await?— this is the killer feature. No sleeps. No polling loops. A proper async wait that resolves the moment the text appears in the pane buffer (with thedefault_timeoutas the bound).pane.snapshot().await?— typedPaneSnapshotwithcols,rows, and structured cell data. You don’t parse strings; you read fields.
The mental model maps almost 1:1 to Playwright’s: a typed handle to a long-lived environment, locator-style waits, structured introspection of state.
Ratatui Integration: Embed Live Panes in TUI Apps
This is the bit that made me sit up. The ratatui-rmux companion crate exposes a PaneWidget that renders a live pane snapshot directly inside a Ratatui TUI app:
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);
}
What you can build with that: a TUI dashboard that owns its own panes (a build log, a server log, an agent’s terminal session) and renders them as widgets next to your own controls, without subprocess-management or PTY-allocation code in your app. The dashboard is the multiplexer’s other face. For anyone building agent observability tools or live operator UIs, this collapses a giant amount of boilerplate.
Why “For the Agentic Era” Actually Means Something Here
A lot of 2026 tooling slaps “for AI agents” on the README and changes nothing about the design. Rmux earns the label because of three concrete properties:
1. Detachable execution + reconnect. When a Claude Code, Codex, or aider run is going for 45 minutes and your SSH connection dies, a regular shell loses the process. With rmux (or tmux), the daemon owns the PTY — the agent keeps running, the new SSH attaches and resumes the human view. For long-lived coding-agent sessions over flaky connections, this isn’t a nice-to-have, it’s the difference between “shipped” and “had to restart from scratch.”
2. Structured snapshots, not byte streams. When an agent supervisor needs to know “did my child process print the success line yet?”, a byte-stream pipe forces it to write a parser. A typed PaneSnapshot lets it pattern-match on rows and cells. The supervisor agent can be small and dumb because the data is shaped right.
3. Real ConPTY on Windows, no WSL. This is the one most projects skip. WezTerm, Alacritty, even some “cross-platform” Rust shells punt to “use WSL” on Windows. Rmux uses real ConPTY (the Windows pseudo-console API) and a per-user Named Pipe for IPC. If you’re building agent tooling that has to run on a developer’s actual Windows machine — or in a Windows Server VM in CI — that matters more than benchmarks.
Community Reception (First 24 Hours)
The Show HN thread was still young when this was written (39 points, 29 comments — it finished at ~194 points), and the author was actively replying. Representative threads:
- “Why not just
script-wrap tmux?” — tmux’s automation surface is the same byte-stream-and-regex pattern that motivated rmux. Wrapping it doesn’t fix the mismatch. - “Daemon protocol stability?” —
rmux-proto(the IPC DTO crate) is published publicly so SDKs in other languages can be built against it. Python and Node bindings aren’t shipped, but the wire format is documented. - “What about screen / zellij?” —
screenpredates structured automation as a concern. Zellij has a WASM-plugin-centric philosophy; rmux bets on out-of-process SDK clients instead. Different shape, not strictly competitive.
The r/rust thread skews implementation-curious: ConPTY integration, the workspace split, and the #![forbid(unsafe_code)] posture in upper crates. Build hygiene is unusually thorough for v0.2: cargo clippy --all-targets --locked -D warnings, a scripts/no-network-in-runtime.sh assertion, and a platform-neutrality checker.
Honest Limitations
This is a fresh preview. Be realistic.
- “Bugs are expected.” The README says it. Don’t put rmux on critical CI paths on day 3 — run it for personal use and prototypes for a release cycle or two first.
- No Lua/scripting parity with tmux configs. Keybindings and core options carry over; a 400-line
.tmux.confwith custom hooks and plugins does not. (Improved since: 0.8.0 added a bigsource-file/hooks/formats compatibility pass and loads real public configs like oh-my-tmux; 0.9.0 tracks tmux 3.7b.) - No official Python / Node SDK yet. (Resolved — as of September 2026 there are official
librmux(PyPI) and@rmux/sdk(npm) packages.) At launch the options were shelling out to the CLI or hand-rolling against the publicrmux-protowire format. - Daemon protocol is local-only by design. Unix socket or Named Pipe. To drive a remote rmux, you SSH in and run the SDK there — which is usually what you want anyway.
- Daemon memory footprint at idle isn’t documented. Irrelevant on a dev machine; you’d want to measure if you’re spawning hundreds per CI build.
How It Compares
| Tool | Daemon | Typed SDK | Windows-native | Snapshot API | License |
|---|---|---|---|---|---|
| rmux 0.10 (0.2 at launch) | yes | yes (Rust, Python, TypeScript) | yes (ConPTY) | yes (typed) | MIT/Apache-2.0 |
| tmux | yes | no | no (WSL) | capture-pane (text) | ISC |
| Zellij | yes | WASM plugins | partial | partial | MIT |
| WezTerm mux | yes | Lua | yes | partial | MIT |
| screen | yes | no | no | no | GPLv3 |
expect / pexpect | no | partial (Python) | partial | byte stream | various |
The closest competitor by design philosophy is honestly Playwright for terminals, which doesn’t really exist as a category yet. Rmux is making it one.
Setup Recipes
Babysit a Coding Agent Over SSH
ssh build-server
rmux new-session -d -s coder
rmux send-keys -t coder 'cd ~/project && claude code' Enter
rmux attach-session -t coder
# do prompt work, then Ctrl+B D to detach
exit # SSH disconnects, agent keeps running
Reconnect from anywhere with ssh build-server && rmux attach-session -t coder. The agent’s terminal is exactly as you left it, scrollback included.
Drive a TUI Installer from CI
pane.send_text("./installer.sh\n").await?;
pane.wait_for_text("License [y/N]").await?;
pane.send_text("y\n").await?;
pane.wait_for_text("Install directory:").await?;
pane.send_text("/opt/myapp\n").await?;
pane.wait_for_text("Installation complete").await?;
This is the genuinely new capability. You could do it before with expect, but expect is a string-soup language from 1990. Rmux makes it a typed Rust program with proper error handling.
FAQ
Is rmux a drop-in replacement for tmux?
For day-to-day use: largely yes. The 90 most-used commands work, your prefix-key reflexes work. For exotic configs (heavy Lua scripting, custom hooks, plugin ecosystems like TPM): not yet. Treat it as “tmux that also happens to be programmable” rather than “tmux but better at everything tmux does.”
Can I use rmux from Python or Node, not Rust?
Yes, as of mid-2026. The project now ships official SDKs: librmux on PyPI and @rmux/sdk on npm, both exposing sessions, panes, streams, waits, and snapshots against the local daemon. (At the May launch neither existed and the options were shelling out to the rmux CLI or writing against the public rmux-proto wire format.) For shell scripts, rmux send-keys --wait-text "…" added in 0.7.0 covers the common wait-then-continue case without any SDK.
Does the Windows version really work without WSL?
Yes. It uses real ConPTY (the Windows pseudo-console API introduced in Windows 10 1809) for PTY allocation and per-user Named Pipes for IPC. The project’s scripts/check-platform-neutrality.sh enforces that platform-specific code stays inside the boundary crates. If you’ve been waiting for a terminal multiplexer that doesn’t make Windows a second-class citizen, this is the first credible one.
Is it stable enough to use today?
For personal automation, prototypes, and exploratory agent work: yes, with the README’s caveat that bugs are expected at v0.2.0. For production CI on critical paths: wait one or two release cycles, watch the issue tracker, and pin the version. (Update, September 2026: eight releases later at v0.10.0, with signed artifacts, a dedicated tmux-compatibility test matrix, and most of the Windows input bugs closed, it’s a much safer bet — but it’s still pre-1.0 and the wire protocol has already been bumped once, so pin the version and restart daemons on upgrade.) The build discipline (clippy, fmt, locked deps, forbid(unsafe_code)) is reassuring; the version number is honest.
How does this fit alongside coding agents like Claude Code or Codex?
Two complementary roles. First, as a host: run the agent’s CLI inside an rmux session so it survives SSH disconnects and you can attach/detach (huge for long runs over flaky connections). Second, as a target: an agent supervisor (a Rust or Python orchestrator) uses the rmux SDK to drive other terminal tools — installers, REPLs, TUI debuggers — that the inner agent needs to interact with. The supervisor pattern is the more interesting one and the one rmux is uniquely good at versus tmux.
How does it compare to Forge?
Different layer. Forge is a reliability layer for the agent’s reasoning and tool-calling loop. Rmux is a reliability layer for the agent’s environment — the terminal sessions the agent (or the human supervising it) lives inside. Both target the same underlying frustration (small models / fragile sessions need scaffolding to be useful), but they don’t overlap.
Verdict
Rmux is the cleanest version of “rebuild a Unix workhorse for the agentic era” I’ve seen in 2026. The decision to ship a tmux-compatible CLI and a typed SDK on the same daemon — instead of forcing users to pick — is the kind of constraint that makes a tool actually adoptable.
The Windows-native story (real ConPTY, no WSL) is what would tip me from “interesting” to “I’m trying this” for any project that needs cross-platform agent tooling. The Ratatui widget integration is what would tip a TUI builder. The wait_for_text locator API is what would tip anyone who has ever written a sleep 3 && grep loop and known it was wrong.
Caveats are real and the author owns them: v0.2.0, bugs expected, no Python/Node SDK yet (since shipped), no scripting parity with mature tmux configs. But the bones are correct, the build hygiene is unusually disciplined for a v0.2 launch, and the design rationale survives contact with the obvious alternatives.
If you run long-lived processes over SSH, supervise CLI tools from code, or build TUI dashboards that wrap other terminal apps — install it today, port one annoying automation script, and report back in 30 days. That’s the right size of bet on a fresh tool that ships its protocol publicly and forbids unsafe code in its upper crates.
Repo: github.com/helvesec/rmux · Docs: rmux.io/docs · Show HN: news.ycombinator.com/item?id=48219918 · License: MIT / Apache-2.0