aboutsummaryrefslogtreecommitdiff
path: root/vendor/libghostty-vt/include
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-04-04 19:22:04 +0300
committerCan Celik <ogulcancelik@gmail.com>2026-04-05 01:23:06 +0300
commit41dd733ca7123c9ac4bfc6c781697a660e95b052 (patch)
tree3fc91815ca139ef2e0b281bba0abda4ef15175f4 /vendor/libghostty-vt/include
parent55c138263e190a1e79d4b997bfb9397306c0ec1f (diff)
feat: finish ghostty pane backend integration
Diffstat (limited to 'vendor/libghostty-vt/include')
-rw-r--r--vendor/libghostty-vt/include/ghostty.h1206
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt.h133
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/allocator.h255
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/build_info.h140
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/color.h97
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/device.h150
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/focus.h75
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/formatter.h225
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/grid_ref.h131
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/key.h73
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/key/encoder.h245
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/key/event.h480
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/modes.h196
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/mouse.h70
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/mouse/encoder.h211
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/mouse/event.h193
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/osc.h233
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/paste.h101
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/point.h88
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/render.h603
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/screen.h340
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/sgr.h358
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/size_report.h100
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/style.h138
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/terminal.h983
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/types.h121
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/wasm.h160
-rw-r--r--vendor/libghostty-vt/include/module.modulemap7
28 files changed, 7112 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/include/ghostty.h b/vendor/libghostty-vt/include/ghostty.h
new file mode 100644
index 00000000..afc20bb3
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty.h
@@ -0,0 +1,1206 @@
+// Ghostty embedding API. The documentation for the embedding API is
+// only within the Zig source files that define the implementations. This
+// isn't meant to be a general purpose embedding API (yet) so there hasn't
+// been documentation or example work beyond that.
+//
+// The only consumer of this API is the macOS app, but the API is built to
+// be more general purpose.
+#ifndef GHOSTTY_H
+#define GHOSTTY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef _MSC_VER
+#include <BaseTsd.h>
+typedef SSIZE_T ssize_t;
+#else
+#include <sys/types.h>
+#endif
+
+//-------------------------------------------------------------------
+// Macros
+
+#define GHOSTTY_SUCCESS 0
+
+// Symbol visibility for shared library builds. On Windows, functions
+// are exported from the DLL when building and imported when consuming.
+// On other platforms with GCC/Clang, functions are marked with default
+// visibility so they remain accessible when the library is built with
+// -fvisibility=hidden. For static library builds, define GHOSTTY_STATIC
+// before including this header to make this a no-op.
+#ifndef GHOSTTY_API
+#if defined(GHOSTTY_STATIC)
+ #define GHOSTTY_API
+#elif defined(_WIN32) || defined(_WIN64)
+ #ifdef GHOSTTY_BUILD_SHARED
+ #define GHOSTTY_API __declspec(dllexport)
+ #else
+ #define GHOSTTY_API __declspec(dllimport)
+ #endif
+#elif defined(__GNUC__) && __GNUC__ >= 4
+ #define GHOSTTY_API __attribute__((visibility("default")))
+#else
+ #define GHOSTTY_API
+#endif
+#endif
+
+//-------------------------------------------------------------------
+// Types
+
+// Opaque types
+typedef void* ghostty_app_t;
+typedef void* ghostty_config_t;
+typedef void* ghostty_surface_t;
+typedef void* ghostty_inspector_t;
+
+// All the types below are fully defined and must be kept in sync with
+// their Zig counterparts. Any changes to these types MUST have an associated
+// Zig change.
+typedef enum {
+ GHOSTTY_PLATFORM_INVALID,
+ GHOSTTY_PLATFORM_MACOS,
+ GHOSTTY_PLATFORM_IOS,
+} ghostty_platform_e;
+
+typedef enum {
+ GHOSTTY_CLIPBOARD_STANDARD,
+ GHOSTTY_CLIPBOARD_SELECTION,
+} ghostty_clipboard_e;
+
+typedef struct {
+ const char *mime;
+ const char *data;
+} ghostty_clipboard_content_s;
+
+typedef enum {
+ GHOSTTY_CLIPBOARD_REQUEST_PASTE,
+ GHOSTTY_CLIPBOARD_REQUEST_OSC_52_READ,
+ GHOSTTY_CLIPBOARD_REQUEST_OSC_52_WRITE,
+} ghostty_clipboard_request_e;
+
+typedef enum {
+ GHOSTTY_MOUSE_RELEASE,
+ GHOSTTY_MOUSE_PRESS,
+} ghostty_input_mouse_state_e;
+
+typedef enum {
+ GHOSTTY_MOUSE_UNKNOWN,
+ GHOSTTY_MOUSE_LEFT,
+ GHOSTTY_MOUSE_RIGHT,
+ GHOSTTY_MOUSE_MIDDLE,
+ GHOSTTY_MOUSE_FOUR,
+ GHOSTTY_MOUSE_FIVE,
+ GHOSTTY_MOUSE_SIX,
+ GHOSTTY_MOUSE_SEVEN,
+ GHOSTTY_MOUSE_EIGHT,
+ GHOSTTY_MOUSE_NINE,
+ GHOSTTY_MOUSE_TEN,
+ GHOSTTY_MOUSE_ELEVEN,
+} ghostty_input_mouse_button_e;
+
+typedef enum {
+ GHOSTTY_MOUSE_MOMENTUM_NONE,
+ GHOSTTY_MOUSE_MOMENTUM_BEGAN,
+ GHOSTTY_MOUSE_MOMENTUM_STATIONARY,
+ GHOSTTY_MOUSE_MOMENTUM_CHANGED,
+ GHOSTTY_MOUSE_MOMENTUM_ENDED,
+ GHOSTTY_MOUSE_MOMENTUM_CANCELLED,
+ GHOSTTY_MOUSE_MOMENTUM_MAY_BEGIN,
+} ghostty_input_mouse_momentum_e;
+
+typedef enum {
+ GHOSTTY_COLOR_SCHEME_LIGHT = 0,
+ GHOSTTY_COLOR_SCHEME_DARK = 1,
+} ghostty_color_scheme_e;
+
+// This is a packed struct (see src/input/mouse.zig) but the C standard
+// afaik doesn't let us reliably define packed structs so we build it up
+// from scratch.
+typedef int ghostty_input_scroll_mods_t;
+
+typedef enum {
+ GHOSTTY_MODS_NONE = 0,
+ GHOSTTY_MODS_SHIFT = 1 << 0,
+ GHOSTTY_MODS_CTRL = 1 << 1,
+ GHOSTTY_MODS_ALT = 1 << 2,
+ GHOSTTY_MODS_SUPER = 1 << 3,
+ GHOSTTY_MODS_CAPS = 1 << 4,
+ GHOSTTY_MODS_NUM = 1 << 5,
+ GHOSTTY_MODS_SHIFT_RIGHT = 1 << 6,
+ GHOSTTY_MODS_CTRL_RIGHT = 1 << 7,
+ GHOSTTY_MODS_ALT_RIGHT = 1 << 8,
+ GHOSTTY_MODS_SUPER_RIGHT = 1 << 9,
+} ghostty_input_mods_e;
+
+typedef enum {
+ GHOSTTY_BINDING_FLAGS_CONSUMED = 1 << 0,
+ GHOSTTY_BINDING_FLAGS_ALL = 1 << 1,
+ GHOSTTY_BINDING_FLAGS_GLOBAL = 1 << 2,
+ GHOSTTY_BINDING_FLAGS_PERFORMABLE = 1 << 3,
+} ghostty_binding_flags_e;
+
+typedef enum {
+ GHOSTTY_ACTION_RELEASE,
+ GHOSTTY_ACTION_PRESS,
+ GHOSTTY_ACTION_REPEAT,
+} ghostty_input_action_e;
+
+// Based on: https://www.w3.org/TR/uievents-code/
+typedef enum {
+ GHOSTTY_KEY_UNIDENTIFIED,
+
+ // "Writing System Keys" § 3.1.1
+ GHOSTTY_KEY_BACKQUOTE,
+ GHOSTTY_KEY_BACKSLASH,
+ GHOSTTY_KEY_BRACKET_LEFT,
+ GHOSTTY_KEY_BRACKET_RIGHT,
+ GHOSTTY_KEY_COMMA,
+ GHOSTTY_KEY_DIGIT_0,
+ GHOSTTY_KEY_DIGIT_1,
+ GHOSTTY_KEY_DIGIT_2,
+ GHOSTTY_KEY_DIGIT_3,
+ GHOSTTY_KEY_DIGIT_4,
+ GHOSTTY_KEY_DIGIT_5,
+ GHOSTTY_KEY_DIGIT_6,
+ GHOSTTY_KEY_DIGIT_7,
+ GHOSTTY_KEY_DIGIT_8,
+ GHOSTTY_KEY_DIGIT_9,
+ GHOSTTY_KEY_EQUAL,
+ GHOSTTY_KEY_INTL_BACKSLASH,
+ GHOSTTY_KEY_INTL_RO,
+ GHOSTTY_KEY_INTL_YEN,
+ GHOSTTY_KEY_A,
+ GHOSTTY_KEY_B,
+ GHOSTTY_KEY_C,
+ GHOSTTY_KEY_D,
+ GHOSTTY_KEY_E,
+ GHOSTTY_KEY_F,
+ GHOSTTY_KEY_G,
+ GHOSTTY_KEY_H,
+ GHOSTTY_KEY_I,
+ GHOSTTY_KEY_J,
+ GHOSTTY_KEY_K,
+ GHOSTTY_KEY_L,
+ GHOSTTY_KEY_M,
+ GHOSTTY_KEY_N,
+ GHOSTTY_KEY_O,
+ GHOSTTY_KEY_P,
+ GHOSTTY_KEY_Q,
+ GHOSTTY_KEY_R,
+ GHOSTTY_KEY_S,
+ GHOSTTY_KEY_T,
+ GHOSTTY_KEY_U,
+ GHOSTTY_KEY_V,
+ GHOSTTY_KEY_W,
+ GHOSTTY_KEY_X,
+ GHOSTTY_KEY_Y,
+ GHOSTTY_KEY_Z,
+ GHOSTTY_KEY_MINUS,
+ GHOSTTY_KEY_PERIOD,
+ GHOSTTY_KEY_QUOTE,
+ GHOSTTY_KEY_SEMICOLON,
+ GHOSTTY_KEY_SLASH,
+
+ // "Functional Keys" § 3.1.2
+ GHOSTTY_KEY_ALT_LEFT,
+ GHOSTTY_KEY_ALT_RIGHT,
+ GHOSTTY_KEY_BACKSPACE,
+ GHOSTTY_KEY_CAPS_LOCK,
+ GHOSTTY_KEY_CONTEXT_MENU,
+ GHOSTTY_KEY_CONTROL_LEFT,
+ GHOSTTY_KEY_CONTROL_RIGHT,
+ GHOSTTY_KEY_ENTER,
+ GHOSTTY_KEY_META_LEFT,
+ GHOSTTY_KEY_META_RIGHT,
+ GHOSTTY_KEY_SHIFT_LEFT,
+ GHOSTTY_KEY_SHIFT_RIGHT,
+ GHOSTTY_KEY_SPACE,
+ GHOSTTY_KEY_TAB,
+ GHOSTTY_KEY_CONVERT,
+ GHOSTTY_KEY_KANA_MODE,
+ GHOSTTY_KEY_NON_CONVERT,
+
+ // "Control Pad Section" § 3.2
+ GHOSTTY_KEY_DELETE,
+ GHOSTTY_KEY_END,
+ GHOSTTY_KEY_HELP,
+ GHOSTTY_KEY_HOME,
+ GHOSTTY_KEY_INSERT,
+ GHOSTTY_KEY_PAGE_DOWN,
+ GHOSTTY_KEY_PAGE_UP,
+
+ // "Arrow Pad Section" § 3.3
+ GHOSTTY_KEY_ARROW_DOWN,
+ GHOSTTY_KEY_ARROW_LEFT,
+ GHOSTTY_KEY_ARROW_RIGHT,
+ GHOSTTY_KEY_ARROW_UP,
+
+ // "Numpad Section" § 3.4
+ GHOSTTY_KEY_NUM_LOCK,
+ GHOSTTY_KEY_NUMPAD_0,
+ GHOSTTY_KEY_NUMPAD_1,
+ GHOSTTY_KEY_NUMPAD_2,
+ GHOSTTY_KEY_NUMPAD_3,
+ GHOSTTY_KEY_NUMPAD_4,
+ GHOSTTY_KEY_NUMPAD_5,
+ GHOSTTY_KEY_NUMPAD_6,
+ GHOSTTY_KEY_NUMPAD_7,
+ GHOSTTY_KEY_NUMPAD_8,
+ GHOSTTY_KEY_NUMPAD_9,
+ GHOSTTY_KEY_NUMPAD_ADD,
+ GHOSTTY_KEY_NUMPAD_BACKSPACE,
+ GHOSTTY_KEY_NUMPAD_CLEAR,
+ GHOSTTY_KEY_NUMPAD_CLEAR_ENTRY,
+ GHOSTTY_KEY_NUMPAD_COMMA,
+ GHOSTTY_KEY_NUMPAD_DECIMAL,
+ GHOSTTY_KEY_NUMPAD_DIVIDE,
+ GHOSTTY_KEY_NUMPAD_ENTER,
+ GHOSTTY_KEY_NUMPAD_EQUAL,
+ GHOSTTY_KEY_NUMPAD_MEMORY_ADD,
+ GHOSTTY_KEY_NUMPAD_MEMORY_CLEAR,
+ GHOSTTY_KEY_NUMPAD_MEMORY_RECALL,
+ GHOSTTY_KEY_NUMPAD_MEMORY_STORE,
+ GHOSTTY_KEY_NUMPAD_MEMORY_SUBTRACT,
+ GHOSTTY_KEY_NUMPAD_MULTIPLY,
+ GHOSTTY_KEY_NUMPAD_PAREN_LEFT,
+ GHOSTTY_KEY_NUMPAD_PAREN_RIGHT,
+ GHOSTTY_KEY_NUMPAD_SUBTRACT,
+ GHOSTTY_KEY_NUMPAD_SEPARATOR,
+ GHOSTTY_KEY_NUMPAD_UP,
+ GHOSTTY_KEY_NUMPAD_DOWN,
+ GHOSTTY_KEY_NUMPAD_RIGHT,
+ GHOSTTY_KEY_NUMPAD_LEFT,
+ GHOSTTY_KEY_NUMPAD_BEGIN,
+ GHOSTTY_KEY_NUMPAD_HOME,
+ GHOSTTY_KEY_NUMPAD_END,
+ GHOSTTY_KEY_NUMPAD_INSERT,
+ GHOSTTY_KEY_NUMPAD_DELETE,
+ GHOSTTY_KEY_NUMPAD_PAGE_UP,
+ GHOSTTY_KEY_NUMPAD_PAGE_DOWN,
+
+ // "Function Section" § 3.5
+ GHOSTTY_KEY_ESCAPE,
+ GHOSTTY_KEY_F1,
+ GHOSTTY_KEY_F2,
+ GHOSTTY_KEY_F3,
+ GHOSTTY_KEY_F4,
+ GHOSTTY_KEY_F5,
+ GHOSTTY_KEY_F6,
+ GHOSTTY_KEY_F7,
+ GHOSTTY_KEY_F8,
+ GHOSTTY_KEY_F9,
+ GHOSTTY_KEY_F10,
+ GHOSTTY_KEY_F11,
+ GHOSTTY_KEY_F12,
+ GHOSTTY_KEY_F13,
+ GHOSTTY_KEY_F14,
+ GHOSTTY_KEY_F15,
+ GHOSTTY_KEY_F16,
+ GHOSTTY_KEY_F17,
+ GHOSTTY_KEY_F18,
+ GHOSTTY_KEY_F19,
+ GHOSTTY_KEY_F20,
+ GHOSTTY_KEY_F21,
+ GHOSTTY_KEY_F22,
+ GHOSTTY_KEY_F23,
+ GHOSTTY_KEY_F24,
+ GHOSTTY_KEY_F25,
+ GHOSTTY_KEY_FN,
+ GHOSTTY_KEY_FN_LOCK,
+ GHOSTTY_KEY_PRINT_SCREEN,
+ GHOSTTY_KEY_SCROLL_LOCK,
+ GHOSTTY_KEY_PAUSE,
+
+ // "Media Keys" § 3.6
+ GHOSTTY_KEY_BROWSER_BACK,
+ GHOSTTY_KEY_BROWSER_FAVORITES,
+ GHOSTTY_KEY_BROWSER_FORWARD,
+ GHOSTTY_KEY_BROWSER_HOME,
+ GHOSTTY_KEY_BROWSER_REFRESH,
+ GHOSTTY_KEY_BROWSER_SEARCH,
+ GHOSTTY_KEY_BROWSER_STOP,
+ GHOSTTY_KEY_EJECT,
+ GHOSTTY_KEY_LAUNCH_APP_1,
+ GHOSTTY_KEY_LAUNCH_APP_2,
+ GHOSTTY_KEY_LAUNCH_MAIL,
+ GHOSTTY_KEY_MEDIA_PLAY_PAUSE,
+ GHOSTTY_KEY_MEDIA_SELECT,
+ GHOSTTY_KEY_MEDIA_STOP,
+ GHOSTTY_KEY_MEDIA_TRACK_NEXT,
+ GHOSTTY_KEY_MEDIA_TRACK_PREVIOUS,
+ GHOSTTY_KEY_POWER,
+ GHOSTTY_KEY_SLEEP,
+ GHOSTTY_KEY_AUDIO_VOLUME_DOWN,
+ GHOSTTY_KEY_AUDIO_VOLUME_MUTE,
+ GHOSTTY_KEY_AUDIO_VOLUME_UP,
+ GHOSTTY_KEY_WAKE_UP,
+
+ // "Legacy, Non-standard, and Special Keys" § 3.7
+ GHOSTTY_KEY_COPY,
+ GHOSTTY_KEY_CUT,
+ GHOSTTY_KEY_PASTE,
+} ghostty_input_key_e;
+
+typedef struct {
+ ghostty_input_action_e action;
+ ghostty_input_mods_e mods;
+ ghostty_input_mods_e consumed_mods;
+ uint32_t keycode;
+ const char* text;
+ uint32_t unshifted_codepoint;
+ bool composing;
+} ghostty_input_key_s;
+
+typedef enum {
+ GHOSTTY_TRIGGER_PHYSICAL,
+ GHOSTTY_TRIGGER_UNICODE,
+ GHOSTTY_TRIGGER_CATCH_ALL,
+} ghostty_input_trigger_tag_e;
+
+typedef union {
+ ghostty_input_key_e translated;
+ ghostty_input_key_e physical;
+ uint32_t unicode;
+ // catch_all has no payload
+} ghostty_input_trigger_key_u;
+
+typedef struct {
+ ghostty_input_trigger_tag_e tag;
+ ghostty_input_trigger_key_u key;
+ ghostty_input_mods_e mods;
+} ghostty_input_trigger_s;
+
+typedef struct {
+ const char* action_key;
+ const char* action;
+ const char* title;
+ const char* description;
+} ghostty_command_s;
+
+typedef enum {
+ GHOSTTY_BUILD_MODE_DEBUG,
+ GHOSTTY_BUILD_MODE_RELEASE_SAFE,
+ GHOSTTY_BUILD_MODE_RELEASE_FAST,
+ GHOSTTY_BUILD_MODE_RELEASE_SMALL,
+} ghostty_build_mode_e;
+
+typedef struct {
+ ghostty_build_mode_e build_mode;
+ const char* version;
+ uintptr_t version_len;
+} ghostty_info_s;
+
+typedef struct {
+ const char* message;
+} ghostty_diagnostic_s;
+
+typedef struct {
+ const char* ptr;
+ uintptr_t len;
+ bool sentinel;
+} ghostty_string_s;
+
+typedef struct {
+ double tl_px_x;
+ double tl_px_y;
+ uint32_t offset_start;
+ uint32_t offset_len;
+ const char* text;
+ uintptr_t text_len;
+} ghostty_text_s;
+
+typedef enum {
+ GHOSTTY_POINT_ACTIVE,
+ GHOSTTY_POINT_VIEWPORT,
+ GHOSTTY_POINT_SCREEN,
+ GHOSTTY_POINT_SURFACE,
+} ghostty_point_tag_e;
+
+typedef enum {
+ GHOSTTY_POINT_COORD_EXACT,
+ GHOSTTY_POINT_COORD_TOP_LEFT,
+ GHOSTTY_POINT_COORD_BOTTOM_RIGHT,
+} ghostty_point_coord_e;
+
+typedef struct {
+ ghostty_point_tag_e tag;
+ ghostty_point_coord_e coord;
+ uint32_t x;
+ uint32_t y;
+} ghostty_point_s;
+
+typedef struct {
+ ghostty_point_s top_left;
+ ghostty_point_s bottom_right;
+ bool rectangle;
+} ghostty_selection_s;
+
+typedef struct {
+ const char* key;
+ const char* value;
+} ghostty_env_var_s;
+
+typedef struct {
+ void* nsview;
+} ghostty_platform_macos_s;
+
+typedef struct {
+ void* uiview;
+} ghostty_platform_ios_s;
+
+typedef union {
+ ghostty_platform_macos_s macos;
+ ghostty_platform_ios_s ios;
+} ghostty_platform_u;
+
+typedef enum {
+ GHOSTTY_SURFACE_CONTEXT_WINDOW = 0,
+ GHOSTTY_SURFACE_CONTEXT_TAB = 1,
+ GHOSTTY_SURFACE_CONTEXT_SPLIT = 2,
+} ghostty_surface_context_e;
+
+typedef struct {
+ ghostty_platform_e platform_tag;
+ ghostty_platform_u platform;
+ void* userdata;
+ double scale_factor;
+ float font_size;
+ const char* working_directory;
+ const char* command;
+ ghostty_env_var_s* env_vars;
+ size_t env_var_count;
+ const char* initial_input;
+ bool wait_after_command;
+ ghostty_surface_context_e context;
+} ghostty_surface_config_s;
+
+typedef struct {
+ uint16_t columns;
+ uint16_t rows;
+ uint32_t width_px;
+ uint32_t height_px;
+ uint32_t cell_width_px;
+ uint32_t cell_height_px;
+} ghostty_surface_size_s;
+
+// Config types
+
+// config.Path
+typedef struct {
+ const char* path;
+ bool optional;
+} ghostty_config_path_s;
+
+// config.Color
+typedef struct {
+ uint8_t r;
+ uint8_t g;
+ uint8_t b;
+} ghostty_config_color_s;
+
+// config.ColorList
+typedef struct {
+ const ghostty_config_color_s* colors;
+ size_t len;
+} ghostty_config_color_list_s;
+
+// config.RepeatableCommand
+typedef struct {
+ const ghostty_command_s* commands;
+ size_t len;
+} ghostty_config_command_list_s;
+
+// config.Palette
+typedef struct {
+ ghostty_config_color_s colors[256];
+} ghostty_config_palette_s;
+
+// config.QuickTerminalSize
+typedef enum {
+ GHOSTTY_QUICK_TERMINAL_SIZE_NONE,
+ GHOSTTY_QUICK_TERMINAL_SIZE_PERCENTAGE,
+ GHOSTTY_QUICK_TERMINAL_SIZE_PIXELS,
+} ghostty_quick_terminal_size_tag_e;
+
+typedef union {
+ float percentage;
+ uint32_t pixels;
+} ghostty_quick_terminal_size_value_u;
+
+typedef struct {
+ ghostty_quick_terminal_size_tag_e tag;
+ ghostty_quick_terminal_size_value_u value;
+} ghostty_quick_terminal_size_s;
+
+typedef struct {
+ ghostty_quick_terminal_size_s primary;
+ ghostty_quick_terminal_size_s secondary;
+} ghostty_config_quick_terminal_size_s;
+
+// config.Fullscreen
+typedef enum {
+ GHOSTTY_CONFIG_FULLSCREEN_FALSE,
+ GHOSTTY_CONFIG_FULLSCREEN_TRUE,
+ GHOSTTY_CONFIG_FULLSCREEN_NON_NATIVE,
+ GHOSTTY_CONFIG_FULLSCREEN_NON_NATIVE_VISIBLE_MENU,
+ GHOSTTY_CONFIG_FULLSCREEN_NON_NATIVE_PADDED_NOTCH,
+} ghostty_config_fullscreen_e;
+
+// apprt.Target.Key
+typedef enum {
+ GHOSTTY_TARGET_APP,
+ GHOSTTY_TARGET_SURFACE,
+} ghostty_target_tag_e;
+
+typedef union {
+ ghostty_surface_t surface;
+} ghostty_target_u;
+
+typedef struct {
+ ghostty_target_tag_e tag;
+ ghostty_target_u target;
+} ghostty_target_s;
+
+// apprt.action.SplitDirection
+typedef enum {
+ GHOSTTY_SPLIT_DIRECTION_RIGHT,
+ GHOSTTY_SPLIT_DIRECTION_DOWN,
+ GHOSTTY_SPLIT_DIRECTION_LEFT,
+ GHOSTTY_SPLIT_DIRECTION_UP,
+} ghostty_action_split_direction_e;
+
+// apprt.action.GotoSplit
+typedef enum {
+ GHOSTTY_GOTO_SPLIT_PREVIOUS,
+ GHOSTTY_GOTO_SPLIT_NEXT,
+ GHOSTTY_GOTO_SPLIT_UP,
+ GHOSTTY_GOTO_SPLIT_LEFT,
+ GHOSTTY_GOTO_SPLIT_DOWN,
+ GHOSTTY_GOTO_SPLIT_RIGHT,
+} ghostty_action_goto_split_e;
+
+// apprt.action.GotoWindow
+typedef enum {
+ GHOSTTY_GOTO_WINDOW_PREVIOUS,
+ GHOSTTY_GOTO_WINDOW_NEXT,
+} ghostty_action_goto_window_e;
+
+// apprt.action.ResizeSplit.Direction
+typedef enum {
+ GHOSTTY_RESIZE_SPLIT_UP,
+ GHOSTTY_RESIZE_SPLIT_DOWN,
+ GHOSTTY_RESIZE_SPLIT_LEFT,
+ GHOSTTY_RESIZE_SPLIT_RIGHT,
+} ghostty_action_resize_split_direction_e;
+
+// apprt.action.ResizeSplit
+typedef struct {
+ uint16_t amount;
+ ghostty_action_resize_split_direction_e direction;
+} ghostty_action_resize_split_s;
+
+// apprt.action.MoveTab
+typedef struct {
+ ssize_t amount;
+} ghostty_action_move_tab_s;
+
+// apprt.action.GotoTab
+typedef enum {
+ GHOSTTY_GOTO_TAB_PREVIOUS = -1,
+ GHOSTTY_GOTO_TAB_NEXT = -2,
+ GHOSTTY_GOTO_TAB_LAST = -3,
+} ghostty_action_goto_tab_e;
+
+// apprt.action.Fullscreen
+typedef enum {
+ GHOSTTY_FULLSCREEN_NATIVE,
+ GHOSTTY_FULLSCREEN_MACOS_NON_NATIVE,
+ GHOSTTY_FULLSCREEN_MACOS_NON_NATIVE_VISIBLE_MENU,
+ GHOSTTY_FULLSCREEN_MACOS_NON_NATIVE_PADDED_NOTCH,
+} ghostty_action_fullscreen_e;
+
+// apprt.action.FloatWindow
+typedef enum {
+ GHOSTTY_FLOAT_WINDOW_ON,
+ GHOSTTY_FLOAT_WINDOW_OFF,
+ GHOSTTY_FLOAT_WINDOW_TOGGLE,
+} ghostty_action_float_window_e;
+
+// apprt.action.SecureInput
+typedef enum {
+ GHOSTTY_SECURE_INPUT_ON,
+ GHOSTTY_SECURE_INPUT_OFF,
+ GHOSTTY_SECURE_INPUT_TOGGLE,
+} ghostty_action_secure_input_e;
+
+// apprt.action.Inspector
+typedef enum {
+ GHOSTTY_INSPECTOR_TOGGLE,
+ GHOSTTY_INSPECTOR_SHOW,
+ GHOSTTY_INSPECTOR_HIDE,
+} ghostty_action_inspector_e;
+
+// apprt.action.QuitTimer
+typedef enum {
+ GHOSTTY_QUIT_TIMER_START,
+ GHOSTTY_QUIT_TIMER_STOP,
+} ghostty_action_quit_timer_e;
+
+// apprt.action.Readonly
+typedef enum {
+ GHOSTTY_READONLY_OFF,
+ GHOSTTY_READONLY_ON,
+} ghostty_action_readonly_e;
+
+// apprt.action.DesktopNotification.C
+typedef struct {
+ const char* title;
+ const char* body;
+} ghostty_action_desktop_notification_s;
+
+// apprt.action.SetTitle.C
+typedef struct {
+ const char* title;
+} ghostty_action_set_title_s;
+
+// apprt.action.PromptTitle
+typedef enum {
+ GHOSTTY_PROMPT_TITLE_SURFACE,
+ GHOSTTY_PROMPT_TITLE_TAB,
+} ghostty_action_prompt_title_e;
+
+// apprt.action.Pwd.C
+typedef struct {
+ const char* pwd;
+} ghostty_action_pwd_s;
+
+// terminal.MouseShape
+typedef enum {
+ GHOSTTY_MOUSE_SHAPE_DEFAULT,
+ GHOSTTY_MOUSE_SHAPE_CONTEXT_MENU,
+ GHOSTTY_MOUSE_SHAPE_HELP,
+ GHOSTTY_MOUSE_SHAPE_POINTER,
+ GHOSTTY_MOUSE_SHAPE_PROGRESS,
+ GHOSTTY_MOUSE_SHAPE_WAIT,
+ GHOSTTY_MOUSE_SHAPE_CELL,
+ GHOSTTY_MOUSE_SHAPE_CROSSHAIR,
+ GHOSTTY_MOUSE_SHAPE_TEXT,
+ GHOSTTY_MOUSE_SHAPE_VERTICAL_TEXT,
+ GHOSTTY_MOUSE_SHAPE_ALIAS,
+ GHOSTTY_MOUSE_SHAPE_COPY,
+ GHOSTTY_MOUSE_SHAPE_MOVE,
+ GHOSTTY_MOUSE_SHAPE_NO_DROP,
+ GHOSTTY_MOUSE_SHAPE_NOT_ALLOWED,
+ GHOSTTY_MOUSE_SHAPE_GRAB,
+ GHOSTTY_MOUSE_SHAPE_GRABBING,
+ GHOSTTY_MOUSE_SHAPE_ALL_SCROLL,
+ GHOSTTY_MOUSE_SHAPE_COL_RESIZE,
+ GHOSTTY_MOUSE_SHAPE_ROW_RESIZE,
+ GHOSTTY_MOUSE_SHAPE_N_RESIZE,
+ GHOSTTY_MOUSE_SHAPE_E_RESIZE,
+ GHOSTTY_MOUSE_SHAPE_S_RESIZE,
+ GHOSTTY_MOUSE_SHAPE_W_RESIZE,
+ GHOSTTY_MOUSE_SHAPE_NE_RESIZE,
+ GHOSTTY_MOUSE_SHAPE_NW_RESIZE,
+ GHOSTTY_MOUSE_SHAPE_SE_RESIZE,
+ GHOSTTY_MOUSE_SHAPE_SW_RESIZE,
+ GHOSTTY_MOUSE_SHAPE_EW_RESIZE,
+ GHOSTTY_MOUSE_SHAPE_NS_RESIZE,
+ GHOSTTY_MOUSE_SHAPE_NESW_RESIZE,
+ GHOSTTY_MOUSE_SHAPE_NWSE_RESIZE,
+ GHOSTTY_MOUSE_SHAPE_ZOOM_IN,
+ GHOSTTY_MOUSE_SHAPE_ZOOM_OUT,
+} ghostty_action_mouse_shape_e;
+
+// apprt.action.MouseVisibility
+typedef enum {
+ GHOSTTY_MOUSE_VISIBLE,
+ GHOSTTY_MOUSE_HIDDEN,
+} ghostty_action_mouse_visibility_e;
+
+// apprt.action.MouseOverLink
+typedef struct {
+ const char* url;
+ size_t len;
+} ghostty_action_mouse_over_link_s;
+
+// apprt.action.SizeLimit
+typedef struct {
+ uint32_t min_width;
+ uint32_t min_height;
+ uint32_t max_width;
+ uint32_t max_height;
+} ghostty_action_size_limit_s;
+
+// apprt.action.InitialSize
+typedef struct {
+ uint32_t width;
+ uint32_t height;
+} ghostty_action_initial_size_s;
+
+// apprt.action.CellSize
+typedef struct {
+ uint32_t width;
+ uint32_t height;
+} ghostty_action_cell_size_s;
+
+// renderer.Health
+typedef enum {
+ GHOSTTY_RENDERER_HEALTH_HEALTHY,
+ GHOSTTY_RENDERER_HEALTH_UNHEALTHY,
+} ghostty_action_renderer_health_e;
+
+// apprt.action.KeySequence
+typedef struct {
+ bool active;
+ ghostty_input_trigger_s trigger;
+} ghostty_action_key_sequence_s;
+
+// apprt.action.KeyTable.Tag
+typedef enum {
+ GHOSTTY_KEY_TABLE_ACTIVATE,
+ GHOSTTY_KEY_TABLE_DEACTIVATE,
+ GHOSTTY_KEY_TABLE_DEACTIVATE_ALL,
+} ghostty_action_key_table_tag_e;
+
+// apprt.action.KeyTable.CValue
+typedef union {
+ struct {
+ const char *name;
+ size_t len;
+ } activate;
+} ghostty_action_key_table_u;
+
+// apprt.action.KeyTable.C
+typedef struct {
+ ghostty_action_key_table_tag_e tag;
+ ghostty_action_key_table_u value;
+} ghostty_action_key_table_s;
+
+// apprt.action.ColorKind
+typedef enum {
+ GHOSTTY_ACTION_COLOR_KIND_FOREGROUND = -1,
+ GHOSTTY_ACTION_COLOR_KIND_BACKGROUND = -2,
+ GHOSTTY_ACTION_COLOR_KIND_CURSOR = -3,
+} ghostty_action_color_kind_e;
+
+// apprt.action.ColorChange
+typedef struct {
+ ghostty_action_color_kind_e kind;
+ uint8_t r;
+ uint8_t g;
+ uint8_t b;
+} ghostty_action_color_change_s;
+
+// apprt.action.ConfigChange
+typedef struct {
+ ghostty_config_t config;
+} ghostty_action_config_change_s;
+
+// apprt.action.ReloadConfig
+typedef struct {
+ bool soft;
+} ghostty_action_reload_config_s;
+
+// apprt.action.OpenUrlKind
+typedef enum {
+ GHOSTTY_ACTION_OPEN_URL_KIND_UNKNOWN,
+ GHOSTTY_ACTION_OPEN_URL_KIND_TEXT,
+ GHOSTTY_ACTION_OPEN_URL_KIND_HTML,
+} ghostty_action_open_url_kind_e;
+
+// apprt.action.OpenUrl.C
+typedef struct {
+ ghostty_action_open_url_kind_e kind;
+ const char* url;
+ uintptr_t len;
+} ghostty_action_open_url_s;
+
+// apprt.action.CloseTabMode
+typedef enum {
+ GHOSTTY_ACTION_CLOSE_TAB_MODE_THIS,
+ GHOSTTY_ACTION_CLOSE_TAB_MODE_OTHER,
+ GHOSTTY_ACTION_CLOSE_TAB_MODE_RIGHT,
+} ghostty_action_close_tab_mode_e;
+
+// apprt.surface.Message.ChildExited
+typedef struct {
+ uint32_t exit_code;
+ uint64_t timetime_ms;
+} ghostty_surface_message_childexited_s;
+
+// terminal.osc.Command.ProgressReport.State
+typedef enum {
+ GHOSTTY_PROGRESS_STATE_REMOVE,
+ GHOSTTY_PROGRESS_STATE_SET,
+ GHOSTTY_PROGRESS_STATE_ERROR,
+ GHOSTTY_PROGRESS_STATE_INDETERMINATE,
+ GHOSTTY_PROGRESS_STATE_PAUSE,
+} ghostty_action_progress_report_state_e;
+
+// terminal.osc.Command.ProgressReport.C
+typedef struct {
+ ghostty_action_progress_report_state_e state;
+ // -1 if no progress was reported, otherwise 0-100 indicating percent
+ // completeness.
+ int8_t progress;
+} ghostty_action_progress_report_s;
+
+// apprt.action.CommandFinished.C
+typedef struct {
+ // -1 if no exit code was reported, otherwise 0-255
+ int16_t exit_code;
+ // number of nanoseconds that command was running for
+ uint64_t duration;
+} ghostty_action_command_finished_s;
+
+// apprt.action.StartSearch.C
+typedef struct {
+ const char* needle;
+} ghostty_action_start_search_s;
+
+// apprt.action.SearchTotal
+typedef struct {
+ ssize_t total;
+} ghostty_action_search_total_s;
+
+// apprt.action.SearchSelected
+typedef struct {
+ ssize_t selected;
+} ghostty_action_search_selected_s;
+
+// terminal.Scrollbar
+typedef struct {
+ uint64_t total;
+ uint64_t offset;
+ uint64_t len;
+} ghostty_action_scrollbar_s;
+
+// apprt.Action.Key
+typedef enum {
+ GHOSTTY_ACTION_QUIT,
+ GHOSTTY_ACTION_NEW_WINDOW,
+ GHOSTTY_ACTION_NEW_TAB,
+ GHOSTTY_ACTION_CLOSE_TAB,
+ GHOSTTY_ACTION_NEW_SPLIT,
+ GHOSTTY_ACTION_CLOSE_ALL_WINDOWS,
+ GHOSTTY_ACTION_TOGGLE_MAXIMIZE,
+ GHOSTTY_ACTION_TOGGLE_FULLSCREEN,
+ GHOSTTY_ACTION_TOGGLE_TAB_OVERVIEW,
+ GHOSTTY_ACTION_TOGGLE_WINDOW_DECORATIONS,
+ GHOSTTY_ACTION_TOGGLE_QUICK_TERMINAL,
+ GHOSTTY_ACTION_TOGGLE_COMMAND_PALETTE,
+ GHOSTTY_ACTION_TOGGLE_VISIBILITY,
+ GHOSTTY_ACTION_TOGGLE_BACKGROUND_OPACITY,
+ GHOSTTY_ACTION_MOVE_TAB,
+ GHOSTTY_ACTION_GOTO_TAB,
+ GHOSTTY_ACTION_GOTO_SPLIT,
+ GHOSTTY_ACTION_GOTO_WINDOW,
+ GHOSTTY_ACTION_RESIZE_SPLIT,
+ GHOSTTY_ACTION_EQUALIZE_SPLITS,
+ GHOSTTY_ACTION_TOGGLE_SPLIT_ZOOM,
+ GHOSTTY_ACTION_PRESENT_TERMINAL,
+ GHOSTTY_ACTION_SIZE_LIMIT,
+ GHOSTTY_ACTION_RESET_WINDOW_SIZE,
+ GHOSTTY_ACTION_INITIAL_SIZE,
+ GHOSTTY_ACTION_CELL_SIZE,
+ GHOSTTY_ACTION_SCROLLBAR,
+ GHOSTTY_ACTION_RENDER,
+ GHOSTTY_ACTION_INSPECTOR,
+ GHOSTTY_ACTION_SHOW_GTK_INSPECTOR,
+ GHOSTTY_ACTION_RENDER_INSPECTOR,
+ GHOSTTY_ACTION_DESKTOP_NOTIFICATION,
+ GHOSTTY_ACTION_SET_TITLE,
+ GHOSTTY_ACTION_SET_TAB_TITLE,
+ GHOSTTY_ACTION_PROMPT_TITLE,
+ GHOSTTY_ACTION_PWD,
+ GHOSTTY_ACTION_MOUSE_SHAPE,
+ GHOSTTY_ACTION_MOUSE_VISIBILITY,
+ GHOSTTY_ACTION_MOUSE_OVER_LINK,
+ GHOSTTY_ACTION_RENDERER_HEALTH,
+ GHOSTTY_ACTION_OPEN_CONFIG,
+ GHOSTTY_ACTION_QUIT_TIMER,
+ GHOSTTY_ACTION_FLOAT_WINDOW,
+ GHOSTTY_ACTION_SECURE_INPUT,
+ GHOSTTY_ACTION_KEY_SEQUENCE,
+ GHOSTTY_ACTION_KEY_TABLE,
+ GHOSTTY_ACTION_COLOR_CHANGE,
+ GHOSTTY_ACTION_RELOAD_CONFIG,
+ GHOSTTY_ACTION_CONFIG_CHANGE,
+ GHOSTTY_ACTION_CLOSE_WINDOW,
+ GHOSTTY_ACTION_RING_BELL,
+ GHOSTTY_ACTION_UNDO,
+ GHOSTTY_ACTION_REDO,
+ GHOSTTY_ACTION_CHECK_FOR_UPDATES,
+ GHOSTTY_ACTION_OPEN_URL,
+ GHOSTTY_ACTION_SHOW_CHILD_EXITED,
+ GHOSTTY_ACTION_PROGRESS_REPORT,
+ GHOSTTY_ACTION_SHOW_ON_SCREEN_KEYBOARD,
+ GHOSTTY_ACTION_COMMAND_FINISHED,
+ GHOSTTY_ACTION_START_SEARCH,
+ GHOSTTY_ACTION_END_SEARCH,
+ GHOSTTY_ACTION_SEARCH_TOTAL,
+ GHOSTTY_ACTION_SEARCH_SELECTED,
+ GHOSTTY_ACTION_READONLY,
+ GHOSTTY_ACTION_COPY_TITLE_TO_CLIPBOARD,
+} ghostty_action_tag_e;
+
+typedef union {
+ ghostty_action_split_direction_e new_split;
+ ghostty_action_fullscreen_e toggle_fullscreen;
+ ghostty_action_move_tab_s move_tab;
+ ghostty_action_goto_tab_e goto_tab;
+ ghostty_action_goto_split_e goto_split;
+ ghostty_action_goto_window_e goto_window;
+ ghostty_action_resize_split_s resize_split;
+ ghostty_action_size_limit_s size_limit;
+ ghostty_action_initial_size_s initial_size;
+ ghostty_action_cell_size_s cell_size;
+ ghostty_action_scrollbar_s scrollbar;
+ ghostty_action_inspector_e inspector;
+ ghostty_action_desktop_notification_s desktop_notification;
+ ghostty_action_set_title_s set_title;
+ ghostty_action_set_title_s set_tab_title;
+ ghostty_action_prompt_title_e prompt_title;
+ ghostty_action_pwd_s pwd;
+ ghostty_action_mouse_shape_e mouse_shape;
+ ghostty_action_mouse_visibility_e mouse_visibility;
+ ghostty_action_mouse_over_link_s mouse_over_link;
+ ghostty_action_renderer_health_e renderer_health;
+ ghostty_action_quit_timer_e quit_timer;
+ ghostty_action_float_window_e float_window;
+ ghostty_action_secure_input_e secure_input;
+ ghostty_action_key_sequence_s key_sequence;
+ ghostty_action_key_table_s key_table;
+ ghostty_action_color_change_s color_change;
+ ghostty_action_reload_config_s reload_config;
+ ghostty_action_config_change_s config_change;
+ ghostty_action_open_url_s open_url;
+ ghostty_action_close_tab_mode_e close_tab_mode;
+ ghostty_surface_message_childexited_s child_exited;
+ ghostty_action_progress_report_s progress_report;
+ ghostty_action_command_finished_s command_finished;
+ ghostty_action_start_search_s start_search;
+ ghostty_action_search_total_s search_total;
+ ghostty_action_search_selected_s search_selected;
+ ghostty_action_readonly_e readonly;
+} ghostty_action_u;
+
+typedef struct {
+ ghostty_action_tag_e tag;
+ ghostty_action_u action;
+} ghostty_action_s;
+
+typedef void (*ghostty_runtime_wakeup_cb)(void*);
+typedef bool (*ghostty_runtime_read_clipboard_cb)(void*,
+ ghostty_clipboard_e,
+ void*);
+typedef void (*ghostty_runtime_confirm_read_clipboard_cb)(
+ void*,
+ const char*,
+ void*,
+ ghostty_clipboard_request_e);
+typedef void (*ghostty_runtime_write_clipboard_cb)(void*,
+ ghostty_clipboard_e,
+ const ghostty_clipboard_content_s*,
+ size_t,
+ bool);
+typedef void (*ghostty_runtime_close_surface_cb)(void*, bool);
+typedef bool (*ghostty_runtime_action_cb)(ghostty_app_t,
+ ghostty_target_s,
+ ghostty_action_s);
+
+typedef struct {
+ void* userdata;
+ bool supports_selection_clipboard;
+ ghostty_runtime_wakeup_cb wakeup_cb;
+ ghostty_runtime_action_cb action_cb;
+ ghostty_runtime_read_clipboard_cb read_clipboard_cb;
+ ghostty_runtime_confirm_read_clipboard_cb confirm_read_clipboard_cb;
+ ghostty_runtime_write_clipboard_cb write_clipboard_cb;
+ ghostty_runtime_close_surface_cb close_surface_cb;
+} ghostty_runtime_config_s;
+
+// apprt.ipc.Target.Key
+typedef enum {
+ GHOSTTY_IPC_TARGET_CLASS,
+ GHOSTTY_IPC_TARGET_DETECT,
+} ghostty_ipc_target_tag_e;
+
+typedef union {
+ char *klass;
+} ghostty_ipc_target_u;
+
+typedef struct {
+ ghostty_ipc_target_tag_e tag;
+ ghostty_ipc_target_u target;
+} chostty_ipc_target_s;
+
+// apprt.ipc.Action.NewWindow
+typedef struct {
+ // This should be a null terminated list of strings.
+ const char **arguments;
+} ghostty_ipc_action_new_window_s;
+
+typedef union {
+ ghostty_ipc_action_new_window_s new_window;
+} ghostty_ipc_action_u;
+
+// apprt.ipc.Action.Key
+typedef enum {
+ GHOSTTY_IPC_ACTION_NEW_WINDOW,
+} ghostty_ipc_action_tag_e;
+
+//-------------------------------------------------------------------
+// Published API
+
+GHOSTTY_API int ghostty_init(uintptr_t, char**);
+GHOSTTY_API void ghostty_cli_try_action(void);
+GHOSTTY_API ghostty_info_s ghostty_info(void);
+GHOSTTY_API const char* ghostty_translate(const char*);
+GHOSTTY_API void ghostty_string_free(ghostty_string_s);
+
+GHOSTTY_API ghostty_config_t ghostty_config_new();
+GHOSTTY_API void ghostty_config_free(ghostty_config_t);
+GHOSTTY_API ghostty_config_t ghostty_config_clone(ghostty_config_t);
+GHOSTTY_API void ghostty_config_load_cli_args(ghostty_config_t);
+GHOSTTY_API void ghostty_config_load_file(ghostty_config_t, const char*);
+GHOSTTY_API void ghostty_config_load_default_files(ghostty_config_t);
+GHOSTTY_API void ghostty_config_load_recursive_files(ghostty_config_t);
+GHOSTTY_API void ghostty_config_finalize(ghostty_config_t);
+GHOSTTY_API bool ghostty_config_get(ghostty_config_t, void*, const char*, uintptr_t);
+GHOSTTY_API ghostty_input_trigger_s ghostty_config_trigger(ghostty_config_t,
+ const char*,
+ uintptr_t);
+GHOSTTY_API uint32_t ghostty_config_diagnostics_count(ghostty_config_t);
+GHOSTTY_API ghostty_diagnostic_s ghostty_config_get_diagnostic(ghostty_config_t, uint32_t);
+GHOSTTY_API ghostty_string_s ghostty_config_open_path(void);
+
+GHOSTTY_API ghostty_app_t ghostty_app_new(const ghostty_runtime_config_s*,
+ ghostty_config_t);
+GHOSTTY_API void ghostty_app_free(ghostty_app_t);
+GHOSTTY_API void ghostty_app_tick(ghostty_app_t);
+GHOSTTY_API void* ghostty_app_userdata(ghostty_app_t);
+GHOSTTY_API void ghostty_app_set_focus(ghostty_app_t, bool);
+GHOSTTY_API bool ghostty_app_key(ghostty_app_t, ghostty_input_key_s);
+GHOSTTY_API bool ghostty_app_key_is_binding(ghostty_app_t, ghostty_input_key_s);
+GHOSTTY_API void ghostty_app_keyboard_changed(ghostty_app_t);
+GHOSTTY_API void ghostty_app_open_config(ghostty_app_t);
+GHOSTTY_API void ghostty_app_update_config(ghostty_app_t, ghostty_config_t);
+GHOSTTY_API bool ghostty_app_needs_confirm_quit(ghostty_app_t);
+GHOSTTY_API bool ghostty_app_has_global_keybinds(ghostty_app_t);
+GHOSTTY_API void ghostty_app_set_color_scheme(ghostty_app_t, ghostty_color_scheme_e);
+
+GHOSTTY_API ghostty_surface_config_s ghostty_surface_config_new();
+
+GHOSTTY_API ghostty_surface_t ghostty_surface_new(ghostty_app_t,
+ const ghostty_surface_config_s*);
+GHOSTTY_API void ghostty_surface_free(ghostty_surface_t);
+GHOSTTY_API void* ghostty_surface_userdata(ghostty_surface_t);
+GHOSTTY_API ghostty_app_t ghostty_surface_app(ghostty_surface_t);
+GHOSTTY_API ghostty_surface_config_s ghostty_surface_inherited_config(ghostty_surface_t, ghostty_surface_context_e);
+GHOSTTY_API void ghostty_surface_update_config(ghostty_surface_t, ghostty_config_t);
+GHOSTTY_API bool ghostty_surface_needs_confirm_quit(ghostty_surface_t);
+GHOSTTY_API bool ghostty_surface_process_exited(ghostty_surface_t);
+GHOSTTY_API void ghostty_surface_refresh(ghostty_surface_t);
+GHOSTTY_API void ghostty_surface_draw(ghostty_surface_t);
+GHOSTTY_API void ghostty_surface_set_content_scale(ghostty_surface_t, double, double);
+GHOSTTY_API void ghostty_surface_set_focus(ghostty_surface_t, bool);
+GHOSTTY_API void ghostty_surface_set_occlusion(ghostty_surface_t, bool);
+GHOSTTY_API void ghostty_surface_set_size(ghostty_surface_t, uint32_t, uint32_t);
+GHOSTTY_API ghostty_surface_size_s ghostty_surface_size(ghostty_surface_t);
+GHOSTTY_API void ghostty_surface_set_color_scheme(ghostty_surface_t,
+ ghostty_color_scheme_e);
+GHOSTTY_API ghostty_input_mods_e ghostty_surface_key_translation_mods(ghostty_surface_t,
+ ghostty_input_mods_e);
+GHOSTTY_API bool ghostty_surface_key(ghostty_surface_t, ghostty_input_key_s);
+GHOSTTY_API bool ghostty_surface_key_is_binding(ghostty_surface_t,
+ ghostty_input_key_s,
+ ghostty_binding_flags_e*);
+GHOSTTY_API void ghostty_surface_text(ghostty_surface_t, const char*, uintptr_t);
+GHOSTTY_API void ghostty_surface_preedit(ghostty_surface_t, const char*, uintptr_t);
+GHOSTTY_API bool ghostty_surface_mouse_captured(ghostty_surface_t);
+GHOSTTY_API bool ghostty_surface_mouse_button(ghostty_surface_t,
+ ghostty_input_mouse_state_e,
+ ghostty_input_mouse_button_e,
+ ghostty_input_mods_e);
+GHOSTTY_API void ghostty_surface_mouse_pos(ghostty_surface_t,
+ double,
+ double,
+ ghostty_input_mods_e);
+GHOSTTY_API void ghostty_surface_mouse_scroll(ghostty_surface_t,
+ double,
+ double,
+ ghostty_input_scroll_mods_t);
+GHOSTTY_API void ghostty_surface_mouse_pressure(ghostty_surface_t, uint32_t, double);
+GHOSTTY_API void ghostty_surface_ime_point(ghostty_surface_t, double*, double*, double*, double*);
+GHOSTTY_API void ghostty_surface_request_close(ghostty_surface_t);
+GHOSTTY_API void ghostty_surface_split(ghostty_surface_t, ghostty_action_split_direction_e);
+GHOSTTY_API void ghostty_surface_split_focus(ghostty_surface_t,
+ ghostty_action_goto_split_e);
+GHOSTTY_API void ghostty_surface_split_resize(ghostty_surface_t,
+ ghostty_action_resize_split_direction_e,
+ uint16_t);
+GHOSTTY_API void ghostty_surface_split_equalize(ghostty_surface_t);
+GHOSTTY_API bool ghostty_surface_binding_action(ghostty_surface_t, const char*, uintptr_t);
+GHOSTTY_API void ghostty_surface_complete_clipboard_request(ghostty_surface_t,
+ const char*,
+ void*,
+ bool);
+GHOSTTY_API bool ghostty_surface_has_selection(ghostty_surface_t);
+GHOSTTY_API bool ghostty_surface_read_selection(ghostty_surface_t, ghostty_text_s*);
+GHOSTTY_API bool ghostty_surface_read_text(ghostty_surface_t,
+ ghostty_selection_s,
+ ghostty_text_s*);
+GHOSTTY_API void ghostty_surface_free_text(ghostty_surface_t, ghostty_text_s*);
+
+#ifdef __APPLE__
+GHOSTTY_API void ghostty_surface_set_display_id(ghostty_surface_t, uint32_t);
+GHOSTTY_API void* ghostty_surface_quicklook_font(ghostty_surface_t);
+GHOSTTY_API bool ghostty_surface_quicklook_word(ghostty_surface_t, ghostty_text_s*);
+#endif
+
+GHOSTTY_API ghostty_inspector_t ghostty_surface_inspector(ghostty_surface_t);
+GHOSTTY_API void ghostty_inspector_free(ghostty_surface_t);
+GHOSTTY_API void ghostty_inspector_set_focus(ghostty_inspector_t, bool);
+GHOSTTY_API void ghostty_inspector_set_content_scale(ghostty_inspector_t, double, double);
+GHOSTTY_API void ghostty_inspector_set_size(ghostty_inspector_t, uint32_t, uint32_t);
+GHOSTTY_API void ghostty_inspector_mouse_button(ghostty_inspector_t,
+ ghostty_input_mouse_state_e,
+ ghostty_input_mouse_button_e,
+ ghostty_input_mods_e);
+GHOSTTY_API void ghostty_inspector_mouse_pos(ghostty_inspector_t, double, double);
+GHOSTTY_API void ghostty_inspector_mouse_scroll(ghostty_inspector_t,
+ double,
+ double,
+ ghostty_input_scroll_mods_t);
+GHOSTTY_API void ghostty_inspector_key(ghostty_inspector_t,
+ ghostty_input_action_e,
+ ghostty_input_key_e,
+ ghostty_input_mods_e);
+GHOSTTY_API void ghostty_inspector_text(ghostty_inspector_t, const char*);
+
+#ifdef __APPLE__
+GHOSTTY_API bool ghostty_inspector_metal_init(ghostty_inspector_t, void*);
+GHOSTTY_API void ghostty_inspector_metal_render(ghostty_inspector_t, void*, void*);
+GHOSTTY_API bool ghostty_inspector_metal_shutdown(ghostty_inspector_t);
+#endif
+
+// APIs I'd like to get rid of eventually but are still needed for now.
+// Don't use these unless you know what you're doing.
+GHOSTTY_API void ghostty_set_window_background_blur(ghostty_app_t, void*);
+
+// Benchmark API, if available.
+GHOSTTY_API bool ghostty_benchmark_cli(const char*, const char*);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GHOSTTY_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt.h b/vendor/libghostty-vt/include/ghostty/vt.h
new file mode 100644
index 00000000..2a52f4b0
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt.h
@@ -0,0 +1,133 @@
+/**
+ * @file vt.h
+ *
+ * libghostty-vt - Virtual terminal emulator library
+ *
+ * This library provides functionality for parsing and handling terminal
+ * escape sequences as well as maintaining terminal state such as styles,
+ * cursor position, screen, scrollback, and more.
+ *
+ * WARNING: This is an incomplete, work-in-progress API. It is not yet
+ * stable and is definitely going to change.
+ */
+
+/**
+ * @mainpage libghostty-vt - Virtual Terminal Emulator Library
+ *
+ * libghostty-vt is a C library which implements a modern terminal emulator,
+ * extracted from the [Ghostty](https://ghostty.org) terminal emulator.
+ *
+ * libghostty-vt contains the logic for handling the core parts of a terminal
+ * emulator: parsing terminal escape sequences, maintaining terminal state,
+ * encoding input events, etc. It can handle scrollback, line wrapping,
+ * reflow on resize, and more.
+ *
+ * @warning This library is currently in development and the API is not yet stable.
+ * Breaking changes are expected in future versions. Use with caution in production code.
+ *
+ * @section groups_sec API Reference
+ *
+ * The API is organized into the following groups:
+ * - @ref terminal "Terminal" - Complete terminal emulator state and rendering
+ * - @ref render "Render State" - Incremental render state updates for custom renderers
+ * - @ref formatter "Formatter" - Format terminal content as plain text, VT sequences, or HTML
+ * - @ref osc "OSC Parser" - Parse OSC (Operating System Command) sequences
+ * - @ref sgr "SGR Parser" - Parse SGR (Select Graphic Rendition) sequences
+ * - @ref paste "Paste Utilities" - Validate paste data safety
+ * - @ref build_info "Build Info" - Query compile-time build configuration
+ * - @ref allocator "Memory Management" - Memory management and custom allocators
+ * - @ref wasm "WebAssembly Utilities" - WebAssembly convenience functions
+ *
+ * Encoding related APIs:
+ * - @ref focus "Focus Encoding" - Encode focus in/out events into terminal sequences
+ * - @ref key "Key Encoding" - Encode key events into terminal sequences
+ * - @ref mouse "Mouse Encoding" - Encode mouse events into terminal sequences
+ *
+ * @section examples_sec Examples
+ *
+ * Complete working examples:
+ * - @ref c-vt-build-info/src/main.c - Build info query example
+ * - @ref c-vt/src/main.c - OSC parser example
+ * - @ref c-vt-encode-key/src/main.c - Key encoding example
+ * - @ref c-vt-encode-mouse/src/main.c - Mouse encoding example
+ * - @ref c-vt-paste/src/main.c - Paste safety check example
+ * - @ref c-vt-sgr/src/main.c - SGR parser example
+ * - @ref c-vt-formatter/src/main.c - Terminal formatter example
+ * - @ref c-vt-grid-traverse/src/main.c - Grid traversal example using grid refs
+ *
+ */
+
+/** @example c-vt-build-info/src/main.c
+ * This example demonstrates how to query compile-time build configuration
+ * such as SIMD support, Kitty graphics, and tmux control mode availability.
+ */
+
+/** @example c-vt/src/main.c
+ * This example demonstrates how to use the OSC parser to parse an OSC sequence,
+ * extract command information, and retrieve command-specific data like window titles.
+ */
+
+/** @example c-vt-encode-key/src/main.c
+ * This example demonstrates how to use the key encoder to convert key events
+ * into terminal escape sequences using the Kitty keyboard protocol.
+ */
+
+/** @example c-vt-encode-mouse/src/main.c
+ * This example demonstrates how to use the mouse encoder to convert mouse events
+ * into terminal escape sequences using the SGR mouse format.
+ */
+
+/** @example c-vt-paste/src/main.c
+ * This example demonstrates how to use the paste utilities to check if
+ * paste data is safe before sending it to the terminal.
+ */
+
+/** @example c-vt-sgr/src/main.c
+ * This example demonstrates how to use the SGR parser to parse terminal
+ * styling sequences and extract text attributes like colors and underline styles.
+ */
+
+/** @example c-vt-formatter/src/main.c
+ * This example demonstrates how to use the terminal and formatter APIs to
+ * create a terminal, write VT-encoded content into it, and format the screen
+ * contents as plain text.
+ */
+
+/** @example c-vt-grid-traverse/src/main.c
+ * This example demonstrates how to traverse the entire terminal grid using
+ * grid refs to inspect cell codepoints, row wrap state, and cell styles.
+ */
+
+#ifndef GHOSTTY_VT_H
+#define GHOSTTY_VT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <ghostty/vt/types.h>
+#include <ghostty/vt/allocator.h>
+#include <ghostty/vt/build_info.h>
+#include <ghostty/vt/color.h>
+#include <ghostty/vt/device.h>
+#include <ghostty/vt/focus.h>
+#include <ghostty/vt/formatter.h>
+#include <ghostty/vt/render.h>
+#include <ghostty/vt/terminal.h>
+#include <ghostty/vt/grid_ref.h>
+#include <ghostty/vt/osc.h>
+#include <ghostty/vt/sgr.h>
+#include <ghostty/vt/style.h>
+#include <ghostty/vt/key.h>
+#include <ghostty/vt/modes.h>
+#include <ghostty/vt/mouse.h>
+#include <ghostty/vt/paste.h>
+#include <ghostty/vt/screen.h>
+#include <ghostty/vt/size_report.h>
+#include <ghostty/vt/wasm.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GHOSTTY_VT_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt/allocator.h b/vendor/libghostty-vt/include/ghostty/vt/allocator.h
new file mode 100644
index 00000000..2e8685e8
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/allocator.h
@@ -0,0 +1,255 @@
+/**
+ * @file allocator.h
+ *
+ * Memory management interface for libghostty-vt.
+ */
+
+#ifndef GHOSTTY_VT_ALLOCATOR_H
+#define GHOSTTY_VT_ALLOCATOR_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <ghostty/vt/types.h>
+
+/** @defgroup allocator Memory Management
+ *
+ * libghostty-vt does require memory allocation for various operations,
+ * but is resilient to allocation failures and will gracefully handle
+ * out-of-memory situations by returning error codes.
+ *
+ * The exact memory management semantics are documented in the relevant
+ * functions and data structures.
+ *
+ * libghostty-vt uses explicit memory allocation via an allocator
+ * interface provided by GhosttyAllocator. The interface is based on the
+ * [Zig](https://ziglang.org) allocator interface, since this has been
+ * shown to be a flexible and powerful interface in practice and enables
+ * a wide variety of allocation strategies.
+ *
+ * **For the common case, you can pass NULL as the allocator for any
+ * function that accepts one,** and libghostty will use a default allocator.
+ * The default allocator will be libc malloc/free if libc is linked.
+ * Otherwise, a custom allocator is used (currently Zig's SMP allocator)
+ * that doesn't require any external dependencies.
+ *
+ * ## Basic Usage
+ *
+ * For simple use cases, you can ignore this interface entirely by passing NULL
+ * as the allocator parameter to functions that accept one. This will use the
+ * default allocator (typically libc malloc/free, if libc is linked, but
+ * we provide our own default allocator if libc isn't linked).
+ *
+ * To use a custom allocator:
+ * 1. Implement the GhosttyAllocatorVtable function pointers
+ * 2. Create a GhosttyAllocator struct with your vtable and context
+ * 3. Pass the allocator to functions that accept one
+ *
+ * ## Alloc/Free Helpers
+ *
+ * ghostty_alloc() and ghostty_free() provide a simple malloc/free-style
+ * interface for allocating and freeing byte buffers through the library's
+ * allocator. These are useful when:
+ *
+ * - You need to allocate a buffer to pass into a libghostty-vt function
+ * (e.g. preparing input data for ghostty_terminal_vt_write()).
+ * - You need to free a buffer returned by a libghostty-vt function
+ * (e.g. the output of ghostty_formatter_format_alloc()).
+ * - You are on a platform where the library's internal allocator differs
+ * from the consumer's C runtime (e.g. Windows, where Zig's libc and
+ * MSVC's CRT maintain separate heaps), so calling the standard C
+ * free() on library-allocated memory would be undefined behavior.
+ *
+ * Always use the same allocator (or NULL) for both the allocation and
+ * the corresponding free.
+ *
+ * @{
+ */
+
+/**
+ * Function table for custom memory allocator operations.
+ *
+ * This vtable defines the interface for a custom memory allocator. All
+ * function pointers must be valid and non-NULL.
+ *
+ * @ingroup allocator
+ *
+ * If you're not going to use a custom allocator, you can ignore all of
+ * this. All functions that take an allocator pointer allow NULL to use a
+ * default allocator.
+ *
+ * The interface is based on the Zig allocator interface. I'll say up front
+ * that it is easy to look at this interface and think "wow, this is really
+ * overcomplicated". The reason for this complexity is well thought out by
+ * the Zig folks, and it enables a diverse set of allocation strategies
+ * as shown by the Zig ecosystem. As a consolation, please note that many
+ * of the arguments are only needed for advanced use cases and can be
+ * safely ignored in simple implementations. For example, if you look at
+ * the Zig implementation of the libc allocator in `lib/std/heap.zig`
+ * (search for CAllocator), you'll see it is very simple.
+ *
+ * We chose to align with the Zig allocator interface because:
+ *
+ * 1. It is a proven interface that serves a wide variety of use cases
+ * in the real world via the Zig ecosystem. It's shown to work.
+ *
+ * 2. Our core implementation itself is Zig, and this lets us very
+ * cheaply and easily convert between C and Zig allocators.
+ *
+ * NOTE(mitchellh): In the future, we can have default implementations of
+ * resize/remap and allow those to be null.
+ */
+typedef struct {
+ /**
+ * Return a pointer to `len` bytes with specified `alignment`, or return
+ * `NULL` indicating the allocation failed.
+ *
+ * @param ctx The allocator context
+ * @param len Number of bytes to allocate
+ * @param alignment Required alignment for the allocation. Guaranteed to
+ * be a power of two between 1 and 16 inclusive.
+ * @param ret_addr First return address of the allocation call stack (0 if not provided)
+ * @return Pointer to allocated memory, or NULL if allocation failed
+ */
+ void* (*alloc)(void *ctx, size_t len, uint8_t alignment, uintptr_t ret_addr);
+
+ /**
+ * Attempt to expand or shrink memory in place.
+ *
+ * `memory_len` must equal the length requested from the most recent
+ * successful call to `alloc`, `resize`, or `remap`. `alignment` must
+ * equal the same value that was passed as the `alignment` parameter to
+ * the original `alloc` call.
+ *
+ * `new_len` must be greater than zero.
+ *
+ * @param ctx The allocator context
+ * @param memory Pointer to the memory block to resize
+ * @param memory_len Current size of the memory block
+ * @param alignment Alignment (must match original allocation)
+ * @param new_len New requested size
+ * @param ret_addr First return address of the allocation call stack (0 if not provided)
+ * @return true if resize was successful in-place, false if relocation would be required
+ */
+ bool (*resize)(void *ctx, void *memory, size_t memory_len, uint8_t alignment, size_t new_len, uintptr_t ret_addr);
+
+ /**
+ * Attempt to expand or shrink memory, allowing relocation.
+ *
+ * `memory_len` must equal the length requested from the most recent
+ * successful call to `alloc`, `resize`, or `remap`. `alignment` must
+ * equal the same value that was passed as the `alignment` parameter to
+ * the original `alloc` call.
+ *
+ * A non-`NULL` return value indicates the resize was successful. The
+ * allocation may have same address, or may have been relocated. In either
+ * case, the allocation now has size of `new_len`. A `NULL` return value
+ * indicates that the resize would be equivalent to allocating new memory,
+ * copying the bytes from the old memory, and then freeing the old memory.
+ * In such case, it is more efficient for the caller to perform the copy.
+ *
+ * `new_len` must be greater than zero.
+ *
+ * @param ctx The allocator context
+ * @param memory Pointer to the memory block to remap
+ * @param memory_len Current size of the memory block
+ * @param alignment Alignment (must match original allocation)
+ * @param new_len New requested size
+ * @param ret_addr First return address of the allocation call stack (0 if not provided)
+ * @return Pointer to resized memory (may be relocated), or NULL if manual copy is needed
+ */
+ void* (*remap)(void *ctx, void *memory, size_t memory_len, uint8_t alignment, size_t new_len, uintptr_t ret_addr);
+
+ /**
+ * Free and invalidate a region of memory.
+ *
+ * `memory_len` must equal the length requested from the most recent
+ * successful call to `alloc`, `resize`, or `remap`. `alignment` must
+ * equal the same value that was passed as the `alignment` parameter to
+ * the original `alloc` call.
+ *
+ * @param ctx The allocator context
+ * @param memory Pointer to the memory block to free
+ * @param memory_len Size of the memory block
+ * @param alignment Alignment (must match original allocation)
+ * @param ret_addr First return address of the allocation call stack (0 if not provided)
+ */
+ void (*free)(void *ctx, void *memory, size_t memory_len, uint8_t alignment, uintptr_t ret_addr);
+} GhosttyAllocatorVtable;
+
+/**
+ * Custom memory allocator.
+ *
+ * For functions that take an allocator pointer, a NULL pointer indicates
+ * that the default allocator should be used. The default allocator will
+ * be libc malloc/free if we're linking to libc. If libc isn't linked,
+ * a custom allocator is used (currently Zig's SMP allocator).
+ *
+ * @ingroup allocator
+ *
+ * Usage example:
+ * @code
+ * GhosttyAllocator allocator = {
+ * .vtable = &my_allocator_vtable,
+ * .ctx = my_allocator_state
+ * };
+ * @endcode
+ */
+typedef struct GhosttyAllocator {
+ /**
+ * Opaque context pointer passed to all vtable functions.
+ * This allows the allocator implementation to maintain state
+ * or reference external resources needed for memory management.
+ */
+ void *ctx;
+
+ /**
+ * Pointer to the allocator's vtable containing function pointers
+ * for memory operations (alloc, resize, remap, free).
+ */
+ const GhosttyAllocatorVtable *vtable;
+} GhosttyAllocator;
+
+/**
+ * Allocate a buffer of `len` bytes.
+ *
+ * Uses the provided allocator, or the default allocator if NULL is passed.
+ * The returned buffer must be freed with ghostty_free() using the same
+ * allocator.
+ *
+ * @param allocator Pointer to the allocator to use, or NULL for the default
+ * @param len Number of bytes to allocate
+ * @return Pointer to the allocated buffer, or NULL if allocation failed
+ *
+ * @ingroup allocator
+ */
+GHOSTTY_API uint8_t* ghostty_alloc(const GhosttyAllocator* allocator, size_t len);
+
+/**
+ * Free memory that was allocated by a libghostty-vt function.
+ *
+ * Use this to free buffers returned by functions such as
+ * ghostty_formatter_format_alloc(). Pass the same allocator that was
+ * used for the allocation, or NULL if the default allocator was used.
+ *
+ * On platforms where the library's internal allocator differs from the
+ * consumer's C runtime (e.g. Windows, where Zig's libc and MSVC's CRT
+ * maintain separate heaps), calling the standard C free() on memory
+ * allocated by the library causes undefined behavior. This function
+ * guarantees the correct allocator is used regardless of platform.
+ *
+ * It is safe to pass a NULL pointer; the call is a no-op in that case.
+ *
+ * @param allocator Pointer to the allocator that was used to allocate the
+ * memory, or NULL if the default allocator was used
+ * @param ptr Pointer to the memory to free (may be NULL)
+ * @param len Length of the allocation in bytes (must match the original
+ * allocation size)
+ *
+ * @ingroup allocator
+ */
+GHOSTTY_API void ghostty_free(const GhosttyAllocator* allocator, uint8_t* ptr, size_t len);
+
+/** @} */
+
+#endif /* GHOSTTY_VT_ALLOCATOR_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt/build_info.h b/vendor/libghostty-vt/include/ghostty/vt/build_info.h
new file mode 100644
index 00000000..7f77a769
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/build_info.h
@@ -0,0 +1,140 @@
+/**
+ * @file build_info.h
+ *
+ * Build info - query compile-time build configuration of libghostty-vt.
+ */
+
+#ifndef GHOSTTY_VT_BUILD_INFO_H
+#define GHOSTTY_VT_BUILD_INFO_H
+
+/** @defgroup build_info Build Info
+ *
+ * Query compile-time build configuration of libghostty-vt.
+ *
+ * These values reflect the options the library was built with and are
+ * constant for the lifetime of the process.
+ *
+ * ## Basic Usage
+ *
+ * Use ghostty_build_info() to query individual build options:
+ *
+ * @snippet c-vt-build-info/src/main.c build-info-query
+ *
+ * @{
+ */
+
+#include <stddef.h>
+#include <stdbool.h>
+
+#include <ghostty/vt/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Build optimization mode.
+ */
+typedef enum {
+ GHOSTTY_OPTIMIZE_DEBUG = 0,
+ GHOSTTY_OPTIMIZE_RELEASE_SAFE = 1,
+ GHOSTTY_OPTIMIZE_RELEASE_SMALL = 2,
+ GHOSTTY_OPTIMIZE_RELEASE_FAST = 3,
+} GhosttyOptimizeMode;
+
+/**
+ * Build info data types that can be queried.
+ *
+ * Each variant documents the expected output pointer type.
+ */
+typedef enum {
+ /** Invalid data type. Never results in any data extraction. */
+ GHOSTTY_BUILD_INFO_INVALID = 0,
+
+ /**
+ * Whether SIMD-accelerated code paths are enabled.
+ *
+ * Output type: bool *
+ */
+ GHOSTTY_BUILD_INFO_SIMD = 1,
+
+ /**
+ * Whether Kitty graphics protocol support is available.
+ *
+ * Output type: bool *
+ */
+ GHOSTTY_BUILD_INFO_KITTY_GRAPHICS = 2,
+
+ /**
+ * Whether tmux control mode support is available.
+ *
+ * Output type: bool *
+ */
+ GHOSTTY_BUILD_INFO_TMUX_CONTROL_MODE = 3,
+
+ /**
+ * The optimization mode the library was built with.
+ *
+ * Output type: GhosttyOptimizeMode *
+ */
+ GHOSTTY_BUILD_INFO_OPTIMIZE = 4,
+
+ /**
+ * The full version string (e.g. "1.2.3" or "1.2.3-dev+abcdef").
+ *
+ * Output type: GhosttyString *
+ */
+ GHOSTTY_BUILD_INFO_VERSION_STRING = 5,
+
+ /**
+ * The major version number.
+ *
+ * Output type: size_t *
+ */
+ GHOSTTY_BUILD_INFO_VERSION_MAJOR = 6,
+
+ /**
+ * The minor version number.
+ *
+ * Output type: size_t *
+ */
+ GHOSTTY_BUILD_INFO_VERSION_MINOR = 7,
+
+ /**
+ * The patch version number.
+ *
+ * Output type: size_t *
+ */
+ GHOSTTY_BUILD_INFO_VERSION_PATCH = 8,
+
+ /**
+ * The build metadata string (e.g. commit hash). Has zero length if
+ * no build metadata is present.
+ *
+ * Output type: GhosttyString *
+ */
+ GHOSTTY_BUILD_INFO_VERSION_BUILD = 9,
+} GhosttyBuildInfo;
+
+/**
+ * Query a compile-time build configuration value.
+ *
+ * The caller must pass a pointer to the correct output type for the
+ * requested data (see GhosttyBuildInfo variants for types).
+ *
+ * @param data The build info field to query
+ * @param out Pointer to store the result (type depends on data parameter)
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if the
+ * data type is invalid
+ *
+ * @ingroup build_info
+ */
+GHOSTTY_API GhosttyResult ghostty_build_info(GhosttyBuildInfo data, void *out);
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif /* GHOSTTY_VT_BUILD_INFO_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt/color.h b/vendor/libghostty-vt/include/ghostty/vt/color.h
new file mode 100644
index 00000000..9dc21864
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/color.h
@@ -0,0 +1,97 @@
+/**
+ * @file color.h
+ *
+ * Color types and utilities.
+ */
+
+#ifndef GHOSTTY_VT_COLOR_H
+#define GHOSTTY_VT_COLOR_H
+
+#include <stdint.h>
+#include <ghostty/vt/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * RGB color value.
+ *
+ * @ingroup sgr
+ */
+typedef struct {
+ uint8_t r; /**< Red component (0-255) */
+ uint8_t g; /**< Green component (0-255) */
+ uint8_t b; /**< Blue component (0-255) */
+} GhosttyColorRgb;
+
+/**
+ * Palette color index (0-255).
+ *
+ * @ingroup sgr
+ */
+typedef uint8_t GhosttyColorPaletteIndex;
+
+/** @addtogroup sgr
+ * @{
+ */
+
+/** Black color (0) @ingroup sgr */
+#define GHOSTTY_COLOR_NAMED_BLACK 0
+/** Red color (1) @ingroup sgr */
+#define GHOSTTY_COLOR_NAMED_RED 1
+/** Green color (2) @ingroup sgr */
+#define GHOSTTY_COLOR_NAMED_GREEN 2
+/** Yellow color (3) @ingroup sgr */
+#define GHOSTTY_COLOR_NAMED_YELLOW 3
+/** Blue color (4) @ingroup sgr */
+#define GHOSTTY_COLOR_NAMED_BLUE 4
+/** Magenta color (5) @ingroup sgr */
+#define GHOSTTY_COLOR_NAMED_MAGENTA 5
+/** Cyan color (6) @ingroup sgr */
+#define GHOSTTY_COLOR_NAMED_CYAN 6
+/** White color (7) @ingroup sgr */
+#define GHOSTTY_COLOR_NAMED_WHITE 7
+/** Bright black color (8) @ingroup sgr */
+#define GHOSTTY_COLOR_NAMED_BRIGHT_BLACK 8
+/** Bright red color (9) @ingroup sgr */
+#define GHOSTTY_COLOR_NAMED_BRIGHT_RED 9
+/** Bright green color (10) @ingroup sgr */
+#define GHOSTTY_COLOR_NAMED_BRIGHT_GREEN 10
+/** Bright yellow color (11) @ingroup sgr */
+#define GHOSTTY_COLOR_NAMED_BRIGHT_YELLOW 11
+/** Bright blue color (12) @ingroup sgr */
+#define GHOSTTY_COLOR_NAMED_BRIGHT_BLUE 12
+/** Bright magenta color (13) @ingroup sgr */
+#define GHOSTTY_COLOR_NAMED_BRIGHT_MAGENTA 13
+/** Bright cyan color (14) @ingroup sgr */
+#define GHOSTTY_COLOR_NAMED_BRIGHT_CYAN 14
+/** Bright white color (15) @ingroup sgr */
+#define GHOSTTY_COLOR_NAMED_BRIGHT_WHITE 15
+
+/** @} */
+
+/**
+ * Get the RGB color components.
+ *
+ * This function extracts the individual red, green, and blue components
+ * from a GhosttyColorRgb value. Primarily useful in WebAssembly environments
+ * where accessing struct fields directly is difficult.
+ *
+ * @param color The RGB color value
+ * @param r Pointer to store the red component (0-255)
+ * @param g Pointer to store the green component (0-255)
+ * @param b Pointer to store the blue component (0-255)
+ *
+ * @ingroup sgr
+ */
+GHOSTTY_API void ghostty_color_rgb_get(GhosttyColorRgb color,
+ uint8_t* r,
+ uint8_t* g,
+ uint8_t* b);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GHOSTTY_VT_COLOR_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt/device.h b/vendor/libghostty-vt/include/ghostty/vt/device.h
new file mode 100644
index 00000000..fdf6bca7
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/device.h
@@ -0,0 +1,150 @@
+/**
+ * @file device.h
+ *
+ * Device types used by the terminal for device status and device attribute
+ * queries.
+ */
+
+#ifndef GHOSTTY_VT_DEVICE_H
+#define GHOSTTY_VT_DEVICE_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+/* DA1 conformance levels (Pp parameter). */
+#define GHOSTTY_DA_CONFORMANCE_VT100 1
+#define GHOSTTY_DA_CONFORMANCE_VT101 1
+#define GHOSTTY_DA_CONFORMANCE_VT102 6
+#define GHOSTTY_DA_CONFORMANCE_VT125 12
+#define GHOSTTY_DA_CONFORMANCE_VT131 7
+#define GHOSTTY_DA_CONFORMANCE_VT132 4
+#define GHOSTTY_DA_CONFORMANCE_VT220 62
+#define GHOSTTY_DA_CONFORMANCE_VT240 62
+#define GHOSTTY_DA_CONFORMANCE_VT320 63
+#define GHOSTTY_DA_CONFORMANCE_VT340 63
+#define GHOSTTY_DA_CONFORMANCE_VT420 64
+#define GHOSTTY_DA_CONFORMANCE_VT510 65
+#define GHOSTTY_DA_CONFORMANCE_VT520 65
+#define GHOSTTY_DA_CONFORMANCE_VT525 65
+#define GHOSTTY_DA_CONFORMANCE_LEVEL_2 62
+#define GHOSTTY_DA_CONFORMANCE_LEVEL_3 63
+#define GHOSTTY_DA_CONFORMANCE_LEVEL_4 64
+#define GHOSTTY_DA_CONFORMANCE_LEVEL_5 65
+
+/* DA1 feature codes (Ps parameters). */
+#define GHOSTTY_DA_FEATURE_COLUMNS_132 1
+#define GHOSTTY_DA_FEATURE_PRINTER 2
+#define GHOSTTY_DA_FEATURE_REGIS 3
+#define GHOSTTY_DA_FEATURE_SIXEL 4
+#define GHOSTTY_DA_FEATURE_SELECTIVE_ERASE 6
+#define GHOSTTY_DA_FEATURE_USER_DEFINED_KEYS 8
+#define GHOSTTY_DA_FEATURE_NATIONAL_REPLACEMENT 9
+#define GHOSTTY_DA_FEATURE_TECHNICAL_CHARACTERS 15
+#define GHOSTTY_DA_FEATURE_LOCATOR 16
+#define GHOSTTY_DA_FEATURE_TERMINAL_STATE 17
+#define GHOSTTY_DA_FEATURE_WINDOWING 18
+#define GHOSTTY_DA_FEATURE_HORIZONTAL_SCROLLING 21
+#define GHOSTTY_DA_FEATURE_ANSI_COLOR 22
+#define GHOSTTY_DA_FEATURE_RECTANGULAR_EDITING 28
+#define GHOSTTY_DA_FEATURE_ANSI_TEXT_LOCATOR 29
+#define GHOSTTY_DA_FEATURE_CLIPBOARD 52
+
+/* DA2 device type identifiers (Pp parameter). */
+#define GHOSTTY_DA_DEVICE_TYPE_VT100 0
+#define GHOSTTY_DA_DEVICE_TYPE_VT220 1
+#define GHOSTTY_DA_DEVICE_TYPE_VT240 2
+#define GHOSTTY_DA_DEVICE_TYPE_VT330 18
+#define GHOSTTY_DA_DEVICE_TYPE_VT340 19
+#define GHOSTTY_DA_DEVICE_TYPE_VT320 24
+#define GHOSTTY_DA_DEVICE_TYPE_VT382 32
+#define GHOSTTY_DA_DEVICE_TYPE_VT420 41
+#define GHOSTTY_DA_DEVICE_TYPE_VT510 61
+#define GHOSTTY_DA_DEVICE_TYPE_VT520 64
+#define GHOSTTY_DA_DEVICE_TYPE_VT525 65
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Color scheme reported in response to a CSI ? 996 n query.
+ *
+ * @ingroup terminal
+ */
+typedef enum {
+ GHOSTTY_COLOR_SCHEME_LIGHT = 0,
+ GHOSTTY_COLOR_SCHEME_DARK = 1,
+} GhosttyColorScheme;
+
+/**
+ * Primary device attributes (DA1) response data.
+ *
+ * Returned as part of GhosttyDeviceAttributes in response to a CSI c query.
+ * The conformance_level is the Pp parameter and features contains the Ps
+ * feature codes.
+ *
+ * @ingroup terminal
+ */
+typedef struct {
+ /** Conformance level (Pp parameter). E.g. 62 for VT220. */
+ uint16_t conformance_level;
+
+ /** DA1 feature codes. Only the first num_features entries are valid. */
+ uint16_t features[64];
+
+ /** Number of valid entries in the features array. */
+ size_t num_features;
+} GhosttyDeviceAttributesPrimary;
+
+/**
+ * Secondary device attributes (DA2) response data.
+ *
+ * Returned as part of GhosttyDeviceAttributes in response to a CSI > c query.
+ * Response format: CSI > Pp ; Pv ; Pc c
+ *
+ * @ingroup terminal
+ */
+typedef struct {
+ /** Terminal type identifier (Pp). E.g. 1 for VT220. */
+ uint16_t device_type;
+
+ /** Firmware/patch version number (Pv). */
+ uint16_t firmware_version;
+
+ /** ROM cartridge registration number (Pc). Always 0 for emulators. */
+ uint16_t rom_cartridge;
+} GhosttyDeviceAttributesSecondary;
+
+/**
+ * Tertiary device attributes (DA3) response data.
+ *
+ * Returned as part of GhosttyDeviceAttributes in response to a CSI = c query.
+ * Response format: DCS ! | D...D ST (DECRPTUI).
+ *
+ * @ingroup terminal
+ */
+typedef struct {
+ /** Unit ID encoded as 8 uppercase hex digits in the response. */
+ uint32_t unit_id;
+} GhosttyDeviceAttributesTertiary;
+
+/**
+ * Device attributes response data for all three DA levels.
+ *
+ * Filled by the device_attributes callback in response to CSI c,
+ * CSI > c, or CSI = c queries. The terminal uses whichever sub-struct
+ * matches the request type.
+ *
+ * @ingroup terminal
+ */
+typedef struct {
+ GhosttyDeviceAttributesPrimary primary;
+ GhosttyDeviceAttributesSecondary secondary;
+ GhosttyDeviceAttributesTertiary tertiary;
+} GhosttyDeviceAttributes;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GHOSTTY_VT_DEVICE_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt/focus.h b/vendor/libghostty-vt/include/ghostty/vt/focus.h
new file mode 100644
index 00000000..6e4c9502
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/focus.h
@@ -0,0 +1,75 @@
+/**
+ * @file focus.h
+ *
+ * Focus encoding - encode focus in/out events into terminal escape sequences.
+ */
+
+#ifndef GHOSTTY_VT_FOCUS_H
+#define GHOSTTY_VT_FOCUS_H
+
+/** @defgroup focus Focus Encoding
+ *
+ * Utilities for encoding focus gained/lost events into terminal escape
+ * sequences (CSI I / CSI O) for focus reporting mode (mode 1004).
+ *
+ * ## Basic Usage
+ *
+ * Use ghostty_focus_encode() to encode a focus event into a caller-provided
+ * buffer. If the buffer is too small, the function returns
+ * GHOSTTY_OUT_OF_SPACE and sets the required size in the output parameter.
+ *
+ * ## Example
+ *
+ * @snippet c-vt-encode-focus/src/main.c focus-encode
+ *
+ * @{
+ */
+
+#include <stddef.h>
+#include <ghostty/vt/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Focus event types for focus reporting mode (mode 1004).
+ */
+typedef enum {
+ /** Terminal window gained focus */
+ GHOSTTY_FOCUS_GAINED = 0,
+ /** Terminal window lost focus */
+ GHOSTTY_FOCUS_LOST = 1,
+} GhosttyFocusEvent;
+
+/**
+ * Encode a focus event into a terminal escape sequence.
+ *
+ * Encodes a focus gained (CSI I) or focus lost (CSI O) report into the
+ * provided buffer.
+ *
+ * If the buffer is too small, the function returns GHOSTTY_OUT_OF_SPACE
+ * and writes the required buffer size to @p out_written. The caller can
+ * then retry with a sufficiently sized buffer.
+ *
+ * @param event The focus event to encode
+ * @param buf Output buffer to write the encoded sequence into (may be NULL)
+ * @param buf_len Size of the output buffer in bytes
+ * @param[out] out_written On success, the number of bytes written. On
+ * GHOSTTY_OUT_OF_SPACE, the required buffer size.
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_OUT_OF_SPACE if the buffer
+ * is too small
+ */
+GHOSTTY_API GhosttyResult ghostty_focus_encode(
+ GhosttyFocusEvent event,
+ char* buf,
+ size_t buf_len,
+ size_t* out_written);
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif /* GHOSTTY_VT_FOCUS_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt/formatter.h b/vendor/libghostty-vt/include/ghostty/vt/formatter.h
new file mode 100644
index 00000000..81efdb27
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/formatter.h
@@ -0,0 +1,225 @@
+/**
+ * @file formatter.h
+ *
+ * Format terminal content as plain text, VT sequences, or HTML.
+ */
+
+#ifndef GHOSTTY_VT_FORMATTER_H
+#define GHOSTTY_VT_FORMATTER_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <ghostty/vt/allocator.h>
+#include <ghostty/vt/types.h>
+#include <ghostty/vt/terminal.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup formatter Formatter
+ *
+ * Format terminal content as plain text, VT sequences, or HTML.
+ *
+ * A formatter captures a reference to a terminal and formatting options.
+ * It can be used repeatedly to produce output that reflects the current
+ * terminal state at the time of each format call.
+ *
+ * The terminal must outlive the formatter.
+ *
+ * @{
+ */
+
+/**
+ * Output format.
+ *
+ * @ingroup formatter
+ */
+typedef enum {
+ /** Plain text (no escape sequences). */
+ GHOSTTY_FORMATTER_FORMAT_PLAIN,
+
+ /** VT sequences preserving colors, styles, URLs, etc. */
+ GHOSTTY_FORMATTER_FORMAT_VT,
+
+ /** HTML with inline styles. */
+ GHOSTTY_FORMATTER_FORMAT_HTML,
+} GhosttyFormatterFormat;
+
+/**
+ * Extra screen state to include in styled output.
+ *
+ * @ingroup formatter
+ */
+typedef struct {
+ /** Size of this struct in bytes. Must be set to sizeof(GhosttyFormatterScreenExtra). */
+ size_t size;
+
+ /** Emit cursor position using CUP (CSI H). */
+ bool cursor;
+
+ /** Emit current SGR style state based on the cursor's active style_id. */
+ bool style;
+
+ /** Emit current hyperlink state using OSC 8 sequences. */
+ bool hyperlink;
+
+ /** Emit character protection mode using DECSCA. */
+ bool protection;
+
+ /** Emit Kitty keyboard protocol state using CSI > u and CSI = sequences. */
+ bool kitty_keyboard;
+
+ /** Emit character set designations and invocations. */
+ bool charsets;
+} GhosttyFormatterScreenExtra;
+
+/**
+ * Extra terminal state to include in styled output.
+ *
+ * @ingroup formatter
+ */
+typedef struct {
+ /** Size of this struct in bytes. Must be set to sizeof(GhosttyFormatterTerminalExtra). */
+ size_t size;
+
+ /** Emit the palette using OSC 4 sequences. */
+ bool palette;
+
+ /** Emit terminal modes that differ from their defaults using CSI h/l. */
+ bool modes;
+
+ /** Emit scrolling region state using DECSTBM and DECSLRM sequences. */
+ bool scrolling_region;
+
+ /** Emit tabstop positions by clearing all tabs and setting each one. */
+ bool tabstops;
+
+ /** Emit the present working directory using OSC 7. */
+ bool pwd;
+
+ /** Emit keyboard modes such as ModifyOtherKeys. */
+ bool keyboard;
+
+ /** Screen-level extras. */
+ GhosttyFormatterScreenExtra screen;
+} GhosttyFormatterTerminalExtra;
+
+/**
+ * Opaque handle to a formatter instance.
+ *
+ * @ingroup formatter
+ */
+typedef struct GhosttyFormatterImpl* GhosttyFormatter;
+
+/**
+ * Options for creating a terminal formatter.
+ *
+ * @ingroup formatter
+ */
+typedef struct {
+ /** Size of this struct in bytes. Must be set to sizeof(GhosttyFormatterTerminalOptions). */
+ size_t size;
+
+ /** Output format to emit. */
+ GhosttyFormatterFormat emit;
+
+ /** Whether to unwrap soft-wrapped lines. */
+ bool unwrap;
+
+ /** Whether to trim trailing whitespace on non-blank lines. */
+ bool trim;
+
+ /** Extra terminal state to include in styled output. */
+ GhosttyFormatterTerminalExtra extra;
+} GhosttyFormatterTerminalOptions;
+
+/**
+ * Create a formatter for a terminal's active screen.
+ *
+ * The terminal must outlive the formatter. The formatter stores a borrowed
+ * reference to the terminal and reads its current state on each format call.
+ *
+ * @param allocator Pointer to allocator, or NULL to use the default allocator
+ * @param formatter Pointer to store the created formatter handle
+ * @param terminal The terminal to format (must not be NULL)
+ * @param options Formatting options
+ * @return GHOSTTY_SUCCESS on success, or an error code on failure
+ *
+ * @ingroup formatter
+ */
+GHOSTTY_API GhosttyResult ghostty_formatter_terminal_new(
+ const GhosttyAllocator* allocator,
+ GhosttyFormatter* formatter,
+ GhosttyTerminal terminal,
+ GhosttyFormatterTerminalOptions options);
+
+/**
+ * Run the formatter and produce output into the caller-provided buffer.
+ *
+ * Each call formats the current terminal state. Pass NULL for buf to
+ * query the required buffer size without writing any output; in that case
+ * out_written receives the required size and the return value is
+ * GHOSTTY_OUT_OF_SPACE.
+ *
+ * If the buffer is too small, returns GHOSTTY_OUT_OF_SPACE and sets
+ * out_written to the required size. The caller can then retry with a
+ * larger buffer.
+ *
+ * @param formatter The formatter handle (must not be NULL)
+ * @param buf Pointer to the output buffer, or NULL to query size
+ * @param buf_len Length of the output buffer in bytes
+ * @param out_written Pointer to receive the number of bytes written,
+ * or the required size on failure
+ * @return GHOSTTY_SUCCESS on success, or an error code on failure
+ *
+ * @ingroup formatter
+ */
+GHOSTTY_API GhosttyResult ghostty_formatter_format_buf(GhosttyFormatter formatter,
+ uint8_t* buf,
+ size_t buf_len,
+ size_t* out_written);
+
+/**
+ * Run the formatter and return an allocated buffer with the output.
+ *
+ * Each call formats the current terminal state. The buffer is allocated
+ * using the provided allocator (or the default allocator if NULL).
+ * The caller is responsible for freeing the returned buffer with
+ * ghostty_free(), passing the same allocator (or NULL for the default)
+ * that was used for the allocation.
+ *
+ * @param formatter The formatter handle (must not be NULL)
+ * @param allocator Pointer to allocator, or NULL to use the default allocator
+ * @param out_ptr Pointer to receive the allocated buffer
+ * @param out_len Pointer to receive the length of the output in bytes
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_OUT_OF_MEMORY on allocation
+ * failure
+ *
+ * @ingroup formatter
+ */
+GHOSTTY_API GhosttyResult ghostty_formatter_format_alloc(GhosttyFormatter formatter,
+ const GhosttyAllocator* allocator,
+ uint8_t** out_ptr,
+ size_t* out_len);
+
+/**
+ * Free a formatter instance.
+ *
+ * Releases all resources associated with the formatter. After this call,
+ * the formatter handle becomes invalid.
+ *
+ * @param formatter The formatter handle to free (may be NULL)
+ *
+ * @ingroup formatter
+ */
+GHOSTTY_API void ghostty_formatter_free(GhosttyFormatter formatter);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GHOSTTY_VT_FORMATTER_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt/grid_ref.h b/vendor/libghostty-vt/include/ghostty/vt/grid_ref.h
new file mode 100644
index 00000000..d3489ea7
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/grid_ref.h
@@ -0,0 +1,131 @@
+/**
+ * @file grid_ref.h
+ *
+ * Terminal grid reference type for referencing a resolved position in the
+ * terminal grid.
+ */
+
+#ifndef GHOSTTY_VT_GRID_REF_H
+#define GHOSTTY_VT_GRID_REF_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <ghostty/vt/types.h>
+#include <ghostty/vt/screen.h>
+#include <ghostty/vt/style.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup grid_ref Grid Reference
+ *
+ * A grid reference is a resolved reference to a specific cell position in the
+ * terminal's internal page structure. Obtain a grid reference from
+ * ghostty_terminal_grid_ref(), then extract the cell or row via
+ * ghostty_grid_ref_cell() and ghostty_grid_ref_row().
+ *
+ * A grid reference is only valid until the next update to the terminal
+ * instance. There is no guarantee that a grid reference will remain
+ * valid after ANY operation, even if a seemingly unrelated part of
+ * the grid is changed, so any information related to the grid reference
+ * should be read and cached immediately after obtaining the grid reference.
+ *
+ * This API is not meant to be used as the core of render loop. It isn't
+ * built to sustain the framerates needed for rendering large screens.
+ * Use the render state API for that.
+ *
+ * ## Example
+ *
+ * @snippet c-vt-grid-traverse/src/main.c grid-ref-traverse
+ *
+ * @{
+ */
+
+/**
+ * A resolved reference to a terminal cell position.
+ *
+ * This is a sized struct. Use GHOSTTY_INIT_SIZED() to initialize it.
+ *
+ * @ingroup grid_ref
+ */
+typedef struct {
+ size_t size;
+ void *node;
+ uint16_t x;
+ uint16_t y;
+} GhosttyGridRef;
+
+/**
+ * Get the cell from a grid reference.
+ *
+ * @param ref Pointer to the grid reference
+ * @param[out] out_cell On success, set to the cell at the ref's position (may be NULL)
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if the ref's
+ * node is NULL
+ *
+ * @ingroup grid_ref
+ */
+GHOSTTY_API GhosttyResult ghostty_grid_ref_cell(const GhosttyGridRef *ref,
+ GhosttyCell *out_cell);
+
+/**
+ * Get the row from a grid reference.
+ *
+ * @param ref Pointer to the grid reference
+ * @param[out] out_row On success, set to the row at the ref's position (may be NULL)
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if the ref's
+ * node is NULL
+ *
+ * @ingroup grid_ref
+ */
+GHOSTTY_API GhosttyResult ghostty_grid_ref_row(const GhosttyGridRef *ref,
+ GhosttyRow *out_row);
+
+/**
+ * Get the grapheme cluster codepoints for the cell at the grid reference's
+ * position.
+ *
+ * Writes the full grapheme cluster (the cell's primary codepoint followed by
+ * any combining codepoints) into the provided buffer. If the cell has no text,
+ * out_len is set to 0 and GHOSTTY_SUCCESS is returned.
+ *
+ * If the buffer is too small (or NULL), the function returns
+ * GHOSTTY_OUT_OF_SPACE and writes the required number of codepoints to
+ * out_len. The caller can then retry with a sufficiently sized buffer.
+ *
+ * @param ref Pointer to the grid reference
+ * @param buf Output buffer of uint32_t codepoints (may be NULL)
+ * @param buf_len Number of uint32_t elements in the buffer
+ * @param[out] out_len On success, the number of codepoints written. On
+ * GHOSTTY_OUT_OF_SPACE, the required buffer size in codepoints.
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if the ref's
+ * node is NULL, GHOSTTY_OUT_OF_SPACE if the buffer is too small
+ *
+ * @ingroup grid_ref
+ */
+GHOSTTY_API GhosttyResult ghostty_grid_ref_graphemes(const GhosttyGridRef *ref,
+ uint32_t *buf,
+ size_t buf_len,
+ size_t *out_len);
+
+/**
+ * Get the style of the cell at the grid reference's position.
+ *
+ * @param ref Pointer to the grid reference
+ * @param[out] out_style On success, set to the cell's style (may be NULL)
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if the ref's
+ * node is NULL
+ *
+ * @ingroup grid_ref
+ */
+GHOSTTY_API GhosttyResult ghostty_grid_ref_style(const GhosttyGridRef *ref,
+ GhosttyStyle *out_style);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GHOSTTY_VT_GRID_REF_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt/key.h b/vendor/libghostty-vt/include/ghostty/vt/key.h
new file mode 100644
index 00000000..61b95475
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/key.h
@@ -0,0 +1,73 @@
+/**
+ * @file key.h
+ *
+ * Key encoding module - encode key events into terminal escape sequences.
+ */
+
+#ifndef GHOSTTY_VT_KEY_H
+#define GHOSTTY_VT_KEY_H
+
+/** @defgroup key Key Encoding
+ *
+ * Utilities for encoding key events into terminal escape sequences,
+ * supporting both legacy encoding as well as Kitty Keyboard Protocol.
+ *
+ * ## Basic Usage
+ *
+ * 1. Create an encoder instance with ghostty_key_encoder_new()
+ * 2. Configure encoder options with ghostty_key_encoder_setopt()
+ * or ghostty_key_encoder_setopt_from_terminal() if you have a
+ * GhosttyTerminal.
+ * 3. For each key event:
+ * - Create a key event with ghostty_key_event_new()
+ * - Set event properties (action, key, modifiers, etc.)
+ * - Encode with ghostty_key_encoder_encode()
+ * - Free the event with ghostty_key_event_free()
+ * - Note: You can also reuse the same key event multiple times by
+ * changing its properties.
+ * 4. Free the encoder with ghostty_key_encoder_free() when done
+ *
+ * For a complete working example, see example/c-vt-encode-key in the
+ * repository.
+ *
+ * ## Example
+ *
+ * @snippet c-vt-encode-key/src/main.c key-encode
+ *
+ * ## Example: Encoding with Terminal State
+ *
+ * When you have a GhosttyTerminal, you can sync its modes (cursor key
+ * application, Kitty flags, etc.) into the encoder automatically:
+ *
+ * @code{.c}
+ * // Create a terminal and feed it some VT data that changes modes
+ * GhosttyTerminal terminal;
+ * ghostty_terminal_new(NULL, &terminal,
+ * (GhosttyTerminalOptions){.cols = 80, .rows = 24, .max_scrollback = 0});
+ *
+ * // Application might write data that enables Kitty keyboard protocol, etc.
+ * ghostty_terminal_vt_write(terminal, vt_data, vt_len);
+ *
+ * // Create an encoder and sync its options from the terminal
+ * GhosttyKeyEncoder encoder;
+ * ghostty_key_encoder_new(NULL, &encoder);
+ * ghostty_key_encoder_setopt_from_terminal(encoder, terminal);
+ *
+ * // Encode a key event using the terminal-derived options
+ * char buf[128];
+ * size_t written = 0;
+ * ghostty_key_encoder_encode(encoder, event, buf, sizeof(buf), &written);
+ *
+ * ghostty_key_encoder_free(encoder);
+ * ghostty_terminal_free(terminal);
+ * @endcode
+ *
+ * @{
+ */
+
+#include <ghostty/vt/key/event.h>
+#include <ghostty/vt/key/encoder.h>
+
+/** @} */
+
+#endif /* GHOSTTY_VT_KEY_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt/key/encoder.h b/vendor/libghostty-vt/include/ghostty/vt/key/encoder.h
new file mode 100644
index 00000000..9d8282ce
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/key/encoder.h
@@ -0,0 +1,245 @@
+/**
+ * @file encoder.h
+ *
+ * Key event encoding to terminal escape sequences.
+ */
+
+#ifndef GHOSTTY_VT_KEY_ENCODER_H
+#define GHOSTTY_VT_KEY_ENCODER_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <ghostty/vt/types.h>
+#include <ghostty/vt/allocator.h>
+#include <ghostty/vt/terminal.h>
+#include <ghostty/vt/key/event.h>
+
+/**
+ * Opaque handle to a key encoder instance.
+ *
+ * This handle represents a key encoder that converts key events into terminal
+ * escape sequences.
+ *
+ * @ingroup key
+ */
+typedef struct GhosttyKeyEncoderImpl *GhosttyKeyEncoder;
+
+/**
+ * Kitty keyboard protocol flags.
+ *
+ * Bitflags representing the various modes of the Kitty keyboard protocol.
+ * These can be combined using bitwise OR operations. Valid values all
+ * start with `GHOSTTY_KITTY_KEY_`.
+ *
+ * @ingroup key
+ */
+typedef uint8_t GhosttyKittyKeyFlags;
+
+/** Kitty keyboard protocol disabled (all flags off) */
+#define GHOSTTY_KITTY_KEY_DISABLED 0
+
+/** Disambiguate escape codes */
+#define GHOSTTY_KITTY_KEY_DISAMBIGUATE (1 << 0)
+
+/** Report key press and release events */
+#define GHOSTTY_KITTY_KEY_REPORT_EVENTS (1 << 1)
+
+/** Report alternate key codes */
+#define GHOSTTY_KITTY_KEY_REPORT_ALTERNATES (1 << 2)
+
+/** Report all key events including those normally handled by the terminal */
+#define GHOSTTY_KITTY_KEY_REPORT_ALL (1 << 3)
+
+/** Report associated text with key events */
+#define GHOSTTY_KITTY_KEY_REPORT_ASSOCIATED (1 << 4)
+
+/** All Kitty keyboard protocol flags enabled */
+#define GHOSTTY_KITTY_KEY_ALL (GHOSTTY_KITTY_KEY_DISAMBIGUATE | GHOSTTY_KITTY_KEY_REPORT_EVENTS | GHOSTTY_KITTY_KEY_REPORT_ALTERNATES | GHOSTTY_KITTY_KEY_REPORT_ALL | GHOSTTY_KITTY_KEY_REPORT_ASSOCIATED)
+
+/**
+ * macOS option key behavior.
+ *
+ * Determines whether the "option" key on macOS is treated as "alt" or not.
+ * See the Ghostty `macos-option-as-alt` configuration option for more details.
+ *
+ * @ingroup key
+ */
+typedef enum {
+ /** Option key is not treated as alt */
+ GHOSTTY_OPTION_AS_ALT_FALSE = 0,
+ /** Option key is treated as alt */
+ GHOSTTY_OPTION_AS_ALT_TRUE = 1,
+ /** Only left option key is treated as alt */
+ GHOSTTY_OPTION_AS_ALT_LEFT = 2,
+ /** Only right option key is treated as alt */
+ GHOSTTY_OPTION_AS_ALT_RIGHT = 3,
+} GhosttyOptionAsAlt;
+
+/**
+ * Key encoder option identifiers.
+ *
+ * These values are used with ghostty_key_encoder_setopt() to configure
+ * the behavior of the key encoder.
+ *
+ * @ingroup key
+ */
+typedef enum {
+ /** Terminal DEC mode 1: cursor key application mode (value: bool) */
+ GHOSTTY_KEY_ENCODER_OPT_CURSOR_KEY_APPLICATION = 0,
+
+ /** Terminal DEC mode 66: keypad key application mode (value: bool) */
+ GHOSTTY_KEY_ENCODER_OPT_KEYPAD_KEY_APPLICATION = 1,
+
+ /** Terminal DEC mode 1035: ignore keypad with numlock (value: bool) */
+ GHOSTTY_KEY_ENCODER_OPT_IGNORE_KEYPAD_WITH_NUMLOCK = 2,
+
+ /** Terminal DEC mode 1036: alt sends escape prefix (value: bool) */
+ GHOSTTY_KEY_ENCODER_OPT_ALT_ESC_PREFIX = 3,
+
+ /** xterm modifyOtherKeys mode 2 (value: bool) */
+ GHOSTTY_KEY_ENCODER_OPT_MODIFY_OTHER_KEYS_STATE_2 = 4,
+
+ /** Kitty keyboard protocol flags (value: GhosttyKittyKeyFlags bitmask) */
+ GHOSTTY_KEY_ENCODER_OPT_KITTY_FLAGS = 5,
+
+ /** macOS option-as-alt setting (value: GhosttyOptionAsAlt) */
+ GHOSTTY_KEY_ENCODER_OPT_MACOS_OPTION_AS_ALT = 6,
+} GhosttyKeyEncoderOption;
+
+/**
+ * Create a new key encoder instance.
+ *
+ * Creates a new key encoder with default options. The encoder can be configured
+ * using ghostty_key_encoder_setopt() and must be freed using
+ * ghostty_key_encoder_free() when no longer needed.
+ *
+ * @param allocator Pointer to the allocator to use for memory management, or NULL to use the default allocator
+ * @param encoder Pointer to store the created encoder handle
+ * @return GHOSTTY_SUCCESS on success, or an error code on failure
+ *
+ * @ingroup key
+ */
+GHOSTTY_API GhosttyResult ghostty_key_encoder_new(const GhosttyAllocator *allocator, GhosttyKeyEncoder *encoder);
+
+/**
+ * Free a key encoder instance.
+ *
+ * Releases all resources associated with the key encoder. After this call,
+ * the encoder handle becomes invalid and must not be used.
+ *
+ * @param encoder The encoder handle to free (may be NULL)
+ *
+ * @ingroup key
+ */
+GHOSTTY_API void ghostty_key_encoder_free(GhosttyKeyEncoder encoder);
+
+/**
+ * Set an option on the key encoder.
+ *
+ * Configures the behavior of the key encoder. Options control various aspects
+ * of encoding such as terminal modes (cursor key application mode, keypad mode),
+ * protocol selection (Kitty keyboard protocol flags), and platform-specific
+ * behaviors (macOS option-as-alt).
+ *
+ * If you are using a terminal instance, you can set the key encoding
+ * options based on the active terminal state (e.g. legacy vs Kitty mode
+ * and associated flags) with ghostty_key_encoder_setopt_from_terminal().
+ *
+ * A null pointer value does nothing. It does not reset the value to the
+ * default. The setopt call will do nothing.
+ *
+ * @param encoder The encoder handle, must not be NULL
+ * @param option The option to set
+ * @param value Pointer to the value to set (type depends on the option)
+ *
+ * @ingroup key
+ */
+GHOSTTY_API void ghostty_key_encoder_setopt(GhosttyKeyEncoder encoder, GhosttyKeyEncoderOption option, const void *value);
+
+/**
+ * Set encoder options from a terminal's current state.
+ *
+ * Reads the terminal's current modes and flags and applies them to the
+ * encoder's options. This sets cursor key application mode, keypad mode,
+ * alt escape prefix, modifyOtherKeys state, and Kitty keyboard protocol
+ * flags from the terminal state.
+ *
+ * Note that the `macos_option_as_alt` option cannot be determined from
+ * terminal state and is reset to `GHOSTTY_OPTION_AS_ALT_FALSE` by this
+ * call. Use ghostty_key_encoder_setopt() to set it afterward if needed.
+ *
+ * @param encoder The encoder handle, must not be NULL
+ * @param terminal The terminal handle, must not be NULL
+ *
+ * @ingroup key
+ */
+GHOSTTY_API void ghostty_key_encoder_setopt_from_terminal(GhosttyKeyEncoder encoder, GhosttyTerminal terminal);
+
+/**
+ * Encode a key event into a terminal escape sequence.
+ *
+ * Converts a key event into the appropriate terminal escape sequence based on
+ * the encoder's current options. The sequence is written to the provided buffer.
+ *
+ * Not all key events produce output. For example, unmodified modifier keys
+ * typically don't generate escape sequences. Check the out_len parameter to
+ * determine if any data was written.
+ *
+ * If the output buffer is too small, this function returns GHOSTTY_OUT_OF_SPACE
+ * and out_len will contain the required buffer size. The caller can then
+ * allocate a larger buffer and call the function again.
+ *
+ * @param encoder The encoder handle, must not be NULL
+ * @param event The key event to encode, must not be NULL
+ * @param out_buf Buffer to write the encoded sequence to
+ * @param out_buf_size Size of the output buffer in bytes
+ * @param out_len Pointer to store the number of bytes written (may be NULL)
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_OUT_OF_SPACE if buffer too small, or other error code
+ *
+ * ## Example: Calculate required buffer size
+ *
+ * @code{.c}
+ * // Query the required size with a NULL buffer (always returns OUT_OF_SPACE)
+ * size_t required = 0;
+ * GhosttyResult result = ghostty_key_encoder_encode(encoder, event, NULL, 0, &required);
+ * assert(result == GHOSTTY_OUT_OF_SPACE);
+ *
+ * // Allocate buffer of required size
+ * char *buf = malloc(required);
+ *
+ * // Encode with properly sized buffer
+ * size_t written = 0;
+ * result = ghostty_key_encoder_encode(encoder, event, buf, required, &written);
+ * assert(result == GHOSTTY_SUCCESS);
+ *
+ * // Use the encoded sequence...
+ *
+ * free(buf);
+ * @endcode
+ *
+ * ## Example: Direct encoding with static buffer
+ *
+ * @code{.c}
+ * // Most escape sequences are short, so a static buffer often suffices
+ * char buf[128];
+ * size_t written = 0;
+ * GhosttyResult result = ghostty_key_encoder_encode(encoder, event, buf, sizeof(buf), &written);
+ *
+ * if (result == GHOSTTY_SUCCESS) {
+ * // Write the encoded sequence to the terminal
+ * write(pty_fd, buf, written);
+ * } else if (result == GHOSTTY_OUT_OF_SPACE) {
+ * // Buffer too small, written contains required size
+ * char *dynamic_buf = malloc(written);
+ * result = ghostty_key_encoder_encode(encoder, event, dynamic_buf, written, &written);
+ * assert(result == GHOSTTY_SUCCESS);
+ * write(pty_fd, dynamic_buf, written);
+ * free(dynamic_buf);
+ * }
+ * @endcode
+ *
+ * @ingroup key
+ */
+GHOSTTY_API GhosttyResult ghostty_key_encoder_encode(GhosttyKeyEncoder encoder, GhosttyKeyEvent event, char *out_buf, size_t out_buf_size, size_t *out_len);
+
+#endif /* GHOSTTY_VT_KEY_ENCODER_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt/key/event.h b/vendor/libghostty-vt/include/ghostty/vt/key/event.h
new file mode 100644
index 00000000..bcc9d8de
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/key/event.h
@@ -0,0 +1,480 @@
+/**
+ * @file event.h
+ *
+ * Key event representation and manipulation.
+ */
+
+#ifndef GHOSTTY_VT_KEY_EVENT_H
+#define GHOSTTY_VT_KEY_EVENT_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <ghostty/vt/types.h>
+#include <ghostty/vt/allocator.h>
+
+/**
+ * Opaque handle to a key event.
+ *
+ * This handle represents a keyboard input event containing information about
+ * the physical key pressed, modifiers, and generated text.
+ *
+ * @ingroup key
+ */
+typedef struct GhosttyKeyEventImpl *GhosttyKeyEvent;
+
+/**
+ * Keyboard input event types.
+ *
+ * @ingroup key
+ */
+typedef enum {
+ /** Key was released */
+ GHOSTTY_KEY_ACTION_RELEASE = 0,
+ /** Key was pressed */
+ GHOSTTY_KEY_ACTION_PRESS = 1,
+ /** Key is being repeated (held down) */
+ GHOSTTY_KEY_ACTION_REPEAT = 2,
+} GhosttyKeyAction;
+
+/**
+ * Keyboard modifier keys bitmask.
+ *
+ * A bitmask representing all keyboard modifiers. This tracks which modifier keys
+ * are pressed and, where supported by the platform, which side (left or right)
+ * of each modifier is active.
+ *
+ * Use the GHOSTTY_MODS_* constants to test and set individual modifiers.
+ *
+ * Modifier side bits are only meaningful when the corresponding modifier bit is set.
+ * Not all platforms support distinguishing between left and right modifier
+ * keys and Ghostty is built to expect that some platforms may not provide this
+ * information.
+ *
+ * @ingroup key
+ */
+typedef uint16_t GhosttyMods;
+
+/** Shift key is pressed */
+#define GHOSTTY_MODS_SHIFT (1 << 0)
+/** Control key is pressed */
+#define GHOSTTY_MODS_CTRL (1 << 1)
+/** Alt/Option key is pressed */
+#define GHOSTTY_MODS_ALT (1 << 2)
+/** Super/Command/Windows key is pressed */
+#define GHOSTTY_MODS_SUPER (1 << 3)
+/** Caps Lock is active */
+#define GHOSTTY_MODS_CAPS_LOCK (1 << 4)
+/** Num Lock is active */
+#define GHOSTTY_MODS_NUM_LOCK (1 << 5)
+
+/**
+ * Right shift is pressed (0 = left, 1 = right).
+ * Only meaningful when GHOSTTY_MODS_SHIFT is set.
+ */
+#define GHOSTTY_MODS_SHIFT_SIDE (1 << 6)
+/**
+ * Right ctrl is pressed (0 = left, 1 = right).
+ * Only meaningful when GHOSTTY_MODS_CTRL is set.
+ */
+#define GHOSTTY_MODS_CTRL_SIDE (1 << 7)
+/**
+ * Right alt is pressed (0 = left, 1 = right).
+ * Only meaningful when GHOSTTY_MODS_ALT is set.
+ */
+#define GHOSTTY_MODS_ALT_SIDE (1 << 8)
+/**
+ * Right super is pressed (0 = left, 1 = right).
+ * Only meaningful when GHOSTTY_MODS_SUPER is set.
+ */
+#define GHOSTTY_MODS_SUPER_SIDE (1 << 9)
+
+/**
+ * Physical key codes.
+ *
+ * The set of key codes that Ghostty is aware of. These represent physical keys
+ * on the keyboard and are layout-independent. For example, the "a" key on a US
+ * keyboard is the same as the "ф" key on a Russian keyboard, but both will
+ * report the same key_a value.
+ *
+ * Layout-dependent strings are provided separately as UTF-8 text and are produced
+ * by the platform. These values are based on the W3C UI Events KeyboardEvent code
+ * standard. See: https://www.w3.org/TR/uievents-code
+ *
+ * @ingroup key
+ */
+typedef enum {
+ GHOSTTY_KEY_UNIDENTIFIED = 0,
+
+ // Writing System Keys (W3C § 3.1.1)
+ GHOSTTY_KEY_BACKQUOTE,
+ GHOSTTY_KEY_BACKSLASH,
+ GHOSTTY_KEY_BRACKET_LEFT,
+ GHOSTTY_KEY_BRACKET_RIGHT,
+ GHOSTTY_KEY_COMMA,
+ GHOSTTY_KEY_DIGIT_0,
+ GHOSTTY_KEY_DIGIT_1,
+ GHOSTTY_KEY_DIGIT_2,
+ GHOSTTY_KEY_DIGIT_3,
+ GHOSTTY_KEY_DIGIT_4,
+ GHOSTTY_KEY_DIGIT_5,
+ GHOSTTY_KEY_DIGIT_6,
+ GHOSTTY_KEY_DIGIT_7,
+ GHOSTTY_KEY_DIGIT_8,
+ GHOSTTY_KEY_DIGIT_9,
+ GHOSTTY_KEY_EQUAL,
+ GHOSTTY_KEY_INTL_BACKSLASH,
+ GHOSTTY_KEY_INTL_RO,
+ GHOSTTY_KEY_INTL_YEN,
+ GHOSTTY_KEY_A,
+ GHOSTTY_KEY_B,
+ GHOSTTY_KEY_C,
+ GHOSTTY_KEY_D,
+ GHOSTTY_KEY_E,
+ GHOSTTY_KEY_F,
+ GHOSTTY_KEY_G,
+ GHOSTTY_KEY_H,
+ GHOSTTY_KEY_I,
+ GHOSTTY_KEY_J,
+ GHOSTTY_KEY_K,
+ GHOSTTY_KEY_L,
+ GHOSTTY_KEY_M,
+ GHOSTTY_KEY_N,
+ GHOSTTY_KEY_O,
+ GHOSTTY_KEY_P,
+ GHOSTTY_KEY_Q,
+ GHOSTTY_KEY_R,
+ GHOSTTY_KEY_S,
+ GHOSTTY_KEY_T,
+ GHOSTTY_KEY_U,
+ GHOSTTY_KEY_V,
+ GHOSTTY_KEY_W,
+ GHOSTTY_KEY_X,
+ GHOSTTY_KEY_Y,
+ GHOSTTY_KEY_Z,
+ GHOSTTY_KEY_MINUS,
+ GHOSTTY_KEY_PERIOD,
+ GHOSTTY_KEY_QUOTE,
+ GHOSTTY_KEY_SEMICOLON,
+ GHOSTTY_KEY_SLASH,
+
+ // Functional Keys (W3C § 3.1.2)
+ GHOSTTY_KEY_ALT_LEFT,
+ GHOSTTY_KEY_ALT_RIGHT,
+ GHOSTTY_KEY_BACKSPACE,
+ GHOSTTY_KEY_CAPS_LOCK,
+ GHOSTTY_KEY_CONTEXT_MENU,
+ GHOSTTY_KEY_CONTROL_LEFT,
+ GHOSTTY_KEY_CONTROL_RIGHT,
+ GHOSTTY_KEY_ENTER,
+ GHOSTTY_KEY_META_LEFT,
+ GHOSTTY_KEY_META_RIGHT,
+ GHOSTTY_KEY_SHIFT_LEFT,
+ GHOSTTY_KEY_SHIFT_RIGHT,
+ GHOSTTY_KEY_SPACE,
+ GHOSTTY_KEY_TAB,
+ GHOSTTY_KEY_CONVERT,
+ GHOSTTY_KEY_KANA_MODE,
+ GHOSTTY_KEY_NON_CONVERT,
+
+ // Control Pad Section (W3C § 3.2)
+ GHOSTTY_KEY_DELETE,
+ GHOSTTY_KEY_END,
+ GHOSTTY_KEY_HELP,
+ GHOSTTY_KEY_HOME,
+ GHOSTTY_KEY_INSERT,
+ GHOSTTY_KEY_PAGE_DOWN,
+ GHOSTTY_KEY_PAGE_UP,
+
+ // Arrow Pad Section (W3C § 3.3)
+ GHOSTTY_KEY_ARROW_DOWN,
+ GHOSTTY_KEY_ARROW_LEFT,
+ GHOSTTY_KEY_ARROW_RIGHT,
+ GHOSTTY_KEY_ARROW_UP,
+
+ // Numpad Section (W3C § 3.4)
+ GHOSTTY_KEY_NUM_LOCK,
+ GHOSTTY_KEY_NUMPAD_0,
+ GHOSTTY_KEY_NUMPAD_1,
+ GHOSTTY_KEY_NUMPAD_2,
+ GHOSTTY_KEY_NUMPAD_3,
+ GHOSTTY_KEY_NUMPAD_4,
+ GHOSTTY_KEY_NUMPAD_5,
+ GHOSTTY_KEY_NUMPAD_6,
+ GHOSTTY_KEY_NUMPAD_7,
+ GHOSTTY_KEY_NUMPAD_8,
+ GHOSTTY_KEY_NUMPAD_9,
+ GHOSTTY_KEY_NUMPAD_ADD,
+ GHOSTTY_KEY_NUMPAD_BACKSPACE,
+ GHOSTTY_KEY_NUMPAD_CLEAR,
+ GHOSTTY_KEY_NUMPAD_CLEAR_ENTRY,
+ GHOSTTY_KEY_NUMPAD_COMMA,
+ GHOSTTY_KEY_NUMPAD_DECIMAL,
+ GHOSTTY_KEY_NUMPAD_DIVIDE,
+ GHOSTTY_KEY_NUMPAD_ENTER,
+ GHOSTTY_KEY_NUMPAD_EQUAL,
+ GHOSTTY_KEY_NUMPAD_MEMORY_ADD,
+ GHOSTTY_KEY_NUMPAD_MEMORY_CLEAR,
+ GHOSTTY_KEY_NUMPAD_MEMORY_RECALL,
+ GHOSTTY_KEY_NUMPAD_MEMORY_STORE,
+ GHOSTTY_KEY_NUMPAD_MEMORY_SUBTRACT,
+ GHOSTTY_KEY_NUMPAD_MULTIPLY,
+ GHOSTTY_KEY_NUMPAD_PAREN_LEFT,
+ GHOSTTY_KEY_NUMPAD_PAREN_RIGHT,
+ GHOSTTY_KEY_NUMPAD_SUBTRACT,
+ GHOSTTY_KEY_NUMPAD_SEPARATOR,
+ GHOSTTY_KEY_NUMPAD_UP,
+ GHOSTTY_KEY_NUMPAD_DOWN,
+ GHOSTTY_KEY_NUMPAD_RIGHT,
+ GHOSTTY_KEY_NUMPAD_LEFT,
+ GHOSTTY_KEY_NUMPAD_BEGIN,
+ GHOSTTY_KEY_NUMPAD_HOME,
+ GHOSTTY_KEY_NUMPAD_END,
+ GHOSTTY_KEY_NUMPAD_INSERT,
+ GHOSTTY_KEY_NUMPAD_DELETE,
+ GHOSTTY_KEY_NUMPAD_PAGE_UP,
+ GHOSTTY_KEY_NUMPAD_PAGE_DOWN,
+
+ // Function Section (W3C § 3.5)
+ GHOSTTY_KEY_ESCAPE,
+ GHOSTTY_KEY_F1,
+ GHOSTTY_KEY_F2,
+ GHOSTTY_KEY_F3,
+ GHOSTTY_KEY_F4,
+ GHOSTTY_KEY_F5,
+ GHOSTTY_KEY_F6,
+ GHOSTTY_KEY_F7,
+ GHOSTTY_KEY_F8,
+ GHOSTTY_KEY_F9,
+ GHOSTTY_KEY_F10,
+ GHOSTTY_KEY_F11,
+ GHOSTTY_KEY_F12,
+ GHOSTTY_KEY_F13,
+ GHOSTTY_KEY_F14,
+ GHOSTTY_KEY_F15,
+ GHOSTTY_KEY_F16,
+ GHOSTTY_KEY_F17,
+ GHOSTTY_KEY_F18,
+ GHOSTTY_KEY_F19,
+ GHOSTTY_KEY_F20,
+ GHOSTTY_KEY_F21,
+ GHOSTTY_KEY_F22,
+ GHOSTTY_KEY_F23,
+ GHOSTTY_KEY_F24,
+ GHOSTTY_KEY_F25,
+ GHOSTTY_KEY_FN,
+ GHOSTTY_KEY_FN_LOCK,
+ GHOSTTY_KEY_PRINT_SCREEN,
+ GHOSTTY_KEY_SCROLL_LOCK,
+ GHOSTTY_KEY_PAUSE,
+
+ // Media Keys (W3C § 3.6)
+ GHOSTTY_KEY_BROWSER_BACK,
+ GHOSTTY_KEY_BROWSER_FAVORITES,
+ GHOSTTY_KEY_BROWSER_FORWARD,
+ GHOSTTY_KEY_BROWSER_HOME,
+ GHOSTTY_KEY_BROWSER_REFRESH,
+ GHOSTTY_KEY_BROWSER_SEARCH,
+ GHOSTTY_KEY_BROWSER_STOP,
+ GHOSTTY_KEY_EJECT,
+ GHOSTTY_KEY_LAUNCH_APP_1,
+ GHOSTTY_KEY_LAUNCH_APP_2,
+ GHOSTTY_KEY_LAUNCH_MAIL,
+ GHOSTTY_KEY_MEDIA_PLAY_PAUSE,
+ GHOSTTY_KEY_MEDIA_SELECT,
+ GHOSTTY_KEY_MEDIA_STOP,
+ GHOSTTY_KEY_MEDIA_TRACK_NEXT,
+ GHOSTTY_KEY_MEDIA_TRACK_PREVIOUS,
+ GHOSTTY_KEY_POWER,
+ GHOSTTY_KEY_SLEEP,
+ GHOSTTY_KEY_AUDIO_VOLUME_DOWN,
+ GHOSTTY_KEY_AUDIO_VOLUME_MUTE,
+ GHOSTTY_KEY_AUDIO_VOLUME_UP,
+ GHOSTTY_KEY_WAKE_UP,
+
+ // Legacy, Non-standard, and Special Keys (W3C § 3.7)
+ GHOSTTY_KEY_COPY,
+ GHOSTTY_KEY_CUT,
+ GHOSTTY_KEY_PASTE,
+} GhosttyKey;
+
+/**
+ * Create a new key event instance.
+ *
+ * Creates a new key event with default values. The event must be freed using
+ * ghostty_key_event_free() when no longer needed.
+ *
+ * @param allocator Pointer to the allocator to use for memory management, or NULL to use the default allocator
+ * @param event Pointer to store the created key event handle
+ * @return GHOSTTY_SUCCESS on success, or an error code on failure
+ *
+ * @ingroup key
+ */
+GHOSTTY_API GhosttyResult ghostty_key_event_new(const GhosttyAllocator *allocator, GhosttyKeyEvent *event);
+
+/**
+ * Free a key event instance.
+ *
+ * Releases all resources associated with the key event. After this call,
+ * the event handle becomes invalid and must not be used.
+ *
+ * @param event The key event handle to free (may be NULL)
+ *
+ * @ingroup key
+ */
+GHOSTTY_API void ghostty_key_event_free(GhosttyKeyEvent event);
+
+/**
+ * Set the key action (press, release, repeat).
+ *
+ * @param event The key event handle, must not be NULL
+ * @param action The action to set
+ *
+ * @ingroup key
+ */
+GHOSTTY_API void ghostty_key_event_set_action(GhosttyKeyEvent event, GhosttyKeyAction action);
+
+/**
+ * Get the key action (press, release, repeat).
+ *
+ * @param event The key event handle, must not be NULL
+ * @return The key action
+ *
+ * @ingroup key
+ */
+GHOSTTY_API GhosttyKeyAction ghostty_key_event_get_action(GhosttyKeyEvent event);
+
+/**
+ * Set the physical key code.
+ *
+ * @param event The key event handle, must not be NULL
+ * @param key The physical key code to set
+ *
+ * @ingroup key
+ */
+GHOSTTY_API void ghostty_key_event_set_key(GhosttyKeyEvent event, GhosttyKey key);
+
+/**
+ * Get the physical key code.
+ *
+ * @param event The key event handle, must not be NULL
+ * @return The physical key code
+ *
+ * @ingroup key
+ */
+GHOSTTY_API GhosttyKey ghostty_key_event_get_key(GhosttyKeyEvent event);
+
+/**
+ * Set the modifier keys bitmask.
+ *
+ * @param event The key event handle, must not be NULL
+ * @param mods The modifier keys bitmask to set
+ *
+ * @ingroup key
+ */
+GHOSTTY_API void ghostty_key_event_set_mods(GhosttyKeyEvent event, GhosttyMods mods);
+
+/**
+ * Get the modifier keys bitmask.
+ *
+ * @param event The key event handle, must not be NULL
+ * @return The modifier keys bitmask
+ *
+ * @ingroup key
+ */
+GHOSTTY_API GhosttyMods ghostty_key_event_get_mods(GhosttyKeyEvent event);
+
+/**
+ * Set the consumed modifiers bitmask.
+ *
+ * @param event The key event handle, must not be NULL
+ * @param consumed_mods The consumed modifiers bitmask to set
+ *
+ * @ingroup key
+ */
+GHOSTTY_API void ghostty_key_event_set_consumed_mods(GhosttyKeyEvent event, GhosttyMods consumed_mods);
+
+/**
+ * Get the consumed modifiers bitmask.
+ *
+ * @param event The key event handle, must not be NULL
+ * @return The consumed modifiers bitmask
+ *
+ * @ingroup key
+ */
+GHOSTTY_API GhosttyMods ghostty_key_event_get_consumed_mods(GhosttyKeyEvent event);
+
+/**
+ * Set whether the key event is part of a composition sequence.
+ *
+ * @param event The key event handle, must not be NULL
+ * @param composing Whether the key event is part of a composition sequence
+ *
+ * @ingroup key
+ */
+GHOSTTY_API void ghostty_key_event_set_composing(GhosttyKeyEvent event, bool composing);
+
+/**
+ * Get whether the key event is part of a composition sequence.
+ *
+ * @param event The key event handle, must not be NULL
+ * @return Whether the key event is part of a composition sequence
+ *
+ * @ingroup key
+ */
+GHOSTTY_API bool ghostty_key_event_get_composing(GhosttyKeyEvent event);
+
+/**
+ * Set the UTF-8 text generated by the key for the current keyboard layout.
+ *
+ * Must contain the unmodified character before any Ctrl/Meta transformations.
+ * The encoder derives modifier sequences from the logical key and mods
+ * bitmask, not from this text. Do not pass C0 control characters
+ * (U+0000-U+001F, U+007F) or platform function key codes (e.g. macOS PUA
+ * U+F700-U+F8FF); pass NULL instead and let the encoder use the logical key.
+ *
+ * The key event does NOT take ownership of the text pointer. The caller
+ * must ensure the string remains valid for the lifetime needed by the event.
+ *
+ * @param event The key event handle, must not be NULL
+ * @param utf8 The UTF-8 text to set (or NULL for empty)
+ * @param len Length of the UTF-8 text in bytes
+ *
+ * @ingroup key
+ */
+GHOSTTY_API void ghostty_key_event_set_utf8(GhosttyKeyEvent event, const char *utf8, size_t len);
+
+/**
+ * Get the UTF-8 text generated by the key event.
+ *
+ * The returned pointer is valid until the event is freed or the UTF-8 text is modified.
+ *
+ * @param event The key event handle, must not be NULL
+ * @param len Pointer to store the length of the UTF-8 text in bytes (may be NULL)
+ * @return The UTF-8 text (or NULL for empty)
+ *
+ * @ingroup key
+ */
+GHOSTTY_API const char *ghostty_key_event_get_utf8(GhosttyKeyEvent event, size_t *len);
+
+/**
+ * Set the unshifted Unicode codepoint.
+ *
+ * @param event The key event handle, must not be NULL
+ * @param codepoint The unshifted Unicode codepoint to set
+ *
+ * @ingroup key
+ */
+GHOSTTY_API void ghostty_key_event_set_unshifted_codepoint(GhosttyKeyEvent event, uint32_t codepoint);
+
+/**
+ * Get the unshifted Unicode codepoint.
+ *
+ * @param event The key event handle, must not be NULL
+ * @return The unshifted Unicode codepoint
+ *
+ * @ingroup key
+ */
+GHOSTTY_API uint32_t ghostty_key_event_get_unshifted_codepoint(GhosttyKeyEvent event);
+
+#endif /* GHOSTTY_VT_KEY_EVENT_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt/modes.h b/vendor/libghostty-vt/include/ghostty/vt/modes.h
new file mode 100644
index 00000000..513aaf5a
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/modes.h
@@ -0,0 +1,196 @@
+/**
+ * @file modes.h
+ *
+ * Terminal mode utilities - pack and unpack ANSI/DEC mode identifiers.
+ */
+
+#ifndef GHOSTTY_VT_MODES_H
+#define GHOSTTY_VT_MODES_H
+
+/** @defgroup modes Mode Utilities
+ *
+ * Utilities for working with terminal modes. A mode is a compact
+ * 16-bit representation of a terminal mode identifier that encodes both
+ * the numeric mode value (up to 15 bits) and whether the mode is an ANSI
+ * mode or a DEC private mode (?-prefixed).
+ *
+ * The packed layout (least-significant bit first) is:
+ * - Bits 0–14: mode value (u15)
+ * - Bit 15: ANSI flag (0 = DEC private mode, 1 = ANSI mode)
+ *
+ * ## Example
+ *
+ * @snippet c-vt-modes/src/main.c modes-pack-unpack
+ *
+ * ## DECRPM Report Encoding
+ *
+ * Use ghostty_mode_report_encode() to encode a DECRPM response into a
+ * caller-provided buffer:
+ *
+ * @snippet c-vt-modes/src/main.c modes-decrpm
+ *
+ * @{
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <ghostty/vt/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @name ANSI Modes
+ * Modes for standard ANSI modes.
+ * @{
+ */
+#define GHOSTTY_MODE_KAM (ghostty_mode_new(2, true)) /**< Keyboard action (disable keyboard) */
+#define GHOSTTY_MODE_INSERT (ghostty_mode_new(4, true)) /**< Insert mode */
+#define GHOSTTY_MODE_SRM (ghostty_mode_new(12, true)) /**< Send/receive mode */
+#define GHOSTTY_MODE_LINEFEED (ghostty_mode_new(20, true)) /**< Linefeed/new line mode */
+/** @} */
+
+/** @name DEC Private Modes
+ * Modes for DEC private modes (?-prefixed).
+ * @{
+ */
+#define GHOSTTY_MODE_DECCKM (ghostty_mode_new(1, false)) /**< Cursor keys */
+#define GHOSTTY_MODE_132_COLUMN (ghostty_mode_new(3, false)) /**< 132/80 column mode */
+#define GHOSTTY_MODE_SLOW_SCROLL (ghostty_mode_new(4, false)) /**< Slow scroll */
+#define GHOSTTY_MODE_REVERSE_COLORS (ghostty_mode_new(5, false)) /**< Reverse video */
+#define GHOSTTY_MODE_ORIGIN (ghostty_mode_new(6, false)) /**< Origin mode */
+#define GHOSTTY_MODE_WRAPAROUND (ghostty_mode_new(7, false)) /**< Auto-wrap mode */
+#define GHOSTTY_MODE_AUTOREPEAT (ghostty_mode_new(8, false)) /**< Auto-repeat keys */
+#define GHOSTTY_MODE_X10_MOUSE (ghostty_mode_new(9, false)) /**< X10 mouse reporting */
+#define GHOSTTY_MODE_CURSOR_BLINKING (ghostty_mode_new(12, false)) /**< Cursor blink */
+#define GHOSTTY_MODE_CURSOR_VISIBLE (ghostty_mode_new(25, false)) /**< Cursor visible (DECTCEM) */
+#define GHOSTTY_MODE_ENABLE_MODE_3 (ghostty_mode_new(40, false)) /**< Allow 132 column mode */
+#define GHOSTTY_MODE_REVERSE_WRAP (ghostty_mode_new(45, false)) /**< Reverse wrap */
+#define GHOSTTY_MODE_ALT_SCREEN_LEGACY (ghostty_mode_new(47, false)) /**< Alternate screen (legacy) */
+#define GHOSTTY_MODE_KEYPAD_KEYS (ghostty_mode_new(66, false)) /**< Application keypad */
+#define GHOSTTY_MODE_LEFT_RIGHT_MARGIN (ghostty_mode_new(69, false)) /**< Left/right margin mode */
+#define GHOSTTY_MODE_NORMAL_MOUSE (ghostty_mode_new(1000, false)) /**< Normal mouse tracking */
+#define GHOSTTY_MODE_BUTTON_MOUSE (ghostty_mode_new(1002, false)) /**< Button-event mouse tracking */
+#define GHOSTTY_MODE_ANY_MOUSE (ghostty_mode_new(1003, false)) /**< Any-event mouse tracking */
+#define GHOSTTY_MODE_FOCUS_EVENT (ghostty_mode_new(1004, false)) /**< Focus in/out events */
+#define GHOSTTY_MODE_UTF8_MOUSE (ghostty_mode_new(1005, false)) /**< UTF-8 mouse format */
+#define GHOSTTY_MODE_SGR_MOUSE (ghostty_mode_new(1006, false)) /**< SGR mouse format */
+#define GHOSTTY_MODE_ALT_SCROLL (ghostty_mode_new(1007, false)) /**< Alternate scroll mode */
+#define GHOSTTY_MODE_URXVT_MOUSE (ghostty_mode_new(1015, false)) /**< URxvt mouse format */
+#define GHOSTTY_MODE_SGR_PIXELS_MOUSE (ghostty_mode_new(1016, false)) /**< SGR-Pixels mouse format */
+#define GHOSTTY_MODE_NUMLOCK_KEYPAD (ghostty_mode_new(1035, false)) /**< Ignore keypad with NumLock */
+#define GHOSTTY_MODE_ALT_ESC_PREFIX (ghostty_mode_new(1036, false)) /**< Alt key sends ESC prefix */
+#define GHOSTTY_MODE_ALT_SENDS_ESC (ghostty_mode_new(1039, false)) /**< Alt sends escape */
+#define GHOSTTY_MODE_REVERSE_WRAP_EXT (ghostty_mode_new(1045, false)) /**< Extended reverse wrap */
+#define GHOSTTY_MODE_ALT_SCREEN (ghostty_mode_new(1047, false)) /**< Alternate screen */
+#define GHOSTTY_MODE_SAVE_CURSOR (ghostty_mode_new(1048, false)) /**< Save cursor (DECSC) */
+#define GHOSTTY_MODE_ALT_SCREEN_SAVE (ghostty_mode_new(1049, false)) /**< Alt screen + save cursor + clear */
+#define GHOSTTY_MODE_BRACKETED_PASTE (ghostty_mode_new(2004, false)) /**< Bracketed paste mode */
+#define GHOSTTY_MODE_SYNC_OUTPUT (ghostty_mode_new(2026, false)) /**< Synchronized output */
+#define GHOSTTY_MODE_GRAPHEME_CLUSTER (ghostty_mode_new(2027, false)) /**< Grapheme cluster mode */
+#define GHOSTTY_MODE_COLOR_SCHEME_REPORT (ghostty_mode_new(2031, false)) /**< Report color scheme */
+#define GHOSTTY_MODE_IN_BAND_RESIZE (ghostty_mode_new(2048, false)) /**< In-band size reports */
+/** @} */
+
+/**
+ * A packed 16-bit terminal mode.
+ *
+ * Encodes a mode value (bits 0–14) and an ANSI flag (bit 15) into a
+ * single 16-bit integer. Use the inline helper functions to construct
+ * and inspect modes rather than manipulating bits directly.
+ */
+typedef uint16_t GhosttyMode;
+
+/**
+ * Create a mode from a mode value and ANSI flag.
+ *
+ * @param value The numeric mode value (0–32767)
+ * @param ansi true for an ANSI mode, false for a DEC private mode
+ * @return The packed mode
+ *
+ * @ingroup modes
+ */
+static inline GhosttyMode ghostty_mode_new(uint16_t value, bool ansi) {
+ return (GhosttyMode)((value & 0x7FFF) | ((uint16_t)ansi << 15));
+}
+
+/**
+ * Extract the numeric mode value from a mode.
+ *
+ * @param mode The mode
+ * @return The mode value (0–32767)
+ *
+ * @ingroup modes
+ */
+static inline uint16_t ghostty_mode_value(GhosttyMode mode) {
+ return mode & 0x7FFF;
+}
+
+/**
+ * Check whether a mode represents an ANSI mode.
+ *
+ * @param mode The mode
+ * @return true if this is an ANSI mode, false if it is a DEC private mode
+ *
+ * @ingroup modes
+ */
+static inline bool ghostty_mode_ansi(GhosttyMode mode) {
+ return (mode >> 15) != 0;
+}
+
+/**
+ * DECRPM report state values.
+ *
+ * These correspond to the Ps2 parameter in a DECRPM response
+ * sequence (CSI ? Ps1 ; Ps2 $ y).
+ */
+typedef enum {
+ /** Mode is not recognized */
+ GHOSTTY_MODE_REPORT_NOT_RECOGNIZED = 0,
+ /** Mode is set (enabled) */
+ GHOSTTY_MODE_REPORT_SET = 1,
+ /** Mode is reset (disabled) */
+ GHOSTTY_MODE_REPORT_RESET = 2,
+ /** Mode is permanently set */
+ GHOSTTY_MODE_REPORT_PERMANENTLY_SET = 3,
+ /** Mode is permanently reset */
+ GHOSTTY_MODE_REPORT_PERMANENTLY_RESET = 4,
+} GhosttyModeReportState;
+
+/**
+ * Encode a DECRPM (DEC Private Mode Report) response sequence.
+ *
+ * Writes a mode report escape sequence into the provided buffer.
+ * The generated sequence has the form:
+ * - DEC private mode: CSI ? Ps1 ; Ps2 $ y
+ * - ANSI mode: CSI Ps1 ; Ps2 $ y
+ *
+ * If the buffer is too small, the function returns GHOSTTY_OUT_OF_SPACE
+ * and writes the required buffer size to @p out_written. The caller can
+ * then retry with a sufficiently sized buffer.
+ *
+ * @param mode The mode identifying the mode to report on
+ * @param state The report state for this mode
+ * @param buf Output buffer to write the encoded sequence into (may be NULL)
+ * @param buf_len Size of the output buffer in bytes
+ * @param[out] out_written On success, the number of bytes written. On
+ * GHOSTTY_OUT_OF_SPACE, the required buffer size.
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_OUT_OF_SPACE if the buffer
+ * is too small
+ */
+GHOSTTY_API GhosttyResult ghostty_mode_report_encode(
+ GhosttyMode mode,
+ GhosttyModeReportState state,
+ char* buf,
+ size_t buf_len,
+ size_t* out_written);
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif /* GHOSTTY_VT_MODES_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt/mouse.h b/vendor/libghostty-vt/include/ghostty/vt/mouse.h
new file mode 100644
index 00000000..4ba5f52e
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/mouse.h
@@ -0,0 +1,70 @@
+/**
+ * @file mouse.h
+ *
+ * Mouse encoding module - encode mouse events into terminal escape sequences.
+ */
+
+#ifndef GHOSTTY_VT_MOUSE_H
+#define GHOSTTY_VT_MOUSE_H
+
+/** @defgroup mouse Mouse Encoding
+ *
+ * Utilities for encoding mouse events into terminal escape sequences,
+ * supporting X10, UTF-8, SGR, URxvt, and SGR-Pixels mouse protocols.
+ *
+ * ## Basic Usage
+ *
+ * 1. Create an encoder instance with ghostty_mouse_encoder_new().
+ * 2. Configure encoder options with ghostty_mouse_encoder_setopt() or
+ * ghostty_mouse_encoder_setopt_from_terminal().
+ * 3. For each mouse event:
+ * - Create a mouse event with ghostty_mouse_event_new().
+ * - Set event properties (action, button, modifiers, position).
+ * - Encode with ghostty_mouse_encoder_encode().
+ * - Free the event with ghostty_mouse_event_free() or reuse it.
+ * 4. Free the encoder with ghostty_mouse_encoder_free() when done.
+ *
+ * For a complete working example, see example/c-vt-encode-mouse in the
+ * repository.
+ *
+ * ## Example
+ *
+ * @snippet c-vt-encode-mouse/src/main.c mouse-encode
+ *
+ * ## Example: Encoding with Terminal State
+ *
+ * When you have a GhosttyTerminal, you can sync its tracking mode and
+ * output format into the encoder automatically:
+ *
+ * @code{.c}
+ * // Create a terminal and feed it some VT data that enables mouse tracking
+ * GhosttyTerminal terminal;
+ * ghostty_terminal_new(NULL, &terminal,
+ * (GhosttyTerminalOptions){.cols = 80, .rows = 24, .max_scrollback = 0});
+ *
+ * // Application might write data that enables mouse reporting, etc.
+ * ghostty_terminal_vt_write(terminal, vt_data, vt_len);
+ *
+ * // Create an encoder and sync its options from the terminal
+ * GhosttyMouseEncoder encoder;
+ * ghostty_mouse_encoder_new(NULL, &encoder);
+ * ghostty_mouse_encoder_setopt_from_terminal(encoder, terminal);
+ *
+ * // Encode a mouse event using the terminal-derived options
+ * char buf[128];
+ * size_t written = 0;
+ * ghostty_mouse_encoder_encode(encoder, event, buf, sizeof(buf), &written);
+ *
+ * ghostty_mouse_encoder_free(encoder);
+ * ghostty_terminal_free(terminal);
+ * @endcode
+ *
+ * @{
+ */
+
+#include <ghostty/vt/mouse/event.h>
+#include <ghostty/vt/mouse/encoder.h>
+
+/** @} */
+
+#endif /* GHOSTTY_VT_MOUSE_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt/mouse/encoder.h b/vendor/libghostty-vt/include/ghostty/vt/mouse/encoder.h
new file mode 100644
index 00000000..744b9930
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/mouse/encoder.h
@@ -0,0 +1,211 @@
+/**
+ * @file encoder.h
+ *
+ * Mouse event encoding to terminal escape sequences.
+ */
+
+#ifndef GHOSTTY_VT_MOUSE_ENCODER_H
+#define GHOSTTY_VT_MOUSE_ENCODER_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <ghostty/vt/allocator.h>
+#include <ghostty/vt/mouse/event.h>
+#include <ghostty/vt/terminal.h>
+#include <ghostty/vt/types.h>
+
+/**
+ * Opaque handle to a mouse encoder instance.
+ *
+ * This handle represents a mouse encoder that converts normalized
+ * mouse events into terminal escape sequences.
+ *
+ * @ingroup mouse
+ */
+typedef struct GhosttyMouseEncoderImpl *GhosttyMouseEncoder;
+
+/**
+ * Mouse tracking mode.
+ *
+ * @ingroup mouse
+ */
+typedef enum {
+ /** Mouse reporting disabled. */
+ GHOSTTY_MOUSE_TRACKING_NONE = 0,
+
+ /** X10 mouse mode. */
+ GHOSTTY_MOUSE_TRACKING_X10 = 1,
+
+ /** Normal mouse mode (button press/release only). */
+ GHOSTTY_MOUSE_TRACKING_NORMAL = 2,
+
+ /** Button-event tracking mode. */
+ GHOSTTY_MOUSE_TRACKING_BUTTON = 3,
+
+ /** Any-event tracking mode. */
+ GHOSTTY_MOUSE_TRACKING_ANY = 4,
+} GhosttyMouseTrackingMode;
+
+/**
+ * Mouse output format.
+ *
+ * @ingroup mouse
+ */
+typedef enum {
+ GHOSTTY_MOUSE_FORMAT_X10 = 0,
+ GHOSTTY_MOUSE_FORMAT_UTF8 = 1,
+ GHOSTTY_MOUSE_FORMAT_SGR = 2,
+ GHOSTTY_MOUSE_FORMAT_URXVT = 3,
+ GHOSTTY_MOUSE_FORMAT_SGR_PIXELS = 4,
+} GhosttyMouseFormat;
+
+/**
+ * Mouse encoder size and geometry context.
+ *
+ * This describes the rendered terminal geometry used to convert
+ * surface-space positions into encoded coordinates.
+ *
+ * @ingroup mouse
+ */
+typedef struct {
+ /** Size of this struct in bytes. Must be set to sizeof(GhosttyMouseEncoderSize). */
+ size_t size;
+
+ /** Full screen width in pixels. */
+ uint32_t screen_width;
+
+ /** Full screen height in pixels. */
+ uint32_t screen_height;
+
+ /** Cell width in pixels. Must be non-zero. */
+ uint32_t cell_width;
+
+ /** Cell height in pixels. Must be non-zero. */
+ uint32_t cell_height;
+
+ /** Top padding in pixels. */
+ uint32_t padding_top;
+
+ /** Bottom padding in pixels. */
+ uint32_t padding_bottom;
+
+ /** Right padding in pixels. */
+ uint32_t padding_right;
+
+ /** Left padding in pixels. */
+ uint32_t padding_left;
+} GhosttyMouseEncoderSize;
+
+/**
+ * Mouse encoder option identifiers.
+ *
+ * These values are used with ghostty_mouse_encoder_setopt() to configure
+ * the behavior of the mouse encoder.
+ *
+ * @ingroup mouse
+ */
+typedef enum {
+ /** Mouse tracking mode (value: GhosttyMouseTrackingMode). */
+ GHOSTTY_MOUSE_ENCODER_OPT_EVENT = 0,
+
+ /** Mouse output format (value: GhosttyMouseFormat). */
+ GHOSTTY_MOUSE_ENCODER_OPT_FORMAT = 1,
+
+ /** Renderer size context (value: GhosttyMouseEncoderSize). */
+ GHOSTTY_MOUSE_ENCODER_OPT_SIZE = 2,
+
+ /** Whether any mouse button is currently pressed (value: bool). */
+ GHOSTTY_MOUSE_ENCODER_OPT_ANY_BUTTON_PRESSED = 3,
+
+ /** Whether to enable motion deduplication by last cell (value: bool). */
+ GHOSTTY_MOUSE_ENCODER_OPT_TRACK_LAST_CELL = 4,
+} GhosttyMouseEncoderOption;
+
+/**
+ * Create a new mouse encoder instance.
+ *
+ * @param allocator Pointer to allocator, or NULL to use the default allocator
+ * @param encoder Pointer to store the created encoder handle
+ * @return GHOSTTY_SUCCESS on success, or an error code on failure
+ *
+ * @ingroup mouse
+ */
+GHOSTTY_API GhosttyResult ghostty_mouse_encoder_new(const GhosttyAllocator *allocator,
+ GhosttyMouseEncoder *encoder);
+
+/**
+ * Free a mouse encoder instance.
+ *
+ * @param encoder The encoder handle to free (may be NULL)
+ *
+ * @ingroup mouse
+ */
+GHOSTTY_API void ghostty_mouse_encoder_free(GhosttyMouseEncoder encoder);
+
+/**
+ * Set an option on the mouse encoder.
+ *
+ * A null pointer value does nothing. It does not reset to defaults.
+ *
+ * @param encoder The encoder handle, must not be NULL
+ * @param option The option to set
+ * @param value Pointer to option value (type depends on option)
+ *
+ * @ingroup mouse
+ */
+GHOSTTY_API void ghostty_mouse_encoder_setopt(GhosttyMouseEncoder encoder,
+ GhosttyMouseEncoderOption option,
+ const void *value);
+
+/**
+ * Set encoder options from a terminal's current state.
+ *
+ * This sets tracking mode and output format from terminal state.
+ * It does not modify size or any-button state.
+ *
+ * @param encoder The encoder handle, must not be NULL
+ * @param terminal The terminal handle, must not be NULL
+ *
+ * @ingroup mouse
+ */
+GHOSTTY_API void ghostty_mouse_encoder_setopt_from_terminal(GhosttyMouseEncoder encoder,
+ GhosttyTerminal terminal);
+
+/**
+ * Reset internal encoder state.
+ *
+ * This clears motion deduplication state (last tracked cell).
+ *
+ * @param encoder The encoder handle (may be NULL)
+ *
+ * @ingroup mouse
+ */
+GHOSTTY_API void ghostty_mouse_encoder_reset(GhosttyMouseEncoder encoder);
+
+/**
+ * Encode a mouse event into a terminal escape sequence.
+ *
+ * Not all mouse events produce output. In such cases this returns
+ * GHOSTTY_SUCCESS with out_len set to 0.
+ *
+ * If the output buffer is too small, this returns GHOSTTY_OUT_OF_SPACE
+ * and out_len contains the required size.
+ *
+ * @param encoder The encoder handle, must not be NULL
+ * @param event The mouse event to encode, must not be NULL
+ * @param out_buf Buffer to write encoded bytes to, or NULL to query required size
+ * @param out_buf_size Size of out_buf in bytes
+ * @param out_len Pointer to store bytes written (or required bytes on failure)
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_OUT_OF_SPACE if buffer is too small,
+ * or another error code
+ *
+ * @ingroup mouse
+ */
+GHOSTTY_API GhosttyResult ghostty_mouse_encoder_encode(GhosttyMouseEncoder encoder,
+ GhosttyMouseEvent event,
+ char *out_buf,
+ size_t out_buf_size,
+ size_t *out_len);
+
+#endif /* GHOSTTY_VT_MOUSE_ENCODER_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt/mouse/event.h b/vendor/libghostty-vt/include/ghostty/vt/mouse/event.h
new file mode 100644
index 00000000..5b72735f
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/mouse/event.h
@@ -0,0 +1,193 @@
+/**
+ * @file event.h
+ *
+ * Mouse event representation and manipulation.
+ */
+
+#ifndef GHOSTTY_VT_MOUSE_EVENT_H
+#define GHOSTTY_VT_MOUSE_EVENT_H
+
+#include <stdbool.h>
+#include <ghostty/vt/allocator.h>
+#include <ghostty/vt/key/event.h>
+#include <ghostty/vt/types.h>
+
+/**
+ * Opaque handle to a mouse event.
+ *
+ * This handle represents a normalized mouse input event containing
+ * action, button, modifiers, and surface-space position.
+ *
+ * @ingroup mouse
+ */
+typedef struct GhosttyMouseEventImpl *GhosttyMouseEvent;
+
+/**
+ * Mouse event action type.
+ *
+ * @ingroup mouse
+ */
+typedef enum {
+ /** Mouse button was pressed. */
+ GHOSTTY_MOUSE_ACTION_PRESS = 0,
+
+ /** Mouse button was released. */
+ GHOSTTY_MOUSE_ACTION_RELEASE = 1,
+
+ /** Mouse moved. */
+ GHOSTTY_MOUSE_ACTION_MOTION = 2,
+} GhosttyMouseAction;
+
+/**
+ * Mouse button identity.
+ *
+ * @ingroup mouse
+ */
+typedef enum {
+ GHOSTTY_MOUSE_BUTTON_UNKNOWN = 0,
+ GHOSTTY_MOUSE_BUTTON_LEFT = 1,
+ GHOSTTY_MOUSE_BUTTON_RIGHT = 2,
+ GHOSTTY_MOUSE_BUTTON_MIDDLE = 3,
+ GHOSTTY_MOUSE_BUTTON_FOUR = 4,
+ GHOSTTY_MOUSE_BUTTON_FIVE = 5,
+ GHOSTTY_MOUSE_BUTTON_SIX = 6,
+ GHOSTTY_MOUSE_BUTTON_SEVEN = 7,
+ GHOSTTY_MOUSE_BUTTON_EIGHT = 8,
+ GHOSTTY_MOUSE_BUTTON_NINE = 9,
+ GHOSTTY_MOUSE_BUTTON_TEN = 10,
+ GHOSTTY_MOUSE_BUTTON_ELEVEN = 11,
+} GhosttyMouseButton;
+
+/**
+ * Mouse position in surface-space pixels.
+ *
+ * @ingroup mouse
+ */
+typedef struct {
+ float x;
+ float y;
+} GhosttyMousePosition;
+
+/**
+ * Create a new mouse event instance.
+ *
+ * @param allocator Pointer to allocator, or NULL to use the default allocator
+ * @param event Pointer to store the created event handle
+ * @return GHOSTTY_SUCCESS on success, or an error code on failure
+ *
+ * @ingroup mouse
+ */
+GHOSTTY_API GhosttyResult ghostty_mouse_event_new(const GhosttyAllocator *allocator,
+ GhosttyMouseEvent *event);
+
+/**
+ * Free a mouse event instance.
+ *
+ * @param event The mouse event handle to free (may be NULL)
+ *
+ * @ingroup mouse
+ */
+GHOSTTY_API void ghostty_mouse_event_free(GhosttyMouseEvent event);
+
+/**
+ * Set the event action.
+ *
+ * @param event The event handle, must not be NULL
+ * @param action The action to set
+ *
+ * @ingroup mouse
+ */
+GHOSTTY_API void ghostty_mouse_event_set_action(GhosttyMouseEvent event,
+ GhosttyMouseAction action);
+
+/**
+ * Get the event action.
+ *
+ * @param event The event handle, must not be NULL
+ * @return The event action
+ *
+ * @ingroup mouse
+ */
+GHOSTTY_API GhosttyMouseAction ghostty_mouse_event_get_action(GhosttyMouseEvent event);
+
+/**
+ * Set the event button.
+ *
+ * This sets a concrete button identity for the event.
+ * To represent "no button" (for motion events), use
+ * ghostty_mouse_event_clear_button().
+ *
+ * @param event The event handle, must not be NULL
+ * @param button The button to set
+ *
+ * @ingroup mouse
+ */
+GHOSTTY_API void ghostty_mouse_event_set_button(GhosttyMouseEvent event,
+ GhosttyMouseButton button);
+
+/**
+ * Clear the event button.
+ *
+ * This sets the event button to "none".
+ *
+ * @param event The event handle, must not be NULL
+ *
+ * @ingroup mouse
+ */
+GHOSTTY_API void ghostty_mouse_event_clear_button(GhosttyMouseEvent event);
+
+/**
+ * Get the event button.
+ *
+ * @param event The event handle, must not be NULL
+ * @param out_button Output pointer for the button value (may be NULL)
+ * @return true if a button is set, false if no button is set
+ *
+ * @ingroup mouse
+ */
+GHOSTTY_API bool ghostty_mouse_event_get_button(GhosttyMouseEvent event,
+ GhosttyMouseButton *out_button);
+
+/**
+ * Set keyboard modifiers held during the event.
+ *
+ * @param event The event handle, must not be NULL
+ * @param mods Modifier bitmask
+ *
+ * @ingroup mouse
+ */
+GHOSTTY_API void ghostty_mouse_event_set_mods(GhosttyMouseEvent event,
+ GhosttyMods mods);
+
+/**
+ * Get keyboard modifiers held during the event.
+ *
+ * @param event The event handle, must not be NULL
+ * @return Modifier bitmask
+ *
+ * @ingroup mouse
+ */
+GHOSTTY_API GhosttyMods ghostty_mouse_event_get_mods(GhosttyMouseEvent event);
+
+/**
+ * Set the event position in surface-space pixels.
+ *
+ * @param event The event handle, must not be NULL
+ * @param position The position to set
+ *
+ * @ingroup mouse
+ */
+GHOSTTY_API void ghostty_mouse_event_set_position(GhosttyMouseEvent event,
+ GhosttyMousePosition position);
+
+/**
+ * Get the event position in surface-space pixels.
+ *
+ * @param event The event handle, must not be NULL
+ * @return The current event position
+ *
+ * @ingroup mouse
+ */
+GHOSTTY_API GhosttyMousePosition ghostty_mouse_event_get_position(GhosttyMouseEvent event);
+
+#endif /* GHOSTTY_VT_MOUSE_EVENT_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt/osc.h b/vendor/libghostty-vt/include/ghostty/vt/osc.h
new file mode 100644
index 00000000..c8649809
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/osc.h
@@ -0,0 +1,233 @@
+/**
+ * @file osc.h
+ *
+ * OSC (Operating System Command) sequence parser and command handling.
+ */
+
+#ifndef GHOSTTY_VT_OSC_H
+#define GHOSTTY_VT_OSC_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <ghostty/vt/types.h>
+#include <ghostty/vt/allocator.h>
+
+/**
+ * Opaque handle to an OSC parser instance.
+ *
+ * This handle represents an OSC (Operating System Command) parser that can
+ * be used to parse the contents of OSC sequences.
+ *
+ * @ingroup osc
+ */
+typedef struct GhosttyOscParserImpl *GhosttyOscParser;
+
+/**
+ * Opaque handle to a single OSC command.
+ *
+ * This handle represents a parsed OSC (Operating System Command) command.
+ * The command can be queried for its type and associated data.
+ *
+ * @ingroup osc
+ */
+typedef struct GhosttyOscCommandImpl *GhosttyOscCommand;
+
+/** @defgroup osc OSC Parser
+ *
+ * OSC (Operating System Command) sequence parser and command handling.
+ *
+ * The parser operates in a streaming fashion, processing input byte-by-byte
+ * to handle OSC sequences that may arrive in fragments across multiple reads.
+ * This interface makes it easy to integrate into most environments and avoids
+ * over-allocating buffers.
+ *
+ * ## Basic Usage
+ *
+ * 1. Create a parser instance with ghostty_osc_new()
+ * 2. Feed bytes to the parser using ghostty_osc_next()
+ * 3. Finalize parsing with ghostty_osc_end() to get the command
+ * 4. Query command type and extract data using ghostty_osc_command_type()
+ * and ghostty_osc_command_data()
+ * 5. Free the parser with ghostty_osc_free() when done
+ *
+ * @{
+ */
+
+/**
+ * OSC command types.
+ *
+ * @ingroup osc
+ */
+typedef enum {
+ GHOSTTY_OSC_COMMAND_INVALID = 0,
+ GHOSTTY_OSC_COMMAND_CHANGE_WINDOW_TITLE = 1,
+ GHOSTTY_OSC_COMMAND_CHANGE_WINDOW_ICON = 2,
+ GHOSTTY_OSC_COMMAND_SEMANTIC_PROMPT = 3,
+ GHOSTTY_OSC_COMMAND_CLIPBOARD_CONTENTS = 4,
+ GHOSTTY_OSC_COMMAND_REPORT_PWD = 5,
+ GHOSTTY_OSC_COMMAND_MOUSE_SHAPE = 6,
+ GHOSTTY_OSC_COMMAND_COLOR_OPERATION = 7,
+ GHOSTTY_OSC_COMMAND_KITTY_COLOR_PROTOCOL = 8,
+ GHOSTTY_OSC_COMMAND_SHOW_DESKTOP_NOTIFICATION = 9,
+ GHOSTTY_OSC_COMMAND_HYPERLINK_START = 10,
+ GHOSTTY_OSC_COMMAND_HYPERLINK_END = 11,
+ GHOSTTY_OSC_COMMAND_CONEMU_SLEEP = 12,
+ GHOSTTY_OSC_COMMAND_CONEMU_SHOW_MESSAGE_BOX = 13,
+ GHOSTTY_OSC_COMMAND_CONEMU_CHANGE_TAB_TITLE = 14,
+ GHOSTTY_OSC_COMMAND_CONEMU_PROGRESS_REPORT = 15,
+ GHOSTTY_OSC_COMMAND_CONEMU_WAIT_INPUT = 16,
+ GHOSTTY_OSC_COMMAND_CONEMU_GUIMACRO = 17,
+ GHOSTTY_OSC_COMMAND_CONEMU_RUN_PROCESS = 18,
+ GHOSTTY_OSC_COMMAND_CONEMU_OUTPUT_ENVIRONMENT_VARIABLE = 19,
+ GHOSTTY_OSC_COMMAND_CONEMU_XTERM_EMULATION = 20,
+ GHOSTTY_OSC_COMMAND_CONEMU_COMMENT = 21,
+ GHOSTTY_OSC_COMMAND_KITTY_TEXT_SIZING = 22,
+} GhosttyOscCommandType;
+
+/**
+ * OSC command data types.
+ *
+ * These values specify what type of data to extract from an OSC command
+ * using `ghostty_osc_command_data`.
+ *
+ * @ingroup osc
+ */
+typedef enum {
+ /** Invalid data type. Never results in any data extraction. */
+ GHOSTTY_OSC_DATA_INVALID = 0,
+
+ /**
+ * Window title string data.
+ *
+ * Valid for: GHOSTTY_OSC_COMMAND_CHANGE_WINDOW_TITLE
+ *
+ * Output type: const char ** (pointer to null-terminated string)
+ *
+ * Lifetime: Valid until the next call to any ghostty_osc_* function with
+ * the same parser instance. Memory is owned by the parser.
+ */
+ GHOSTTY_OSC_DATA_CHANGE_WINDOW_TITLE_STR = 1,
+} GhosttyOscCommandData;
+
+/**
+ * Create a new OSC parser instance.
+ *
+ * Creates a new OSC (Operating System Command) parser using the provided
+ * allocator. The parser must be freed using ghostty_vt_osc_free() when
+ * no longer needed.
+ *
+ * @param allocator Pointer to the allocator to use for memory management, or NULL to use the default allocator
+ * @param parser Pointer to store the created parser handle
+ * @return GHOSTTY_SUCCESS on success, or an error code on failure
+ *
+ * @ingroup osc
+ */
+GHOSTTY_API GhosttyResult ghostty_osc_new(const GhosttyAllocator *allocator, GhosttyOscParser *parser);
+
+/**
+ * Free an OSC parser instance.
+ *
+ * Releases all resources associated with the OSC parser. After this call,
+ * the parser handle becomes invalid and must not be used.
+ *
+ * @param parser The parser handle to free (may be NULL)
+ *
+ * @ingroup osc
+ */
+GHOSTTY_API void ghostty_osc_free(GhosttyOscParser parser);
+
+/**
+ * Reset an OSC parser instance to its initial state.
+ *
+ * Resets the parser state, clearing any partially parsed OSC sequences
+ * and returning the parser to its initial state. This is useful for
+ * reusing a parser instance or recovering from parse errors.
+ *
+ * @param parser The parser handle to reset, must not be null.
+ *
+ * @ingroup osc
+ */
+GHOSTTY_API void ghostty_osc_reset(GhosttyOscParser parser);
+
+/**
+ * Parse the next byte in an OSC sequence.
+ *
+ * Processes a single byte as part of an OSC sequence. The parser maintains
+ * internal state to track the progress through the sequence. Call this
+ * function for each byte in the sequence data.
+ *
+ * When finished pumping the parser with bytes, call ghostty_osc_end
+ * to get the final result.
+ *
+ * @param parser The parser handle, must not be null.
+ * @param byte The next byte to parse
+ *
+ * @ingroup osc
+ */
+GHOSTTY_API void ghostty_osc_next(GhosttyOscParser parser, uint8_t byte);
+
+/**
+ * Finalize OSC parsing and retrieve the parsed command.
+ *
+ * Call this function after feeding all bytes of an OSC sequence to the parser
+ * using ghostty_osc_next() with the exception of the terminating character
+ * (ESC or ST). This function finalizes the parsing process and returns the
+ * parsed OSC command.
+ *
+ * The return value is never NULL. Invalid commands will return a command
+ * with type GHOSTTY_OSC_COMMAND_INVALID.
+ *
+ * The terminator parameter specifies the byte that terminated the OSC sequence
+ * (typically 0x07 for BEL or 0x5C for ST after ESC). This information is
+ * preserved in the parsed command so that responses can use the same terminator
+ * format for better compatibility with the calling program. For commands that
+ * do not require a response, this parameter is ignored and the resulting
+ * command will not retain the terminator information.
+ *
+ * The returned command handle is valid until the next call to any
+ * `ghostty_osc_*` function with the same parser instance with the exception
+ * of command introspection functions such as `ghostty_osc_command_type`.
+ *
+ * @param parser The parser handle, must not be null.
+ * @param terminator The terminating byte of the OSC sequence (0x07 for BEL, 0x5C for ST)
+ * @return Handle to the parsed OSC command
+ *
+ * @ingroup osc
+ */
+GHOSTTY_API GhosttyOscCommand ghostty_osc_end(GhosttyOscParser parser, uint8_t terminator);
+
+/**
+ * Get the type of an OSC command.
+ *
+ * Returns the type identifier for the given OSC command. This can be used
+ * to determine what kind of command was parsed and what data might be
+ * available from it.
+ *
+ * @param command The OSC command handle to query (may be NULL)
+ * @return The command type, or GHOSTTY_OSC_COMMAND_INVALID if command is NULL
+ *
+ * @ingroup osc
+ */
+GHOSTTY_API GhosttyOscCommandType ghostty_osc_command_type(GhosttyOscCommand command);
+
+/**
+ * Extract data from an OSC command.
+ *
+ * Extracts typed data from the given OSC command based on the specified
+ * data type. The output pointer must be of the appropriate type for the
+ * requested data kind. Valid command types, output types, and memory
+ * safety information are documented in the `GhosttyOscCommandData` enum.
+ *
+ * @param command The OSC command handle to query (may be NULL)
+ * @param data The type of data to extract
+ * @param out Pointer to store the extracted data (type depends on data parameter)
+ * @return true if data extraction was successful, false otherwise
+ *
+ * @ingroup osc
+ */
+GHOSTTY_API bool ghostty_osc_command_data(GhosttyOscCommand command, GhosttyOscCommandData data, void *out);
+
+/** @} */
+
+#endif /* GHOSTTY_VT_OSC_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt/paste.h b/vendor/libghostty-vt/include/ghostty/vt/paste.h
new file mode 100644
index 00000000..b3df5be4
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/paste.h
@@ -0,0 +1,101 @@
+/**
+ * @file paste.h
+ *
+ * Paste utilities - validate and encode paste data for terminal input.
+ */
+
+#ifndef GHOSTTY_VT_PASTE_H
+#define GHOSTTY_VT_PASTE_H
+
+/** @defgroup paste Paste Utilities
+ *
+ * Utilities for validating and encoding paste data for terminal input.
+ *
+ * ## Basic Usage
+ *
+ * Use ghostty_paste_is_safe() to check if paste data contains potentially
+ * dangerous sequences before sending it to the terminal.
+ *
+ * Use ghostty_paste_encode() to encode paste data for writing to the pty,
+ * including bracketed paste wrapping and unsafe byte stripping.
+ *
+ * ## Examples
+ *
+ * ### Safety Check
+ *
+ * @snippet c-vt-paste/src/main.c paste-safety
+ *
+ * ### Encoding
+ *
+ * @snippet c-vt-paste/src/main.c paste-encode
+ *
+ * @{
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <ghostty/vt/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Check if paste data is safe to paste into the terminal.
+ *
+ * Data is considered unsafe if it contains:
+ * - Newlines (`\n`) which can inject commands
+ * - The bracketed paste end sequence (`\x1b[201~`) which can be used
+ * to exit bracketed paste mode and inject commands
+ *
+ * This check is conservative and considers data unsafe regardless of
+ * current terminal state.
+ *
+ * @param data The paste data to check (must not be NULL)
+ * @param len The length of the data in bytes
+ * @return true if the data is safe to paste, false otherwise
+ */
+GHOSTTY_API bool ghostty_paste_is_safe(const char* data, size_t len);
+
+/**
+ * Encode paste data for writing to the terminal pty.
+ *
+ * This function prepares paste data for terminal input by:
+ * - Stripping unsafe control bytes (NUL, ESC, DEL, etc.) by replacing
+ * them with spaces
+ * - Wrapping the data in bracketed paste sequences if @p bracketed is true
+ * - Replacing newlines with carriage returns if @p bracketed is false
+ *
+ * The input @p data buffer is modified in place during encoding. The
+ * encoded result (potentially with bracketed paste prefix/suffix) is
+ * written to the output buffer.
+ *
+ * If the output buffer is too small, the function returns
+ * GHOSTTY_OUT_OF_SPACE and sets the required size in @p out_written.
+ * The caller can then retry with a sufficiently sized buffer.
+ *
+ * @param data The paste data to encode (modified in place, may be NULL)
+ * @param data_len The length of the input data in bytes
+ * @param bracketed Whether bracketed paste mode is active
+ * @param buf Output buffer to write the encoded result into (may be NULL)
+ * @param buf_len Size of the output buffer in bytes
+ * @param[out] out_written On success, the number of bytes written. On
+ * GHOSTTY_OUT_OF_SPACE, the required buffer size.
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_OUT_OF_SPACE if the buffer
+ * is too small
+ */
+GHOSTTY_API GhosttyResult ghostty_paste_encode(
+ char* data,
+ size_t data_len,
+ bool bracketed,
+ char* buf,
+ size_t buf_len,
+ size_t* out_written);
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif /* GHOSTTY_VT_PASTE_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt/point.h b/vendor/libghostty-vt/include/ghostty/vt/point.h
new file mode 100644
index 00000000..f152a5c4
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/point.h
@@ -0,0 +1,88 @@
+/**
+ * @file point.h
+ *
+ * Terminal point types for referencing locations in the terminal grid.
+ */
+
+#ifndef GHOSTTY_VT_POINT_H
+#define GHOSTTY_VT_POINT_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup point Point
+ *
+ * Types for referencing x/y positions in the terminal grid under
+ * different coordinate systems (active area, viewport, full screen,
+ * scrollback history).
+ *
+ * @{
+ */
+
+/**
+ * A coordinate in the terminal grid.
+ *
+ * @ingroup point
+ */
+typedef struct {
+ /** Column (0-indexed). */
+ uint16_t x;
+
+ /** Row (0-indexed). May exceed page size for screen/history tags. */
+ uint32_t y;
+} GhosttyPointCoordinate;
+
+/**
+ * Point reference tag.
+ *
+ * Determines which coordinate system a point uses.
+ *
+ * @ingroup point
+ */
+typedef enum {
+ /** Active area where the cursor can move. */
+ GHOSTTY_POINT_TAG_ACTIVE = 0,
+
+ /** Visible viewport (changes when scrolled). */
+ GHOSTTY_POINT_TAG_VIEWPORT = 1,
+
+ /** Full screen including scrollback. */
+ GHOSTTY_POINT_TAG_SCREEN = 2,
+
+ /** Scrollback history only (before active area). */
+ GHOSTTY_POINT_TAG_HISTORY = 3,
+} GhosttyPointTag;
+
+/**
+ * Point value union.
+ *
+ * @ingroup point
+ */
+typedef union {
+ /** Coordinate (used for all tag variants). */
+ GhosttyPointCoordinate coordinate;
+
+ /** Padding for ABI compatibility. Do not use. */
+ uint64_t _padding[2];
+} GhosttyPointValue;
+
+/**
+ * Tagged union for a point in the terminal grid.
+ *
+ * @ingroup point
+ */
+typedef struct {
+ GhosttyPointTag tag;
+ GhosttyPointValue value;
+} GhosttyPoint;
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GHOSTTY_VT_POINT_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt/render.h b/vendor/libghostty-vt/include/ghostty/vt/render.h
new file mode 100644
index 00000000..163a4e1d
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/render.h
@@ -0,0 +1,603 @@
+/**
+ * @file render.h
+ *
+ * Render state for creating high performance renderers.
+ */
+
+#ifndef GHOSTTY_VT_RENDER_H
+#define GHOSTTY_VT_RENDER_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <ghostty/vt/allocator.h>
+#include <ghostty/vt/color.h>
+#include <ghostty/vt/terminal.h>
+#include <ghostty/vt/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup render Render State
+ *
+ * Represents the state required to render a visible screen (a viewport)
+ * of a terminal instance. This is stateful and optimized for repeated
+ * updates from a single terminal instance and only updating dirty regions
+ * of the screen.
+ *
+ * The key design principle of this API is that it only needs read/write
+ * access to the terminal instance during the update call. This allows
+ * the render state to minimally impact terminal IO performance and also
+ * allows the renderer to be safely multi-threaded (as long as a lock is
+ * held during the update call to ensure exclusive access to the terminal
+ * instance).
+ *
+ * The basic usage of this API is:
+ *
+ * 1. Create an empty render state
+ * 2. Update it from a terminal instance whenever you need.
+ * 3. Read from the render state to get the data needed to draw your frame.
+ *
+ * ## Dirty Tracking
+ *
+ * Dirty tracking is a key feature of the render state that allows renderers
+ * to efficiently determine what parts of the screen have changed and only
+ * redraw changed regions.
+ *
+ * The render state API keeps track of dirty state at two independent layers:
+ * a global dirty state that indicates whether the entire frame is clean,
+ * partially dirty, or fully dirty, and a per-row dirty state that allows
+ * tracking which rows in a partially dirty frame have changed.
+ *
+ * The user of the render state API is expected to unset both of these.
+ * The `update` call does not unset dirty state, it only updates it.
+ *
+ * An extremely important detail: setting one dirty state doesn't unset
+ * the other. For example, setting the global dirty state to false does not
+ * reset the row-level dirty flags. So, the caller of the render state API must
+ * be careful to manage both layers of dirty state correctly.
+ *
+ * ## Examples
+ *
+ * ### Creating and updating render state
+ * @snippet c-vt-render/src/main.c render-state-update
+ *
+ * ### Checking dirty state
+ * @snippet c-vt-render/src/main.c render-dirty-check
+ *
+ * ### Reading colors
+ * @snippet c-vt-render/src/main.c render-colors
+ *
+ * ### Reading cursor state
+ * @snippet c-vt-render/src/main.c render-cursor
+ *
+ * ### Iterating rows and cells
+ * @snippet c-vt-render/src/main.c render-row-iterate
+ *
+ * ### Resetting dirty state after rendering
+ * @snippet c-vt-render/src/main.c render-dirty-reset
+ *
+ * @{
+ */
+
+/**
+ * Opaque handle to a render state instance.
+ *
+ * @ingroup render
+ */
+typedef struct GhosttyRenderStateImpl* GhosttyRenderState;
+
+/**
+ * Opaque handle to a render-state row iterator.
+ *
+ * @ingroup render
+ */
+typedef struct GhosttyRenderStateRowIteratorImpl* GhosttyRenderStateRowIterator;
+
+/**
+ * Opaque handle to render-state row cells.
+ *
+ * @ingroup render
+ */
+typedef struct GhosttyRenderStateRowCellsImpl* GhosttyRenderStateRowCells;
+
+/**
+ * Dirty state of a render state after update.
+ *
+ * @ingroup render
+ */
+typedef enum {
+ /** Not dirty at all; rendering can be skipped. */
+ GHOSTTY_RENDER_STATE_DIRTY_FALSE = 0,
+
+ /** Some rows changed; renderer can redraw incrementally. */
+ GHOSTTY_RENDER_STATE_DIRTY_PARTIAL = 1,
+
+ /** Global state changed; renderer should redraw everything. */
+ GHOSTTY_RENDER_STATE_DIRTY_FULL = 2,
+} GhosttyRenderStateDirty;
+
+/**
+ * Visual style of the cursor.
+ *
+ * @ingroup render
+ */
+typedef enum {
+ /** Bar cursor (DECSCUSR 5, 6). */
+ GHOSTTY_RENDER_STATE_CURSOR_VISUAL_STYLE_BAR = 0,
+
+ /** Block cursor (DECSCUSR 1, 2). */
+ GHOSTTY_RENDER_STATE_CURSOR_VISUAL_STYLE_BLOCK = 1,
+
+ /** Underline cursor (DECSCUSR 3, 4). */
+ GHOSTTY_RENDER_STATE_CURSOR_VISUAL_STYLE_UNDERLINE = 2,
+
+ /** Hollow block cursor. */
+ GHOSTTY_RENDER_STATE_CURSOR_VISUAL_STYLE_BLOCK_HOLLOW = 3,
+} GhosttyRenderStateCursorVisualStyle;
+
+/**
+ * Queryable data kinds for ghostty_render_state_get().
+ *
+ * @ingroup render
+ */
+typedef enum {
+ /** Invalid / sentinel value. */
+ GHOSTTY_RENDER_STATE_DATA_INVALID = 0,
+
+ /** Viewport width in cells (uint16_t). */
+ GHOSTTY_RENDER_STATE_DATA_COLS = 1,
+
+ /** Viewport height in cells (uint16_t). */
+ GHOSTTY_RENDER_STATE_DATA_ROWS = 2,
+
+ /** Current dirty state (GhosttyRenderStateDirty). */
+ GHOSTTY_RENDER_STATE_DATA_DIRTY = 3,
+
+ /** Populate a pre-allocated GhosttyRenderStateRowIterator with row data
+ * from the render state (GhosttyRenderStateRowIterator). Row data is
+ * only valid as long as the underlying render state is not updated.
+ * It is unsafe to use row data after updating the render state.
+ * */
+ GHOSTTY_RENDER_STATE_DATA_ROW_ITERATOR = 4,
+
+ /** Default/current background color (GhosttyColorRgb). */
+ GHOSTTY_RENDER_STATE_DATA_COLOR_BACKGROUND = 5,
+
+ /** Default/current foreground color (GhosttyColorRgb). */
+ GHOSTTY_RENDER_STATE_DATA_COLOR_FOREGROUND = 6,
+
+ /** Cursor color when explicitly set by terminal state (GhosttyColorRgb).
+ * Returns GHOSTTY_INVALID_VALUE if no explicit cursor color is set;
+ * use COLOR_CURSOR_HAS_VALUE to check first. */
+ GHOSTTY_RENDER_STATE_DATA_COLOR_CURSOR = 7,
+
+ /** Whether an explicit cursor color is set (bool). */
+ GHOSTTY_RENDER_STATE_DATA_COLOR_CURSOR_HAS_VALUE = 8,
+
+ /** The active 256-color palette (GhosttyColorRgb[256]). */
+ GHOSTTY_RENDER_STATE_DATA_COLOR_PALETTE = 9,
+
+ /** The visual style of the cursor (GhosttyRenderStateCursorVisualStyle). */
+ GHOSTTY_RENDER_STATE_DATA_CURSOR_VISUAL_STYLE = 10,
+
+ /** Whether the cursor is visible based on terminal modes (bool). */
+ GHOSTTY_RENDER_STATE_DATA_CURSOR_VISIBLE = 11,
+
+ /** Whether the cursor should blink based on terminal modes (bool). */
+ GHOSTTY_RENDER_STATE_DATA_CURSOR_BLINKING = 12,
+
+ /** Whether the cursor is at a password input field (bool). */
+ GHOSTTY_RENDER_STATE_DATA_CURSOR_PASSWORD_INPUT = 13,
+
+ /** Whether the cursor is visible within the viewport (bool).
+ * If false, the cursor viewport position values are undefined. */
+ GHOSTTY_RENDER_STATE_DATA_CURSOR_VIEWPORT_HAS_VALUE = 14,
+
+ /** Cursor viewport x position in cells (uint16_t).
+ * Only valid when CURSOR_VIEWPORT_HAS_VALUE is true. */
+ GHOSTTY_RENDER_STATE_DATA_CURSOR_VIEWPORT_X = 15,
+
+ /** Cursor viewport y position in cells (uint16_t).
+ * Only valid when CURSOR_VIEWPORT_HAS_VALUE is true. */
+ GHOSTTY_RENDER_STATE_DATA_CURSOR_VIEWPORT_Y = 16,
+
+ /** Whether the cursor is on the tail of a wide character (bool).
+ * Only valid when CURSOR_VIEWPORT_HAS_VALUE is true. */
+ GHOSTTY_RENDER_STATE_DATA_CURSOR_VIEWPORT_WIDE_TAIL = 17,
+} GhosttyRenderStateData;
+
+/**
+ * Settable options for ghostty_render_state_set().
+ *
+ * @ingroup render
+ */
+typedef enum {
+ /** Set dirty state (GhosttyRenderStateDirty). */
+ GHOSTTY_RENDER_STATE_OPTION_DIRTY = 0,
+} GhosttyRenderStateOption;
+
+/**
+ * Queryable data kinds for ghostty_render_state_row_get().
+ *
+ * @ingroup render
+ */
+typedef enum {
+ /** Invalid / sentinel value. */
+ GHOSTTY_RENDER_STATE_ROW_DATA_INVALID = 0,
+
+ /** Whether the current row is dirty (bool). */
+ GHOSTTY_RENDER_STATE_ROW_DATA_DIRTY = 1,
+
+ /** The raw row value (GhosttyRow). */
+ GHOSTTY_RENDER_STATE_ROW_DATA_RAW = 2,
+
+ /** Populate a pre-allocated GhosttyRenderStateRowCells with cell data for
+ * the current row (GhosttyRenderStateRowCells). Cell data is only
+ * valid as long as the underlying render state is not updated.
+ * It is unsafe to use cell data after updating the render state. */
+ GHOSTTY_RENDER_STATE_ROW_DATA_CELLS = 3,
+} GhosttyRenderStateRowData;
+
+/**
+ * Settable options for ghostty_render_state_row_set().
+ *
+ * @ingroup render
+ */
+typedef enum {
+ /** Set dirty state for the current row (bool). */
+ GHOSTTY_RENDER_STATE_ROW_OPTION_DIRTY = 0,
+} GhosttyRenderStateRowOption;
+
+/**
+ * Render-state color information.
+ *
+ * This struct uses the sized-struct ABI pattern. Initialize with
+ * GHOSTTY_INIT_SIZED(GhosttyRenderStateColors) before calling
+ * ghostty_render_state_colors_get().
+ *
+ * Example:
+ * @code
+ * GhosttyRenderStateColors colors = GHOSTTY_INIT_SIZED(GhosttyRenderStateColors);
+ * GhosttyResult result = ghostty_render_state_colors_get(state, &colors);
+ * @endcode
+ *
+ * @ingroup render
+ */
+typedef struct {
+ /** Size of this struct in bytes. Must be set to sizeof(GhosttyRenderStateColors). */
+ size_t size;
+
+ /** The default/current background color for the render state. */
+ GhosttyColorRgb background;
+
+ /** The default/current foreground color for the render state. */
+ GhosttyColorRgb foreground;
+
+ /** The cursor color when explicitly set by terminal state. */
+ GhosttyColorRgb cursor;
+
+ /**
+ * True when cursor contains a valid explicit cursor color value.
+ * If this is false, the cursor color should be ignored; it will
+ * contain undefined data.
+ * */
+ bool cursor_has_value;
+
+ /** The active 256-color palette for this render state. */
+ GhosttyColorRgb palette[256];
+} GhosttyRenderStateColors;
+
+/**
+ * Create a new render state instance.
+ *
+ * @param allocator Pointer to allocator, or NULL to use the default allocator
+ * @param state Pointer to store the created render state handle
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_OUT_OF_MEMORY on allocation
+ * failure
+ *
+ * @ingroup render
+ */
+GHOSTTY_API GhosttyResult ghostty_render_state_new(const GhosttyAllocator* allocator,
+ GhosttyRenderState* state);
+
+/**
+ * Free a render state instance.
+ *
+ * Releases all resources associated with the render state. After this call,
+ * the render state handle becomes invalid.
+ *
+ * @param state The render state handle to free (may be NULL)
+ *
+ * @ingroup render
+ */
+GHOSTTY_API void ghostty_render_state_free(GhosttyRenderState state);
+
+/**
+ * Update a render state instance from a terminal.
+ *
+ * This consumes terminal/screen dirty state in the same way as the internal
+ * render state update path.
+ *
+ * @param state The render state handle (NULL returns GHOSTTY_INVALID_VALUE)
+ * @param terminal The terminal handle to read from (NULL returns GHOSTTY_INVALID_VALUE)
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if `state` or
+ * `terminal` is NULL, GHOSTTY_OUT_OF_MEMORY if updating the state requires
+ * allocation and that allocation fails
+ *
+ * @ingroup render
+ */
+GHOSTTY_API GhosttyResult ghostty_render_state_update(GhosttyRenderState state,
+ GhosttyTerminal terminal);
+
+/**
+ * Get a value from a render state.
+ *
+ * The `out` pointer must point to a value of the type corresponding to the
+ * requested data kind (see GhosttyRenderStateData).
+ *
+ * @param state The render state handle (NULL returns GHOSTTY_INVALID_VALUE)
+ * @param data The data kind to query
+ * @param[out] out Pointer to receive the queried value
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if `state` is
+ * NULL or `data` is not a recognized enum value
+ *
+ * @ingroup render
+ */
+GHOSTTY_API GhosttyResult ghostty_render_state_get(GhosttyRenderState state,
+ GhosttyRenderStateData data,
+ void* out);
+
+/**
+ * Set an option on a render state.
+ *
+ * The `value` pointer must point to a value of the type corresponding to the
+ * requested option kind (see GhosttyRenderStateOption).
+ *
+ * @param state The render state handle (NULL returns GHOSTTY_INVALID_VALUE)
+ * @param option The option to set
+ * @param[in] value Pointer to the value to set (NULL returns
+ * GHOSTTY_INVALID_VALUE)
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if `state` or
+ * `value` is NULL
+ *
+ * @ingroup render
+ */
+GHOSTTY_API GhosttyResult ghostty_render_state_set(GhosttyRenderState state,
+ GhosttyRenderStateOption option,
+ const void* value);
+
+/**
+ * Get the current color information from a render state.
+ *
+ * This writes as many fields as fit in the caller-provided sized struct.
+ * `out_colors->size` must be set by the caller (typically via
+ * GHOSTTY_INIT_SIZED(GhosttyRenderStateColors)).
+ *
+ * @param state The render state handle (NULL returns GHOSTTY_INVALID_VALUE)
+ * @param[out] out_colors Sized output struct to receive render-state colors
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if `state` or
+ * `out_colors` is NULL, or if `out_colors->size` is smaller than
+ * `sizeof(size_t)`
+ *
+ * @ingroup render
+ */
+GHOSTTY_API GhosttyResult ghostty_render_state_colors_get(GhosttyRenderState state,
+ GhosttyRenderStateColors* out_colors);
+
+/**
+ * Create a new row iterator instance.
+ *
+ * All fields except the allocator are left undefined until populated
+ * via ghostty_render_state_get() with
+ * GHOSTTY_RENDER_STATE_DATA_ROW_ITERATOR.
+ *
+ * @param allocator Pointer to allocator, or NULL to use the default allocator
+ * @param[out] out_iterator On success, receives the created iterator handle
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_OUT_OF_MEMORY on allocation
+ * failure
+ *
+ * @ingroup render
+ */
+GHOSTTY_API GhosttyResult ghostty_render_state_row_iterator_new(
+ const GhosttyAllocator* allocator,
+ GhosttyRenderStateRowIterator* out_iterator);
+
+/**
+ * Free a render-state row iterator.
+ *
+ * @param iterator The iterator handle to free (may be NULL)
+ *
+ * @ingroup render
+ */
+GHOSTTY_API void ghostty_render_state_row_iterator_free(GhosttyRenderStateRowIterator iterator);
+
+/**
+ * Move a render-state row iterator to the next row.
+ *
+ * Returns true if the iterator moved successfully and row data is
+ * available to read at the new position.
+ *
+ * @param iterator The iterator handle to advance (may be NULL)
+ * @return true if advanced to the next row, false if `iterator` is
+ * NULL or if the iterator has reached the end
+ *
+ * @ingroup render
+ */
+GHOSTTY_API bool ghostty_render_state_row_iterator_next(GhosttyRenderStateRowIterator iterator);
+
+/**
+ * Get a value from the current row in a render-state row iterator.
+ *
+ * The `out` pointer must point to a value of the type corresponding to the
+ * requested data kind (see GhosttyRenderStateRowData).
+ * Call ghostty_render_state_row_iterator_next() at least once before
+ * calling this function.
+ *
+ * @param iterator The iterator handle to query (NULL returns GHOSTTY_INVALID_VALUE)
+ * @param data The data kind to query
+ * @param[out] out Pointer to receive the queried value
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if
+ * `iterator` is NULL or the iterator is not positioned on a row
+ *
+ * @ingroup render
+ */
+GHOSTTY_API GhosttyResult ghostty_render_state_row_get(
+ GhosttyRenderStateRowIterator iterator,
+ GhosttyRenderStateRowData data,
+ void* out);
+
+/**
+ * Set an option on the current row in a render-state row iterator.
+ *
+ * The `value` pointer must point to a value of the type corresponding to the
+ * requested option kind (see GhosttyRenderStateRowOption).
+ * Call ghostty_render_state_row_iterator_next() at least once before
+ * calling this function.
+ *
+ * @param iterator The iterator handle to update (NULL returns GHOSTTY_INVALID_VALUE)
+ * @param option The option to set
+ * @param[in] value Pointer to the value to set (NULL returns
+ * GHOSTTY_INVALID_VALUE)
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if
+ * `iterator` is NULL or the iterator is not positioned on a row
+ *
+ * @ingroup render
+ */
+GHOSTTY_API GhosttyResult ghostty_render_state_row_set(
+ GhosttyRenderStateRowIterator iterator,
+ GhosttyRenderStateRowOption option,
+ const void* value);
+
+/**
+ * Create a new row cells instance.
+ *
+ * All fields except the allocator are left undefined until populated
+ * via ghostty_render_state_row_get() with
+ * GHOSTTY_RENDER_STATE_ROW_DATA_CELLS.
+ *
+ * You can reuse this value repeatedly with ghostty_render_state_row_get() to
+ * avoid allocating a new cells container for every row.
+ *
+ * @param allocator Pointer to allocator, or NULL to use the default allocator
+ * @param[out] out_cells On success, receives the created row cells handle
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_OUT_OF_MEMORY on allocation
+ * failure
+ *
+ * @ingroup render
+ */
+GHOSTTY_API GhosttyResult ghostty_render_state_row_cells_new(
+ const GhosttyAllocator* allocator,
+ GhosttyRenderStateRowCells* out_cells);
+
+/**
+ * Queryable data kinds for ghostty_render_state_row_cells_get().
+ *
+ * @ingroup render
+ */
+typedef enum {
+ /** Invalid / sentinel value. */
+ GHOSTTY_RENDER_STATE_ROW_CELLS_DATA_INVALID = 0,
+
+ /** The raw cell value (GhosttyCell). */
+ GHOSTTY_RENDER_STATE_ROW_CELLS_DATA_RAW = 1,
+
+ /** The style for the current cell (GhosttyStyle). */
+ GHOSTTY_RENDER_STATE_ROW_CELLS_DATA_STYLE = 2,
+
+ /** The total number of grapheme codepoints including the base codepoint
+ * (uint32_t). Returns 0 if the cell has no text. */
+ GHOSTTY_RENDER_STATE_ROW_CELLS_DATA_GRAPHEMES_LEN = 3,
+
+ /** Write grapheme codepoints into a caller-provided buffer (uint32_t*).
+ * The buffer must be at least graphemes_len elements. The base codepoint
+ * is written first, followed by any extra codepoints. */
+ GHOSTTY_RENDER_STATE_ROW_CELLS_DATA_GRAPHEMES_BUF = 4,
+
+ /** The resolved background color of the cell (GhosttyColorRgb).
+ * Flattens the three possible sources: content-tag bg_color_rgb,
+ * content-tag bg_color_palette (looked up in the palette), or the
+ * style's bg_color. Returns GHOSTTY_INVALID_VALUE if the cell has
+ * no background color, in which case the caller should use whatever
+ * default background color it wants (e.g. the terminal background). */
+ GHOSTTY_RENDER_STATE_ROW_CELLS_DATA_BG_COLOR = 5,
+
+ /** The resolved foreground color of the cell (GhosttyColorRgb).
+ * Resolves palette indices through the palette. Bold color handling
+ * is not applied; the caller should handle bold styling separately.
+ * Returns GHOSTTY_INVALID_VALUE if the cell has no explicit foreground
+ * color, in which case the caller should use whatever default foreground
+ * color it wants (e.g. the terminal foreground). */
+ GHOSTTY_RENDER_STATE_ROW_CELLS_DATA_FG_COLOR = 6,
+} GhosttyRenderStateRowCellsData;
+
+/**
+ * Move a render-state row cells iterator to the next cell.
+ *
+ * Returns true if the iterator moved successfully and cell data is
+ * available to read at the new position.
+ *
+ * @param cells The row cells handle to advance (may be NULL)
+ * @return true if advanced to the next cell, false if `cells` is
+ * NULL or if the iterator has reached the end
+ *
+ * @ingroup render
+ */
+GHOSTTY_API bool ghostty_render_state_row_cells_next(GhosttyRenderStateRowCells cells);
+
+/**
+ * Move a render-state row cells iterator to a specific column.
+ *
+ * Positions the iterator at the given x (column) index so that
+ * subsequent reads return data for that cell.
+ *
+ * @param cells The row cells handle to reposition (NULL returns
+ * GHOSTTY_INVALID_VALUE)
+ * @param x The zero-based column index to select
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if `cells`
+ * is NULL or `x` is out of range
+ *
+ * @ingroup render
+ */
+GHOSTTY_API GhosttyResult ghostty_render_state_row_cells_select(
+ GhosttyRenderStateRowCells cells, uint16_t x);
+
+/**
+ * Get a value from the current cell in a render-state row cells iterator.
+ *
+ * The `out` pointer must point to a value of the type corresponding to the
+ * requested data kind (see GhosttyRenderStateRowCellsData).
+ * Call ghostty_render_state_row_cells_next() or
+ * ghostty_render_state_row_cells_select() at least once before
+ * calling this function.
+ *
+ * @param cells The row cells handle to query (NULL returns GHOSTTY_INVALID_VALUE)
+ * @param data The data kind to query
+ * @param[out] out Pointer to receive the queried value
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if
+ * `cells` is NULL or the iterator is not positioned on a cell
+ *
+ * @ingroup render
+ */
+GHOSTTY_API GhosttyResult ghostty_render_state_row_cells_get(
+ GhosttyRenderStateRowCells cells,
+ GhosttyRenderStateRowCellsData data,
+ void* out);
+
+/**
+ * Free a row cells instance.
+ *
+ * @param cells The row cells handle to free (may be NULL)
+ *
+ * @ingroup render
+ */
+GHOSTTY_API void ghostty_render_state_row_cells_free(GhosttyRenderStateRowCells cells);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GHOSTTY_VT_RENDER_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt/screen.h b/vendor/libghostty-vt/include/ghostty/vt/screen.h
new file mode 100644
index 00000000..89b4825f
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/screen.h
@@ -0,0 +1,340 @@
+/**
+ * @file screen.h
+ *
+ * Terminal screen cell and row types.
+ */
+
+#ifndef GHOSTTY_VT_SCREEN_H
+#define GHOSTTY_VT_SCREEN_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <ghostty/vt/color.h>
+#include <ghostty/vt/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup screen Screen
+ *
+ * Terminal screen cell and row types.
+ *
+ * These types represent the contents of a terminal screen. A GhosttyCell
+ * is a single grid cell and a GhosttyRow is a single row. Both are opaque
+ * values whose fields are accessed via ghostty_cell_get() and
+ * ghostty_row_get() respectively.
+ *
+ * @{
+ */
+
+/**
+ * Opaque cell value.
+ *
+ * Represents a single terminal cell. The internal layout is opaque and
+ * must be queried via ghostty_cell_get(). Obtain cell values from
+ * terminal query APIs.
+ *
+ * @ingroup screen
+ */
+typedef uint64_t GhosttyCell;
+
+/**
+ * Opaque row value.
+ *
+ * Represents a single terminal row. The internal layout is opaque and
+ * must be queried via ghostty_row_get(). Obtain row values from
+ * terminal query APIs.
+ *
+ * @ingroup screen
+ */
+typedef uint64_t GhosttyRow;
+
+/**
+ * Cell content tag.
+ *
+ * Describes what kind of content a cell holds.
+ *
+ * @ingroup screen
+ */
+typedef enum {
+ /** A single codepoint (may be zero for empty). */
+ GHOSTTY_CELL_CONTENT_CODEPOINT = 0,
+
+ /** A codepoint that is part of a multi-codepoint grapheme cluster. */
+ GHOSTTY_CELL_CONTENT_CODEPOINT_GRAPHEME = 1,
+
+ /** No text; background color from palette. */
+ GHOSTTY_CELL_CONTENT_BG_COLOR_PALETTE = 2,
+
+ /** No text; background color as RGB. */
+ GHOSTTY_CELL_CONTENT_BG_COLOR_RGB = 3,
+} GhosttyCellContentTag;
+
+/**
+ * Cell wide property.
+ *
+ * Describes the width behavior of a cell.
+ *
+ * @ingroup screen
+ */
+typedef enum {
+ /** Not a wide character, cell width 1. */
+ GHOSTTY_CELL_WIDE_NARROW = 0,
+
+ /** Wide character, cell width 2. */
+ GHOSTTY_CELL_WIDE_WIDE = 1,
+
+ /** Spacer after wide character. Do not render. */
+ GHOSTTY_CELL_WIDE_SPACER_TAIL = 2,
+
+ /** Spacer at end of soft-wrapped line for a wide character. */
+ GHOSTTY_CELL_WIDE_SPACER_HEAD = 3,
+} GhosttyCellWide;
+
+/**
+ * Semantic content type of a cell.
+ *
+ * Set by semantic prompt sequences (OSC 133) to distinguish between
+ * command output, user input, and shell prompt text.
+ *
+ * @ingroup screen
+ */
+typedef enum {
+ /** Regular output content, such as command output. */
+ GHOSTTY_CELL_SEMANTIC_OUTPUT = 0,
+
+ /** Content that is part of user input. */
+ GHOSTTY_CELL_SEMANTIC_INPUT = 1,
+
+ /** Content that is part of a shell prompt. */
+ GHOSTTY_CELL_SEMANTIC_PROMPT = 2,
+} GhosttyCellSemanticContent;
+
+/**
+ * Cell data types.
+ *
+ * These values specify what type of data to extract from a cell
+ * using `ghostty_cell_get`.
+ *
+ * @ingroup screen
+ */
+typedef enum {
+ /** Invalid data type. Never results in any data extraction. */
+ GHOSTTY_CELL_DATA_INVALID = 0,
+
+ /**
+ * The codepoint of the cell (0 if empty or bg-color-only).
+ *
+ * Output type: uint32_t *
+ */
+ GHOSTTY_CELL_DATA_CODEPOINT = 1,
+
+ /**
+ * The content tag describing what kind of content is in the cell.
+ *
+ * Output type: GhosttyCellContentTag *
+ */
+ GHOSTTY_CELL_DATA_CONTENT_TAG = 2,
+
+ /**
+ * The wide property of the cell.
+ *
+ * Output type: GhosttyCellWide *
+ */
+ GHOSTTY_CELL_DATA_WIDE = 3,
+
+ /**
+ * Whether the cell has text to render.
+ *
+ * Output type: bool *
+ */
+ GHOSTTY_CELL_DATA_HAS_TEXT = 4,
+
+ /**
+ * Whether the cell has non-default styling.
+ *
+ * Output type: bool *
+ */
+ GHOSTTY_CELL_DATA_HAS_STYLING = 5,
+
+ /**
+ * The style ID for the cell (for use with style lookups).
+ *
+ * Output type: uint16_t *
+ */
+ GHOSTTY_CELL_DATA_STYLE_ID = 6,
+
+ /**
+ * Whether the cell has a hyperlink.
+ *
+ * Output type: bool *
+ */
+ GHOSTTY_CELL_DATA_HAS_HYPERLINK = 7,
+
+ /**
+ * Whether the cell is protected.
+ *
+ * Output type: bool *
+ */
+ GHOSTTY_CELL_DATA_PROTECTED = 8,
+
+ /**
+ * The semantic content type of the cell (from OSC 133).
+ *
+ * Output type: GhosttyCellSemanticContent *
+ */
+ GHOSTTY_CELL_DATA_SEMANTIC_CONTENT = 9,
+
+ /**
+ * The palette index for the cell's background color.
+ * Only valid when content_tag is GHOSTTY_CELL_CONTENT_BG_COLOR_PALETTE.
+ *
+ * Output type: GhosttyColorPaletteIndex *
+ */
+ GHOSTTY_CELL_DATA_COLOR_PALETTE = 10,
+
+ /**
+ * The RGB value for the cell's background color.
+ * Only valid when content_tag is GHOSTTY_CELL_CONTENT_BG_COLOR_RGB.
+ *
+ * Output type: GhosttyColorRgb *
+ */
+ GHOSTTY_CELL_DATA_COLOR_RGB = 11,
+} GhosttyCellData;
+
+/**
+ * Row semantic prompt state.
+ *
+ * Indicates whether any cells in a row are part of a shell prompt,
+ * as reported by OSC 133 sequences.
+ *
+ * @ingroup screen
+ */
+typedef enum {
+ /** No prompt cells in this row. */
+ GHOSTTY_ROW_SEMANTIC_NONE = 0,
+
+ /** Prompt cells exist and this is a primary prompt line. */
+ GHOSTTY_ROW_SEMANTIC_PROMPT = 1,
+
+ /** Prompt cells exist and this is a continuation line. */
+ GHOSTTY_ROW_SEMANTIC_PROMPT_CONTINUATION = 2,
+} GhosttyRowSemanticPrompt;
+
+/**
+ * Row data types.
+ *
+ * These values specify what type of data to extract from a row
+ * using `ghostty_row_get`.
+ *
+ * @ingroup screen
+ */
+typedef enum {
+ /** Invalid data type. Never results in any data extraction. */
+ GHOSTTY_ROW_DATA_INVALID = 0,
+
+ /**
+ * Whether this row is soft-wrapped.
+ *
+ * Output type: bool *
+ */
+ GHOSTTY_ROW_DATA_WRAP = 1,
+
+ /**
+ * Whether this row is a continuation of a soft-wrapped row.
+ *
+ * Output type: bool *
+ */
+ GHOSTTY_ROW_DATA_WRAP_CONTINUATION = 2,
+
+ /**
+ * Whether any cells in this row have grapheme clusters.
+ *
+ * Output type: bool *
+ */
+ GHOSTTY_ROW_DATA_GRAPHEME = 3,
+
+ /**
+ * Whether any cells in this row have styling (may have false positives).
+ *
+ * Output type: bool *
+ */
+ GHOSTTY_ROW_DATA_STYLED = 4,
+
+ /**
+ * Whether any cells in this row have hyperlinks (may have false positives).
+ *
+ * Output type: bool *
+ */
+ GHOSTTY_ROW_DATA_HYPERLINK = 5,
+
+ /**
+ * The semantic prompt state of this row.
+ *
+ * Output type: GhosttyRowSemanticPrompt *
+ */
+ GHOSTTY_ROW_DATA_SEMANTIC_PROMPT = 6,
+
+ /**
+ * Whether this row contains a Kitty virtual placeholder.
+ *
+ * Output type: bool *
+ */
+ GHOSTTY_ROW_DATA_KITTY_VIRTUAL_PLACEHOLDER = 7,
+
+ /**
+ * Whether this row is dirty and requires a redraw.
+ *
+ * Output type: bool *
+ */
+ GHOSTTY_ROW_DATA_DIRTY = 8,
+} GhosttyRowData;
+
+/**
+ * Get data from a cell.
+ *
+ * Extracts typed data from the given cell based on the specified
+ * data type. The output pointer must be of the appropriate type for the
+ * requested data kind. Valid data types and output types are documented
+ * in the `GhosttyCellData` enum.
+ *
+ * @param cell The cell value
+ * @param data The type of data to extract
+ * @param out Pointer to store the extracted data (type depends on data parameter)
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if the
+ * data type is invalid
+ *
+ * @ingroup screen
+ */
+GHOSTTY_API GhosttyResult ghostty_cell_get(GhosttyCell cell,
+ GhosttyCellData data,
+ void *out);
+
+/**
+ * Get data from a row.
+ *
+ * Extracts typed data from the given row based on the specified
+ * data type. The output pointer must be of the appropriate type for the
+ * requested data kind. Valid data types and output types are documented
+ * in the `GhosttyRowData` enum.
+ *
+ * @param row The row value
+ * @param data The type of data to extract
+ * @param out Pointer to store the extracted data (type depends on data parameter)
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if the
+ * data type is invalid
+ *
+ * @ingroup screen
+ */
+GHOSTTY_API GhosttyResult ghostty_row_get(GhosttyRow row,
+ GhosttyRowData data,
+ void *out);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GHOSTTY_VT_SCREEN_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt/sgr.h b/vendor/libghostty-vt/include/ghostty/vt/sgr.h
new file mode 100644
index 00000000..01ea3a35
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/sgr.h
@@ -0,0 +1,358 @@
+/**
+ * @file sgr.h
+ *
+ * SGR (Select Graphic Rendition) attribute parsing and handling.
+ */
+
+#ifndef GHOSTTY_VT_SGR_H
+#define GHOSTTY_VT_SGR_H
+
+/** @defgroup sgr SGR Parser
+ *
+ * SGR (Select Graphic Rendition) attribute parser.
+ *
+ * SGR sequences are the syntax used to set styling attributes such as
+ * bold, italic, underline, and colors for text in terminal emulators.
+ * For example, you may be familiar with sequences like `ESC[1;31m`. The
+ * `1;31` is the SGR attribute list.
+ *
+ * The parser processes SGR parameters from CSI sequences (e.g., `ESC[1;31m`)
+ * and returns individual text attributes like bold, italic, colors, etc.
+ * It supports both semicolon (`;`) and colon (`:`) separators, possibly mixed,
+ * and handles various color formats including 8-color, 16-color, 256-color,
+ * X11 named colors, and RGB in multiple formats.
+ *
+ * ## Basic Usage
+ *
+ * 1. Create a parser instance with ghostty_sgr_new()
+ * 2. Set SGR parameters with ghostty_sgr_set_params()
+ * 3. Iterate through attributes using ghostty_sgr_next()
+ * 4. Free the parser with ghostty_sgr_free() when done
+ *
+ * ## Example
+ *
+ * @snippet c-vt-sgr/src/main.c sgr-basic
+ *
+ * @{
+ */
+
+#include <ghostty/vt/allocator.h>
+#include <ghostty/vt/color.h>
+#include <ghostty/vt/types.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Opaque handle to an SGR parser instance.
+ *
+ * This handle represents an SGR (Select Graphic Rendition) parser that can
+ * be used to parse SGR sequences and extract individual text attributes.
+ *
+ * @ingroup sgr
+ */
+typedef struct GhosttySgrParserImpl* GhosttySgrParser;
+
+/**
+ * SGR attribute tags.
+ *
+ * These values identify the type of an SGR attribute in a tagged union.
+ * Use the tag to determine which field in the attribute value union to access.
+ *
+ * @ingroup sgr
+ */
+typedef enum {
+ GHOSTTY_SGR_ATTR_UNSET = 0,
+ GHOSTTY_SGR_ATTR_UNKNOWN = 1,
+ GHOSTTY_SGR_ATTR_BOLD = 2,
+ GHOSTTY_SGR_ATTR_RESET_BOLD = 3,
+ GHOSTTY_SGR_ATTR_ITALIC = 4,
+ GHOSTTY_SGR_ATTR_RESET_ITALIC = 5,
+ GHOSTTY_SGR_ATTR_FAINT = 6,
+ GHOSTTY_SGR_ATTR_UNDERLINE = 7,
+ GHOSTTY_SGR_ATTR_UNDERLINE_COLOR = 8,
+ GHOSTTY_SGR_ATTR_UNDERLINE_COLOR_256 = 9,
+ GHOSTTY_SGR_ATTR_RESET_UNDERLINE_COLOR = 10,
+ GHOSTTY_SGR_ATTR_OVERLINE = 11,
+ GHOSTTY_SGR_ATTR_RESET_OVERLINE = 12,
+ GHOSTTY_SGR_ATTR_BLINK = 13,
+ GHOSTTY_SGR_ATTR_RESET_BLINK = 14,
+ GHOSTTY_SGR_ATTR_INVERSE = 15,
+ GHOSTTY_SGR_ATTR_RESET_INVERSE = 16,
+ GHOSTTY_SGR_ATTR_INVISIBLE = 17,
+ GHOSTTY_SGR_ATTR_RESET_INVISIBLE = 18,
+ GHOSTTY_SGR_ATTR_STRIKETHROUGH = 19,
+ GHOSTTY_SGR_ATTR_RESET_STRIKETHROUGH = 20,
+ GHOSTTY_SGR_ATTR_DIRECT_COLOR_FG = 21,
+ GHOSTTY_SGR_ATTR_DIRECT_COLOR_BG = 22,
+ GHOSTTY_SGR_ATTR_BG_8 = 23,
+ GHOSTTY_SGR_ATTR_FG_8 = 24,
+ GHOSTTY_SGR_ATTR_RESET_FG = 25,
+ GHOSTTY_SGR_ATTR_RESET_BG = 26,
+ GHOSTTY_SGR_ATTR_BRIGHT_BG_8 = 27,
+ GHOSTTY_SGR_ATTR_BRIGHT_FG_8 = 28,
+ GHOSTTY_SGR_ATTR_BG_256 = 29,
+ GHOSTTY_SGR_ATTR_FG_256 = 30,
+} GhosttySgrAttributeTag;
+
+/**
+ * Underline style types.
+ *
+ * @ingroup sgr
+ */
+typedef enum {
+ GHOSTTY_SGR_UNDERLINE_NONE = 0,
+ GHOSTTY_SGR_UNDERLINE_SINGLE = 1,
+ GHOSTTY_SGR_UNDERLINE_DOUBLE = 2,
+ GHOSTTY_SGR_UNDERLINE_CURLY = 3,
+ GHOSTTY_SGR_UNDERLINE_DOTTED = 4,
+ GHOSTTY_SGR_UNDERLINE_DASHED = 5,
+} GhosttySgrUnderline;
+
+/**
+ * Unknown SGR attribute data.
+ *
+ * Contains the full parameter list and the partial list where parsing
+ * encountered an unknown or invalid sequence.
+ *
+ * @ingroup sgr
+ */
+typedef struct {
+ const uint16_t* full_ptr;
+ size_t full_len;
+ const uint16_t* partial_ptr;
+ size_t partial_len;
+} GhosttySgrUnknown;
+
+/**
+ * SGR attribute value union.
+ *
+ * This union contains all possible attribute values. Use the tag field
+ * to determine which union member is active. Attributes without associated
+ * data (like bold, italic) don't use the union value.
+ *
+ * @ingroup sgr
+ */
+typedef union {
+ GhosttySgrUnknown unknown;
+ GhosttySgrUnderline underline;
+ GhosttyColorRgb underline_color;
+ GhosttyColorPaletteIndex underline_color_256;
+ GhosttyColorRgb direct_color_fg;
+ GhosttyColorRgb direct_color_bg;
+ GhosttyColorPaletteIndex bg_8;
+ GhosttyColorPaletteIndex fg_8;
+ GhosttyColorPaletteIndex bright_bg_8;
+ GhosttyColorPaletteIndex bright_fg_8;
+ GhosttyColorPaletteIndex bg_256;
+ GhosttyColorPaletteIndex fg_256;
+ uint64_t _padding[8];
+} GhosttySgrAttributeValue;
+
+/**
+ * SGR attribute (tagged union).
+ *
+ * A complete SGR attribute with both its type tag and associated value.
+ * Always check the tag field to determine which value union member is valid.
+ *
+ * Attributes without associated data (e.g., GHOSTTY_SGR_ATTR_BOLD) can be
+ * identified by tag alone; the value union is not used for these and
+ * the memory in the value field is undefined.
+ *
+ * @ingroup sgr
+ */
+typedef struct {
+ GhosttySgrAttributeTag tag;
+ GhosttySgrAttributeValue value;
+} GhosttySgrAttribute;
+
+/**
+ * Create a new SGR parser instance.
+ *
+ * Creates a new SGR (Select Graphic Rendition) parser using the provided
+ * allocator. The parser must be freed using ghostty_sgr_free() when
+ * no longer needed.
+ *
+ * @param allocator Pointer to the allocator to use for memory management, or
+ * NULL to use the default allocator
+ * @param parser Pointer to store the created parser handle
+ * @return GHOSTTY_SUCCESS on success, or an error code on failure
+ *
+ * @ingroup sgr
+ */
+GHOSTTY_API GhosttyResult ghostty_sgr_new(const GhosttyAllocator* allocator,
+ GhosttySgrParser* parser);
+
+/**
+ * Free an SGR parser instance.
+ *
+ * Releases all resources associated with the SGR parser. After this call,
+ * the parser handle becomes invalid and must not be used. This includes
+ * any attributes previously returned by ghostty_sgr_next().
+ *
+ * @param parser The parser handle to free (may be NULL)
+ *
+ * @ingroup sgr
+ */
+GHOSTTY_API void ghostty_sgr_free(GhosttySgrParser parser);
+
+/**
+ * Reset an SGR parser instance to the beginning of the parameter list.
+ *
+ * Resets the parser's iteration state without clearing the parameters.
+ * After calling this, ghostty_sgr_next() will start from the beginning
+ * of the parameter list again.
+ *
+ * @param parser The parser handle to reset, must not be NULL
+ *
+ * @ingroup sgr
+ */
+GHOSTTY_API void ghostty_sgr_reset(GhosttySgrParser parser);
+
+/**
+ * Set SGR parameters for parsing.
+ *
+ * Sets the SGR parameter list to parse. Parameters are the numeric values
+ * from a CSI SGR sequence (e.g., for `ESC[1;31m`, params would be {1, 31}).
+ *
+ * The separators array optionally specifies the separator type for each
+ * parameter position. Each byte should be either ';' for semicolon or ':'
+ * for colon. This is needed for certain color formats that use colon
+ * separators (e.g., `ESC[4:3m` for curly underline). Any invalid separator
+ * values are treated as semicolons. The separators array must have the same
+ * length as the params array, if it is not NULL.
+ *
+ * If separators is NULL, all parameters are assumed to be semicolon-separated.
+ *
+ * This function makes an internal copy of the parameter and separator data,
+ * so the caller can safely free or modify the input arrays after this call.
+ *
+ * After calling this function, the parser is automatically reset and ready
+ * to iterate from the beginning.
+ *
+ * @param parser The parser handle, must not be NULL
+ * @param params Array of SGR parameter values
+ * @param separators Optional array of separator characters (';' or ':'), or
+ * NULL
+ * @param len Number of parameters (and separators if provided)
+ * @return GHOSTTY_SUCCESS on success, or an error code on failure
+ *
+ * @ingroup sgr
+ */
+GHOSTTY_API GhosttyResult ghostty_sgr_set_params(GhosttySgrParser parser,
+ const uint16_t* params,
+ const char* separators,
+ size_t len);
+
+/**
+ * Get the next SGR attribute.
+ *
+ * Parses and returns the next attribute from the parameter list.
+ * Call this function repeatedly until it returns false to process
+ * all attributes in the sequence.
+ *
+ * @param parser The parser handle, must not be NULL
+ * @param attr Pointer to store the next attribute
+ * @return true if an attribute was returned, false if no more attributes
+ *
+ * @ingroup sgr
+ */
+GHOSTTY_API bool ghostty_sgr_next(GhosttySgrParser parser, GhosttySgrAttribute* attr);
+
+/**
+ * Get the full parameter list from an unknown SGR attribute.
+ *
+ * This function retrieves the full parameter list that was provided to the
+ * parser when an unknown attribute was encountered. Primarily useful in
+ * WebAssembly environments where accessing struct fields directly is difficult.
+ *
+ * @param unknown The unknown attribute data
+ * @param ptr Pointer to store the pointer to the parameter array (may be NULL)
+ * @return The length of the full parameter array
+ *
+ * @ingroup sgr
+ */
+GHOSTTY_API size_t ghostty_sgr_unknown_full(GhosttySgrUnknown unknown,
+ const uint16_t** ptr);
+
+/**
+ * Get the partial parameter list from an unknown SGR attribute.
+ *
+ * This function retrieves the partial parameter list where parsing stopped
+ * when an unknown attribute was encountered. Primarily useful in WebAssembly
+ * environments where accessing struct fields directly is difficult.
+ *
+ * @param unknown The unknown attribute data
+ * @param ptr Pointer to store the pointer to the parameter array (may be NULL)
+ * @return The length of the partial parameter array
+ *
+ * @ingroup sgr
+ */
+GHOSTTY_API size_t ghostty_sgr_unknown_partial(GhosttySgrUnknown unknown,
+ const uint16_t** ptr);
+
+/**
+ * Get the tag from an SGR attribute.
+ *
+ * This function extracts the tag that identifies which type of attribute
+ * this is. Primarily useful in WebAssembly environments where accessing
+ * struct fields directly is difficult.
+ *
+ * @param attr The SGR attribute
+ * @return The attribute tag
+ *
+ * @ingroup sgr
+ */
+GHOSTTY_API GhosttySgrAttributeTag ghostty_sgr_attribute_tag(GhosttySgrAttribute attr);
+
+/**
+ * Get the value from an SGR attribute.
+ *
+ * This function returns a pointer to the value union from an SGR attribute. Use
+ * the tag to determine which field of the union is valid. Primarily useful in
+ * WebAssembly environments where accessing struct fields directly is difficult.
+ *
+ * @param attr Pointer to the SGR attribute
+ * @return Pointer to the attribute value union
+ *
+ * @ingroup sgr
+ */
+GHOSTTY_API GhosttySgrAttributeValue* ghostty_sgr_attribute_value(
+ GhosttySgrAttribute* attr);
+
+#ifdef __wasm__
+/**
+ * Allocate memory for an SGR attribute (WebAssembly only).
+ *
+ * This is a convenience function for WebAssembly environments to allocate
+ * memory for an SGR attribute structure that can be passed to ghostty_sgr_next.
+ *
+ * @return Pointer to the allocated attribute structure
+ *
+ * @ingroup wasm
+ */
+GHOSTTY_API GhosttySgrAttribute* ghostty_wasm_alloc_sgr_attribute(void);
+
+/**
+ * Free memory for an SGR attribute (WebAssembly only).
+ *
+ * Frees memory allocated by ghostty_wasm_alloc_sgr_attribute.
+ *
+ * @param attr Pointer to the attribute structure to free
+ *
+ * @ingroup wasm
+ */
+GHOSTTY_API void ghostty_wasm_free_sgr_attribute(GhosttySgrAttribute* attr);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif /* GHOSTTY_VT_SGR_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt/size_report.h b/vendor/libghostty-vt/include/ghostty/vt/size_report.h
new file mode 100644
index 00000000..98c67c5e
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/size_report.h
@@ -0,0 +1,100 @@
+/**
+ * @file size_report.h
+ *
+ * Size report encoding - encode terminal size reports into escape sequences.
+ */
+
+#ifndef GHOSTTY_VT_SIZE_REPORT_H
+#define GHOSTTY_VT_SIZE_REPORT_H
+
+/** @defgroup size_report Size Report Encoding
+ *
+ * Utilities for encoding terminal size reports into escape sequences,
+ * supporting in-band size reports (mode 2048) and XTWINOPS responses
+ * (CSI 14 t, CSI 16 t, CSI 18 t).
+ *
+ * ## Basic Usage
+ *
+ * Use ghostty_size_report_encode() to encode a size report into a
+ * caller-provided buffer. If the buffer is too small, the function
+ * returns GHOSTTY_OUT_OF_SPACE and sets the required size in the
+ * output parameter.
+ *
+ * ## Example
+ *
+ * @snippet c-vt-size-report/src/main.c size-report-encode
+ *
+ * @{
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <ghostty/vt/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Size report style.
+ *
+ * Determines the output format for the terminal size report.
+ */
+typedef enum {
+ /** In-band size report (mode 2048): ESC [ 48 ; rows ; cols ; height ; width t */
+ GHOSTTY_SIZE_REPORT_MODE_2048 = 0,
+ /** XTWINOPS text area size in pixels: ESC [ 4 ; height ; width t */
+ GHOSTTY_SIZE_REPORT_CSI_14_T = 1,
+ /** XTWINOPS cell size in pixels: ESC [ 6 ; height ; width t */
+ GHOSTTY_SIZE_REPORT_CSI_16_T = 2,
+ /** XTWINOPS text area size in characters: ESC [ 8 ; rows ; cols t */
+ GHOSTTY_SIZE_REPORT_CSI_18_T = 3,
+} GhosttySizeReportStyle;
+
+/**
+ * Terminal size information for encoding size reports.
+ */
+typedef struct {
+ /** Terminal row count in cells. */
+ uint16_t rows;
+ /** Terminal column count in cells. */
+ uint16_t columns;
+ /** Width of a single terminal cell in pixels. */
+ uint32_t cell_width;
+ /** Height of a single terminal cell in pixels. */
+ uint32_t cell_height;
+} GhosttySizeReportSize;
+
+/**
+ * Encode a terminal size report into an escape sequence.
+ *
+ * Encodes a size report in the format specified by @p style into the
+ * provided buffer.
+ *
+ * If the buffer is too small, the function returns GHOSTTY_OUT_OF_SPACE
+ * and writes the required buffer size to @p out_written. The caller can
+ * then retry with a sufficiently sized buffer.
+ *
+ * @param style The size report format to encode
+ * @param size Terminal size information
+ * @param buf Output buffer to write the encoded sequence into (may be NULL)
+ * @param buf_len Size of the output buffer in bytes
+ * @param[out] out_written On success, the number of bytes written. On
+ * GHOSTTY_OUT_OF_SPACE, the required buffer size.
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_OUT_OF_SPACE if the buffer
+ * is too small
+ */
+GHOSTTY_API GhosttyResult ghostty_size_report_encode(
+ GhosttySizeReportStyle style,
+ GhosttySizeReportSize size,
+ char* buf,
+ size_t buf_len,
+ size_t* out_written);
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif /* GHOSTTY_VT_SIZE_REPORT_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt/style.h b/vendor/libghostty-vt/include/ghostty/vt/style.h
new file mode 100644
index 00000000..ac049560
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/style.h
@@ -0,0 +1,138 @@
+/**
+ * @file style.h
+ *
+ * Terminal cell style types.
+ */
+
+#ifndef GHOSTTY_VT_STYLE_H
+#define GHOSTTY_VT_STYLE_H
+
+#include <ghostty/vt/color.h>
+#include <ghostty/vt/types.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup style Style
+ *
+ * Terminal cell style attributes.
+ *
+ * A style describes the visual attributes of a terminal cell, including
+ * foreground, background, and underline colors, as well as flags for
+ * bold, italic, underline, and other text decorations.
+ *
+ * @{
+ */
+
+/**
+ * Style identifier type.
+ *
+ * Used to look up the full style from a grid reference.
+ * Obtain this from a cell via GHOSTTY_CELL_DATA_STYLE_ID.
+ *
+ * @ingroup style
+ */
+typedef uint16_t GhosttyStyleId;
+
+/**
+ * Style color tags.
+ *
+ * These values identify the type of color in a style color.
+ * Use the tag to determine which field in the color value union to access.
+ *
+ * @ingroup style
+ */
+typedef enum {
+ GHOSTTY_STYLE_COLOR_NONE = 0,
+ GHOSTTY_STYLE_COLOR_PALETTE = 1,
+ GHOSTTY_STYLE_COLOR_RGB = 2,
+} GhosttyStyleColorTag;
+
+/**
+ * Style color value union.
+ *
+ * Use the tag to determine which field is active.
+ *
+ * @ingroup style
+ */
+typedef union {
+ GhosttyColorPaletteIndex palette;
+ GhosttyColorRgb rgb;
+ uint64_t _padding;
+} GhosttyStyleColorValue;
+
+/**
+ * Style color (tagged union).
+ *
+ * A color used in a style attribute. Can be unset (none), a palette
+ * index, or a direct RGB value.
+ *
+ * @ingroup style
+ */
+typedef struct {
+ GhosttyStyleColorTag tag;
+ GhosttyStyleColorValue value;
+} GhosttyStyleColor;
+
+/**
+ * Terminal cell style.
+ *
+ * Describes the complete visual style for a terminal cell, including
+ * foreground, background, and underline colors, as well as text
+ * decoration flags. The underline field uses the same values as
+ * GhosttySgrUnderline.
+ *
+ * This is a sized struct. Use GHOSTTY_INIT_SIZED() to initialize it.
+ *
+ * @ingroup style
+ */
+typedef struct {
+ size_t size;
+ GhosttyStyleColor fg_color;
+ GhosttyStyleColor bg_color;
+ GhosttyStyleColor underline_color;
+ bool bold;
+ bool italic;
+ bool faint;
+ bool blink;
+ bool inverse;
+ bool invisible;
+ bool strikethrough;
+ bool overline;
+ int underline; /**< One of GHOSTTY_SGR_UNDERLINE_* values */
+} GhosttyStyle;
+
+/**
+ * Get the default style.
+ *
+ * Initializes the style to the default values (no colors, no flags).
+ *
+ * @param style Pointer to the style to initialize
+ *
+ * @ingroup style
+ */
+GHOSTTY_API void ghostty_style_default(GhosttyStyle* style);
+
+/**
+ * Check if a style is the default style.
+ *
+ * Returns true if all colors are unset and all flags are off.
+ *
+ * @param style Pointer to the style to check
+ * @return true if the style is the default style
+ *
+ * @ingroup style
+ */
+GHOSTTY_API bool ghostty_style_is_default(const GhosttyStyle* style);
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif /* GHOSTTY_VT_STYLE_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt/terminal.h b/vendor/libghostty-vt/include/ghostty/vt/terminal.h
new file mode 100644
index 00000000..b43e37cf
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/terminal.h
@@ -0,0 +1,983 @@
+/**
+ * @file terminal.h
+ *
+ * Complete terminal emulator state and rendering.
+ */
+
+#ifndef GHOSTTY_VT_TERMINAL_H
+#define GHOSTTY_VT_TERMINAL_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <ghostty/vt/types.h>
+#include <ghostty/vt/allocator.h>
+#include <ghostty/vt/device.h>
+#include <ghostty/vt/modes.h>
+#include <ghostty/vt/size_report.h>
+#include <ghostty/vt/grid_ref.h>
+#include <ghostty/vt/screen.h>
+#include <ghostty/vt/point.h>
+#include <ghostty/vt/style.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup terminal Terminal
+ *
+ * Complete terminal emulator state and rendering.
+ *
+ * A terminal instance manages the full emulator state including the screen,
+ * scrollback, cursor, styles, modes, and VT stream processing.
+ *
+ * Once a terminal session is up and running, you can configure a key encoder
+ * to write keyboard input via ghostty_key_encoder_setopt_from_terminal().
+ *
+ * ### Example: VT stream processing
+ * @snippet c-vt-stream/src/main.c vt-stream-init
+ * @snippet c-vt-stream/src/main.c vt-stream-write
+ *
+ * ## Effects
+ *
+ * By default, the terminal sequence processing with ghostty_terminal_vt_write()
+ * only process sequences that directly affect terminal state and
+ * ignores sequences that have side effect behavior or require responses.
+ * These sequences include things like bell characters, title changes, device
+ * attributes queries, and more. To handle these sequences, the embedder
+ * must configure "effects."
+ *
+ * Effects are callbacks that the terminal invokes in response to VT
+ * sequences processed during ghostty_terminal_vt_write(). They let the
+ * embedding application react to terminal-initiated events such as bell
+ * characters, title changes, device status report responses, and more.
+ *
+ * Each effect is registered with ghostty_terminal_set() using the
+ * corresponding `GhosttyTerminalOption` identifier. A `NULL` value
+ * pointer clears the callback and disables the effect.
+ *
+ * A userdata pointer can be attached via `GHOSTTY_TERMINAL_OPT_USERDATA`
+ * and is passed to every callback, allowing callers to route events
+ * back to their own application state without global variables.
+ * You cannot specify different userdata for different callbacks.
+ *
+ * All callbacks are invoked synchronously during
+ * ghostty_terminal_vt_write(). Callbacks **must not** call
+ * ghostty_terminal_vt_write() on the same terminal (no reentrancy).
+ * And callbacks must be very careful to not block for too long or perform
+ * expensive operations, since they are blocking further IO processing.
+ *
+ * The available effects are:
+ *
+ * | Option | Callback Type | Trigger |
+ * |-----------------------------------------|-----------------------------------|-------------------------------------------|
+ * | `GHOSTTY_TERMINAL_OPT_WRITE_PTY` | `GhosttyTerminalWritePtyFn` | Query responses written back to the pty |
+ * | `GHOSTTY_TERMINAL_OPT_BELL` | `GhosttyTerminalBellFn` | BEL character (0x07) |
+ * | `GHOSTTY_TERMINAL_OPT_TITLE_CHANGED` | `GhosttyTerminalTitleChangedFn` | Title change via OSC 0 / OSC 2 |
+ * | `GHOSTTY_TERMINAL_OPT_ENQUIRY` | `GhosttyTerminalEnquiryFn` | ENQ character (0x05) |
+ * | `GHOSTTY_TERMINAL_OPT_XTVERSION` | `GhosttyTerminalXtversionFn` | XTVERSION query (CSI > q) |
+ * | `GHOSTTY_TERMINAL_OPT_SIZE` | `GhosttyTerminalSizeFn` | XTWINOPS size query (CSI 14/16/18 t) |
+ * | `GHOSTTY_TERMINAL_OPT_COLOR_SCHEME` | `GhosttyTerminalColorSchemeFn` | Color scheme query (CSI ? 996 n) |
+ * | `GHOSTTY_TERMINAL_OPT_DEVICE_ATTRIBUTES`| `GhosttyTerminalDeviceAttributesFn`| Device attributes query (CSI c / > c / = c)|
+ *
+ * ### Defining a write_pty callback
+ * @snippet c-vt-effects/src/main.c effects-write-pty
+ *
+ * ### Defining a bell callback
+ * @snippet c-vt-effects/src/main.c effects-bell
+ *
+ * ### Defining a title_changed callback
+ * @snippet c-vt-effects/src/main.c effects-title-changed
+ *
+ * ### Registering effects and processing VT data
+ * @snippet c-vt-effects/src/main.c effects-register
+ *
+ * ## Color Theme
+ *
+ * The terminal maintains a set of colors used for rendering: a foreground
+ * color, a background color, a cursor color, and a 256-color palette. Each
+ * of these has two layers: a **default** value set by the embedder, and an
+ * **override** value that programs running in the terminal can set via OSC
+ * escape sequences (e.g. OSC 10/11/12 for foreground/background/cursor,
+ * OSC 4 for individual palette entries).
+ *
+ * ### Default Colors
+ *
+ * Use ghostty_terminal_set() with the color options to configure the
+ * default colors. These represent the theme or configuration chosen by
+ * the embedder. Passing `NULL` clears the default, leaving the color
+ * unset.
+ *
+ * | Option | Input Type | Description |
+ * |-----------------------------------------|-------------------------|--------------------------------------|
+ * | `GHOSTTY_TERMINAL_OPT_COLOR_FOREGROUND` | `GhosttyColorRgb*` | Default foreground color |
+ * | `GHOSTTY_TERMINAL_OPT_COLOR_BACKGROUND` | `GhosttyColorRgb*` | Default background color |
+ * | `GHOSTTY_TERMINAL_OPT_COLOR_CURSOR` | `GhosttyColorRgb*` | Default cursor color |
+ * | `GHOSTTY_TERMINAL_OPT_COLOR_PALETTE` | `GhosttyColorRgb[256]*` | Default 256-color palette |
+ *
+ * For the palette, passing `NULL` resets to the built-in default palette.
+ * The palette set operation preserves any per-index OSC overrides that
+ * programs have applied; only unmodified indices are updated.
+ *
+ * ### Reading colors
+ *
+ * Use ghostty_terminal_get() to read colors. There are two variants for
+ * each color: the **effective** value (which returns the OSC override if
+ * one is active, otherwise the default) and the **default** value (which
+ * ignores any OSC overrides).
+ *
+ * | Data | Output Type | Description |
+ * |---------------------------------------------------|-------------------------|------------------------------------------------|
+ * | `GHOSTTY_TERMINAL_DATA_COLOR_FOREGROUND` | `GhosttyColorRgb*` | Effective foreground (override or default) |
+ * | `GHOSTTY_TERMINAL_DATA_COLOR_BACKGROUND` | `GhosttyColorRgb*` | Effective background (override or default) |
+ * | `GHOSTTY_TERMINAL_DATA_COLOR_CURSOR` | `GhosttyColorRgb*` | Effective cursor (override or default) |
+ * | `GHOSTTY_TERMINAL_DATA_COLOR_PALETTE` | `GhosttyColorRgb[256]*` | Current palette (with any OSC overrides) |
+ * | `GHOSTTY_TERMINAL_DATA_COLOR_FOREGROUND_DEFAULT` | `GhosttyColorRgb*` | Default foreground only (ignores OSC override) |
+ * | `GHOSTTY_TERMINAL_DATA_COLOR_BACKGROUND_DEFAULT` | `GhosttyColorRgb*` | Default background only (ignores OSC override) |
+ * | `GHOSTTY_TERMINAL_DATA_COLOR_CURSOR_DEFAULT` | `GhosttyColorRgb*` | Default cursor only (ignores OSC override) |
+ * | `GHOSTTY_TERMINAL_DATA_COLOR_PALETTE_DEFAULT` | `GhosttyColorRgb[256]*` | Default palette only (ignores OSC overrides) |
+ *
+ * For foreground, background, and cursor colors, the getters return
+ * `GHOSTTY_NO_VALUE` if no color is configured (neither a default nor an
+ * OSC override). The palette getters always succeed since the palette
+ * always has a value (the built-in default if nothing else is set).
+ *
+ * ### Setting a color theme
+ * @snippet c-vt-colors/src/main.c colors-set-defaults
+ *
+ * ### Reading effective and default colors
+ * @snippet c-vt-colors/src/main.c colors-read
+ *
+ * ### Full example with OSC overrides
+ * @snippet c-vt-colors/src/main.c colors-main
+ *
+ * @{
+ */
+
+/**
+ * Opaque handle to a terminal instance.
+ *
+ * @ingroup terminal
+ */
+typedef struct GhosttyTerminalImpl* GhosttyTerminal;
+
+/**
+ * Terminal initialization options.
+ *
+ * @ingroup terminal
+ */
+typedef struct {
+ /** Terminal width in cells. Must be greater than zero. */
+ uint16_t cols;
+
+ /** Terminal height in cells. Must be greater than zero. */
+ uint16_t rows;
+
+ /** Maximum number of lines to keep in scrollback history. */
+ size_t max_scrollback;
+
+ // TODO: Consider ABI compatibility implications of this struct.
+ // We may want to artificially pad it significantly to support
+ // future options.
+} GhosttyTerminalOptions;
+
+/**
+ * Scroll viewport behavior tag.
+ *
+ * @ingroup terminal
+ */
+typedef enum {
+ /** Scroll to the top of the scrollback. */
+ GHOSTTY_SCROLL_VIEWPORT_TOP,
+
+ /** Scroll to the bottom (active area). */
+ GHOSTTY_SCROLL_VIEWPORT_BOTTOM,
+
+ /** Scroll by a delta amount (up is negative). */
+ GHOSTTY_SCROLL_VIEWPORT_DELTA,
+} GhosttyTerminalScrollViewportTag;
+
+/**
+ * Scroll viewport value.
+ *
+ * @ingroup terminal
+ */
+typedef union {
+ /** Scroll delta (only used with GHOSTTY_SCROLL_VIEWPORT_DELTA). Up is negative. */
+ intptr_t delta;
+
+ /** Padding for ABI compatibility. Do not use. */
+ uint64_t _padding[2];
+} GhosttyTerminalScrollViewportValue;
+
+/**
+ * Tagged union for scroll viewport behavior.
+ *
+ * @ingroup terminal
+ */
+typedef struct {
+ GhosttyTerminalScrollViewportTag tag;
+ GhosttyTerminalScrollViewportValue value;
+} GhosttyTerminalScrollViewport;
+
+/**
+ * Terminal screen identifier.
+ *
+ * Identifies which screen buffer is active in the terminal.
+ *
+ * @ingroup terminal
+ */
+typedef enum {
+ /** The primary (normal) screen. */
+ GHOSTTY_TERMINAL_SCREEN_PRIMARY = 0,
+
+ /** The alternate screen. */
+ GHOSTTY_TERMINAL_SCREEN_ALTERNATE = 1,
+} GhosttyTerminalScreen;
+
+/**
+ * Scrollbar state for the terminal viewport.
+ *
+ * Represents the scrollable area dimensions needed to render a scrollbar.
+ *
+ * @ingroup terminal
+ */
+typedef struct {
+ /** Total size of the scrollable area in rows. */
+ uint64_t total;
+
+ /** Offset into the total area that the viewport is at. */
+ uint64_t offset;
+
+ /** Length of the visible area in rows. */
+ uint64_t len;
+} GhosttyTerminalScrollbar;
+
+/**
+ * Callback function type for bell.
+ *
+ * Called when the terminal receives a BEL character (0x07).
+ *
+ * @param terminal The terminal handle
+ * @param userdata The userdata pointer set via GHOSTTY_TERMINAL_OPT_USERDATA
+ *
+ * @ingroup terminal
+ */
+typedef void (*GhosttyTerminalBellFn)(GhosttyTerminal terminal,
+ void* userdata);
+
+/**
+ * Callback function type for color scheme queries (CSI ? 996 n).
+ *
+ * Called when the terminal receives a color scheme device status report
+ * query. Return true and fill *out_scheme with the current color scheme,
+ * or return false to silently ignore the query.
+ *
+ * @param terminal The terminal handle
+ * @param userdata The userdata pointer set via GHOSTTY_TERMINAL_OPT_USERDATA
+ * @param[out] out_scheme Pointer to store the current color scheme
+ * @return true if the color scheme was filled, false to ignore the query
+ *
+ * @ingroup terminal
+ */
+typedef bool (*GhosttyTerminalColorSchemeFn)(GhosttyTerminal terminal,
+ void* userdata,
+ GhosttyColorScheme* out_scheme);
+
+/**
+ * Callback function type for device attributes queries (DA1/DA2/DA3).
+ *
+ * Called when the terminal receives a device attributes query (CSI c,
+ * CSI > c, or CSI = c). Return true and fill *out_attrs with the
+ * response data, or return false to silently ignore the query.
+ *
+ * The terminal uses whichever sub-struct (primary, secondary, tertiary)
+ * matches the request type, but all three should be filled for simplicity.
+ *
+ * @param terminal The terminal handle
+ * @param userdata The userdata pointer set via GHOSTTY_TERMINAL_OPT_USERDATA
+ * @param[out] out_attrs Pointer to store the device attributes response
+ * @return true if attributes were filled, false to ignore the query
+ *
+ * @ingroup terminal
+ */
+typedef bool (*GhosttyTerminalDeviceAttributesFn)(GhosttyTerminal terminal,
+ void* userdata,
+ GhosttyDeviceAttributes* out_attrs);
+
+/**
+ * Callback function type for enquiry (ENQ, 0x05).
+ *
+ * Called when the terminal receives an ENQ character. Return the
+ * response bytes as a GhosttyString. The memory must remain valid
+ * until the callback returns. Return a zero-length string to send
+ * no response.
+ *
+ * @param terminal The terminal handle
+ * @param userdata The userdata pointer set via GHOSTTY_TERMINAL_OPT_USERDATA
+ * @return The response bytes to write back to the pty
+ *
+ * @ingroup terminal
+ */
+typedef GhosttyString (*GhosttyTerminalEnquiryFn)(GhosttyTerminal terminal,
+ void* userdata);
+
+/**
+ * Callback function type for size queries (XTWINOPS).
+ *
+ * Called in response to XTWINOPS size queries (CSI 14/16/18 t).
+ * Return true and fill *out_size with the current terminal geometry,
+ * or return false to silently ignore the query.
+ *
+ * @param terminal The terminal handle
+ * @param userdata The userdata pointer set via GHOSTTY_TERMINAL_OPT_USERDATA
+ * @param[out] out_size Pointer to store the terminal size information
+ * @return true if size was filled, false to ignore the query
+ *
+ * @ingroup terminal
+ */
+typedef bool (*GhosttyTerminalSizeFn)(GhosttyTerminal terminal,
+ void* userdata,
+ GhosttySizeReportSize* out_size);
+
+/**
+ * Callback function type for title_changed.
+ *
+ * Called when the terminal title changes via escape sequences
+ * (e.g. OSC 0 or OSC 2). The new title can be queried from the
+ * terminal after the callback returns.
+ *
+ * @param terminal The terminal handle
+ * @param userdata The userdata pointer set via GHOSTTY_TERMINAL_OPT_USERDATA
+ *
+ * @ingroup terminal
+ */
+typedef void (*GhosttyTerminalTitleChangedFn)(GhosttyTerminal terminal,
+ void* userdata);
+
+/**
+ * Callback function type for write_pty.
+ *
+ * Called when the terminal needs to write data back to the pty, for
+ * example in response to a device status report or mode query. The
+ * data is only valid for the duration of the call; callers must copy
+ * it if it needs to persist.
+ *
+ * @param terminal The terminal handle
+ * @param userdata The userdata pointer set via GHOSTTY_TERMINAL_OPT_USERDATA
+ * @param data Pointer to the response bytes
+ * @param len Length of the response in bytes
+ *
+ * @ingroup terminal
+ */
+typedef void (*GhosttyTerminalWritePtyFn)(GhosttyTerminal terminal,
+ void* userdata,
+ const uint8_t* data,
+ size_t len);
+
+/**
+ * Callback function type for XTVERSION.
+ *
+ * Called when the terminal receives an XTVERSION query (CSI > q).
+ * Return the version string (e.g. "myterm 1.0") as a GhosttyString.
+ * The memory must remain valid until the callback returns. Return a
+ * zero-length string to report the default "libghostty" version.
+ *
+ * @param terminal The terminal handle
+ * @param userdata The userdata pointer set via GHOSTTY_TERMINAL_OPT_USERDATA
+ * @return The version string to report
+ *
+ * @ingroup terminal
+ */
+typedef GhosttyString (*GhosttyTerminalXtversionFn)(GhosttyTerminal terminal,
+ void* userdata);
+
+/**
+ * Terminal option identifiers.
+ *
+ * These values are used with ghostty_terminal_set() to configure
+ * terminal callbacks and associated state.
+ *
+ * @ingroup terminal
+ */
+typedef enum {
+ /**
+ * Opaque userdata pointer passed to all callbacks.
+ *
+ * Input type: void*
+ */
+ GHOSTTY_TERMINAL_OPT_USERDATA = 0,
+
+ /**
+ * Callback invoked when the terminal needs to write data back
+ * to the pty (e.g. in response to a DECRQM query or device
+ * status report). Set to NULL to ignore such sequences.
+ *
+ * Input type: GhosttyTerminalWritePtyFn
+ */
+ GHOSTTY_TERMINAL_OPT_WRITE_PTY = 1,
+
+ /**
+ * Callback invoked when the terminal receives a BEL character
+ * (0x07). Set to NULL to ignore bell events.
+ *
+ * Input type: GhosttyTerminalBellFn
+ */
+ GHOSTTY_TERMINAL_OPT_BELL = 2,
+
+ /**
+ * Callback invoked when the terminal receives an ENQ character
+ * (0x05). Set to NULL to send no response.
+ *
+ * Input type: GhosttyTerminalEnquiryFn
+ */
+ GHOSTTY_TERMINAL_OPT_ENQUIRY = 3,
+
+ /**
+ * Callback invoked when the terminal receives an XTVERSION query
+ * (CSI > q). Set to NULL to report the default "libghostty" string.
+ *
+ * Input type: GhosttyTerminalXtversionFn
+ */
+ GHOSTTY_TERMINAL_OPT_XTVERSION = 4,
+
+ /**
+ * Callback invoked when the terminal title changes via escape
+ * sequences (e.g. OSC 0 or OSC 2). Set to NULL to ignore title
+ * change events.
+ *
+ * Input type: GhosttyTerminalTitleChangedFn
+ */
+ GHOSTTY_TERMINAL_OPT_TITLE_CHANGED = 5,
+
+ /**
+ * Callback invoked in response to XTWINOPS size queries
+ * (CSI 14/16/18 t). Set to NULL to silently ignore size queries.
+ *
+ * Input type: GhosttyTerminalSizeFn
+ */
+ GHOSTTY_TERMINAL_OPT_SIZE = 6,
+
+ /**
+ * Callback invoked in response to a color scheme device status
+ * report query (CSI ? 996 n). Return true and fill the out pointer
+ * to report the current scheme, or return false to silently ignore.
+ * Set to NULL to ignore color scheme queries.
+ *
+ * Input type: GhosttyTerminalColorSchemeFn
+ */
+ GHOSTTY_TERMINAL_OPT_COLOR_SCHEME = 7,
+
+ /**
+ * Callback invoked in response to a device attributes query
+ * (CSI c, CSI > c, or CSI = c). Return true and fill the out
+ * pointer with response data, or return false to silently ignore.
+ * Set to NULL to ignore device attributes queries.
+ *
+ * Input type: GhosttyTerminalDeviceAttributesFn
+ */
+ GHOSTTY_TERMINAL_OPT_DEVICE_ATTRIBUTES = 8,
+
+ /**
+ * Set the terminal title manually.
+ *
+ * The string data is copied into the terminal. A NULL value pointer
+ * clears the title (equivalent to setting an empty string).
+ *
+ * Input type: GhosttyString*
+ */
+ GHOSTTY_TERMINAL_OPT_TITLE = 9,
+
+ /**
+ * Set the terminal working directory manually.
+ *
+ * The string data is copied into the terminal. A NULL value pointer
+ * clears the pwd (equivalent to setting an empty string).
+ *
+ * Input type: GhosttyString*
+ */
+ GHOSTTY_TERMINAL_OPT_PWD = 10,
+
+ /**
+ * Set the default foreground color.
+ *
+ * A NULL value pointer clears the default (unset).
+ *
+ * Input type: GhosttyColorRgb*
+ */
+ GHOSTTY_TERMINAL_OPT_COLOR_FOREGROUND = 11,
+
+ /**
+ * Set the default background color.
+ *
+ * A NULL value pointer clears the default (unset).
+ *
+ * Input type: GhosttyColorRgb*
+ */
+ GHOSTTY_TERMINAL_OPT_COLOR_BACKGROUND = 12,
+
+ /**
+ * Set the default cursor color.
+ *
+ * A NULL value pointer clears the default (unset).
+ *
+ * Input type: GhosttyColorRgb*
+ */
+ GHOSTTY_TERMINAL_OPT_COLOR_CURSOR = 13,
+
+ /**
+ * Set the default 256-color palette.
+ *
+ * The value must point to an array of exactly 256 GhosttyColorRgb values.
+ * A NULL value pointer resets to the built-in default palette.
+ *
+ * Input type: GhosttyColorRgb[256]*
+ */
+ GHOSTTY_TERMINAL_OPT_COLOR_PALETTE = 14,
+} GhosttyTerminalOption;
+
+/**
+ * Terminal data types.
+ *
+ * These values specify what type of data to extract from a terminal
+ * using `ghostty_terminal_get`.
+ *
+ * @ingroup terminal
+ */
+typedef enum {
+ /** Invalid data type. Never results in any data extraction. */
+ GHOSTTY_TERMINAL_DATA_INVALID = 0,
+
+ /**
+ * Terminal width in cells.
+ *
+ * Output type: uint16_t *
+ */
+ GHOSTTY_TERMINAL_DATA_COLS = 1,
+
+ /**
+ * Terminal height in cells.
+ *
+ * Output type: uint16_t *
+ */
+ GHOSTTY_TERMINAL_DATA_ROWS = 2,
+
+ /**
+ * Cursor column position (0-indexed).
+ *
+ * Output type: uint16_t *
+ */
+ GHOSTTY_TERMINAL_DATA_CURSOR_X = 3,
+
+ /**
+ * Cursor row position within the active area (0-indexed).
+ *
+ * Output type: uint16_t *
+ */
+ GHOSTTY_TERMINAL_DATA_CURSOR_Y = 4,
+
+ /**
+ * Whether the cursor has a pending wrap (next print will soft-wrap).
+ *
+ * Output type: bool *
+ */
+ GHOSTTY_TERMINAL_DATA_CURSOR_PENDING_WRAP = 5,
+
+ /**
+ * The currently active screen.
+ *
+ * Output type: GhosttyTerminalScreen *
+ */
+ GHOSTTY_TERMINAL_DATA_ACTIVE_SCREEN = 6,
+
+ /**
+ * Whether the cursor is visible (DEC mode 25).
+ *
+ * Output type: bool *
+ */
+ GHOSTTY_TERMINAL_DATA_CURSOR_VISIBLE = 7,
+
+ /**
+ * Current Kitty keyboard protocol flags.
+ *
+ * Output type: GhosttyKittyKeyFlags * (uint8_t *)
+ */
+ GHOSTTY_TERMINAL_DATA_KITTY_KEYBOARD_FLAGS = 8,
+
+ /**
+ * Scrollbar state for the terminal viewport.
+ *
+ * This may be expensive to calculate depending on where the viewport
+ * is (arbitrary pins are expensive). The caller should take care to only
+ * call this as needed and not too frequently.
+ *
+ * Output type: GhosttyTerminalScrollbar *
+ */
+ GHOSTTY_TERMINAL_DATA_SCROLLBAR = 9,
+
+ /**
+ * The current SGR style of the cursor.
+ *
+ * This is the style that will be applied to newly printed characters.
+ *
+ * Output type: GhosttyStyle *
+ */
+ GHOSTTY_TERMINAL_DATA_CURSOR_STYLE = 10,
+
+ /**
+ * Whether any mouse tracking mode is active.
+ *
+ * Returns true if any of the mouse tracking modes (X10, normal, button,
+ * or any-event) are enabled.
+ *
+ * Output type: bool *
+ */
+ GHOSTTY_TERMINAL_DATA_MOUSE_TRACKING = 11,
+
+ /**
+ * The terminal title as set by escape sequences (e.g. OSC 0/2).
+ *
+ * Returns a borrowed string. The pointer is valid until the next call
+ * to ghostty_terminal_vt_write() or ghostty_terminal_reset(). An empty
+ * string (len=0) is returned when no title has been set.
+ *
+ * Output type: GhosttyString *
+ */
+ GHOSTTY_TERMINAL_DATA_TITLE = 12,
+
+ /**
+ * The terminal's current working directory as set by escape sequences
+ * (e.g. OSC 7).
+ *
+ * Returns a borrowed string. The pointer is valid until the next call
+ * to ghostty_terminal_vt_write() or ghostty_terminal_reset(). An empty
+ * string (len=0) is returned when no pwd has been set.
+ *
+ * Output type: GhosttyString *
+ */
+ GHOSTTY_TERMINAL_DATA_PWD = 13,
+
+ /**
+ * The total number of rows in the active screen including scrollback.
+ *
+ * Output type: size_t *
+ */
+ GHOSTTY_TERMINAL_DATA_TOTAL_ROWS = 14,
+
+ /**
+ * The number of scrollback rows (total rows minus viewport rows).
+ *
+ * Output type: size_t *
+ */
+ GHOSTTY_TERMINAL_DATA_SCROLLBACK_ROWS = 15,
+
+ /**
+ * The total width of the terminal in pixels.
+ *
+ * This is cols * cell_width_px as set by ghostty_terminal_resize().
+ *
+ * Output type: uint32_t *
+ */
+ GHOSTTY_TERMINAL_DATA_WIDTH_PX = 16,
+
+ /**
+ * The total height of the terminal in pixels.
+ *
+ * This is rows * cell_height_px as set by ghostty_terminal_resize().
+ *
+ * Output type: uint32_t *
+ */
+ GHOSTTY_TERMINAL_DATA_HEIGHT_PX = 17,
+
+ /**
+ * The effective foreground color (override or default).
+ *
+ * Returns GHOSTTY_NO_VALUE if no foreground color is set.
+ *
+ * Output type: GhosttyColorRgb *
+ */
+ GHOSTTY_TERMINAL_DATA_COLOR_FOREGROUND = 18,
+
+ /**
+ * The effective background color (override or default).
+ *
+ * Returns GHOSTTY_NO_VALUE if no background color is set.
+ *
+ * Output type: GhosttyColorRgb *
+ */
+ GHOSTTY_TERMINAL_DATA_COLOR_BACKGROUND = 19,
+
+ /**
+ * The effective cursor color (override or default).
+ *
+ * Returns GHOSTTY_NO_VALUE if no cursor color is set.
+ *
+ * Output type: GhosttyColorRgb *
+ */
+ GHOSTTY_TERMINAL_DATA_COLOR_CURSOR = 20,
+
+ /**
+ * The current 256-color palette.
+ *
+ * Output type: GhosttyColorRgb[256] *
+ */
+ GHOSTTY_TERMINAL_DATA_COLOR_PALETTE = 21,
+
+ /**
+ * The default foreground color (ignoring any OSC override).
+ *
+ * Returns GHOSTTY_NO_VALUE if no default foreground color is set.
+ *
+ * Output type: GhosttyColorRgb *
+ */
+ GHOSTTY_TERMINAL_DATA_COLOR_FOREGROUND_DEFAULT = 22,
+
+ /**
+ * The default background color (ignoring any OSC override).
+ *
+ * Returns GHOSTTY_NO_VALUE if no default background color is set.
+ *
+ * Output type: GhosttyColorRgb *
+ */
+ GHOSTTY_TERMINAL_DATA_COLOR_BACKGROUND_DEFAULT = 23,
+
+ /**
+ * The default cursor color (ignoring any OSC override).
+ *
+ * Returns GHOSTTY_NO_VALUE if no default cursor color is set.
+ *
+ * Output type: GhosttyColorRgb *
+ */
+ GHOSTTY_TERMINAL_DATA_COLOR_CURSOR_DEFAULT = 24,
+
+ /**
+ * The default 256-color palette (ignoring any OSC overrides).
+ *
+ * Output type: GhosttyColorRgb[256] *
+ */
+ GHOSTTY_TERMINAL_DATA_COLOR_PALETTE_DEFAULT = 25,
+} GhosttyTerminalData;
+
+/**
+ * Create a new terminal instance.
+ *
+ * @param allocator Pointer to allocator, or NULL to use the default allocator
+ * @param terminal Pointer to store the created terminal handle
+ * @param options Terminal initialization options
+ * @return GHOSTTY_SUCCESS on success, or an error code on failure
+ *
+ * @ingroup terminal
+ */
+GHOSTTY_API GhosttyResult ghostty_terminal_new(const GhosttyAllocator* allocator,
+ GhosttyTerminal* terminal,
+ GhosttyTerminalOptions options);
+
+/**
+ * Free a terminal instance.
+ *
+ * Releases all resources associated with the terminal. After this call,
+ * the terminal handle becomes invalid and must not be used.
+ *
+ * @param terminal The terminal handle to free (may be NULL)
+ *
+ * @ingroup terminal
+ */
+GHOSTTY_API void ghostty_terminal_free(GhosttyTerminal terminal);
+
+/**
+ * Perform a full reset of the terminal (RIS).
+ *
+ * Resets all terminal state back to its initial configuration, including
+ * modes, scrollback, scrolling region, and screen contents. The terminal
+ * dimensions are preserved.
+ *
+ * @param terminal The terminal handle (may be NULL, in which case this is a no-op)
+ *
+ * @ingroup terminal
+ */
+GHOSTTY_API void ghostty_terminal_reset(GhosttyTerminal terminal);
+
+/**
+ * Resize the terminal to the given dimensions.
+ *
+ * Changes the number of columns and rows in the terminal. The primary
+ * screen will reflow content if wraparound mode is enabled; the alternate
+ * screen does not reflow. If the dimensions are unchanged, this is a no-op.
+ *
+ * This also updates the terminal's pixel dimensions (used for image
+ * protocols and size reports), disables synchronized output mode (allowed
+ * by the spec so that resize results are shown immediately), and sends an
+ * in-band size report if mode 2048 is enabled.
+ *
+ * @param terminal The terminal handle (NULL returns GHOSTTY_INVALID_VALUE)
+ * @param cols New width in cells (must be greater than zero)
+ * @param rows New height in cells (must be greater than zero)
+ * @param cell_width_px Width of a single cell in pixels
+ * @param cell_height_px Height of a single cell in pixels
+ * @return GHOSTTY_SUCCESS on success, or an error code on failure
+ *
+ * @ingroup terminal
+ */
+GHOSTTY_API GhosttyResult ghostty_terminal_resize(GhosttyTerminal terminal,
+ uint16_t cols,
+ uint16_t rows,
+ uint32_t cell_width_px,
+ uint32_t cell_height_px);
+
+/**
+ * Set an option on the terminal.
+ *
+ * Configures terminal callbacks and associated state such as the
+ * write_pty callback and userdata pointer. The value is passed
+ * directly for pointer types (callbacks, userdata) or as a pointer
+ * to the value for non-pointer types (e.g. GhosttyString*).
+ * NULL clears the option to its default.
+ *
+ * Callbacks are invoked synchronously during ghostty_terminal_vt_write().
+ * Callbacks must not call ghostty_terminal_vt_write() on the same
+ * terminal (no reentrancy).
+ *
+ * @param terminal The terminal handle (may be NULL, in which case this is a no-op)
+ * @param option The option to set
+ * @param value Pointer to the value to set (type depends on the option),
+ * or NULL to clear the option
+ *
+ * @ingroup terminal
+ */
+GHOSTTY_API GhosttyResult ghostty_terminal_set(GhosttyTerminal terminal,
+ GhosttyTerminalOption option,
+ const void* value);
+
+/**
+ * Write VT-encoded data to the terminal for processing.
+ *
+ * Feeds raw bytes through the terminal's VT stream parser, updating
+ * terminal state accordingly. By default, sequences that require output
+ * (queries, device status reports) are silently ignored. Use
+ * ghostty_terminal_set() with GHOSTTY_TERMINAL_OPT_WRITE_PTY to install
+ * a callback that receives response data.
+ *
+ * This never fails. Any erroneous input or errors in processing the
+ * input are logged internally but do not cause this function to fail
+ * because this input is assumed to be untrusted and from an external
+ * source; so the primary goal is to keep the terminal state consistent and
+ * not allow malformed input to corrupt or crash.
+ *
+ * @param terminal The terminal handle
+ * @param data Pointer to the data to write
+ * @param len Length of the data in bytes
+ *
+ * @ingroup terminal
+ */
+GHOSTTY_API void ghostty_terminal_vt_write(GhosttyTerminal terminal,
+ const uint8_t* data,
+ size_t len);
+
+/**
+ * Scroll the terminal viewport.
+ *
+ * Scrolls the terminal's viewport according to the given behavior.
+ * When using GHOSTTY_SCROLL_VIEWPORT_DELTA, set the delta field in
+ * the value union to specify the number of rows to scroll (negative
+ * for up, positive for down). For other behaviors, the value is ignored.
+ *
+ * @param terminal The terminal handle (may be NULL, in which case this is a no-op)
+ * @param behavior The scroll behavior as a tagged union
+ *
+ * @ingroup terminal
+ */
+GHOSTTY_API void ghostty_terminal_scroll_viewport(GhosttyTerminal terminal,
+ GhosttyTerminalScrollViewport behavior);
+
+/**
+ * Get the current value of a terminal mode.
+ *
+ * Returns the value of the mode identified by the given mode.
+ *
+ * @param terminal The terminal handle (NULL returns GHOSTTY_INVALID_VALUE)
+ * @param mode The mode identifying the mode to query
+ * @param[out] out_value On success, set to true if the mode is set, false
+ * if it is reset
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if the terminal
+ * is NULL or the mode does not correspond to a known mode
+ *
+ * @ingroup terminal
+ */
+GHOSTTY_API GhosttyResult ghostty_terminal_mode_get(GhosttyTerminal terminal,
+ GhosttyMode mode,
+ bool* out_value);
+
+/**
+ * Set the value of a terminal mode.
+ *
+ * Sets the mode identified by the given mode to the specified value.
+ *
+ * @param terminal The terminal handle (NULL returns GHOSTTY_INVALID_VALUE)
+ * @param mode The mode identifying the mode to set
+ * @param value true to set the mode, false to reset it
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if the terminal
+ * is NULL or the mode does not correspond to a known mode
+ *
+ * @ingroup terminal
+ */
+GHOSTTY_API GhosttyResult ghostty_terminal_mode_set(GhosttyTerminal terminal,
+ GhosttyMode mode,
+ bool value);
+
+/**
+ * Get data from a terminal instance.
+ *
+ * Extracts typed data from the given terminal based on the specified
+ * data type. The output pointer must be of the appropriate type for the
+ * requested data kind. Valid data types and output types are documented
+ * in the `GhosttyTerminalData` enum.
+ *
+ * @param terminal The terminal handle (may be NULL)
+ * @param data The type of data to extract
+ * @param out Pointer to store the extracted data (type depends on data parameter)
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if the terminal
+ * is NULL or the data type is invalid
+ *
+ * @ingroup terminal
+ */
+GHOSTTY_API GhosttyResult ghostty_terminal_get(GhosttyTerminal terminal,
+ GhosttyTerminalData data,
+ void *out);
+
+/**
+ * Resolve a point in the terminal grid to a grid reference.
+ *
+ * Resolves the given point (which can be in active, viewport, screen,
+ * or history coordinates) to a grid reference for that location. Use
+ * ghostty_grid_ref_cell() and ghostty_grid_ref_row() to extract the cell
+ * and row.
+ *
+ * Lookups using the `active` and `viewport` tags are fast. The `screen`
+ * and `history` tags may require traversing the full scrollback page list
+ * to resolve the y coordinate, so they can be expensive for large
+ * scrollback buffers.
+ *
+ * This function isn't meant to be used as the core of render loop. It
+ * isn't built to sustain the framerates needed for rendering large screens.
+ * Use the render state API for that. This API is instead meant for less
+ * strictly performance-sensitive use cases.
+ *
+ * @param terminal The terminal handle (NULL returns GHOSTTY_INVALID_VALUE)
+ * @param point The point specifying which cell to look up
+ * @param[out] out_ref On success, set to the grid reference at the given point (may be NULL)
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if the terminal
+ * is NULL or the point is out of bounds
+ *
+ * @ingroup terminal
+ */
+GHOSTTY_API GhosttyResult ghostty_terminal_grid_ref(GhosttyTerminal terminal,
+ GhosttyPoint point,
+ GhosttyGridRef *out_ref);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GHOSTTY_VT_TERMINAL_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt/types.h b/vendor/libghostty-vt/include/ghostty/vt/types.h
new file mode 100644
index 00000000..8f0be776
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/types.h
@@ -0,0 +1,121 @@
+/**
+ * @file types.h
+ *
+ * Common types, macros, and utilities for libghostty-vt.
+ */
+
+#ifndef GHOSTTY_VT_TYPES_H
+#define GHOSTTY_VT_TYPES_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+// Symbol visibility for shared library builds. On Windows, functions
+// are exported from the DLL when building and imported when consuming.
+// On other platforms with GCC/Clang, functions are marked with default
+// visibility so they remain accessible when the library is built with
+// -fvisibility=hidden. For static library builds, define GHOSTTY_STATIC
+// before including this header to make this a no-op.
+#ifndef GHOSTTY_API
+#if defined(GHOSTTY_STATIC)
+ #define GHOSTTY_API
+#elif defined(_WIN32) || defined(_WIN64)
+ #ifdef GHOSTTY_BUILD_SHARED
+ #define GHOSTTY_API __declspec(dllexport)
+ #else
+ #define GHOSTTY_API __declspec(dllimport)
+ #endif
+#elif defined(__GNUC__) && __GNUC__ >= 4
+ #define GHOSTTY_API __attribute__((visibility("default")))
+#else
+ #define GHOSTTY_API
+#endif
+#endif
+
+/**
+ * Result codes for libghostty-vt operations.
+ */
+typedef enum {
+ /** Operation completed successfully */
+ GHOSTTY_SUCCESS = 0,
+ /** Operation failed due to failed allocation */
+ GHOSTTY_OUT_OF_MEMORY = -1,
+ /** Operation failed due to invalid value */
+ GHOSTTY_INVALID_VALUE = -2,
+ /** Operation failed because the provided buffer was too small */
+ GHOSTTY_OUT_OF_SPACE = -3,
+ /** The requested value has no value */
+ GHOSTTY_NO_VALUE = -4,
+} GhosttyResult;
+
+/**
+ * A borrowed byte string (pointer + length).
+ *
+ * The memory is not owned by this struct. The pointer is only valid
+ * for the lifetime documented by the API that produces or consumes it.
+ */
+typedef struct {
+ /** Pointer to the string bytes. */
+ const uint8_t* ptr;
+
+ /** Length of the string in bytes. */
+ size_t len;
+} GhosttyString;
+
+/**
+ * Initialize a sized struct to zero and set its size field.
+ *
+ * Sized structs use a `size` field as the first member for ABI
+ * compatibility. This macro zero-initializes the struct and sets the
+ * size field to `sizeof(type)`, which allows the library to detect
+ * which version of the struct the caller was compiled against.
+ *
+ * @param type The struct type to initialize
+ * @return A zero-initialized struct with the size field set
+ *
+ * Example:
+ * @code
+ * GhosttyFormatterTerminalOptions opts = GHOSTTY_INIT_SIZED(GhosttyFormatterTerminalOptions);
+ * opts.emit = GHOSTTY_FORMATTER_FORMAT_PLAIN;
+ * opts.trim = true;
+ * @endcode
+ */
+#define GHOSTTY_INIT_SIZED(type) \
+ ((type){ .size = sizeof(type) })
+
+/**
+ * Return a pointer to a null-terminated JSON string describing the
+ * layout of every C API struct for the current target.
+ *
+ * This is primarily useful for language bindings that can't easily
+ * set C struct fields and need to do so via byte offsets. For example,
+ * WebAssembly modules can't share struct definitions with the host.
+ *
+ * Example (abbreviated):
+ * @code{.json}
+ * {
+ * "GhosttyMouseEncoderSize": {
+ * "size": 40,
+ * "align": 8,
+ * "fields": {
+ * "size": { "offset": 0, "size": 8, "type": "u64" },
+ * "screen_width": { "offset": 8, "size": 4, "type": "u32" },
+ * "screen_height": { "offset": 12, "size": 4, "type": "u32" },
+ * "cell_width": { "offset": 16, "size": 4, "type": "u32" },
+ * "cell_height": { "offset": 20, "size": 4, "type": "u32" },
+ * "padding_top": { "offset": 24, "size": 4, "type": "u32" },
+ * "padding_bottom": { "offset": 28, "size": 4, "type": "u32" },
+ * "padding_right": { "offset": 32, "size": 4, "type": "u32" },
+ * "padding_left": { "offset": 36, "size": 4, "type": "u32" }
+ * }
+ * }
+ * }
+ * @endcode
+ *
+ * The returned pointer is valid for the lifetime of the process.
+ *
+ * @return Pointer to the null-terminated JSON string.
+ */
+GHOSTTY_API const char *ghostty_type_json(void);
+
+#endif /* GHOSTTY_VT_TYPES_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt/wasm.h b/vendor/libghostty-vt/include/ghostty/vt/wasm.h
new file mode 100644
index 00000000..e2b63e2c
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/wasm.h
@@ -0,0 +1,160 @@
+/**
+ * @file wasm.h
+ *
+ * WebAssembly utility functions for libghostty-vt.
+ */
+
+#ifndef GHOSTTY_VT_WASM_H
+#define GHOSTTY_VT_WASM_H
+
+#ifdef __wasm__
+
+#include <stddef.h>
+#include <stdint.h>
+#include <ghostty/vt/types.h>
+
+/** @defgroup wasm WebAssembly Utilities
+ *
+ * Convenience functions for allocating various types in WebAssembly builds.
+ * **These are only available the libghostty-vt wasm module.**
+ *
+ * Ghostty relies on pointers to various types for ABI compatibility, and
+ * creating those pointers in Wasm can be tedious. These functions provide
+ * a purely additive set of utilities that simplify memory management in
+ * Wasm environments without changing the core C library API.
+ *
+ * @note These functions always use the default allocator. If you need
+ * custom allocation strategies, you should allocate types manually using
+ * your custom allocator. This is a very rare use case in the WebAssembly
+ * world so these are optimized for simplicity.
+ *
+ * ## Example Usage
+ *
+ * Here's a simple example of using the Wasm utilities with the key encoder:
+ *
+ * @code
+ * const { exports } = wasmInstance;
+ * const view = new DataView(wasmMemory.buffer);
+ *
+ * // Create key encoder
+ * const encoderPtr = exports.ghostty_wasm_alloc_opaque();
+ * exports.ghostty_key_encoder_new(null, encoderPtr);
+ * const encoder = view.getUint32(encoder, true);
+ *
+ * // Configure encoder with Kitty protocol flags
+ * const flagsPtr = exports.ghostty_wasm_alloc_u8();
+ * view.setUint8(flagsPtr, 0x1F);
+ * exports.ghostty_key_encoder_setopt(encoder, 5, flagsPtr);
+ *
+ * // Allocate output buffer and size pointer
+ * const bufferSize = 32;
+ * const bufPtr = exports.ghostty_wasm_alloc_u8_array(bufferSize);
+ * const writtenPtr = exports.ghostty_wasm_alloc_usize();
+ *
+ * // Encode the key event
+ * exports.ghostty_key_encoder_encode(
+ * encoder, eventPtr, bufPtr, bufferSize, writtenPtr
+ * );
+ *
+ * // Read encoded output
+ * const bytesWritten = view.getUint32(writtenPtr, true);
+ * const encoded = new Uint8Array(wasmMemory.buffer, bufPtr, bytesWritten);
+ * @endcode
+ *
+ * @remark The code above is pretty ugly! This is the lowest level interface
+ * to the libghostty-vt Wasm module. In practice, this should be wrapped
+ * in a higher-level API that abstracts away all this.
+ *
+ * @{
+ */
+
+/**
+ * Allocate an opaque pointer. This can be used for any opaque pointer
+ * types such as GhosttyKeyEncoder, GhosttyKeyEvent, etc.
+ *
+ * @return Pointer to allocated opaque pointer, or NULL if allocation failed
+ * @ingroup wasm
+ */
+GHOSTTY_API void** ghostty_wasm_alloc_opaque(void);
+
+/**
+ * Free an opaque pointer allocated by ghostty_wasm_alloc_opaque().
+ *
+ * @param ptr Pointer to free, or NULL (NULL is safely ignored)
+ * @ingroup wasm
+ */
+GHOSTTY_API void ghostty_wasm_free_opaque(void **ptr);
+
+/**
+ * Allocate an array of uint8_t values.
+ *
+ * @param len Number of uint8_t elements to allocate
+ * @return Pointer to allocated array, or NULL if allocation failed
+ * @ingroup wasm
+ */
+GHOSTTY_API uint8_t* ghostty_wasm_alloc_u8_array(size_t len);
+
+/**
+ * Free an array allocated by ghostty_wasm_alloc_u8_array().
+ *
+ * @param ptr Pointer to the array to free, or NULL (NULL is safely ignored)
+ * @param len Length of the array (must match the length passed to alloc)
+ * @ingroup wasm
+ */
+GHOSTTY_API void ghostty_wasm_free_u8_array(uint8_t *ptr, size_t len);
+
+/**
+ * Allocate an array of uint16_t values.
+ *
+ * @param len Number of uint16_t elements to allocate
+ * @return Pointer to allocated array, or NULL if allocation failed
+ * @ingroup wasm
+ */
+GHOSTTY_API uint16_t* ghostty_wasm_alloc_u16_array(size_t len);
+
+/**
+ * Free an array allocated by ghostty_wasm_alloc_u16_array().
+ *
+ * @param ptr Pointer to the array to free, or NULL (NULL is safely ignored)
+ * @param len Length of the array (must match the length passed to alloc)
+ * @ingroup wasm
+ */
+GHOSTTY_API void ghostty_wasm_free_u16_array(uint16_t *ptr, size_t len);
+
+/**
+ * Allocate a single uint8_t value.
+ *
+ * @return Pointer to allocated uint8_t, or NULL if allocation failed
+ * @ingroup wasm
+ */
+GHOSTTY_API uint8_t* ghostty_wasm_alloc_u8(void);
+
+/**
+ * Free a uint8_t allocated by ghostty_wasm_alloc_u8().
+ *
+ * @param ptr Pointer to free, or NULL (NULL is safely ignored)
+ * @ingroup wasm
+ */
+GHOSTTY_API void ghostty_wasm_free_u8(uint8_t *ptr);
+
+/**
+ * Allocate a single size_t value.
+ *
+ * @return Pointer to allocated size_t, or NULL if allocation failed
+ * @ingroup wasm
+ */
+GHOSTTY_API size_t* ghostty_wasm_alloc_usize(void);
+
+/**
+ * Free a size_t allocated by ghostty_wasm_alloc_usize().
+ *
+ * @param ptr Pointer to free, or NULL (NULL is safely ignored)
+ * @ingroup wasm
+ */
+GHOSTTY_API void ghostty_wasm_free_usize(size_t *ptr);
+
+/** @} */
+
+#endif /* __wasm__ */
+
+#endif /* GHOSTTY_VT_WASM_H */
diff --git a/vendor/libghostty-vt/include/module.modulemap b/vendor/libghostty-vt/include/module.modulemap
new file mode 100644
index 00000000..8961f5c0
--- /dev/null
+++ b/vendor/libghostty-vt/include/module.modulemap
@@ -0,0 +1,7 @@
+// This makes Ghostty available to the XCode build for the macOS app.
+// We append "Kit" to it not to be cute, but because targets have to have
+// unique names and we use Ghostty for other things.
+module GhosttyKit {
+ umbrella header "ghostty.h"
+ export *
+}