ztmux-core is the engine that lets a GUI drive tmux without shelling out. Instead of spawning the tmux binary and scraping its text, it implements the client side of tmux's wire protocol directly against the server's Unix socket (imsg framing, protocol v8, ported from tmux 3.6). Every operation returns a serde_json::Value, so each host renders sessions, windows, and panes in its own frontend. Created by MenkeTechnologies.
Wire protocol, not subprocess
Speaks imsg framing straight to the tmux server socket — no tmux child process, no text scraping, no control-mode parsing.
JSON out
Session tree, pane previews, search corpus, broadcast list, dashboard summary — all returned as serde_json::Value for the host to render.
Native process inspection
Reads the full command line running in each pane via libproc / /proc — again, no subprocess.
Snapshot save / restore
A native tmux-resurrect replacement: layout, cwd, full command line, active state, pane contents, and a process whitelist.
Owned on both ends
The same protocol version 8 is pinned by ztmux-core (client) and ztmux (the tmux server rewritten in Rust). Upstream tmux cannot break the pairing — both ends move together under one owner.
Capabilities
- Session tree — sessions, windows, panes with previews (
ops::tree,sessions_summary). - Send keys / broadcast — type to one or many panes (
send_keys,broadcast_list). - Synchronize panes — toggle synchronize-panes per window (
set_sync). - Focus — switch the active session/window/pane (
focus). - Capture — capture pane contents (
capture). - Search corpus — searchable index across panes (
search_corpus). - Pane process — the real command line per pane (
proc). - Snapshot — save / restore sessions natively (
snapshot).
Layers
A thin module set; the host calls these and renders the JSON.
use ztmux_core::{transport, ops, snapshot};
// the wire client: run a tmux command over the server socket
let sock = transport::socket_path().unwrap();
let out = transport::command(&sock, &["list-sessions"])?;
// high-level ops return serde_json::Value for the GUI to render
let tree = ops::tree(); // sessions → windows → panes (+ previews)
ops::send_keys(&panes, "echo hi", true);
Vertical integration — the wire protocol is owned end-to-end
ztmux-core is one half of a client/server pair MenkeTechnologies controls on both ends. The client pins PROTOCOL_VERSION = 8 (src/transport.rs); the server it talks to can be upstream tmux or ztmux — the from-source tmux rewrite in Rust — which pins the identical PROTOCOL_VERSION = 8. Upstream tmux is free to bump its protocol in a future release, which would break ztmux-core against a system tmux server; the ztmux-core ↔ ztmux pairing stays version-locked because both endpoints move together under one owner. The wire contract is fixed by this stack, not by upstream tmux's release cadence. The client leans into the owned server by default — socket_path() probes the ztmux-<uid> socket dir before tmux-<uid>, and ops::tmux_bin prefers the ztmux binary — so a running ztmux server is what gets driven when both are present.
- GUI host — zterminal embeds ztmux-core and renders the JSON.
- Client engine — ztmux-core speaks the imsg wire protocol (v8) to the server socket.
- Server — ztmux, the tmux server+client rewritten in Rust, pins the same v8.
- Shell — zshrs runs inside the panes.
- CLI suite — zpwr is the command environment on top.
Hosts
ztmux-core is consumed by the zterminal GUI and is built to drop into other MenkeTechnologies apps: each calls these functions and renders the JSON in its own frontend. See the engineering report for the module map.