Files
ghostty-rs/docs/rewrite/ARCHITECTURE.md
T
ddidderr 2aa2a12de0 fix: close remaining gaps found by the completeness audit
Addresses the partial ports listed in
docs/rewrite/notes/review-completeness-codex.md (details in
docs/rewrite/notes/gaps-X2.md):
- Flatpak: the exit watcher no longer consumes the host command; a
  shared FlatpakSignalHandle lets closing a surface still SIGHUP the
  host process group.
- Child environment is byte-preserving end to end (ghostty_os::EnvMap
  of OsStrings) and Snap paths are filtered like filterSnapPaths.
- argv handling no longer panics on non-UTF-8 arguments.
- URI percent-decoding keeps raw bytes; OSC 7 pwd is passed through
  without lossy conversion.
- Keybinding comparison/hashing uses full Unicode case folding from a
  table generated from CaseFolding.txt (Unicode 17.0.0).
- Link regexes set Oniguruma's whole-search retry limit through the new
  minimal ghostty-onig crate (one SAFETY-commented FFI call).
- OSC 9 NUL-capacity check ordering matches Zig.
- Wayland registry binds/clears globals advertised after startup.
- Custom shaders may pass sampler2D to helper functions (naga adapter).
- +list-themes preview renders OSC 8 links, styled underlines and
  follows color-scheme reports.

Also includes the inspector's integration edits in shared files
(renderer state hook, termio VT recording, core/apprt-gtk wiring), X1's
config/input/cli additions for completion generation, and a fix for a
race in the termio backpressure test (it wrote before `stty raw`
applied, so the cooked line discipline dropped bytes past MAX_CANON).

Test Plan:
- cargo test --workspace
- cargo clippy --workspace --all-targets -- -D warnings
2026-10-12 04:39:24 +02:00

6.2 KiB
Raw Blame History

Ghostty-rs Architecture

Rust rewrite of Ghostty 1.3.1. Reference source: ../ghostty/ (Zig), referred to below as ZIG/ (= /pantheon/pfs/git/rust/ghostty-rewrite/ghostty).

Target platform: Linux (GTK4 + libadwaita, OpenGL). macOS/Metal/CoreText, WASM, Windows and the embedded C API (libghostty) are out of scope.

Crate map (workspace crates/)

Crate Ports (ZIG/src/...) Depends on
ghostty-vt terminal/Parser, parse_table, UTF8Decoder, osc.zig + osc/*, csi, dcs, apc, sgr, color, x11_color, charsets, modes, ansi, device_status, mouse_shape, kitty/key, kitty/color, kitty/graphics_command, stream.zig –
ghostty-unicode unicode/* (width, grapheme break, props) –
ghostty-datastruct datastruct/* (split_tree, lru, circ_buf, blocking_queue, cache_table, ...) –
ghostty-os os/* (xdg, homedir, shell, locale, passwd, env, open, desktop, resourcesdir, hostname, TempDir, uri, ...) –
ghostty-input input/* (key, key_mods, keycodes, function_keys, key_encode, Binding, command, mouse, paste, kitty, Link) vt
ghostty-config config/*, cli/args.zig, cli/CommaSplitter.zig, cli/diagnostics.zig input, os, vt
ghostty-terminal terminal/ page, PageList, Screen, ScreenSet, Terminal, style, hyperlink, Tabstops, size, point, Selection, formatter, render, highlight, search/, kitty/graphics_{image,storage,exec,unicode,render}, tmux/, stream_readonly, StringMap, ref_counted_set, bitmap_allocator semantics vt, unicode, datastruct
ghostty-font font/* (Metrics, sprite/, Atlas, discovery via fontconfig, face via freetype, shaper via harfbuzz, Collection, CodepointResolver, SharedGrid(Set), opentype/, nerd_font_attributes) config, unicode, terminal
ghostty-renderer renderer/ generic, OpenGL (+ opengl/*), cell, cursor, image, link, size, State, Thread, Overlay, shadertoy, row, shaders/glsl config, font, terminal
ghostty-termio termio/*, pty.zig, Command.zig, shell-integration resources config, terminal, os
ghostty-cli cli/* actions (+list-themes, +show-config, +list-keybinds, ...) config, input, os, font
ghostty-inspector inspector/* (Dear ImGui terminal inspector: widgets, key + VT event recording) input, renderer, terminal, vt, font, dear-imgui-rs
ghostty-core App.zig, Surface.zig, surface_mouse.zig, apprt/action.zig, apprt/structs.zig, apprt/surface.zig, global.zig everything below
ghostty-apprt apprt/action.zig, structs.zig, surface.zig, ipc.zig (core↔runtime contract types) vt, input, config, datastruct
ghostty-apprt-gtk apprt/gtk/* core, config, input
root ghostty-rs (bin ghostty) main_ghostty.zig, build_config.zig core, config, apprt-gtk

Key design decisions

  1. Safe Rust by default. Workspace lint unsafe_code = "forbid". Crates that must do FFI/syscalls (renderer GL loader, termio pty/fork, apprt-gtk) may override with unsafe_code = "deny" and #[allow(unsafe_code)] on minimal, // SAFETY:-commented items. Prefer safe wrapper crates (rustix, glow, gtk4-rs) over raw FFI.
  2. Pages without raw memory. Ghostty's page.zig packs a page into one mmap'd buffer with offsets. In Rust a Page owns Vec<Row> + Vec<Cell> (row-major, cols per row) plus per-page RefCountedSet<Style>, grapheme map HashMap<cell_index, Vec<u32>>, hyperlink set/map, string storage. Capacity accounting is preserved logically (styles, grapheme bytes, hyperlink bytes, string bytes, rows/cols), including Ghostty's byte-size layout formula (Page::layout(cap).total_size), because PageList pruning (scrollback-limit is in bytes), page splitting and capacity-adjust behaviour — and the tests for them — depend on it.
  3. PageList as an index-based linked list. Nodes live in a slab (Vec<Option<Node>> + free list); NodeId is an index (+ generation for debug checks). Pin { node: NodeId, y, x, garbage } is Copy. Tracked pins live in a PageList-owned slab; holders keep a TrackedPin handle (index) and read/write through the PageList. All operations that move rows update tracked pins exactly like the Zig code.
  4. Cell is a compact Copy value (target 8 bytes, bit-packed u64 with accessor methods mirroring Zig field names), so memory accounting and copying behaviour stay close to Ghostty.
  5. Parser → Stream → Handler. ghostty-vt::Parser yields actions; ghostty-vt::stream::Stream<H: Handler> decodes CSI/ESC/OSC/DCS/APC into high-level actions and calls Handler. Terminal state changes live in ghostty-terminal (stream_readonly handler applies to Terminal), and ghostty-termio::StreamHandler handles side-effecting actions.
  6. Rendering: OpenGL 4.3 via glow, inside a gtk::GLArea. Shaders are copied verbatim from ZIG/src/renderer/shaders/glsl. Renderer logic follows renderer/generic.zig (cell contents rebuilt from terminal::render::RenderState).
  7. Fonts: fontconfig (discovery), freetype (rasterization), harfbuzz (shaping). Sprite font (box drawing etc.) is pure Rust, ported 1:1.
  8. Threads: like Ghostty — per surface: IO thread (termio), renderer thread, plus a pty read thread. Mailboxes are crossbeam-channel / std::sync::mpsc; the GTK main thread is woken via glib channels. The Terminal is shared behind Arc<Mutex<..>> (Ghostty's renderer mutex).
  9. Config: same file format, same keys, same defaults, same CLI flags, same docs text (used by +show-config --docs and --help).
  10. Tests: every Zig test "..." block in a ported file is ported to a Rust #[test] with the same name (snake_cased) in the same module. scripts/test-progress.sh tracks counts.

Out of scope / deferred

  • macOS (Swift app, Metal, CoreText), Windows, WASM, libghostty C API.
  • (The ImGui inspector was deferred and is now ported: docs/rewrite/notes/ghostty-inspector.md.)

Intentional omissions (decided by the orchestrator)

  • Sentry crash reporting (crash/*): optional and disabled by default in upstream Linux builds; +crash-report listing is ported.
  • GTK < 4.14 / libadwaita < 1.5 compatibility fallbacks (MessageDialog, pre-Banner widgets, old about dialog, 1.0–1.3 blueprint variants): the Rust port requires GTK ≥ 4.14 and libadwaita ≥ 1.5.