# Ghostty-rs Architecture Rust rewrite of Ghostty 1.3.1. Reference source: `../ghostty/` (Zig), referred to below as `ZIG/` (= `../../../ghostty`). Primary platform: **Linux (GTK4 + libadwaita, OpenGL)** — built, tested and verified at runtime here. Phase 8 extends the port to the rest of Ghostty's Zig code: the embedded `libghostty` C API (identical `include/ghostty.h` ABI, so Ghostty's unchanged Swift macOS app can link the Rust library), the `libghostty-vt` C API (`include/ghostty/vt*.h`), WASM (wasm32), macOS (Metal renderer, CoreText fonts, Darwin keymap/os) and Windows (ConPTY). Non-Linux targets are compile-checked (`cargo check --target ...`) on this machine; they cannot be run here. Phase 9 additionally ports the Swift macOS app (`macos/`) to Rust (`crates/ghostty-macos`, AppKit via objc2), compile-checked like the rest of the Apple code; the C ABI stays available for the original Swift app. ## Top-down decomposition ``` ghostty (bin, src/main.rs) CLI `+action` dispatch or GTK app startup ├── ghostty-cli `ghostty +action` commands ├── ghostty-apprt-gtk GTK4/libadwaita runtime: windows, tabs, splits, │ │ dialogs, GLArea surfaces, IPC, inspector windows │ └── ghostty-apprt core<->runtime contract (actions, messages, traits) └── ghostty-core App + Surface: input routing, bindings, mouse, │ clipboard, config reload, per-surface threads ├── ghostty-termio IO thread, pty, child process, stream handler │ └── ghostty-terminal terminal state machine │ ├── Terminal / Screen cursor, modes, scrolling, alt screen, selection │ ├── PageList / Page scrollback memory model (slab nodes, tracked pins) │ ├── render / formatter per-frame RenderState, text/VT/HTML export │ ├── kitty / search / tmux kitty graphics, search thread, tmux control mode │ └── ghostty-vt byte stream -> Parser -> Stream -> Handler actions ├── ghostty-renderer OpenGL renderer (glow), renderer thread, shaders │ └── ghostty-font fontconfig/freetype/harfbuzz, sprite font, atlas ├── ghostty-inspector Dear ImGui terminal inspector └── ghostty-config config file/CLI parsing, themes, keybinds ├── ghostty-input keys, key encoding, binding sets, mouse └── ghostty-os XDG, env, shell, locale, resources dir, flatpak Support: ghostty-unicode (width/grapheme/case-fold tables), ghostty-datastruct (split tree, LRU, queues), ghostty-onig (Oniguruma retry-limit FFI), ghostty-bench (benchmarks), ghostty-build-data (completions, man pages, syntax). ``` ## Crate map (workspace `crates/`) | Crate | Ports (ZIG/src/...) | Internal deps | |---|---|---| | `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,color,graphics_command}, tmux/control, stream.zig, simd (scalar) | – | | `ghostty-unicode` | unicode/* (width, grapheme break, props, symbols) + case folding, generated from vendored UCD 17.0.0 | – | | `ghostty-datastruct` | datastruct/* (split_tree, lru, circ_buf, blocking_queue, cache_table, ...) | – | | `ghostty-onig` | (Oniguruma whole-search retry limit used by StringMap.zig) | – | | `ghostty-os` | os/* (xdg, homedir, shell, locale, passwd, env, open, desktop, resourcesdir, hostname, TempDir, uri, flatpak, systemd, cgroup, ...) | vt | | `ghostty-input` | input/* (key, key_mods, keycodes, function_keys, key_encode, Binding, command, mouse, paste, kitty, Link) | vt, unicode | | `ghostty-terminal` | terminal/ page, PageList, Screen, ScreenSet, Terminal, style, hyperlink, Tabstops, size, point, Selection, formatter, render, highlight, search/*, kitty/graphics_*, tmux/{layout,output,viewer}, stream_readonly, StringMap, ref_counted_set | vt, unicode, datastruct, onig | | `ghostty-config` | config/*, cli/args.zig, cli/CommaSplitter.zig, cli/diagnostics.zig | input, os, terminal, vt | | `ghostty-font` | font/* (Metrics, sprite/*, Atlas, discovery (fontconfig), face (freetype), shaper (harfbuzz) + run, Collection, CodepointResolver, SharedGrid(Set), opentype/*, nerd_font_attributes) | config, terminal, unicode, datastruct | | `ghostty-renderer` | renderer/ generic, OpenGL + opengl/*, cell, cursor, image, link, size, State, Thread, Overlay, shadertoy, row, shaders/glsl | config, font, terminal, input, unicode, vt, datastruct | | `ghostty-inspector` | inspector/* (Dear ImGui terminal inspector) | font, input, renderer, terminal, vt | | `ghostty-apprt` | apprt/action.zig, structs.zig, surface.zig, ipc.zig, runtime traits | config, input, inspector, renderer, terminal, vt, datastruct | | `ghostty-termio` | termio/*, pty.zig, Command.zig, terminfo/*, shell integration | apprt, config, os, renderer, terminal, vt, datastruct | | `ghostty-core` | App.zig, Surface.zig, surface_mouse.zig, global.zig | apprt, config, font, input, inspector, os, renderer, terminal, termio, ... | | `ghostty-cli` | cli/* actions, build_config.zig (build info) | apprt, config, font, input, os, vt | | `ghostty-apprt-gtk` | apprt/gtk/* (+ ui/*.blp, css) | apprt, config, input, inspector, os, vt, datastruct | | `ghostty-bench` | benchmark/*, synthetic/* | terminal, unicode, vt | | `ghostty-helpgen` | helpgen.zig (build-time doc-comment extraction for CLI-action and keybind-action help; used from `build.rs` of ghostty-cli / ghostty-input) | – | | `ghostty-build-data` | main_build_data.zig, extra/*, build/mdgen | cli, config, input, os, termio | | root `ghostty-rs` (bin `ghostty`) | main_ghostty.zig | apprt, apprt-gtk, cli, config, core, os | Non-code: `resources/` (shell-integration, themes, terminfo), `dist/` (desktop integration), `po/` (translations), crate-local `res/`/`shaders/`/`resources/`. Resource lookup: `ghostty-os::resourcesdir` accepts the optional build-time `GHOSTTY_BUILD_RESOURCES_DIR` path (watched by `ghostty-os/build.rs`). Runtime `GHOSTTY_RESOURCES_DIR` overrides a configured build path; otherwise that path precedes automatic discovery. Relative build paths resolve from the executable's directory, allowing relocatable installations. Without a build path, upstream's environment/terminfo lookup and the checkout resource fallback apply. See `README.md` (Build-time resource directory) and `DEVIANT_FIXES.md`. Build inputs: `ghostty-build-info/build.rs` derives version metadata from the workspace manifest and Git HEAD/refs, watching `packed-refs` only when it exists (packing loose refs also changes the watched `refs` directory). The GTK build script compiles `resources/` in checkouts and watches the optional `dist/ghostty.gresource` bundle only when consuming it from a source tarball. Missing optional files must not be emitted as Cargo `rerun-if-changed` inputs: they invalidate every subsequent build and rebuild downstream crates. GTK invokes `glib-compile-resources` directly so generated XML/UI files in `OUT_DIR` are not watched as inputs; the `resources/` watch covers their sources. ## 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` + `Vec` (row-major, `cols` per row) plus per-page `RefCountedSet