Ghostling: Stripping the Terminal to its High-Performance Core

How Mitchell Hashimoto decoupled the terminal engine from the emulator to create a universal, embeddable CLI component.

6 min read • View on GitHub • More from ghostty-org

A massive clockwork engine connected to a small glass window by a single wire, illustrating the concept of a massive terminal engine driving a minimal frontend.
Ghostling acts as a thin, transparent pane of glass in front of the massive, complex machinery of the Ghostty engine.
Portrait of Mitchell Hashimoto

I started the project in 2022 merely as a way to play with Zig, do some graphics programming, and deepen my understanding of terminals. I never intended to release it. I didn't think there was innovation to be had. I thought I would learn a lot over a few months and move on.

Mitchell Hashimoto, Creator · Ghostty: Reflecting on Reaching 1.0
Key Takeaways

The 600-Line Mirage

The terminal is computing's most resilient interface. Yet for decades, building a functional, high-performance terminal emulator has required tens of thousands of lines of code. It is a domain notorious for edge cases, obscure escape sequences, and complex state management. Ghostling flips this script entirely. It delivers a world-class, SIMD-optimized terminal in under 600 lines of C.

This minimalist footprint is not a trick. Ghostling is a fully functional MVP built to demonstrate the power of libghostty. By extracting the core emulation logic from the popular Ghostty terminal, its creator provided a way to embed a professional-grade command-line interface into virtually any application.

The "Headless" Engine

Ghostling achieves its small size through a strict separation of concerns. The underlying library, libghostty-vt, acts as the brain. It parses VT sequences (like ANSI and XTERM), manages cursor state, and handles text reflow. However, it refuses to draw a single pixel.

The developer provides the body. In Ghostling's case, a single C file named main.c uses the Raylib graphics library to create a window, capture keyboard input, and render the terminal's state to the screen. This headless architecture means the engine can be embedded anywhere without dragging along a heavy GUI toolkit like GTK or Qt.

The lifecycle of a single keystroke in Ghostling. Show a pipeline starting with User Input (Keyboard)

Instead of dictating how the screen should be drawn, the library provides a render state API. Ghostling queries this state every frame to see which glyphs, colors, and styles need to be pushed to the GPU. It is a pure data loop.

A human brain in a glass jar connected by cables to a mechanical puppet drawing on a canvas, illustrating the headless engine concept.
The headless architecture separates the "thinking" (parsing and state management) from the "doing" (rendering pixels).

A Polyglot Handshake

The technical elegance of Ghostling lies in the marriage of C and Zig. The core emulation logic is written in Zig, taking advantage of modern SIMD optimizations and strict memory safety. Yet, it exposes a pure C API.

The build system orchestrates this polyglot environment seamlessly. Using CMake, the project fetches the Zig codebase and compiles it into a zero-dependency library. This allows a traditional C project to consume cutting-edge Zig code without forcing the developer to abandon their existing C toolchain.

// The non-blocking polling loop in main.c
while (!WindowShouldClose()) {
    // Read from the PTY into libghostty
    ssize_t n = pty_read(pty_fd, buf, sizeof(buf));
    if (n > 0) {
        ghostty_terminal_vt_write(term, buf, n);
    }
    
    // Translate Raylib input back to the PTY
    raylib_key_to_ghostty(term, pty_fd);
    
    // Draw the current state
    render_terminal_grid(term);
}
A side-by-side comparison of two terminal grids showing how libghostty communicates changes without redrawing everything. An animated diff highlight flickers only the cells that changed between frame A and frame B. Include a slider interaction to increase the scroll speed

Because the PTY is set to non-blocking mode, the entire application runs in a single-threaded game loop. There are no complex mutexes or threading models to debug. The application simply reads bytes, updates the state, and draws the screen 60 times a second.

Beyond the Application

Ghostling is not meant to replace your daily terminal. It exists to prove that the terminal can be treated as a component. Historically, embedding a terminal required relying on libvte, which tightly coupled the developer to the GNOME ecosystem and GTK.

Libghostty is an embeddable library extracted from Ghostty's core, exposing a C and Zig API so any application can embed correct, fast terminal emulation.

By removing all dependencies (even libc is optional for the core engine), Ghostling opens the door to new environments. Developers can now drop a high-performance, GPU-accelerated terminal into a custom game engine dashboard, an embedded industrial device, or a bespoke IDE without importing a massive dependency tree.

Project Dependencies Architecture Primary Use Case
Ghostling (libghostty) None (Zero-dependency core) Headless / API-driven Embedding in custom apps, games, or hardware
st (Suckless) Xlib, Fontconfig Monolithic C application Minimalist daily-driver for end users
libvte GTK, GLib, Pango Tightly coupled widget Linux desktop environments (GNOME, Xfce)
A heavy cast-iron stove compared to a sleek modular induction burner integrated into a tabletop, illustrating the shift from monolithic application to embeddable component.
The evolution of terminal architecture: from standalone, monolithic appliances to sleek, integrated components.

Ghostling represents a fundamental shift in systems programming. It proves that complex legacy interfaces do not have to remain black boxes. By isolating the complexity of VT parsing into a clean, portable library, the terminal is finally free to live anywhere.