TL;DR — Both are client/server terminal workspaces with the same default Ctrl+b prefix. tmux is a general-purpose multiplexer that is usually already installed on servers; herdr is a younger, agent-native workspace that tracks which pane is working, blocked, or idle and exposes that state through a JSON CLI and socket API. Pick tmux for ubiquity, plugins, and text-protocol automation. Pick herdr when orchestrating several coding agents is the main job.
| tmux 3.8 | herdr 0.9.5 | |
|---|---|---|
| First release | 2007 | 2026 (0.1.0 in March) |
| Implementation | C, with libevent and ncurses | Rust, native binary, vendored Ghostty VT parser |
| License | ISC | Apache-2.0 |
| Design centre | Any terminal workload | Terminal workspace for AI coding agents |
| Object model | Sessions → windows → panes | Sessions → workspaces → tabs → panes |
| Configuration | ~/.tmux.conf, command language | ~/.config/herdr/config.toml (%APPDATA%\herdr on Windows), TOML |
| Default prefix | Ctrl+b | Ctrl+b |
| Mouse | On by default (set -g mouse off) | Mouse-first UI; capture can be disabled |
| Agent state | Not built in; assemble it from pane data | Built-in detection: working, blocked, done, idle |
| Automation | Shell commands, formats, hooks, text control mode | JSON CLI and socket API, agent-aware waits |
| Remote hosts | SSH per host, then attach | Saved SSH machines in one client with a combined agent list |
| Plugins | TPM and a large third-party ecosystem | Manifest plugins, marketplace and agent integrations |
| Platforms | OpenBSD, FreeBSD, NetBSD, Linux, macOS, Solaris; Windows via WSL | Linux, macOS, Windows; remote servers Linux/macOS and Windows x86_64 |
| Floating panes | Yes, expanded in 3.8 | Pane zoom plus popup/overlay panes; no general floating layer |
| Restore after reboot | Not native; add tmux-resurrect/continuum | Restores layout and resumes supported agent sessions; processes do not survive |
Both tools put a long-lived server between your terminal and the programs you run. In tmux the server owns sessions, windows, and panes; clients attach to that server and can detach without stopping anything. In herdr the server owns pane processes and terminal state, while the TUI is just one client. Multiple clients can attach, and each can view a different tab.
The difference is what the hierarchy is for. A tmux window is a layout container; a herdr workspace is a project container whose sidebar state rolls up from the agents inside it, and tabs separate views such as agents, logs, and review. Herdr also gives workspaces, tabs, and panes first-class IDs that the CLI and socket API can address; a pane such as w1:p1 can be targeted directly, which matters later when you script panes by name.
Under the terminal layer, tmux carries its own VT parser and renderer in C. Herdr vendors libghostty-vt for terminal parsing and renders the result in its Rust TUI. Both are native terminal programs — there is no Electron or browser runtime in either.
On detach, both tools behave the same way: the server keeps running, so shells, agents, test runs, and servers keep working. The commands differ only in the key:
# tmux: detach with prefix + d
tmux new-session -s work
tmux attach -t work
# herdr: detach with prefix + q
herdr --session work
herdr session listA server restart is where the designs separate. tmux has no native snapshot or reboot recovery: when the server process dies, the panes die with it. The usual answer is tmux-resurrect and tmux-continuum, which save and replay session shape, not live processes.
Herdr writes its session shape to session.json and restores workspaces, tabs, panes, cwd, layout, and focus after a server restart. The original processes are still gone. It can additionally replay recent pane screen history (opt-in, because that history can contain secrets) and, for agents with an installed integration, resume the agent's native conversation using its own resume command. Live handoff across a binary update is experimental and opt-in.
| Failure | tmux 3.8 | herdr 0.9.5 |
|---|---|---|
| Client detaches or SSH drops | Everything keeps running | Everything keeps running |
| Server process stops | Panes are lost | Layout restores; panes restart as new shells |
| Machine reboots | Nothing restores without plugins | Layout restores; supported agents resume their sessions |
| Binary upgrade | Restart server, lose panes | Compatible servers keep running; --handoff can move live panes |
tmux treats every pane as an opaque terminal. It exposes excellent primitives — #{pane_current_command}, pane titles, capture-pane, hooks, and, in 3.8, OSC 133 events for command start and finish — but it does not know that the thing in pane 2 is waiting for approval. You build that state machine yourself.
Herdr ships one. It identifies agents from foreground processes, screen manifests, and optional integrations, then classifies each pane as working, blocked, done, idle, or unknown. State rolls up to tabs and workspaces so the sidebar can point at the agent that needs an answer. That classification is the product, so it is also the part to evaluate critically: detection reads the visible bottom of the pane, and herdr's own docs warn that an unfamiliar approval prompt may read as idle until a manifest learns its shape.
# herdr: wait for an agent to need input, then answer it
herdr agent wait reviewer --until blocked
herdr agent prompt reviewer "fix the failing test" --wait
# tmux: send input, but you decide when the agent is ready
tmux send-keys -t agents:0.1 'fix the failing test' Enter
tmux capture-pane -p -t agents:0.1 | tail -20Herdr also folds Git worktrees into the model: herdr worktree create makes a checkout, opens it as a workspace, and groups it under the source repo. In tmux the same workflow is git worktree add plus a new window or session — perfectly workable, just not part of the tool.
tmux automation is a text protocol with decades of scripting behind it. One-shot commands return text; control mode (tmux -C) frames command output with %begin, %end, and %error and streams notifications. Formats such as #{session_name} are a small query language, and 3.8 adds event payloads, monitor hooks, and wait-for -E.
Herdr's CLI is a thin wrapper over its local socket API, and most commands print JSON. IDs are explicit and addressable, and several commands are agent-aware rather than screen-aware. The socket schema is inspectable with herdr api schema.
| Task | tmux 3.8 | herdr 0.9.5 |
|---|---|---|
| Run a command in a pane | send-keys -t … 'cmd' Enter | pane run or agent prompt |
| Read the screen | capture-pane -p -t … | pane read / agent read |
| Wait for output | poll capture-pane, or build a hook | pane wait-output --match/--regex |
| Wait for an agent | not built in | agent wait --until blocked |
| Machine-readable output | formats and control-mode text | JSON responses and herdr api schema |
| Event stream | control-mode notifications, hooks, monitors | socket API plus blocking waits |
| Attached TUI required | No | No |
Which is better depends on the consumer. If an existing script already parses tmux formats or control mode, tmux remains the lowest-friction choice. If a program wants structured IDs and typed agent states, herdr's JSON surface is cleaner than parsing capture-pane output.
tmux's remote story is SSH plus attach: connect to a host, attach to the server already running there, and detach when you leave. It is simple, assumes nothing, and works on machines where you cannot install new software. Managing several hosts means several terminals or several clients.
Herdr saves SSH machines as profiles and shows their workspaces beside Local in one UI. Each machine keeps its own server, sessions, and processes, and a lost connection to one does not disconnect the others. The agent list spans connected machines, and CLI commands can be routed with herdr --machine "Build machine" agent list. It uses OpenSSH for authentication and does not store passwords or keys. The trade is that the remote side needs a compatible herdr server, which machine add can install or update with approval.
Both default to Ctrl+b, and the muscle memory transfers surprisingly well. tmux is keyboard-first and its mouse handling is a single session option: with mouse off, applications inside panes still receive mouse events, but tmux itself does not bind them. Herdr is mouse-first — click panes, drag borders, right-click menus — with the prefix as an optional layer and direct chords configurable for prefix-free use.
tmux 3.8 is the stronger choice for pane geometry. Floating panes gained modal panes, mouse move and resize, new-pane -A, JSON layout strings, and default bindings such as Ctrl+b * for a new floating pane and Ctrl+b @ to toggle floating and tiled. Herdr has pane zoom and popup/overlay panes for plugins and custom commands, but not a general floating-pane layer.
Copy mode is close enough to be uneventful. Both open it with Ctrl+b [ and support movement, search, and selection, though the default key set differs: tmux uses emacs bindings unless you set -g mode-keys vi or start it with $EDITOR/$VISUAL set to something containing vi, while herdr is vi-style out of the box. Herdr keeps the pane's output flowing while you navigate history; tmux 3.8 can auto-refresh copy mode and adds scrollbars that auto-hide instead of resizing the pane.
A tmux config is a script. .tmux.conf is a list of tmux commands, which means any option, binding, hook, or conditional can be expressed without a separate plugin API. Extensibility grew around that: TPM installs plugins, and plugins are usually shell scripts that call tmux commands. The result is a very large, very mature ecosystem, at the cost of configuration that reads like code.
Herdr config is declarative TOML and optional — it runs without a config file, and herdr --default-config prints a complete starting point. Its plugin model is a manifest plus out-of-process commands, so a plugin can be written in any language; integrations add agent session tracking. The ecosystem is much younger, and the 0.x version number is a fair warning that defaults and APIs can still move.
| tmux 3.8 | herdr 0.9.5 | |
|---|---|---|
| Config format | Command script | TOML |
| Extend by | Shell scripts, hooks, formats, TPM plugins | Manifest plugins, integrations, socket API |
| Ecosystem size | Large and long-running | New, with an indexed marketplace that is not a reviewed catalog |
| Stability signal | Mature major release | 0.x, pre-1.0 |
tmux is available from the package manager of essentially every Unix-like system, is part of the OpenBSD base system, and runs on FreeBSD, NetBSD, Linux, macOS, and Solaris. On Windows it runs under WSL. That ubiquity is a feature no competing tool has matched: you can assume tmux on a server in a way you cannot assume anything else.
Herdr ships native Rust builds for Linux (x86_64, aarch64), macOS (x86_64, aarch64), and Windows x86_64, which is generally available with documented platform limits and a ConPTY-based runtime. Install options include its install script, Homebrew, mise, and PowerShell. For remote use, the server must run on Linux or macOS (x86_64 or aarch64) or Windows x86_64. Both tools are native and fast; the practical difference is distribution reach, not raw rendering speed.
On graphics, tmux handles sixel images in-tree when built with --enable-sixel, while herdr renders the Kitty graphics protocol and crops images around popups and menus. Neither is a reason alone to switch, but it matters if your agent tooling emits images.
| Task | tmux 3.8 | herdr 0.9.5 |
|---|---|---|
| Start or attach | tmux | herdr |
| Named session | tmux new -s work / tmux attach -t work | herdr --session work / herdr session attach work |
| Detach | Ctrl+b d | Ctrl+b q |
| Split right / down | Ctrl+b % / " | Ctrl+b v / - |
| Move between panes | Ctrl+b o or arrow keys | Ctrl+b h/j/k/l |
| Rename window / tab | Ctrl+b , | Ctrl+b Shift+t |
| List sessions | tmux ls | herdr session list |
| New workspace | new session or window | Ctrl+b Shift+n |
| Pick a window or pane | Ctrl+b w | Ctrl+b g |
| Send input | tmux send-keys -t … | herdr pane send-text … |
| Read output | tmux capture-pane -p | herdr pane read |
| Config | ~/.tmux.conf | ~/.config/herdr/config.toml (Windows: %APPDATA%\herdr\config.toml) |