// ZTERMINAL — ENGINEERING REPORT

GPU-accelerated cross-platform terminal in Rust · OpenGL ES 2.0 glyph-atlas renderer · xterm-compatible VT engine · native tiling splits · inline graphics (Kitty / Sixel / iTerm2) · first-class tmux over the native wire protocol

Docs
// Color scheme

>_EXECUTIVE SUMMARY

zterminal is a fast, GPU-accelerated terminal emulator written in Rust, organized as a 5-crate workspace. A terminal engine (zterminal_core) owns the xterm-compatible VT parser, the grid and scrollback, inline-graphics state, and PTY I/O; the application shell (zterminal) owns the OpenGL ES 2.0 glyph-atlas renderer, window/display driver, the native binary-split pane tree, input and keybindings, and a configuration model bridged to an in-process WebView control panel. tmux integration rides on a dedicated wire-protocol client (ztmux-core) that speaks imsg framing directly to the server socket — no tmux subprocess. Configuration is deserialized through a custom derive crate (zterminal_config_derive). ~47k Rust source lines across 105 files + ~5k lines of control-panel JavaScript + 305 test functions, in a vendored, self-contained build with no external runtime dependencies, targeting Linux, BSD, macOS, and Windows.

46,761
Rust Source Lines
35,435
Code Lines (tokei)
105
Rust Files
5
Workspace Crates
305
Test Functions
4,954
Control-Panel JS Lines
41
Direct Dependencies
535
Crates In Tree
3
Inline-Image Protocols

Crate Distribution — 46,761 Rust lines

29,173 zterminal / 14,721 zterminal_core / 2,263 ztmux-core / 604 config · 62.4% app shell

zterminal (64 files) — renderer, display, input, splits, config, platform. zterminal_core (30 files) — VT engine, grid, graphics, PTY, vi mode, selection. crates/ztmux-core (5 files) — tmux wire protocol. zterminal_config + zterminal_config_derive (6 files) — config deserialization.


#SUBSYSTEM BREAKDOWN

Source partitioned by role across the workspace, measured in total source lines. The application shell’s event loop and configuration surface lead, followed closely by the VT engine, the GPU renderer, and the display/windowing driver. Percentages are of the 46,761-line Rust slice.

SubsystemKey pathsLines%ShareDescription
Config & settingsconfig/, settings.rs, migrate/7,06515.1%
Config schema (colors, window, opacity, background image), keybinding table, settings model + persistence, and migration of older configs. Bridged to the WebView control panel.
Event loop & app coreevent.rs, window_context.rs, pane.rs, main.rs, daemon.rs6,74514.4%
Central event dispatch (window / keyboard / mouse / IPC), per-window context (tabs, panes, focus, MRU), the native binary-split pane tree, app entry, and the background daemon.
Terminal / VT enginecore/term/5,39211.5%
The xterm-compatible VT parser and terminal state machine: escape / CSI / OSC handling, modes, cursor, charsets, tab stops, and in-scrollback regex search.
Display & windowingdisplay/4,95810.6%
Per-window draw orchestration, damage tracking, cursor and overlays, hint / hyperlink overlay, OS window creation and management.
GPU rendererrenderer/4,67210.0%
OpenGL ES 2.0 glyph-atlas renderer: text shaping into a texture atlas, GLES2 draw path, and an embedded fallback glyph font so the build is self-contained.
Grid & scrollbackcore/grid/2,5195.4%
Cell storage, rows, resize / reflow, and the scrollback ring-buffer storage.
Utilitiescli.rs, message_bar.rs, logging.rs, string.rs, clipboard.rs2,4075.1%
CLI argument parsing, the on-screen message bar, structured logging, string helpers, clipboard integration, and assorted app glue (panic handler, recent dirs, scheduler, triggers, Windows support).
Input & keybindingsinput/2,3465.0%
Key / mouse → action mapping, modifier handling, keysym → escape-sequence encoding, bracketed paste.
tmux wire protocolcrates/ztmux-core/2,2634.8%
First-class tmux client over the server’s Unix socket (imsg framing, protocol v8): command encode / decode, transport, and session snapshot — no tmux subprocess.
Inline graphicscore/graphics/2,1894.7%
Image-placement state and GPU upload queue for inline graphics, plus the scanner that extracts Kitty (APC), Sixel (DCS), and iTerm2 (OSC) image sequences ahead of the escape parser.
PTY / TTYcore/tty/1,6013.4%
Pseudo-terminal spawn and I/O: child process, resize, and the read/write loop feeding the VT engine.
Core event loop & indexcore/event_loop.rs, index.rs, sync.rs1,4403.1%
The terminal engine’s event loop, grid coordinate / index types, shell helpers, and synchronization primitives shared with the shell.
vi modecore/vi_mode.rs8931.9%
vi-style cursor motions, selections, and operators over the grid and scrollback.
Selectioncore/selection.rs6871.5%
Selection model (block / semantic / line) and clipboard text extraction.
Config derive macroszterminal_config*/6041.3%
Procedural-macro config deserialization (struct / enum) and serde replace support, plus the thin config crate entry.
macOS platformmacos/5811.2%
macOS-specific glue: native menu, global hotkey (Quake dropdown), and app integration.
Pollingpolling/3990.9%
Periodic polling for telemetry / tmux refresh feeding the dashboard.
TOTAL46,761100%

$TOP 20 FILES BY SIZE

The 20 largest source files account for 58.2% of the Rust slice. The event loop and the terminal-state core are by far the largest single files — the two hubs that everything else hangs off.

FileLinesRole
zterminal/src/event.rs4,233Central event loop: window / keyboard / mouse / IPC event dispatch and the application state machine
zterminal_core/src/term/mod.rs3,757Terminal state: the VT / xterm parser core, grid mutation, modes, cursor, charsets
zterminal/src/settings.rs2,107Settings model and persistence, bridged to the WebView control panel
zterminal/src/display/mod.rs1,996Display driver: per-window draw orchestration, damage, cursor, overlays
zterminal/src/input/mod.rs1,628Input handling: key / mouse → action mapping, modifiers, bracketed paste
zterminal/src/config/bindings.rs1,562Keybinding table, default chords, and the rebindable action registry
zterminal_core/src/term/search.rs1,251In-scrollback regex search engine
zterminal/src/window_context.rs1,144Per-window context: tabs, panes, focus, MRU quick-switch
crates/ztmux-core/src/ops.rs1,081tmux wire operations: encode / decode commands over the server socket
zterminal/src/renderer/text/builtin_font.rs1,032Embedded fallback glyph font — keeps the renderer self-contained with no external font dependency
zterminal/src/pane.rs898Native split tree: pane geometry, split / focus / resize / zoom
zterminal_core/src/vi_mode.rs893vi-mode cursor motions, selections, and operators
zterminal/src/config/ui_config.rs790UI config schema: colors, window geometry, opacity, background image
zterminal_core/src/grid/storage.rs769Scrollback ring-buffer storage
zterminal/src/input/keyboard.rs718Keyboard layout / keysym → escape-sequence encoding
zterminal/src/display/hint.rs703Hint overlay: URL and path hints over the grid
zterminal_core/src/selection.rs687Selection model (block / semantic / line) and clipboard text extraction
zterminal_core/src/grid/mod.rs678Grid: cell storage, rows, resize / reflow
zterminal_core/src/graphics/scanner.rs659Image scanner: peels Kitty (APC) / Sixel (DCS) / iTerm2 (OSC) sequences ahead of the escape parser
zterminal_core/src/graphics/mod.rs637Inline-graphics state: image placements and the GPU upload queue
TOP 20 SUBTOTAL27,22358.2% of the 46,761-line Rust slice

@DATA-FLOW PIPELINE

Bytes flow from the child PTY through the VT engine into the grid, then onto the GPU. An image scanner sits ahead of the escape parser so Kitty / Sixel / iTerm2 sequences are peeled off and uploaded as textures while ordinary text and control sequences pass through untouched. tmux traffic takes a parallel path over the wire-protocol client.

  child process (shell, vim, htop, …)
       │  PTY
       ▼
  ┌──────────────┐     ┌──────────────────┐     ┌──────────────┐
  │  core/tty/   │────▶│ graphics/scanner │────▶│  core/term/  │
  │  (1,601)     │     │  (peel Kitty /   │     │  (5,392)     │
  │  PTY read/   │     │   Sixel / iTerm2 │     │  VT / xterm  │
  │  write loop  │     │   image seqs)    │     │  parser      │
  └──────────────┘     └────────┬─────────┘     └──────┬───────┘
                                │                       │
                       image bytes                cell writes
                                │                       │
                                ▼                       ▼
                       ┌──────────────┐         ┌──────────────┐
                       │ core/graphics│         │  core/grid/  │
                       │  (2,189)     │         │  (2,519)     │
                       │  placements  │         │  cells +     │
                       │  + GPU queue │         │  scrollback  │
                       └──────┬───────┘         └──────┬───────┘
                              │                        │
                              └───────────┬────────────┘
                                          ▼
                              ┌───────────────────────┐
                              │   renderer/ (4,672)   │
                              │  GLES2 glyph atlas +  │
                              │  image texture blits  │
                              └───────────┬───────────┘
                                          ▼
                              ┌───────────────────────┐
                              │   display/ (4,958)    │
                              │  per-window draw,     │
                              │  panes, overlays      │
                              └───────────────────────┘

  tmux:  crates/ztmux-core (2,263)  ──imsg / socket──▶  server  (no subprocess)
  input: input/ (2,346)  ──key/mouse → action──▶  event.rs (4,233)  ──▶  term / display

&SUBSYSTEM HIGHLIGHTS

What each major subsystem ships. Three of these — live tmux config, profile-switchable tmux state, and the in-app telemetry dashboard — are terminal-emulator firsts; see Inventions.

GPU renderer

OpenGL ES 2.0 glyph-atlas renderer. Text is shaped into a texture atlas and blitted per cell; inline images upload as GPU textures and blit over the cells they occupy. Ships an embedded fallback font (builtin_font.rs) so the binary is self-contained.

VT engine

Full xterm-compatible VT parsing in core/term/ — vim, tmux, htop, and ncurses apps run correctly. 24-bit truecolor, scrollback, in-scrollback regex search, and a complete vi mode with motions, selections, and operators.

Native tiling splits

An i3-style binary split tree in pane.rs — one independent shell + PTY per pane, GL-scissored into the window, no tmux required. Splits nest arbitrarily; each pane renders in its own sub-viewport. Layouts save / restore the split tree, cwd, and command.

Inline graphics

All three terminal image protocols — Kitty (transmit / display / animation / Unicode placeholders), Sixel, and iTerm2. A scanner peels image sequences ahead of the escape parser; ESC Ptmux;…-wrapped sequences are unwrapped and decoded, so images survive tmux redraws.

First-class tmux

ztmux-core speaks tmux’s client/server wire protocol directly to the Unix socket (imsg framing, protocol v8) — no subprocess. Drives the live tmux tab, Sessions save/restore, cross-pane search, broadcast, and live editing of server options / buffers / keybindings.

In-process control panel

~5k lines of JavaScript (consuming the shared zgui-core component library) render Settings, Dashboard, tmux, Keybindings, Logs, and About tabs in an embedded WebView, plus the command palette, Exposé, sessions, and broadcast overlays. All state lives under ~/.zterminal.


~MEASUREMENT NOTES

How the numbers were counted, so they can be reproduced.


Links