Commit Graph

522 Commits

Author SHA1 Message Date
Mitchell Hashimoto
dd2edd760d libvt: return safe pointers for empty output
Normalize empty buffers and borrowed strings at the libghostty-vt C
boundary to null pointers.

Zig can use sentinel addresses such as 0x1 for empty slices. Returning
these pointers to Go can cause a fatal invalid-pointer error when the
runtime relocates a goroutine's stack, even though the length is zero.
2026-09-07 20:42:28 -07:00
Mitchell Hashimoto
4b51f521d4 libghostty: add terminal search API (#14097)
This exposes the terminal search API through libghostty C and Zig APIs.

This was previously available through the Zig APIs but forced our
threading model. I've now extracted the full terminal search state to a
new `terminal.search.TerminalSearch` structure so threading isn't
forced. The C API is completely new.

## Example (C)

```c
GhosttySearch search;
ghostty_search_new(NULL, &search, terminal);

GhosttyString needle = { (const uint8_t *)"error", 5 };
ghostty_search_set(search, GHOSTTY_SEARCH_OPT_NEEDLE, &needle);
ghostty_search_run(search);

// Find bar chrome: "k of n"
size_t total, idx;
ghostty_search_get(search, GHOSTTY_SEARCH_DATA_TOTAL_MATCHES, &total);

// Enter: select the next match (wraps, scrolls the viewport if needed)
ghostty_search_set(search, GHOSTTY_SEARCH_OPT_SELECT_NEXT, NULL);
ghostty_search_get(search, GHOSTTY_SEARCH_DATA_SELECTED_INDEX, &idx);

ghostty_search_free(search);
```
2026-08-31 14:23:38 -07:00
Mitchell Hashimoto
76d9fcefef libghostty: set the search needle via ghostty_search_set, drop GhosttySearchOptions 2026-08-31 14:08:07 -07:00
Mitchell Hashimoto
674abd8a19 example: add c-vt-search demonstrating the terminal search C API 2026-08-31 13:49:55 -07:00
Mitchell Hashimoto
f9202919f7 libghostty: add ghostty_search_* terminal search C API 2026-08-31 13:49:25 -07:00
Uzair Aftab
a5423592cd libghostty: use caller allocation on native freestanding
Native freestanding targets have neither an OS page allocator nor a usable default SMP allocator. Use the allocator supplied through libghostty for terminal page storage and make a missing C allocator fail with out-of-memory instead of instantiating hosted allocation machinery. Document that native freestanding C callers must supply an allocator for allocating operations.
2026-08-29 22:12:38 +02:00
Mitchell Hashimoto
70f0065759 terminal: reject oversized Kitty clipboard writes
Update OSC 5522 writes to reject every transaction that exceeds the
configured decoded-data limit. The previous behavior truncated text
while rejecting only non-text data.

Programs now receive EFBIG as soon as a write crosses the limit. The
clipboard remains untouched, and remaining write packets are ignored
until a new transaction begins. Raise the default to the protocol
minimum of 64 MiB.

This applies the latest spec change:
32ea104192
2026-08-24 21:14:36 -07:00
Mitchell Hashimoto
600a86dcfd terminal: make Kitty clipboard write limit configurable (#14002)
Add a new `clipboard-write-limit-bytes` option (similar to
`scrollback-limit-bytes`) to limit the maximum OSC 5522 write size.
Defaults to 32 MB.

This also adds a new `GHOSTTY_TERMINAL_OPT_CLIPBOARD_WRITE_MAX_BYTES`
option for libghostty-vt embedders to control the same.

Kitty has a limit too and it works by truncating all data. I decided on
purpose to diverge from this because I don't think truncated binary data
is useful. Instead, we reject it so the application knows the write
didn't work.

We truncate text data, and we try to do it at the nearest complete UTF-8
sequence (if possible).

For the future: Kitty spools any write data more than some size (can't
remember) to a temp file on disk. We might want to consider doing
something similar since we're all in-memory at the moment. This PR
doesn't change that.
2026-08-24 13:55:29 -07:00
Mitchell Hashimoto
75606a6900 terminal: exempt Kitty clipboard listing reads from permission prompts (#14001)
A Kitty clipboard protocol (OSC 5522) read that only requests the
targets type ('.') is now served without a permission prompt and never
consults (or consumes) session password grants.

The spec requires this so that a client listing the available data types
before reading one doesn't present the user with a double permission
prompt.
2026-08-24 13:35:44 -07:00
Mitchell Hashimoto
5350d4a5f5 terminal: make Kitty clipboard write limit configurable
Add a new `clipboard-write-limit-bytes` option (similar to 
`scrollback-limit-bytes`) to limit the maximum OSC 5522 write size.
Defaults to 32 MB.

This also adds a new `GHOSTTY_TERMINAL_OPT_CLIPBOARD_WRITE_MAX_BYTES`
option for libghostty-vt embedders to control the same.

Kitty has a limit too and it works by truncating all data. I decided on
purpose to diverge from this because I don't think truncated binary data
is useful. Instead, we reject it so the application knows the write
didn't work.

We truncate text data, and we try to do it at the nearest complete UTF-8
sequence (if possible).
2026-08-24 13:34:46 -07:00
Mitchell Hashimoto
928c7f0e79 terminal: exempt Kitty clipboard listing reads from permission prompts
A Kitty clipboard protocol (OSC 5522) read that only requests the
targets type ('.') is now served without a permission prompt and never
consults (or consumes) session password grants. 

The spec requires this so that a client listing the available data types 
before reading one doesn't present the user with a double permission prompt.
2026-08-24 13:25:12 -07:00
Mitchell Hashimoto
1334cc213e macos: answer ENOSYS for Kitty clipboard writes to primary
A Kitty clipboard protocol (OSC 5522) write transaction targeting
`loc=primary` replied `type=write:status=DONE` in the macOS app even
though macOS has no primary selection and the data was silently
discarded. 

The spec requires ENOSYS when the requested location is not
available on the system, which the read path already answers correctly:
https://sw.kovidgoyal.net/kitty/clipboard/
2026-08-24 13:11:23 -07:00
Mitchell Hashimoto
25c61e852f macos: implement Kitty clipboard protocol writes
Programs can now write the system clipboard through the Kitty
clipboard protocol in the macOS app. This also does all the hard work
plumbing through core termio/apprt so GTK should be an easy follow.

This functionality lets clients copy arbitrary representations (images, 
HTML, etc.) into the clipboard. Writes honor `clipboard-write`: allow 
applies silently, deny answers EPERM up front before any data is used, 
and ask shows the standard confirmation prompt.
2026-08-24 12:18:46 -07:00
Mitchell Hashimoto
c2c0db68aa macOS: enable mode 5522 paste events
Advertise Kitty clipboard protocol mode 5522 on macOS and route
clipboard paste requests through the protocol when it is enabled.
2026-08-24 09:37:57 -07:00
Mitchell Hashimoto
75d657788a macOS: Kitty clipboard read support (#13993)
This adds Kitty clipboard protocol _read_ support to macOS. In the
process, this also does most of the core termio, apprt, and Surface work
so GTK is likely very easy to do, I just didn't have the machine on hand
to test at the given moment. I will create an issue to follow up with
that.

This fully supports:

- Non-text data, like images! For this, we show an image preview.
- Per-program "remember"
- Showing the program name if given instead of generic "An application"

<img width="1848" height="996" alt="CleanShot 2026-08-24 at 08 37 45@2x"
src="https://github.com/user-attachments/assets/549d9031-2e98-46bf-90d4-94171b255c42"
/>
2026-08-24 09:00:58 -07:00
Mitchell Hashimoto
7ae9b11138 libghostty: Kitty clipboard write permission prompts and grants
The `clipboard_write` effect now is similar to read: it must response
to a "reply" callback synchronously. This lets the embedder ask for write
permission, too.

We also now pass through program name and grant information from Kitty 
clipboard protocol so that embedders can use that if they want.

This is a breaking ABI change.
2026-08-24 08:35:34 -07:00
Mitchell Hashimoto
af9470b19b macos: Kitty clipboard reads support pw/name session grants 2026-08-24 08:18:36 -07:00
Mitchell Hashimoto
8c7a34d4c9 macos: Kitty clipboard reads serve all clipboard content types 2026-08-24 08:18:36 -07:00
Mitchell Hashimoto
0ce9054bf9 macos: implement Kitty clipboard protocol reads (OSC 5522) 2026-08-24 08:18:36 -07:00
Mitchell Hashimoto
da27e6c908 libghostty: paste reads clipboard contents on demand, streams to pty
Follow up to #13978

`ghostty_terminal_paste` no longer takes the clipboard's data up front.
The request now carries only the list of available MIME types plus a
a callback that writes one representation's bytes into a `GhosttyWriter`. 

Previously an embedder had to load every representation for every MIME
type into memory before pasting. For a clipboard holding a large image
or video next to some text that could be hundreds of megabytes that
were never used.

I also took care to make sure that the data is only read once, to avoid
any time-of-check/time-of-use (TOCTOU) issues.

There is only one case where data might be fully buffered in memory now:
unsafe text data that needs to be checked. This is true for how Ghostty
GUI works today too.
2026-08-23 20:40:40 -07:00
Mitchell Hashimoto
60a1ae2df7 libghostty: add ghostty_terminal_paste C API with paste events example 2026-08-22 15:16:30 -07:00
Mitchell Hashimoto
dda8e6f314 sys: add secure random override option with a platform default 2026-08-22 15:16:30 -07:00
Mitchell Hashimoto
4f49dc2b8b libghostty: implement Kitty clipboard protocol reads via clipboard_read effect 2026-08-22 07:02:09 -07:00
Mitchell Hashimoto
6959fd46c6 libghostty: implement Kitty clipboard protocol write only
This implements only the clipboard _write_ side of the Kitty clipboard
protocol for libghostty-vt. libghostty users don't need to do anything,
this all automatically works since it just piggy-backs on the previous
clipboard write effect.

Clipboard reading is far more complicated because we don't have anything
designed yet for libghostty-vt that does async requests (e.g. to ask the
user for permission). I need to think about that more.
2026-08-21 21:16:14 -07:00
Mitchell Hashimoto
e03475c0cc libghostty: clipboard_read effect, enables OSC52 reads
This adds a `clipboard_read` effect to the stream terminal handler and a
matching `GHOSTTY_TERMINAL_OPT_CLIPBOARD_READ` callback to the
libghostty-vt C API so that embedders can answer OSC 52 read requests
(the `?` payload). 

This is a _blocking_ effect: if the embedder needs to ask the user for
permission, the entire VT processing pipeline is _blocked_ during the
callback. This is a purposeful simplification choice compared to how
Ghostty GUI works with async requests. I think its reasonable, it
eliminates a TON of complexity.

If the effect isn't set, then any clipboard reads are denied.

This can be expanded easily to support Kitty clipboard protocol later.
2026-08-21 20:51:31 -07:00
Mitchell Hashimoto
ca9e5b1301 terminal/osc: kitty notification parsing feedback 2026-08-21 14:00:30 -07:00
Mitchell Hashimoto
819b241dec terminal: Kitty Clipboard core logic (no apprt hookups yet) (#13962)
This adds all the core logic and tests for the full Kitty Clipboard
protocol in the `src/terminal` package.

This is purposefully shaped similarly to the way we organize Kitty
graphics. There is an umbrella `clipboard.zig` and then a bunch of leaf
zig files that cover: request parsing, response encoding, state
management, etc. I think that worked really well for Kitty graphics so
we're doing it here too.

The core logic covers every part of the protocol: read and write.

The only thing hooked up to the end user is a DECRQM for mode 5522 will
return unset. And it can't be set currently (since it never works yet).
Outside of that, nothing in this diff is actually used in the real
binary.

**AI usage:** Validation against the spec and Kitty impl, test writing
and coverage validation, of course some code writing but within the
broad organizational shape I defined. I went through and either rewrote
or wrote all the comments myself plus this PR message.
2026-08-21 13:13:58 -07:00
Mitchell Hashimoto
07c6fc21ba terminal: add kitty clipboard paste events mode (5522), disabled for now 2026-08-21 12:16:38 -07:00
Mitchell Hashimoto
73903f76aa terminal/c: image data returns the current animation frame 2026-08-21 09:45:58 -07:00
Elias Andualem
5b9a77f203 terminal: document mode 2048 size reports 2026-08-18 15:34:07 +03:00
Mitchell Hashimoto
9be6c2ea28 libghostty: option to retain continuations on snapshot decode
Add a snapshot decoder option that leaves continuation tracking
enabled on decoded terminals. This lets caller access the continuation
bytes (if any) that were applied to the terminal.

This lets replay callers export an unfinished parser or UTF-8 sequence
from the returned terminal.

This defaults to off.
2026-08-17 13:30:41 -07:00
Mitchell Hashimoto
924c8a90de libghostty: C api to stream formatter output through a GhosttyWriter
Add `ghostty_formatter_format` which uses a streaming GhosttyWriter
type to write. Update the example to show this.
2026-08-17 09:34:52 -07:00
Mitchell Hashimoto
a8e9b413f1 libghostty: simplify Wasm allocation API
Replace a bunch of type-specific Wasm allocation functions with a generic
byte allocator and reusable opaque out-parameters for pointers. This
makes it a lot more ergonomic (relatively) to use the Wasm interface
and removes a dozen or so exports.

This also updates the `ghostty_type_json` `abi` field with a maximum
alignment value that host sides can use to keep every allocation aligned
properly, easily, without hardcoding numbers.

This adds a test to verify this all works as intended and runs in CI.
2026-08-16 12:39:51 -07:00
Mitchell Hashimoto
0e8b7bea63 vt: expose packed cell layout
GhosttyCell was exposed as a raw integer while its manifest entry was only an alias, forcing bulk-read consumers to duplicate the internal cell bit layout.\n\nAdd reflection helpers for packed structs and tagged unions, and keep the C-facing layout metadata next to Cell itself. Extend the ABI manifest and schema with recursive bit descriptors so every content arm, including palette and RGB backgrounds, can be decoded without hardcoded masks.\n\nDocument manifest-driven cell decoding and test the metadata against Zig reflection and real cell values.
2026-08-15 21:16:34 -07:00
Mitchell Hashimoto
c75559589e libghostty: add ABI manifest schema
The ABI manifest previously had no machine-readable grammar or test that
the public export conformed to it.

Define a Draft 2020-12 schema and add a build check that executes
ghostty_type_json for native and wasm libraries before validation. Run
both forms in CI and publish the schema with the generated API docs.
2026-08-15 21:16:34 -07:00
Mitchell Hashimoto
9673a22b01 libghostty: expand ABI type metadata
The type metadata export only described extern struct layouts, leaving embedders to mirror enum values and tagged union relationships.

Describe every public C type in a versioned manifest with target and build metadata. Keep union field renames alongside their source tagged unions so the manifest uses public C names without changing Zig value layouts.
2026-08-15 21:16:34 -07:00
Mitchell Hashimoto
ad6e72ddc4 libghostty: add dedicated dirty row iteration + clear functions (#13852)
Add render state C APIs for iterating only rows that require a redraw
and for marking a completed frame clean in one call.

A one-row update in a 24-row viewport reduces dirty-row discovery from
50 calls to two, while cleanup becomes one call instead of O(N) of rows.

This lower call count is massive for environments where FFI is expensive
(Go, wasm).

The dirty next API outputs the viewport y because it jumps, unlike the
normal sequential next where its trivial for a caller to keep track.
2026-08-15 21:11:21 -07:00
Mitchell Hashimoto
0d37f2d34d libghostty: add dedicated dirty row iteration + clear functions
Add render state C APIs for iterating only rows that require a redraw
and for marking a completed frame clean in one call.  

A one-row update in a 24-row viewport reduces dirty-row discovery from 
50 calls to two, while cleanup becomes one call instead of O(N) of rows.

This lower call count is massive for environments where FFI is expensive
(Go, wasm).

The dirty next API outputs the viewport y because it jumps, unlike the
normal sequential next where its trivial for a caller to keep track.
2026-08-15 20:59:01 -07:00
Mitchell Hashimoto
b4079f00c8 libghostty: add render state structured cursor read
A normal renderer would have to call `ghostty_render_state_get`
_eight times_ to reconstruct the cursor. In languages where FFI is
expensive (Go, wasm, etc.), this showed up in profiles of every frame.

Add a sized cursor snapshot and expose it. Also expose the existing color
snapshot through ghostty_render_state_get and remove the older
dedicated color getter.
2026-08-15 20:54:40 -07:00
Mitchell Hashimoto
74a233b543 libghostty: faster render state reads and updates on wasm targets
This makes the `ghostty_render_state_*` C API significantly faster on
wasm32-freestanding, measured in V8 via Node for Chrome. Also verified
in `jsc` for Safari.

The major change is a new bulk row read API that makes full-screen cell reads
roughly 10x faster for wasm embedders. This should help any embedder with
high FFI overhead, such as Go, Python, etc. too.

Non-wasm performance is not impacted, all benchmarks were run on my mac
too w/ no regressions (two of the changes are native wins as well).

## Changes

* color: the "vectorized" palette conversion loop was silently
  scalarized by LLVM into per-byte ops because it loaded/stored through
  array-typed pointers. Zig 0.16 disables the LLVM loop vectorizer, so
  manually vectorized loops must go through vector-typed pointers.
* C styles: major optimizations to converting Zig styles to C styles.
  This is a heavy operation for render state.
* render: `endUpdate`'s style-run fill (`@memset` with a struct value)
  re-loaded its source every iteration and stored field by field. Now
  manually vectorized.
* render: new `GHOSTTY_RENDER_STATE_ROW_DATA_CELLS_RAW` returns a
  borrowed `GhosttyCellsView` of the current row's raw cell values, valid
  until the next update. One call per row instead of 3-6 calls per cell.

## Benchmarks

| Benchmark | Before | After | Speedup |
|---|---|---|---|
| colors_get | 114 ns | 35 ns | 3.3x |
| style get, per styled cell | 7.8 ns | 6.7 ns | 1.2x |
| raw+style read, per cell | 8.6 ns | 7.7 ns | 1.1x |
| full-screen text read, per cell | 7.5 ns | 0.7 ns | 10.7x |
| full-screen text+style read, per cell | 8.6 ns | 1.7 ns | 5.1x |
| render state update, styled full frame | 3.4 us | 2.6 us | 1.3x |

**AI usage:** Fable did the implementation and benchmarking and drafted
this message. Comments were partially rewritten by me.
2026-08-14 11:40:01 -07:00
Mitchell Hashimoto
d930c74c4d libghostty: make sized initialization valid C++
Use an immediately invoked lambda for GHOSTTY_INIT_SIZED in C++ so the 
macro value-initializes every field before setting the ABI size. The 
previous C compound literal and designated initializer required compiler 
extensions in C++17 and C++20.

Keep the existing standard compound literal for C callers.
2026-08-13 12:39:25 -07:00
Mitchell Hashimoto
e4ec4f0f95 libghostty: fix enum underlying type detection
Use fixed int enum types for C++11, C23, Clang's fixed-enum extension, 
and GCC 13 or newer. Previously only finalized C23 mode selected an explicit 
underlying type, leaving C++ and common older C modes with 
implementation-defined enum types.
2026-08-13 12:39:25 -07:00
Mitchell Hashimoto
51992ab01a libghostty: make device and point headers self-contained 2026-08-13 12:39:25 -07:00
Vishal Kapur
c80c373627 Remove internal surface prompt query 2026-08-12 13:24:21 -07:00
Vishal Kapur
bdb566068e Expose semantic prompt state through C APIs 2026-08-12 12:20:04 -07:00
Leah Amelia Chen
1eaf457b18 gtk: add window title renaming (#10999)
Fixes #10469 for GTK.
2026-08-13 01:11:12 +08:00
Mitchell Hashimoto
a69a591af1 libghostty: functions to detect and write until stream ground state
This adds new functions to both C and Zig to write VT data until the
VT parser reaches a "ground" state. The ground state is when the
parser/stream is stateless: between all partial UTF-8, OSC, CSI, etc.

This lets embedders safely interleave custom VT sequences from multiple
sources. A practical example is a standard terminal reading from a pty
that is then doing custom APC or something mid-stream for their emulator
client.
2026-08-12 06:26:29 -07:00
Jeffrey C. Ollie
8b7c57c756 gtk: add window title renaming
Fixes #10469 for GTK.
2026-08-10 10:07:11 -05:00
Jeffrey C. Ollie
0a183c923b core/gtk: allow editing Ghostty config in a Ghostty window
This PR extends the `open_config` keybind action to allow editing the
Ghostty config in a new Ghostty window using the editor configured in
`$EDITOR` or `$VISUAL`.
2026-08-10 08:54:36 -05:00
Lukas
7e463bc65d ghostty.h: mark as internal (#13724) 2026-08-10 09:20:18 +02:00