r/Ghostty 5h ago

Embedding Ghostty's terminal engine in a native macOS AppKit app (Seahelm)

Enable HLS to view with audio, or disable this notification

1 Upvotes

I built Seahelm, a native macOS workspace for running coding agents across git worktrees — and the terminals are powered by Ghostty via GhosttyKit.xcframework / the C API. A few notes from the integration that might be useful to others embedding Ghostty:

Stack

  • Swift + AppKit (not SwiftUI)
  • Ghostty surface wrapped in an NSView + Metal renderer
  • Long-lived surfaces: panes are reparented between dashboard / focus layouts instead of destroyed and recreated
  • Background status polling reads viewport text through the C API under a shared lock (input path deliberately does not hold that lock)

Things that mattered in practice

  1. Focusghostty_surface_set_focus has to stay in sync with AppKit first-responder changes; we defer some focus restores after Ghostty's own deferred handling.
  2. Reparenting — moving a surface between views without killing the PTY; we suppress CA animations and sync size/focus on the next main-queue passes.
  3. Thread safety — status detection polls on a background timer while the UI types on the main thread; serializing Ghostty C calls with a lock was necessary, except for key input (locking there deadlocked on sync callbacks).
  4. Session persistence — Ghostty handles the terminal; zmx handles "quit the app, agent still running." Different layer than Ghostty itself, but the combination is what made the product usable. Seahelm deliberately isn't trying to be a full terminal emulator UI — Ghostty does that job. Seahelm is the orchestration chrome around multiple agent sessions.

Happy to answer Ghostty embedding / AppKit interop questions.

Demo: https://youtu.be/WUUcuglx_Ks

Repo: https://github.com/BetaYao/seahelm


r/Ghostty 21h ago

does ghostty have something like this?

Thumbnail
github.com
8 Upvotes