>_ZTERMINAL — A FAST, MODERN TERMINAL
A fast, GPU-accelerated, cross-platform terminal emulator and part of the MenkeTechnologies stack. OpenGL ES 2.0 glyph-atlas rendering, full xterm-compatible VT parsing (vim, tmux, htop, ncurses), 24-bit truecolor, scrollback, vi mode, search, and hints — in a vendored, self-contained build with no external runtime dependencies. Runs on Linux, BSD, macOS, and Windows.
Quickstart
Build from source, then run the binary:
# debug build cargo build # → target/debug/zterminal # release build cargo build --release
macOS installer (.pkg)
make pkg builds a single installer that drops Zterminal.app into /Applications and the zterminal-icat helper into /usr/local/bin:
make pkg # → target/release/osx/Zterminal-<version>.pkg # install sudo installer -pkg target/release/osx/Zterminal-<version>.pkg -target /
It builds a release binary, assembles + ad-hoc-signs the app bundle (stamping the version from zterminal/Cargo.toml), and packages both targets. The package is unsigned (no Developer ID), so first launch needs a right-click → Open. make app / make dmg build just the app bundle / disk image.
Full install + usage live in the README and man 5 zterminal.
Features
GPU renderer
OpenGL ES 2.0 glyph-atlas renderer — text and inline images uploaded as GPU textures and blitted per cell.
xterm VT parsing
Full xterm-compatible VT parsing — vim, tmux, htop, and ncurses apps run correctly.
Truecolor & more
24-bit truecolor, scrollback, vi mode, search, and link/path hints.
Native tiling splits
i3-style binary split tree, one shell + PTY per pane, GL-scissored — no tmux required.
Inline graphics
Kitty graphics protocol, Sixel, and iTerm2 inline images — drawn on the GPU, scrolling with the buffer.
First-class tmux
Speaks tmux's wire protocol directly to the server socket — live config, profiles, sessions, broadcast, and search.
Self-contained build
Vendored, no external runtime dependencies. Linux, BSD, macOS, and Windows.
In-process GUI suite
Control panel + dashboard rendered in an embedded WebView; all state under ~/.zterminal.
Inventions
Firsts that zterminal introduces to the terminal-emulator space. Each is, to our knowledge, novel — no shipping terminal emulator did it before.
First terminal emulator to modify tmux settings live
zterminal speaks tmux's native wire protocol directly to the server socket (crates/ztmux-core) — it is a first-class tmux client, with no tmux subprocess and nothing typed into the shell line. On top of that it ships live editors for the running server:
- tmux server options — read every
show-optionsscope (server / session / window) and edit any of them in place (set-option), applied instantly. - tmux paste buffers — list, view, edit, create, paste, and delete buffers.
- tmux key bindings — list every binding across the key tables and rebind / unbind them live (
bind-key/unbind-key), with the command re-tokenized for the wire.
No other terminal emulator edits a live tmux server's options, buffers, and keybindings from its own UI.
First terminal emulator to store tmux state in switchable profiles
zterminal's profiles are named snapshots of the entire configuration that you switch between in one click — and they capture far more than the terminal config:
- the full terminal config (
zterminal.toml), - the GUI look (color scheme, light/dark, custom scheme, effects),
- and the tmux server state — options, buffers, and key bindings.
Switching a profile restores the whole set, including reconfiguring the live tmux server over the wire. No emulator has profile-switchable tmux configuration.
First terminal emulator with a custom, live telemetry dashboard
zterminal ships an in-app dashboard — a live, polling telemetry surface built from a real component library (zgui-core): PTY throughput, render timing, scrollback, the full tmux summary (clients, sessions, windows, panes, server identity), and system metrics, rendered with gauges, sparklines, donuts, meters, tables, and stat strips. It doubles as a showcase of the component library. No terminal emulator ships a custom dashboard of this kind.
First terminal emulator to diff a command's output against its previous run
Every command block is captured through OSC 133, so a re-run can be compared to the run before it. zterminal_core/src/diff.rs diffs the two printed outputs in place — no tee to a file, no manual diff, and it works retroactively on blocks you never planned to compare.
First terminal emulator to trend a number from a command's output across runs
Pick a numeric column or field out of a command's printed output and zterminal_core/src/metric.rs tracks it across every recorded run of that command, so a latency, a size or a count becomes a series without wrapping the command in a script.
First terminal emulator to sort a command's printed output by column
zterminal_core/src/column.rs re-sorts a finished command's output by any detected column, in place in the scrollback — the output is re-rendered sorted rather than re-run through sort.
First terminal emulator to compare broadcast output across panes while the command runs
With input broadcast to several panes, zterminal streams a per-line consensus across them and flags the pane that diverges, live, as the command runs (⌃⌘G) — the fleet-wide "which host is different" question answered without collecting logs afterwards.
First terminal emulator to keep a command's output queryable after it leaves the buffer
The command-block ledger (crates/zterminal-ledger) durably captures blocks, so diff, trend and sort still work on output that has been evicted from the scrollback. Durable capture is an opt-in switch on the Commands tab.
First terminal emulator to run a relational query — including a cross-command JOIN — over its own captured output
zterminal_core/src/query.rs treats captured command blocks as relations: the printed output of two different commands can be JOINed on a shared column, retroactively, inside the terminal.
First tool to join the plain-text output of one command across N hosts
An operand can name a pane (`df -h` @pane 3), and under broadcast a pane is a host. All N answers are already resident in one process’s grids, so correlating them is an in-memory hash join over text a plain shell printed — no agent on any host, no serialization format, no network fan-in.
First terminal emulator with a pane that is a query
Pinning a statement to a split makes a pane whose contents are the relation: it re-executes and repaints every time an OSC 133 block finishes in the window. Query mode borrows the alternate screen the way less does, so the shell underneath is untouched and nothing is re-run to refresh.
First terminal emulator whose output triggers fire on a typed column predicate
Every trigger system in the category matches a regex against one rendered line. A zterminal trigger can instead carry %CPU > 90 or Use% > 85 — resolved to a detected column and compared with magnitude awareness, so 4.0K is below 2.0G and 93% is ninety-three.
First terminal emulator that can be told to wait on the pane you are watching
Every emulator can send text into a live pane; none can block on what comes back, so automation means driving a second, invisible shell through expect/pexpect or polling the screen in a sleep loop. pane_await holds its bus reply until a condition holds on the pane you already have open — a regex, an OSC 133 block finishing with a given exit code, or a typed column predicate like %CPU > 90 that a regex cannot express at all.
First tool that can block until N interactive shell sessions agree
panes_await decides one condition over a set of panes — all, any, quorum n, or agree. The first three are quantifiers over a per-host condition and have prior art (kubectl wait --all, Ansible wait_for); agree does not, because the value is not in the call. "Wait until every replica reports the same WAL position" cannot be written as "wait for X" — nobody knows X until the fleet settles on it, and a per-host waiter has exactly one host's answer in scope. A timeout answers with the straggler matrix: who holds which value, and who never spoke.
Control panel & shortcuts
zterminal hosts an in-process GUI suite (rendered in an embedded WebView) for configuration and inspection. All of its state and logs live under ~/.zterminal. The control panel has 19 tabs — Settings, Dashboard, Commands, Sessions, Layouts, Profiles, Keybindings, Triggers, Hints, Snippets, Processes, Recent dirs, Env vars, Logs, About, and the four tmux surfaces (config, sessions, buffers, keys).
| Shortcut | Opens |
|---|---|
⌘, | Control panel — Settings tab |
⌃⌘D | Control panel — Dashboard tab (telemetry / sessions / system) |
⌘K | Command palette — searchable window/tab/terminal/panel/pane actions |
⌘R | Shell-history palette — fuzzy-search history, insert the pick at the prompt |
⌘↑ / ⌘↓ | Jump to the previous / next shell prompt (OSC 133 shell integration) |
⌘⇧O | Select the most recently finished command’s output (OSC 133) |
⌘E | Switch to the most-recently-used other tab (MRU quick-switch) |
⌃⌘E | Exposé — tile grid of every zterminal window and tmux pane; click to focus |
⌃⌘P | Search all tmux panes — grep every pane's scrollback, jump to a match |
⌃⌘B | Broadcast — send-keys to a selected set of tmux panes / toggle synchronize-panes |
⌃⌘S | Sessions — save / restore the full tmux layout (replaces tmux-resurrect) |
⌃⌘G | Fan-out divergence — live per-line consensus across the panes a broadcast went to |
⌃⌘` | Quake dropdown — global hotkey, a terminal that slides down from the top |
The command palette reaches every panel tab plus the terminal actions, and is searchable, so the action list stays out of the way. Every action is also a rebindable keyboard shortcut (see the Keybindings tab).
Splits (native tiling)
zterminal tiles natively — its own i3-style binary split tree, one independent shell + PTY per pane, GL-scissored into the window (no tmux required). Any pane splits in either direction, nests arbitrarily, and each pane renders in its own sub-viewport.
| Shortcut | Action |
|---|---|
⌘D / ⌘⇧D | Split the focused pane vertically / horizontally |
⌘] / ⌘[ | Focus the next / previous pane |
⌥⌘←↑↓→ | Focus the pane in that direction (spatial) |
⌃⌘←↑↓→ | Move (swap) the focused pane in that direction |
⌘⇧←↑↓→ | Resize the focused pane along its split |
⌘⇧↩ | Zoom the focused pane to fill the window (toggle) |
⌘⇧W | Close the focused pane |
⌘⇧L | Layouts — save / restore the window's split layout |
Layouts (⌘⇧L) save and restore a window's native split tree. Save captures the split geometry plus each pane's working directory and foreground command to ~/.zterminal/layouts/<name>.json; restore rebuilds the splits, respawns every pane in its directory and replants the saved command at the prompt (it is not run — you review and press Enter). Live process state isn't restored — panes return in the right layout/cwd as fresh shells. This is the native counterpart to the tmux Sessions save/restore.
All split, history, MRU, and layout actions are in the command palette too, so a key binding is never required — by design, no zterminal binding masks a shell or tmux key on any OS (macOS uses ⌘; Linux/Windows use ⌃⇧ or palette-only).
Inline graphics
zterminal renders images inline in the grid via the GPU, supporting all three common terminal image protocols:
- Kitty graphics protocol — transmit (
a=t), transmit-and-display (a=T), put-by-id (a=p), support query (a=q, so capable tools auto-detect zterminal), and delete (a=d); RGB / RGBA / PNG (f=24/32/100); direct and file (t=f) transmission; zlib compression (o=z); chunked payloads; stacking order (z=); Unicode placeholders (U=1) for grid-anchored placement; and animation (a=fframes +a=aplay/stop/loop control), played back on a timer. - Sixel —
ESC P … q … ST, with RGB and HLS color registers, run-length, and raster attributes. - iTerm2 inline images — OSC
1337;File=…(imgcat), any format the decoder handles (PNG / JPEG / GIF).
Images are uploaded as GPU textures and blitted over the cells they occupy; they scroll with the buffer, clip at pane edges, draw behind (z < 0) or over the text, and are freed when they scroll out of the scrollback. A scanner sits ahead of the escape-sequence parser to extract image sequences (Kitty APC, Sixel DCS, iTerm2 OSC) — ordinary text and control sequences are untouched. Sequences wrapped by tmux (ESC Ptmux;…, with set -g allow-passthrough on) are unwrapped and decoded, and Kitty's Unicode-placeholder placement also works through tmux.
Background image
zterminal can draw an image behind the cells (a terminal / desktop background), set in config rather than via an escape sequence — so it works everywhere, including inside tmux:
[window] opacity = 0.85 # < 1 so the image shows through cells background_image = "~/Pictures/wall.png" background_image_opacity = 1.0 # 0.0–1.0
The image is uploaded once as a GPU texture and drawn each frame (cover: fills the window preserving aspect, cropping overflow), behind any cell whose background is the default color — lower opacity to reveal more of it. Reloads live when the path changes; PNG / JPEG / GIF.
Displaying an image
extra/zterminal-icat picture.png # bundled, zero deps (base64 + sips on macOS) kitten icat picture.png # kitty timg picture.png # brew install timg chafa picture.png # brew install chafa (kitty/sixel/iterm2) img2sixel picture.png # libsixel imgcat picture.png # iTerm2's imgcat
The bundled extra/zterminal-icat needs no extra tools — it emits the Kitty protocol from any image with just base64 (and sips, on macOS, to convert non-PNG input). It works inside tmux with no setup: it enables allow-passthrough itself and places the image via Kitty Unicode placeholders, so the picture survives tmux redraws.
tmux integration
zterminal speaks tmux's client/server wire protocol directly to the server's Unix socket (imsg framing, protocol version 8) — no tmux subprocess. The target server is resolved from $TMUX or the default socket.
The tmux tab is a live manager: the full session → window → pane tree, each pane with a capture-pane text preview. Click a pane to switch the attached client to it; toolbar and per-session buttons create/split/zoom/rotate/kill windows, panes, and sessions. It refreshes while the tab is open.
- Sessions (
⌃⌘S) — save and restore the full tmux layout, a native replacement for tmux-resurrect/continuum. Save snapshots every session → window → pane (with exactwindow_layout, cwd, command) to~/.zterminal/snapshots/; restore rebuilds it over the wire protocol, including the exact split geometry and active window/pane, and can start a server if none is running. Opt-in relaunch re-runs each pane's full command line with arguments; Save pane contents replays each pane's scrollback. Atmux_restore_processespref gives the resurrect-style whitelist. Mark a snapshot Set startup to auto-restore on launch. - Broadcast (
⌃⌘B) — sends keystrokes to a chosen set of panes at once, across any windows/sessions, which native tmux can't do (synchronize-panes is whole-window). Per-window synchronize-panes can also be toggled from the same overlay. - Cross-pane search (
⌃⌘P) — fuzzy-matches (sharedZGui.fzf) the recent scrollback of every tmux pane at once: type a query, see panes ranked by fzf score with matched characters highlighted, and press Enter (or click) to jump to that pane.
The command palette includes tmux: actions — new window, split horizontal/vertical, next/previous window/session, zoom/rotate/break pane, next layout, choose-tree switcher, new/kill session, detach. The Dashboard shows the server's sessions (name, window count, attached state).
Configuration
zterminal does not create a config file for you. It looks for one in the following locations (first match wins):
$XDG_CONFIG_HOME/MenkeTechnologies/zterminal.toml$XDG_CONFIG_HOME/zterminal.toml$HOME/.config/MenkeTechnologies/zterminal.toml$HOME/.zterminal.toml/etc/MenkeTechnologies/zterminal.toml
On Windows: %APPDATA%\zterminal\zterminal.toml. Configuration is documented in man 5 zterminal.
terminfo
zterminal sets TERM to zterminal when that terminfo entry is installed, otherwise it falls back to xterm-256color. The terminfo source ships in extra/Zterminal.info.
Repository & links
- Source — GitHub repo
- Issues — issue tracker
- README — README on GitHub (features, control panel, splits, inline graphics, tmux, build, configuration).
- Inventions —
docs/INVENTIONS.md - Manual —
man 1 zterminalandman 5 zterminal(configuration).