# Ghostty's Implementation of the Kitty Graphics Protocol: Architecture and API

> Discover Ghostty's implementation of the Kitty graphics protocol. Learn about its three-layer Zig subsystem, OSC _G escape sequence parsing, image storage, viewport layout, and C ABI for seamless integration.

- Repository: [Ghostty/ghostty](https://github.com/ghostty-org/ghostty)
- Tags: architecture
- Published: 2026-05-01

---

**Ghostty implements the Kitty graphics protocol as a three-layer Zig subsystem that parses `OSC _G` escape sequences, manages image storage and viewport layout through `ImageStorage`, and exposes a stable C ABI via `GhosttyKittyGraphics*` handles for downstream integration.**

Ghostty, the GPU-accelerated terminal emulator written in Zig, provides full support for the Kitty graphics protocol through a self-contained subsystem integrated into its terminal core. This implementation enables terminal applications to display images, animations, and other graphical content using standard escape sequences. The architecture deliberately separates parsing logic, storage management, and API exposure while maintaining strict compliance with the protocol specification.

## Architecture of the Graphics Subsystem

Ghostty's Kitty graphics implementation consists of three distinct layers that handle different aspects of the protocol. Each layer resides in specific source files within the `src/terminal/kitty/` directory.

- **Parsing and command handling** in `graphics_command.zig` tokenizes the `OSC _G` escape sequences and builds strongly-typed `Command` structures.
- **Storage and layout** in `graphics_storage.zig` maintains `ImageStorage` instances attached to each screen, handling allocation, eviction, and viewport calculations.
- **C-API façade** in `src/terminal/c/kitty_graphics.zig` exposes opaque pointers and iterators that wrap the Zig internals for C consumers.

The public entry point re-exports these modules through `src/terminal/kitty.zig` and registers the capability under the `.kitty_graphics` namespace accessible via `terminal.get(...)`.

## Parsing and Command Handling

When Ghostty receives an escape sequence starting with `\x1b_G` (the Kitty graphics OSC), the parser in **`src/terminal/kitty/graphics_command.zig`** processes the parameters (e.g., `a=T,t=d,f=24,i=1,p=1,…`). The parser constructs a `Command` union enum that represents the specific operation:

```zig
pub const Command = union(enum) {
    transmit: Transmit,
    display: Display,
    delete: Delete,
    // …
};

```

Each variant contains a strongly-typed struct mirroring the Kitty spec, including fields for image format, compression, placement coordinates, and z-index. The parser enforces strict validation—unknown parameters immediately return an `invalid_value` error that the terminal surface reports as a failed OSC sequence.

## Image Storage and Layout Management

All images and their placements reside in an **`ImageStorage`** instance attached to each screen (main or alternate). The implementation in **`src/terminal/kitty/graphics_storage.zig`** provides comprehensive resource management:

- **Image management** via `addImage`, `imageById`, and `imageByNumber`, with automatic eviction based on a configurable `total_limit` memory budget.
- **Placement management** through `addPlacement`, `gridSize`, `pixelSize`, and `rect` methods that handle pixel-to-grid mapping and source-rectangle clipping.
- **Viewport calculations** using `computeViewportPos`, which translates internal placement pins into viewport-relative coordinates while handling scrolling and virtual placements.

The `Placement` struct defines the layout metadata:

```zig
pub const Placement = struct {
    location: Location,
    x_offset: u32 = 0,
    y_offset: u32 = 0,
    source_x: u32 = 0,
    source_y: u32 = 0,
    source_width: u32 = 0,
    source_height: u32 = 0,
    columns: u32 = 0,
    rows: u32 = 0,
    z: i32 = 0,
    // …
};

```

## C API Façade for External Integration

The stable C ABI exposed in **`src/terminal/c/kitty_graphics.zig`** allows the rest of Ghostty (and external bindings) to interact with the graphics subsystem without importing Zig internals. This façade conditionally compiles only when the `kitty_graphics` build option is enabled, using compile-time guards:

```zig
if (comptime !build_options.kitty_graphics) return .no_value;

```

Key abstractions include:

- **`KittyGraphics`** – an opaque pointer to the `ImageStorage` for the current screen.
- **`ImageHandle`** – a nullable pointer to a stored image (`*const Image`).
- **`PlacementIterator`** – an opaque iterator for walking placements with configurable filters.

The public header at **[`include/ghostty/vt/kitty_graphics.h`](https://github.com/ghostty-org/ghostty/blob/main/include/ghostty/vt/kitty_graphics.h)** defines all enums (such as `ImageData`, `PlacementData`, and `PlacementLayer`) and function signatures for C consumers.

## Public Entry Point and Module Organization

The **`src/terminal/kitty.zig`** module serves as the public interface, re-exporting the graphics, key, and color sub-modules. Graphics objects are retrieved through the generic `terminal.get` API:

```zig
var graphics: KittyGraphics = undefined;
try testing.expectEqual(Result.success,
    terminal_c.get(t, .kitty_graphics, @ptrCast(&graphics)));

```

This design allows the terminal surface to query the graphics capability uniformly across different screen instances while keeping the implementation details encapsulated.

## Practical Code Examples

The following examples demonstrate how client code interacts with Ghostty's Kitty graphics subsystem through the C API.

### Listing All Image IDs in the Current Screen

This snippet iterates over all placements to extract associated image identifiers:

```c
Result r;
KittyGraphics gfx;
PlacementIterator *iter = NULL;

/* Obtain the graphics storage for the terminal `term`. */
r = ghostty_kitty_graphics_get(term, DataPlacementIterator, &iter);
if (r != ResultSuccess) return r;

/* Create a fresh iterator */
r = placement_iterator_new(NULL, &iter);
if (r != ResultSuccess) return r;

/* Walk the placements */
while (placement_iterator_next(iter)) {
    uint32_t img_id;
    r = placement_get(iter, PlacementDataImageId, &img_id);
    if (r == ResultSuccess) {
        printf("placement uses image %u\n", img_id);
    }
}
placement_iterator_free(iter);

```

### Querying Pixel Size of a Displayed Image

To determine the pixel dimensions of a rendered image:

```c
/* Assume we already have an ImageHandle `img` from image_get_handle(...). */
uint32_t w, h;
Result r = placement_pixel_size(iter, img, term, &w, &h);
if (r == ResultSuccess) {
    printf("Image occupies %u × %u pixels\n", w, h);
}

```

### Deleting Placements by Cell Intersection

To filter and remove specific placements based on grid position:

```c
/* Delete placements that intersect column 42, without deleting the images. */
PlacementIteratorOption opt = PlacementIteratorOptionColumn;
uint32_t col = 42;
Result r = placement_iterator_set(iter, opt, &col);
if (r != ResultSuccess) return r;

/* The iterator now only yields placements that intersect column 42. */
while (placement_iterator_next(iter)) {
    /* Perform custom cleanup … */
}

```

The underlying filter logic executes through `ImageStorage.delete` methods such as `delete_by_column`.

## Summary

- **Ghostty's Kitty graphics protocol implementation** resides in `src/terminal/kitty/` as a modular Zig subsystem with three distinct layers.
- **Strict parsing** in `graphics_command.zig` converts `OSC _G` sequences into strongly-typed `Command` unions, rejecting malformed input immediately.
- **Centralized storage** in `graphics_storage.zig` manages image lifecycles and placement geometry through the `ImageStorage` struct, supporting eviction policies and viewport-aware positioning.
- **Stable C interoperability** is provided by `src/terminal/c/kitty_graphics.zig`, which exposes `GhosttyKittyGraphics*` handles and placement iterators while supporting conditional compilation.
- **Public access** occurs through `src/terminal/kitty.zig` via the `.kitty_graphics` terminal capability, enabling uniform access across main and alternate screens.

## Frequently Asked Questions

### What file handles the parsing of Kitty graphics escape sequences in Ghostty?

The parser lives in **`src/terminal/kitty/graphics_command.zig`**. This module tokenizes the `OSC _G` parameters and constructs a `Command` union enum representing transmit, display, or delete operations, with strict validation that rejects unknown parameters via `invalid_value` errors.

### How does Ghostty manage memory limits for stored images?

Memory management is handled by the **`ImageStorage`** struct in `src/terminal/kitty/graphics_storage.zig`. The implementation tracks a configurable `total_limit` budget and performs automatic eviction when new image data would exceed the allocated memory threshold, ensuring the terminal remains responsive under heavy graphics load.

### Is the Kitty graphics subsystem always included in Ghostty builds?

No. The implementation is gated by the **`kitty_graphics`** build option. The C façade in `src/terminal/c/kitty_graphics.zig` uses compile-time guards (`if (comptime !build_options.kitty_graphics)`) to return `.no_value` when the feature is disabled, allowing for smaller binaries when graphics support is not required.

### How can C applications query specific placements by grid coordinates?

C applications use the **`PlacementIterator`** API with filter options. Call `placement_iterator_set` with `PlacementIteratorOptionColumn` or similar filters to constrain the iteration, then walk the results with `placement_iterator_next` and `placement_get` to retrieve metadata such as `PlacementDataImageId` for each intersecting placement.