libghostty-cpp

May 25, 2026 · View on GitHub

May the Lord have mercy upon my soul.

Minimal C++ wrapper around libghostty-vt, with the high-level API shape aligned closely to libghostty-rs while leaning into RAII and value-typed C++ APIs.

Current wrapper coverage:

  • Terminal basics, byte-oriented VT IO, typed resize/value accessors, typed viewport scrolling, active screen and scrollback metadata queries, cursor and mode queries, safe title and pwd accessors with explicit borrowed views, point-based grid refs for hit-testing/traversal, typed color palette accessors, and effect callbacks
  • RenderState basics for render metadata, colors, dirty tracking, and row/cell traversal
  • key encoder and key event wrappers for VT input encoding
  • mouse encoder and mouse event wrappers for VT mouse encoding
  • focus helpers for focus gained/lost event encoding
  • paste helpers for safe paste checks and bracketed paste encoding
  • build_info queries for the bundled Ghostty build configuration and version
  • osc streaming parser for operating system command sequences
  • sgr parser for typed SGR attribute decoding
  • fmt formatter for plain text, VT, and HTML exports from terminal state
  • Kitty graphics image and placement helpers, including aggregate image info, placement info, render sizing, source rectangles, viewport positions, and placement bounding rectangles

The public entry points are the headers under include/libghostty_cpp/. Most terminal-facing APIs are available through terminal.hpp or vt.hpp.

Building

Requirements:

  • CMake 3.19+
  • Ninja
  • A C++ compiler with C++20 support
  • Zig 0.15.x on PATH (flake.nix pins 0.15.2)
  • git for CMake FetchContent
  • macOS: Command Line Tools or Xcode
cmake -B build -G Ninja
cmake --build build
ctest --test-dir build --output-on-failure

By default, libghostty_cpp links to the shared libghostty-vt library. To link against the static libghostty-vt archive instead, configure with:

cmake -B build -G Ninja -DLIBGHOSTTY_CPP_LINK_GHOSTTY_STATIC=ON
cmake --build build

With Nix, the default flake package builds the library:

nix build

The Ghostty dependency is pinned to commit cb28160b5a2fd32d2e1cfeefb01d4297dbca8b18, which matches the currently targeted libghostty-rs API generation.

Kitty Graphics

The Kitty graphics wrapper exposes typed image and placement views from Ghostty's terminal state. Images and placements are non-owning handles into the terminal, so callers should treat values returned from Graphics::find_image and PlacementIterator::next as render-pass scoped.

Image::info() returns image metadata plus a ByteView for the decoded image data. That byte view is borrowed from Ghostty-owned storage and is invalidated when the terminal mutates, resets, or is destroyed. Copy the bytes if they must outlive the current render pass.

Placement::render_info() groups the placement calculations commonly needed by renderers: rendered pixel size, grid size, optional viewport position, source rectangle, and optional bounding rectangle. Bounding rectangles use the same Point::Kind coordinate spaces as terminal grid references, so callers can ask for viewport, active, screen, or history-relative coordinates without learning the C ABI tags.

Optional Example

ghostling_cpp is a Qt Widgets tech demo that exercises the higher-level wrappers, including key, mouse, focus, title, render, and bracketed paste handling.

It is disabled by default so the normal build produces the library. If Qt6 Core, Gui, and Widgets are available, build it explicitly with:

cmake -B build -G Ninja -DLIBGHOSTTY_CPP_BUILD_GHOSTLING_CPP=ON
cmake --build build --target ghostling_cpp

With Nix, run the demo with:

nix run .#ghostling

Quick Start

#include "libghostty_cpp/terminal.hpp"
#include "libghostty_cpp/render.hpp"

#include <cstdio>

int main() {
    // Create a terminal with 80 columns, 24 rows, and scrollback.
    libghostty_cpp::Terminal terminal({80, 24, 10'000});

    // Register an effect handler for PTY write-back (e.g. query responses).
    terminal.on_pty_write([](const libghostty_cpp::Terminal&, libghostty_cpp::ByteView data) {
        std::printf("PTY response: %zu bytes\n", data.size);
    });

    // Feed VT-encoded data into the terminal.
    terminal.vt_write(libghostty_cpp::ByteView{"Hello, \x1b[1;32mworld\x1b[0m!\r\n"});
    terminal.vt_write(libghostty_cpp::ByteView{"\x1b[38;2;255;128;0morange text\x1b[0m\r\n"});

    // Capture a render snapshot and iterate rows/cells.
    libghostty_cpp::RenderState render_state;
    libghostty_cpp::RowIterator rows;
    libghostty_cpp::CellIterator cells;

    render_state.update(terminal);
    rows.bind(render_state);

    while (rows.next()) {
        cells.bind(rows);
        while (cells.next()) {
            const auto graphemes = cells.graphemes();
            // … render each cell
        }
    }
}