Adds tools/difftest: a Zig driver built against a copy of Ghostty
1.3.1's own src/terminal (Zig 0.15.2, set up under target/ by
tools/difftest/setup.sh) and a Rust twin on ghostty-terminal, both
printing a canonical dump of every scrollback/active row (cells,
graphemes, styles, hyperlinks, row flags), cursor, modes, regions,
tabstops and colors. A seeded generator produces escape-heavy streams
(UTF-8/wide/combining/emoji, C0, CSI with edge params, SGR, modes, ESC,
OSC, DCS, margins, insert/delete); `just difftest` runs it with Zig
assertions on (ReleaseSafe vs debug Rust) and off (ReleaseFast vs
production Rust), with minimizers and a triage script.
Divergences found and fixed in Rust (each with a regression test):
- ill-formed UTF-8 decoding follows the SIMD path a default Ghostty
build uses (not Zig's scalar fallback)
- PageList::erase_rows keeps Zig's row-flag behavior on regrow
- grapheme move on wrap with left/right margins uses the original cell
Upstream bugs found and deliberately NOT replicated (per the project
rule): a stale cell pointer after page growth in Terminal.zig:482/539
that drops a grapheme, plus several Zig assertion failures/segfaults;
documented with minimized repros in docs/rewrite/notes/difftest-DF.md.
Final run: 390k cases across many geometries, 0 divergences (Zig-abort
cases, ~0.1-0.5%, are not compared).
Test Plan:
- just difftest 20000 "1 2 3"
- cargo test -p ghostty-terminal (regression tests)
The non-Linux code paths can only be compile-checked on this machine;
agents had used ad-hoc wrapper setups. These scripts make the checks
reproducible and are wired into `just check-macos`, `check-windows`,
`check-wasm` and `check-all`:
- macos-crosscheck.sh: zig cc wrappers (dropping -arch/-mmacosx-
version-min) plus a declaration-only os/log.h stub so the few C build
scripts compile; clippy -D warnings on all 17 cross-platform crates
for aarch64/x86_64-apple-darwin.
- windows-crosscheck.sh: mingw toolchain and a stub fontconfig.pc;
clippy -D warnings for x86_64-pc-windows-gnu.
- wasm-check.sh: wasm32 clippy/build and the node-based wasm tests.
Also fixes a needless_pass_by_value lint in osbytes' non-Unix branch
that only the Windows check surfaces.
Test Plan:
- just check-macos; just check-macos x86_64-apple-darwin
- just check-windows; just check-wasm
Closes the remaining artifact rows of the final audit
(docs/rewrite/notes/final-Z4.md):
- webgen: config.mdx, actions.mdx, commands.mdx (byte-identical to
Zig's webgen output once its missing stdout flush is added)
- `just install-lib`: libghostty (+ ghostty.h, modulemap) and
libghostty-vt with versioned symlinks, headers and libghostty-vt.pc
- scripts/xcframework.sh: per-arch builds, lipo and
xcodebuild -create-xcframework for GhosttyKit (dry-run verified only)
- `just install` builds --profile production so the installed app id is
com.mitchellh.ghostty; other profiles install the -debug id/name
- `just update-translations`: xgettext/msgmerge pipeline; extracted
msgids equal upstream's .pot (found and fixed an untranslated string
in the child-exited banner)
- `just dist` / `distcheck`: versioned source tarball with VERSION and a
prebuilt GTK resource bundle
- Windows: icon, version resource and DPI/common-controls manifest
embedded via embed-resource, GUI subsystem
Test Plan:
- just install-lib /tmp/p release all && pkg-config --cflags \
--libs /tmp/p/share/pkgconfig/libghostty-vt.pc
- just distcheck
Ports the macOS-specific Zig code behind cfg(target_os = "macos"):
- renderer: a GraphicsApi trait with generic::Renderer<G>; Metal backend
(all renderer/metal/* files, shaders.metal verbatim, runtime library
compile, IOSurface layer, CVDisplayLink), shadertoy -> MSL via naga;
OpenGL remains the backend elsewhere.
- font: CoreText face, shaper and discovery with build.rs backend
selection (coretext default; coretext-freetype / coretext-harfbuzz /
coretext-noshape features), no fontconfig/freetype/harfbuzz on Apple.
- input: KeymapDarwin via UCKeyTranslate, option-as-alt, mac keycodes.
- os: macos, mach, cf_release_thread, NSProcessInfo args and macOS
branches; config: macOS defaults, keybinds, Application Support paths.
- termio/core: login(1) wrapping, openpty/execvpe, Darwin child exit
handling, os_log logging.
Compile-checked for aarch64/x86_64-apple-darwin (clippy -D warnings
clean) using the cross setup in docs/rewrite/notes/macos-M1.md; cannot
run here. The embedded runtime/C API (embedded.zig) is the next step.
Also includes the cross-platform integration edits shared by the crash,
verification, Windows and macOS work (Cargo target-gating, thread
crash-context hooks, apprt-gtk surface/IME refactor, termio/os cfg
gates), a cfg fix so ghostty-config builds on wasm32, and an allow for
the intentional recursion in the crash overflow test.
Test Plan:
- cargo test --workspace (3224 passed)
- cargo clippy --workspace --all-targets -- -D warnings
- cargo check --target aarch64-apple-darwin -p ghostty-renderer (with
the documented cross env)
Ports Ghostty's build-data helpers (main_build_data.zig, src/extra/*,
build/mdgen) as the ghostty-build-data binary: bash/zsh/fish
completions, Vim syntax/ftdetect/ftplugin/compiler, Sublime syntax (also
used by bat), terminfo source and ghostty(1)/ghostty(5) markdown. With
the version set to the installed 1.3.1-arch2, all generated files are
byte-identical to the installed Ghostty's.
- `just docs` renders man pages and HTML with pandoc.
- po/: Ghostty's 29 translation catalogs; `just locales` compiles them
into the com.mitchellh.ghostty gettext domain.
- `just install PREFIX FLATPAK SYSTEM_PACKAGE` installs everything incl.
terminfo text/termcap outputs and mirrors GhosttyResources.zig install
modes (Flatpak D-Bus template without systemd; lib/systemd/user for
system packages).
- Build metadata (version, tip/stable channel, commit, build mode) is
derived at build time like build_config.zig; GTK/libadwaita
compile-time versions come from pkg-config instead of constants.
Test Plan:
- cargo run -p ghostty-build-data -- +bash | diff - \
/usr/share/bash-completion/completions/ghostty (same for zsh/fish/vim)
- just install /tmp/prefix
Cleanup pass over items collected in docs/rewrite/INTEGRATION_TODO.md:
- OSC 133 printf-q / percent decoders live once in
ghostty_vt::string_encoding; ghostty-os re-exports them.
- CursorStyle and clipboard codepoint map entries have one definition
(ghostty-terminal); ghostty-config now depends on ghostty-terminal.
- ActionKey::docs() trailing blank lines fixed at the source; cli's
workaround removed (+list-actions --docs still byte-identical).
- x11_color exposes names in original case; cli no longer re-parses
rgb.txt.
- One cgroup scope wait loop (ghostty_os::cgroup::wait_for_scope).
- Flatpak passwd lookup implemented in ghostty-os via a local pty.
- +version shows the rustc version captured at build time.
Resources: dev builds find <workspace>/resources automatically (keeping
Ghostty's sentinel-file detection and GHOSTTY_RESOURCES_DIR);
scripts/gen-terminfo.sh (just terminfo) regenerates the compiled
terminfo; `just install [PREFIX]` installs binary, share/ghostty,
terminfo, desktop/D-Bus/systemd/metainfo files and icons.
Test Plan:
- cargo test for vt, os, config, input, cli
- diff `+list-keybinds`, `+list-actions --docs`, `+show-config --default`
against /usr/bin/ghostty