We Rewrote the Ghostty GTK Application

· systems · Source ↗

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 Config struct.
  • 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 main and will be included in Ghostty 1.2, releasing in weeks.

Mitchell Hashimoto · 2025-08-14 · Read the original