libghostty C API for Terminal Embedding: A Complete Guide to Ghostty's VT Library
The libghostty C API exposes Ghostty's terminal emulator as libghostty-vt, a C-compatible library centered on the GhosttyTerminal opaque handle with functions for creation, VT stream processing, callbacks, and screen extraction.
The libghostty-vt library provides a stable, embeddable interface to the ghostty-org/ghostty terminal engine, allowing developers to integrate full VT emulation into applications using standard C linkage. All exported symbols live under include/ghostty/vt/ and follow strict ABI stability guarantees, making the library safe for long-term integration across language boundaries via FFI.
Core Architecture and ABI Stability
The libghostty-vt C API is deliberately designed as a façade over Ghostty's Zig-based core, exposing only plain C functions and opaque pointers to ensure forward compatibility. This architecture prevents breaking changes when the underlying implementation evolves.
Opaque Handles and Sized Initialization
All long-lived objects are referenced through opaque handles, with GhosttyTerminal serving as the primary instance pointer. Structures use the GHOSTTY_INIT_SIZED pattern, carrying a size field to allow future extension without breaking existing callers. This design philosophy is documented in src/terminal/c/AGENTS.md, which establishes the ABI stability contract for embedders.
The library exports two build artifacts: libghostty-vt.a (static) and libghostty-vt.so (or .dylib on macOS), accompanied by pkg-config files generated by src/build/GhosttyLibVt.zig.
Creating and Configuring a Terminal
Terminal Initialization
To embed a terminal, allocate a GhosttyTerminal instance using ghostty_terminal_new(), declared in include/ghostty/vt/terminal.h at lines 884-889. The function requires a GhosttyTerminalOptions structure specifying columns, rows, and scrollback limits.
#include <ghostty/vt.h>
GhosttyTerminal terminal;
GhosttyTerminalOptions opts = {
.cols = 80,
.rows = 24,
.max_scrollback = 0,
};
GhosttyResult r = ghostty_terminal_new(NULL, &terminal, opts);
assert(r == GHOSTTY_SUCCESS);
Registering Callbacks with ghostty_terminal_set
Terminal behavior is customized through synchronous callbacks registered via ghostty_terminal_set(). The GhosttyTerminalOption enum (defined at lines 994-1005 in terminal.h) specifies configurable behaviors, including:
- Write PTY (
GhosttyTerminalWritePtyFn) for handling query responses - Bell (
GhosttyTerminalBellFn) triggered by ASCII BEL characters - Title changes (
GhosttyTerminalTitleChangedFn) for window title updates
All callbacks receive a user-provided opaque pointer (GHOSTTY_TERMINAL_OPT_USERDATA) and execute synchronously during input processing. Critical constraint: callbacks must not invoke ghostty_terminal_vt_write() on the same terminal instance, as the API does not support re-entrancy.
void bell_cb(GhosttyTerminal term, void *userdata) {
printf("Bell received!\n");
}
// Register the callback
ghostty_terminal_set(terminal, GHOSTTY_TERMINAL_OPT_BELL, (const void *)bell_cb);
Processing VT Streams and Querying State
Feeding Input with ghostty_terminal_vt_write
Raw VT-encoded byte streams are processed through ghostty_terminal_vt_write(), defined at lines 865-873 in terminal.h. The parser updates internal terminal state and triggers registered effects synchronously.
const char *text = "Hello, World!\r\n";
ghostty_terminal_vt_write(terminal, (const uint8_t *)text, strlen(text));
// Escape sequences are fully parsed
text = "\x1b[1;32mGreen Text\x1b[0m\r\n";
ghostty_terminal_vt_write(terminal, (const uint8_t *)text, strlen(text));
Querying Terminal Data
State inspection uses ghostty_terminal_get() for single values or ghostty_terminal_get_multi() for batch queries. The GhosttyTerminalData enum (lines 606-718 in terminal.h) defines queryable attributes including cursor position (GHOSTTY_TERMINAL_DATA_COLS, GHOSTTY_TERMINAL_DATA_ROWS), color palette, and title.
uint16_t cols, rows;
ghostty_terminal_get(terminal, GHOSTTY_TERMINAL_DATA_COLS, &cols);
ghostty_terminal_get(terminal, GHOSTTY_TERMINAL_DATA_ROWS, &rows);
GhosttyString title;
ghostty_terminal_get(terminal, GHOSTTY_TERMINAL_DATA_TITLE, &title);
printf("Size: %ux%u, Title: %.*s\n", cols, rows, (int)title.len, title.data);
Extracting Screen Content with the Formatter API
The formatter sub-API provides plain-text extraction of the terminal screen. Create a GhosttyFormatter via ghostty_formatter_terminal_new() (defined in include/ghostty/vt/formatter.h at lines 8-19), then allocate output buffers with ghostty_formatter_format_alloc().
GhosttyFormatterTerminalOptions fmt_opts =
GHOSTTY_INIT_SIZED(GhosttyFormatterTerminalOptions);
fmt_opts.emit = GHOSTTY_FORMATTER_FORMAT_PLAIN;
fmt_opts.trim = true;
GhosttyFormatter formatter;
ghostty_formatter_terminal_new(NULL, &formatter, terminal, fmt_opts);
uint8_t *buf = NULL;
size_t len = 0;
ghostty_formatter_format_alloc(formatter, NULL, &buf, &len);
fwrite(buf, 1, len, stdout);
ghostty_free(NULL, buf, len);
Memory Management and Custom Allocators
libghostty-vt exports ghostty_alloc() and ghostty_free() for internal use and host applications, particularly critical for WASM build paths where the host environment must provide memory management. These symbols are conditionally exported in src/lib_vt.zig (lines 271-285), allowing embedders to control allocation strategies for opaque objects.
Summary
- libghostty-vt provides a C-compatible, ABI-stable wrapper around Ghostty's terminal engine via opaque
GhosttyTerminalhandles. - Core workflow: Initialize with
ghostty_terminal_new(), feed data viaghostty_terminal_vt_write(), register effects withghostty_terminal_set(), and query state usingghostty_terminal_get(). - Screen extraction uses the formatter API (
ghostty_formatter_terminal_new()andghostty_formatter_format_alloc()) to obtain plain-text representations. - Critical constraints: Callbacks execute synchronously and must not re-enter the VT write path; all structures use sized initialization for forward compatibility.
- Key headers:
include/ghostty/vt/terminal.hfor core operations,include/ghostty/vt/formatter.hfor output, andsrc/terminal/c/AGENTS.mdfor ABI stability guidelines.
Frequently Asked Questions
How does libghostty-vt handle ABI stability across versions?
The library uses opaque pointers for all objects and requires sized initialization via GHOSTTY_INIT_SIZED macros. Structure definitions include size fields, allowing the addition of new members without changing the layout seen by existing compiled code. This approach is formally specified in src/terminal/c/AGENTS.md.
Can I use libghostty-vt from languages other than C?
Yes. The API exposes standard C symbols (exported via extern "C" in src/lib_vt.zig) using primitive types and opaque pointers, making it compatible with C++, Rust FFI, Go cgo, or any language that can link against C libraries. The GhosttyString type uses explicit length fields rather than null-termination for FFI safety.
What happens if I call ghostty_terminal_vt_write from within a callback?
This creates undefined behavior. The libghostty-vt API does not support re-entrancy; callbacks execute synchronously during input processing and must not invoke VT write operations on the same terminal instance. Queue any write operations for execution after the initial call returns.
How do I build and link libghostty-vt into my project?
The build system generates libghostty-vt.a (static) and libghostty-vt.so (shared) along with pkg-config files (libghostty-vt.pc). Link against these artifacts and include the headers from include/ghostty/vt/. The Zig build process in src/build/GhosttyLibVt.zig handles platform-specific variations automatically.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →