We Rewrote the Ghostty GTK Application
TLDR
- Ghostty’s GTK frontend was rewritten in Zig using the full GObject type system, eliminating a class of lifetime/memory bugs and enabling richer GTK-native features.
Key Takeaways
- The old GTK code avoided GObject, causing mismatched frees between Zig-owned and GTK-owned memory; the rewrite wraps Zig structs in reference-counted GObjects.
-
Config reload now uses GObject property change notifications instead of manually propagating updates across the GUI before freeing the old
Configstruct. - Adopting GObject unlocked GTK-native signals, properties, actions, and Blueprint UI files, which directly enabled features like titlebar tabs and animated bell borders.
- Valgrind was run on every PR throughout the rewrite; the Zig codebase itself had only one leak and one undefined memory access, both at C API boundaries.
- All other memory issues found (dozens) were inside GObject lifetime semantics or at C API boundaries, not in Zig code itself.
Why It Matters
- Empirical Valgrind results from a large multi-threaded Zig project show that Zig’s safety tooling works in practice, not just theory.
- C API boundaries remain the practical danger zone regardless of the calling language; wrapping them correctly requires explicit lifetime discipline and external tooling.
-
The rewritten GTK app ships as default on
mainand will be included in Ghostty 1.2, releasing in weeks.
Mitchell Hashimoto · 2025-08-14 · Read the original