>_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.
Crate Distribution — 46,761 Rust lines
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.
| Subsystem | Key paths | Lines | % | Share | Description |
|---|---|---|---|---|---|
| Config & settings | config/, settings.rs, migrate/ | 7,065 | 15.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 core | event.rs, window_context.rs, pane.rs, main.rs, daemon.rs | 6,745 | 14.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 engine | core/term/ | 5,392 | 11.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 & windowing | display/ | 4,958 | 10.6% | Per-window draw orchestration, damage tracking, cursor and overlays, hint / hyperlink overlay, OS window creation and management. | |
| GPU renderer | renderer/ | 4,672 | 10.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 & scrollback | core/grid/ | 2,519 | 5.4% | Cell storage, rows, resize / reflow, and the scrollback ring-buffer storage. | |
| Utilities | cli.rs, message_bar.rs, logging.rs, string.rs, clipboard.rs | 2,407 | 5.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 & keybindings | input/ | 2,346 | 5.0% | Key / mouse → action mapping, modifier handling, keysym → escape-sequence encoding, bracketed paste. | |
| tmux wire protocol | crates/ztmux-core/ | 2,263 | 4.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 graphics | core/graphics/ | 2,189 | 4.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 / TTY | core/tty/ | 1,601 | 3.4% | Pseudo-terminal spawn and I/O: child process, resize, and the read/write loop feeding the VT engine. | |
| Core event loop & index | core/event_loop.rs, index.rs, sync.rs | 1,440 | 3.1% | The terminal engine’s event loop, grid coordinate / index types, shell helpers, and synchronization primitives shared with the shell. | |
| vi mode | core/vi_mode.rs | 893 | 1.9% | vi-style cursor motions, selections, and operators over the grid and scrollback. | |
| Selection | core/selection.rs | 687 | 1.5% | Selection model (block / semantic / line) and clipboard text extraction. | |
| Config derive macros | zterminal_config*/ | 604 | 1.3% | Procedural-macro config deserialization (struct / enum) and serde replace support, plus the thin config crate entry. | |
| macOS platform | macos/ | 581 | 1.2% | macOS-specific glue: native menu, global hotkey (Quake dropdown), and app integration. | |
| Polling | polling/ | 399 | 0.9% | Periodic polling for telemetry / tmux refresh feeding the dashboard. | |
| TOTAL | 46,761 | 100% | |||
$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.
| File | Lines | Role |
|---|---|---|
| zterminal/src/event.rs | 4,233 | Central event loop: window / keyboard / mouse / IPC event dispatch and the application state machine |
| zterminal_core/src/term/mod.rs | 3,757 | Terminal state: the VT / xterm parser core, grid mutation, modes, cursor, charsets |
| zterminal/src/settings.rs | 2,107 | Settings model and persistence, bridged to the WebView control panel |
| zterminal/src/display/mod.rs | 1,996 | Display driver: per-window draw orchestration, damage, cursor, overlays |
| zterminal/src/input/mod.rs | 1,628 | Input handling: key / mouse → action mapping, modifiers, bracketed paste |
| zterminal/src/config/bindings.rs | 1,562 | Keybinding table, default chords, and the rebindable action registry |
| zterminal_core/src/term/search.rs | 1,251 | In-scrollback regex search engine |
| zterminal/src/window_context.rs | 1,144 | Per-window context: tabs, panes, focus, MRU quick-switch |
| crates/ztmux-core/src/ops.rs | 1,081 | tmux wire operations: encode / decode commands over the server socket |
| zterminal/src/renderer/text/builtin_font.rs | 1,032 | Embedded fallback glyph font — keeps the renderer self-contained with no external font dependency |
| zterminal/src/pane.rs | 898 | Native split tree: pane geometry, split / focus / resize / zoom |
| zterminal_core/src/vi_mode.rs | 893 | vi-mode cursor motions, selections, and operators |
| zterminal/src/config/ui_config.rs | 790 | UI config schema: colors, window geometry, opacity, background image |
| zterminal_core/src/grid/storage.rs | 769 | Scrollback ring-buffer storage |
| zterminal/src/input/keyboard.rs | 718 | Keyboard layout / keysym → escape-sequence encoding |
| zterminal/src/display/hint.rs | 703 | Hint overlay: URL and path hints over the grid |
| zterminal_core/src/selection.rs | 687 | Selection model (block / semantic / line) and clipboard text extraction |
| zterminal_core/src/grid/mod.rs | 678 | Grid: cell storage, rows, resize / reflow |
| zterminal_core/src/graphics/scanner.rs | 659 | Image scanner: peels Kitty (APC) / Sixel (DCS) / iTerm2 (OSC) sequences ahead of the escape parser |
| zterminal_core/src/graphics/mod.rs | 637 | Inline-graphics state: image placements and the GPU upload queue |
| TOP 20 SUBTOTAL | 27,223 | 58.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.
- Rust source lines (46,761) & files (105) —
wc -lover every*.rsunder the five workspace crates’src/trees (zterminal,zterminal_core,zterminal_config,zterminal_config_derive,crates/ztmux-core), excludingtarget/and thezgui-coresubmodule. - Code lines (35,435) —
tokei, Rust only, excluding comments and blank lines. - Test functions (305) — count of
#[test]/#[tokio::test]attributes across the same trees. - Control-panel JS (4,954) —
wc -loversettings/+frontend/JavaScript, excluding the vendoredzgui-corecomponent library. - Dependencies — 41 direct dependencies declared in
zterminal/Cargo.toml; 535 total crates resolved inCargo.lock(full transitive tree). - Subsystem percentages — each subsystem’s total source lines as a fraction of 46,761; rows sum to 100%.
Links
- Docs — zterminal documentation
- Inventions — terminal-emulator firsts
- Source — GitHub repo