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:
Terminalbasics, 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 callbacksRenderStatebasics for render metadata, colors, dirty tracking, and row/cell traversalkeyencoder and key event wrappers for VT input encodingmouseencoder and mouse event wrappers for VT mouse encodingfocushelpers for focus gained/lost event encodingpastehelpers for safe paste checks and bracketed paste encodingbuild_infoqueries for the bundled Ghostty build configuration and versionoscstreaming parser for operating system command sequencessgrparser for typed SGR attribute decodingfmtformatter 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.nixpins0.15.2) gitfor CMakeFetchContent- 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
}
}
}