// ZTMUX — ENGINEERING REPORT

A Rust port of tmux — full server + client, ported against the tmux C sources.

Status: 100% functional — building, running, and self-hosting its own tooling. ztmux is the tmux program itself — server and client — reimplemented from the C in Rust. It builds and runs (ztmux new-session, ztmux attach), passes its 1080-case parity suite at 100% (byte-for-byte vs upstream tmux, zero known divergences), has every harness-found bug fixed, and ships original extensions the C tmux has no equivalent for.

>_PARITY VS tmux

1080
Cases passing
1080
Total parity cases
100%
vs tmux next-3.7
0
Known divergences

ztmux is a port of tmux, so "correct" means tmux itself. The parity suite runs the same inputs through the vendored tmux (reference) and ztmux (port) and compares byte-for-byte — the same shape as the sibling ports (zshrs vs zsh, strykelang vs perl). The suite has grown from a handful of format cases to 1080 covering formats, arithmetic, conditionals, string ops, options, buffers, windows, panes, and layouts — and every one now passes byte-for-byte, with zero known divergences.

>_REPOSITORY LAYOUT

Original code is kept apart from the port so the fidelity gate only judges what is meant to mirror C:

PathWhat
src/ported/The tmux port — 138 modules plus 23 compat shims that mirror vendor/tmux one-to-one. Held to C-name fidelity by the anti-drift gate.
src/extensions/Original ztmux features with no C counterpart — structured output, the dashboard and fuzzy-switcher TUIs, and the family of pipeable client subcommands (see Extensions). Exempt from the gate.
src/lib.rs, src/main.rsCrate roots: the module tree (which re-points every ported module's file into ported/) plus the binary entry.
vendor/tmuxRead-only, SHA-pinned reference — see How the port is built.

>_EXTENSIONS — BEYOND tmux

Because ztmux owns the whole stack, it adds capabilities upstream tmux does not have. They are plain clients — they re-invoke the ztmux binary and read its own machine-readable output, so they need no linkage to the server internals. The foundation is structured output plus the two interactive TUIs:

FeatureInvocationWhat
Structured outputlist-* -o json|jsonl|csv|tsv|tableTyped, machine-readable output for every list-* command, driven by the same #{…} format engine. table is aligned columns for humans; json feeds scripts and the TUIs below.
Live dashboardztmux dashboardA ratatui TUI: the session→window→pane tree, per-pane detail table, live server stats with a pane-count sparkline, kill-with-confirm, and 1 s auto-refresh.
Fuzzy switcherztmux switcherType-to-filter picker over every session, window, and pane; Enter runs the right switch-client / select-window / select-pane to jump there.

On top of that sits a family of one-shot client subcommands, each resolving the running server over the list-* -o json query layer. The inspection verbs are pipeable tables that also emit -o json / --json; the action verbs are dry-run by default and only mutate when passed -f / --force.

// INSPECTION — read-only, pipeable:

CommandWhat
ztmux activeFocused window/pane of every session.
ztmux ageSessions ranked by creation age, oldest first.
ztmux aheadHow far each repo is ahead of/behind upstream.
ztmux alertsWindows with a pending bell/activity/silence alert.
ztmux autonameWindows with a pinned name (automatic-rename off).
ztmux bordersWindows that draw a status line on their pane borders.
ztmux buffersThe server's paste buffers, largest first.
ztmux busyPanes running a program, not idle at a prompt.
ztmux changesUncommitted file count per pane's repo, dirtiest first.
ztmux cmdHistogram of commands running across panes.
ztmux commitThe last commit in every pane's repo.
ztmux conflictsRepos with unresolved merge conflicts.
ztmux connectedAttached clients ranked by connection age.
ztmux constrainAttached clients ranked by screen size, smallest first.
ztmux controlClients attached in control mode (-CC).
ztmux cwdWorking directories in use, busiest first.
ztmux deadDead panes still held open in a window.
ztmux dedupFind redundant panes (same cwd + command).
ztmux densityWindows ranked by pane count, most first.
ztmux destroySessions that self-destruct when the last client detaches.
ztmux detachedSessions with no client attached, freshest first.
ztmux diskFilesystem usage behind each pane's cwd.
ztmux doctorEnvironment / server health check.
ztmux elapsedHow long each pane's process has been running.
ztmux envPer-session environment overrides.
ztmux eventsStream server lifecycle events as JSONL.
ztmux fanoutSessions ranked by total pane count.
ztmux finderSearch panes by command/path/title/window.
ztmux focusThe active pane of every window.
ztmux gitGit branch + dirty state of every pane's repo.
ztmux gonePanes whose working directory no longer exists.
ztmux graphRender the server tree as DOT/Mermaid/HTML.
ztmux grepSearch the live contents of every pane.
ztmux groupsCluster sessions by session group.
ztmux historyRank panes by scrollback buffer size.
ztmux hooksThe command hooks configured on each session.
ztmux idleAttached clients ranked by time since last activity.
ztmux infoDeep inspector for a single pane.
ztmux inputPanes that are ignoring keyboard input.
ztmux keysHow many key bindings live in each key table.
ztmux keytableClients parked on a non-root key table.
ztmux layoutsThe current layout string of every window.
ztmux limitEach session's scrollback capacity, largest first.
ztmux linkedWindows linked into more than one session.
ztmux autolockSessions set to lock themselves after idle time.
ztmux marksThe marked pane(s).
ztmux memPanes ranked by process resident memory.
ztmux modePanes currently frozen in a mode.
ztmux monitorWindows armed to alert on activity or silence.
ztmux mouseWhich sessions have mouse mode enabled.
ztmux namedWindows with a deliberate name, not the running command.
ztmux nestedPanes running a nested terminal multiplexer.
ztmux netEstablished outbound connections per pane.
ztmux peekDump the visible contents of every pane.
ztmux pipedPanes with an active pipe-pane capture.
ztmux portsListening TCP ports mapped to panes.
ztmux projectProject kind and root behind every pane.
ztmux psOne-shot pipeable per-pane process table.
ztmux pstreeProcess tree running under every pane.
ztmux readonlyClients attached in read-only mode.
ztmux recentList sessions ranked by last activity.
ztmux remainWindows that keep panes open after they exit.
ztmux remoteThe git remote each pane's repo points at.
ztmux shellsPanes sitting at a bare shell prompt.
ztmux sizeReport pane geometry, smallest first.
ztmux snapshotDump the whole server as one nested JSON document.
ztmux soloWindows holding a single, unsplit pane.
ztmux sshWhich panes hold an SSH connection, and where.
ztmux startcmdThe command line each pane was launched with.
ztmux stashRepositories with stashed work behind a pane.
ztmux statePanes whose process is in an abnormal state.
ztmux statsOne-shot server summary report.
ztmux statusSessions with the status line turned off.
ztmux submodulesRepos with submodules and how many are out of sync.
ztmux syncWindows with synchronize-panes turned on.
ztmux tagThe git describe/tag context of every pane's repo.
ztmux termHistogram of attached client terminal types.
ztmux titlebarSessions that push a title to the outer terminal.
ztmux titlesEvery pane's advertised title.
ztmux treePrint the session/window/pane tree.
ztmux ttyMap every pane to its terminal device.
ztmux usagePer-session CPU/MEM/RSS resource rollup.
ztmux userThe owner of every pane's process.
ztmux utf8The UTF-8 state of every attached client.
ztmux vcsWhich version-control system each pane is under.
ztmux viewersHow many clients are attached to each session.
ztmux visualSessions that show alerts visually instead of just beeping.
ztmux watchTop-like live per-pane process monitor.
ztmux whoClients attached to the server, by session.
ztmux winsizeWindows whose sizing mode differs from the default.
ztmux worktreePanes sitting in a linked git worktree.
ztmux writablePanes whose working directory is read-only.
ztmux zoomWindows with a zoomed pane.

// ACTIONS — dry-run by default, apply with -f:

CommandWhat
ztmux bcastBroadcast a command to many panes at once.
ztmux clearallFree the scrollback of every pane.
ztmux equalizeRe-balance every multi-pane window's layout.
ztmux layoutApply a named layout preset to a window.
ztmux pickBatch ops over the multi-pane mark set (sync/unmark/clear/list).
ztmux pruneRemove dead/empty/idle server objects.
ztmux reviveRevive every dead pane in place.
ztmux retitleLabel every pane with its running command.

>_HOW THE PORT IS BUILT

Two references, both vendored under vendor/ as plain, read-only, SHA-pinned copies so the clone is self-contained:

PathWhatRole
vendor/tmuxupstream tmux C sources (next-3.7)Source of truth — every ported module is diffed against its C counterpart
src/ported/the ztmux portThe living code we own and evolve toward safe, idiomatic Rust

Every ported function carries a back-link to its C origin as a doc comment, e.g. /// C vendor/tmux/grid.c:320: grid_create(). The port report tracks per-function C→Rust coverage: 2,127 of tmux's 2,696 functions ported so far.

>_BUGS THE HARNESS CAUGHT

Verifying against C at every step turns "looks right" into "is right." A sample of faults the parity suite and unit tests root-caused to a single line — each now locked by a regression test (the full log is in BUGS.md):

  1. Mouse-driven TUIs froze mid-pane — a stale - 1 in the SGR-mouse encoder (input_keys.rs) dropped the sequence's M/m terminator after xsnprintf was corrected to exclude the NUL. ztmux wrote \033[<35;69;44 with no terminator; crossterm blocked in read() waiting for an end byte that never came, so rich ratatui/crossterm panes locked up on any click or focus change while keyboard input still worked.
  2. ztmux hijacked real tmux's socket — it resolved its default socket from $TMUX, so launched inside a tmux pane it connected to tmux's server and spoke protocol 8 at it (server exited unexpectedly). Fixed to resolve only from $ZTMUX and advertise both $TMUX and $ZTMUX to panes, so the two multiplexers run side by side.
  3. Server crash on bind-key h then l — the red-black tree's delete rebalance (rb_remove_color, compat/tree.rs) rotated around the wrong node. Rebinding a key that already had a default removed the old node first, corrupting the key-bindings tree and segfaulting the server on startup.
  4. Powerline glyphs rendered as \202\202\202utf8_strvis's inner loop never advanced the source pointer (the C is while (++src < end …)), so each multibyte UTF-8 character was re-read and mangled into raw bytes plus octal escapes.
  5. even-* layouts off by onelayout_spread_cell dumped the leftover column on the last pane instead of handing it to the leading cells; an 80-col two-pane split came out 39|40 instead of tmux's 40|39.
  6. Pane spawn hung on macOS — the ported closefrom looped close() up to the server-raised RLIMIT_NOFILE; replaced with the libproc PROC_PIDLISTFDS path tmux actually compiles on macOS, so the forked child reaches execvp.

>_ANTI-DRIFT GATE

A port can be faked by inventing Rust-only "helper" functions that don't exist in tmux, inflating apparent completeness. tests/ported_fn_names_match_c.rs fails the build when a free fn is added under src/ported/ whose name has no counterpart in vendor/tmux. src/extensions/ is exempt by design — it is original code, not a mirror of C — exactly as #[cfg(test)] blocks are skipped. Pre-existing exceptions (libc/libevent wrappers, Rust glue) are frozen in an allowlist: an audit trail to burn down, not a free pass.

>_TESTING

1080/1080
Parity cases (100%)
1253
Unit tests
2127
C fns ported
125k
Lines of Rust

Three layers stack: byte-for-byte parity against the vendored tmux; in-tree unit tests for pure logic (red-black tree invariants under randomized insert/delete, UTF-8 round-trips, layout arithmetic, and the extensions' rendering via ratatui's headless backend); and the anti-drift gate that fails the build on invented functions.

>_"DONE RIGHT"

  1. Start from a working skeleton — a running program to refactor, not a blank page.
  2. Shrink the unsafe surface — replace raw-pointer intrusive lists and C-isms with safe Rust where behavior allows.
  3. Verify against C at every step — a module isn't "ported" until it matches the C reference (parity suite).
  4. Keep it greencargo build and cargo clippy stay clean as code comes over.

>_BUILD & RUN

Requires a C libevent and a terminfo database (ncurses), matching tmux itself. On macOS the build links Homebrew's libevent automatically (TMUX_RS_DISABLE_HOMEBREW_LIBS=1 to opt out). Then the binary ztmux speaks the same commands as tmux — on its own socket namespace (ztmux-<uid>, from $ZTMUX, never $TMUX) so it never collides with a running tmux — plus the extension subcommands:

CommandDoes
cargo build --releaseBuilds the ztmux server + client binary.
ztmux new-session -s workStart a session (as tmux).
ztmux list-panes -a -o tableEvery pane, as an aligned table (or -o json).
ztmux dashboard / ztmux switcherLaunch the live dashboard / the fuzzy switcher.