Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
6a1f7b2
renderer: split scene projection from terminal capture
lawrencecchen Jul 17, 2026
066f7a3
renderer: complete isolated scene worker ABI
lawrencecchen Jul 18, 2026
2e11055
renderer: complete external scene fidelity
lawrencecchen Jul 18, 2026
b9746b9
renderer: preserve advanced external scene fidelity
lawrencecchen Jul 18, 2026
eefdfed
instrument process-lifetime terminal ownership
lawrencecchen Jul 18, 2026
0638be5
instrument runtime app construction
lawrencecchen Jul 18, 2026
b11389d
build: add scene-only renderer kit
lawrencecchen Jul 18, 2026
0e750d5
feat(config): add isolated GhosttyConfigKit
lawrencecchen Jul 18, 2026
df34f85
Merge commit '19d03fa4d0161e60e02de2e42601992be0c001c3' into task-pr8…
lawrencecchen Aug 10, 2026
886562d
Adapt scene libraries to Zig 0.16
lawrencecchen Aug 10, 2026
3062d4e
Adapt isolated libraries to current terminal options
lawrencecchen Aug 10, 2026
3133004
Adapt scene libc discovery to Zig 0.16
lawrencecchen Aug 10, 2026
0a9ffc6
Adapt isolated dependency links to Zig 0.16
lawrencecchen Aug 10, 2026
b324109
Use the shared Unicode module in isolated libraries
lawrencecchen Aug 10, 2026
08bdf55
Reconcile renderer ownership with Ghostty main
lawrencecchen Aug 10, 2026
ca0a01d
Adapt terminal scene APIs to Zig 0.16
lawrencecchen Aug 10, 2026
7f2cfba
Adapt scene capture to current terminal cells
lawrencecchen Aug 10, 2026
c0d3d64
Expose persistent VT parser state
lawrencecchen Aug 10, 2026
eff2e98
Adapt scene runtime to Zig 0.16 clocks
lawrencecchen Aug 10, 2026
cf4d82a
Adapt scene materialization to current renderer state
lawrencecchen Aug 10, 2026
3b2013f
Specialize Metal surface access for scenes
lawrencecchen Aug 10, 2026
cfdc783
Merge commit 'f76c132e526f124fe4aaebd39f516751656844bc' into task-pr8…
lawrencecchen Aug 10, 2026
02bc6f6
Restrict scene renderer process capabilities
lawrencecchen Aug 10, 2026
311a819
Merge remote-tracking branch 'origin/main' into task-pr8378-terminal-…
lawrencecchen Aug 10, 2026
aa5c316
Materialize only allowed scene IO capabilities
lawrencecchen Aug 10, 2026
aa13651
Fix compile-time scene IO selection
lawrencecchen Aug 10, 2026
825c6bd
scene: fail closed over process syscalls
lawrencecchen Aug 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 43 additions & 13 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -116,21 +116,22 @@ pub fn build(b: *std.Build) !void {
check_step.dependOn(dist.install_step);
}

// libghostty-vt
const libghostty_vt_shared = shared: {
if (config.target.result.cpu.arch.isWasm()) {
break :shared try buildpkg.GhosttyLibVt.initWasm(
b,
&mod,
);
}

break :shared try buildpkg.GhosttyLibVt.initShared(
// libghostty-vt dynamic library. The WebAssembly module is the primary
// lib-vt artifact for that target and is therefore unaffected by the
// native-only shared-library switch.
if (config.target.result.cpu.arch.isWasm()) {
const libghostty_vt_wasm = try buildpkg.GhosttyLibVt.initWasm(
b,
&mod,
);
libghostty_vt_wasm.install(b.getInstallStep());
} else if (config.emit_lib_vt_shared) {
const libghostty_vt_shared = try buildpkg.GhosttyLibVt.initShared(
b,
&mod,
);
};
libghostty_vt_shared.install(b.getInstallStep());
libghostty_vt_shared.install(b.getInstallStep());
}

// libghostty-vt static lib
const libghostty_vt_static = try buildpkg.GhosttyLibVt.initStatic(
Expand Down Expand Up @@ -183,7 +184,10 @@ pub fn build(b: *std.Build) !void {
resources.install();
if (i18n) |v| v.install();
}
} else if (!config.emit_lib_vt) {
} else if (!config.emit_lib_vt and
!config.emit_scene_xcframework and
!config.emit_config_xcframework)
{
// The macOS Ghostty Library
//
// This is NOT libghostty (even though its named that for historical
Expand Down Expand Up @@ -245,6 +249,32 @@ pub fn build(b: *std.Build) !void {
}
}

// The scene renderer is independently selectable so artifact audits and
// worker-only builds never schedule full GhosttyKit compilation.
if (!config.emit_lib_vt and config.target.result.os.tag.isDarwin() and
config.emit_scene_xcframework)
{
const scene_xcframework = try buildpkg.GhosttySceneXCFramework.init(
b,
&deps,
config.xcframework_target,
);
scene_xcframework.install();
}

// ConfigKit is a separate artifact so daemon processes never link the
// scene renderer merely to resolve Ghostty configuration.
if (!config.emit_lib_vt and config.target.result.os.tag == .macos and
config.emit_config_xcframework)
{
const config_xcframework = try buildpkg.GhosttyConfigXCFramework.init(
b,
&deps,
config.xcframework_target,
);
config_xcframework.install();
}

// Run step
run: {
if (config.app_runtime != .none) {
Expand Down
187 changes: 187 additions & 0 deletions include/ghostty.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,110 @@ typedef void* ghostty_app_t;
typedef void* ghostty_config_t;
typedef void* ghostty_surface_t;
typedef void* ghostty_inspector_t;
typedef void* ghostty_scene_renderer_t;

typedef enum {
GHOSTTY_SCENE_RENDERER_SUCCESS = 0,
GHOSTTY_SCENE_RENDERER_INVALID_ARGUMENT = 1,
GHOSTTY_SCENE_RENDERER_UNSUPPORTED = 2,
GHOSTTY_SCENE_RENDERER_OUT_OF_MEMORY = 3,
GHOSTTY_SCENE_RENDERER_INVALID_SCENE = 4,
GHOSTTY_SCENE_RENDERER_REPLAY_REJECTED = 5,
GHOSTTY_SCENE_RENDERER_UNSUPPORTED_CAPABILITY = 6,
GHOSTTY_SCENE_RENDERER_LIMIT_EXCEEDED = 7,
GHOSTTY_SCENE_RENDERER_NO_SCENE = 8,
GHOSTTY_SCENE_RENDERER_BUSY = 9,
GHOSTTY_SCENE_RENDERER_LEASE_MISMATCH = 10,
GHOSTTY_SCENE_RENDERER_GPU_ERROR = 11,
GHOSTTY_SCENE_RENDERER_OUTSTANDING_LEASES = 12,
GHOSTTY_SCENE_RENDERER_INTERNAL_ERROR = 13,
} ghostty_scene_renderer_status_e;

typedef enum {
GHOSTTY_SCENE_RENDERER_FRAME_READY = 1,
GHOSTTY_SCENE_RENDERER_HEALTHY = 2,
GHOSTTY_SCENE_RENDERER_UNHEALTHY = 3,
} ghostty_scene_renderer_event_e;

typedef enum {
// Use the explicit physical-pixel padding fields in the options.
GHOSTTY_SCENE_RENDERER_PADDING_EXPLICIT = 0,
// Derive physical-pixel padding and balancing from the finalized config.
GHOSTTY_SCENE_RENDERER_PADDING_CONFIG = 1,
} ghostty_scene_renderer_padding_mode_e;

// Exact provenance and ownership fence for one GPU-complete IOSurface frame.
// The host must return every field unchanged after its Metal copy completes.
typedef struct {
uint64_t renderer_epoch;
uint8_t terminal_id[16];
uint64_t terminal_epoch;
uint64_t content_sequence;
uint8_t presentation_id[16];
uint64_t presentation_generation;
uint64_t presentation_sequence;
uint64_t frame_sequence;
uint32_t iosurface_id;
uint32_t width;
uint32_t height;
} ghostty_scene_renderer_frame_s;

// The frame pointer is non-null only for FRAME_READY and is valid only for
// the callback duration. Callbacks must not block or re-enter the handle.
typedef void (*ghostty_scene_renderer_event_cb)(
void* userdata,
ghostty_scene_renderer_event_e event,
const ghostty_scene_renderer_frame_s* frame);

typedef struct {
ghostty_config_t config;
uint32_t width;
uint32_t height;
uint32_t padding_top;
uint32_t padding_right;
uint32_t padding_bottom;
uint32_t padding_left;
ghostty_scene_renderer_padding_mode_e padding_mode;
double content_scale;
uint64_t renderer_epoch;
uint8_t terminal_id[16];
uint64_t terminal_epoch;
uint8_t presentation_id[16];
uint64_t presentation_generation;
// Zero selects the library's bounded default.
size_t max_scene_bytes;
// Zero selects the library's bounded default.
size_t max_allocation_bytes;
void* userdata;
ghostty_scene_renderer_event_cb event_callback;
} ghostty_scene_renderer_options_s;

// Exact worker-owned pixel geometry for coordinate mapping and PTY resize.
typedef struct {
uint32_t columns;
uint32_t rows;
uint32_t cell_width;
uint32_t cell_height;
uint32_t padding_top;
uint32_t padding_right;
uint32_t padding_bottom;
uint32_t padding_left;
} ghostty_scene_renderer_metrics_s;

typedef struct {
uint32_t width;
uint32_t height;
uint32_t padding_top;
uint32_t padding_right;
uint32_t padding_bottom;
uint32_t padding_left;
// Must be greater than the current renderer epoch.
uint64_t renderer_epoch;
uint8_t terminal_id[16];
uint64_t terminal_epoch;
uint8_t presentation_id[16];
uint64_t presentation_generation;
} ghostty_scene_renderer_configure_s;

// 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
Expand Down Expand Up @@ -1291,6 +1395,10 @@ 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);
// Translate an AppKit NSEvent.keyCode with Ghostty's canonical physical-key
// table. This is layout-independent and returns GHOSTTY_KEY_UNIDENTIFIED for
// unknown or unsupported native codes.
GHOSTTY_API ghostty_input_key_e ghostty_input_key_from_macos_keycode(uint32_t);

GHOSTTY_API ghostty_config_t ghostty_config_new();
GHOSTTY_API void ghostty_config_free(ghostty_config_t);
Expand All @@ -1305,6 +1413,18 @@ GHOSTTY_API void ghostty_config_load_string(ghostty_config_t, const char*, uintp
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);
/**
* Serialize the current config as parseable overrides relative to the
* defaults built into this Ghostty library. Consumers must load the bytes
* over defaults from the same Ghostty build before finalizing.
* Config-source keys are omitted so consuming the snapshot never reopens the
* original theme or recursive config files.
*
* The returned bytes are independently allocated and remain valid after the
* config is mutated or freed. The caller must release the value with
* ghostty_string_free. An empty value with a null pointer reports failure.
*/
GHOSTTY_API ghostty_string_s ghostty_config_serialize(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*,
Expand All @@ -1314,6 +1434,53 @@ 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);

// Renderer-only semantic-scene API. A handle is single-threaded and owns no
// Surface, PTY, parser, mailbox, or terminal IO thread.
GHOSTTY_API ghostty_scene_renderer_t ghostty_scene_renderer_new(
const ghostty_scene_renderer_options_s*,
ghostty_scene_renderer_status_e*);
// Returns OUTSTANDING_LEASES without destroying the handle when frames remain.
GHOSTTY_API ghostty_scene_renderer_status_e ghostty_scene_renderer_destroy(
ghostty_scene_renderer_t);
GHOSTTY_API ghostty_scene_renderer_status_e ghostty_scene_renderer_configure(
ghostty_scene_renderer_t,
const ghostty_scene_renderer_configure_s*);
GHOSTTY_API ghostty_scene_renderer_status_e ghostty_scene_renderer_get_metrics(
ghostty_scene_renderer_t,
ghostty_scene_renderer_metrics_s*);
GHOSTTY_API ghostty_scene_renderer_status_e ghostty_scene_renderer_apply(
ghostty_scene_renderer_t,
const uint8_t*,
size_t);
GHOSTTY_API ghostty_scene_renderer_status_e ghostty_scene_renderer_render(
ghostty_scene_renderer_t);
// Reports whether the resolved shader policy and current semantic scene want
// another animation frame. `visible=false` always returns false so a worker
// can keep dormant presentations at zero render cadence.
GHOSTTY_API ghostty_scene_renderer_status_e
ghostty_scene_renderer_should_animate(
ghostty_scene_renderer_t,
bool visible,
bool*);
// Borrowing preserves neither object lifetime nor immutable pixels beyond the
// exact lease. The host releases the lease only after its GPU copy completes.
GHOSTTY_API ghostty_scene_renderer_status_e
ghostty_scene_renderer_borrow_iosurface(
ghostty_scene_renderer_t,
const ghostty_scene_renderer_frame_s*,
void**);
// Retention extends Core Foundation object lifetime only. It does not permit
// releasing the exact frame lease before the host GPU copy completes.
GHOSTTY_API ghostty_scene_renderer_status_e
ghostty_scene_renderer_retain_iosurface(
ghostty_scene_renderer_t,
const ghostty_scene_renderer_frame_s*,
void**);
GHOSTTY_API void ghostty_scene_renderer_release_retained_iosurface(void*);
GHOSTTY_API ghostty_scene_renderer_status_e ghostty_scene_renderer_release_frame(
ghostty_scene_renderer_t,
const ghostty_scene_renderer_frame_s*);

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);
Expand All @@ -1339,6 +1506,26 @@ GHOSTTY_API ghostty_surface_t ghostty_surface_new_with_scrollback_limit(
ghostty_app_t,
const ghostty_surface_config_s*,
size_t scrollback_limit_bytes);
// Process-lifetime constructor census. Values are monotonic and never reset,
// so freeing an app or surface cannot erase evidence that this process created
// a Ghostty runtime, constructed a canonical terminal, or allocated a PTY.
typedef struct {
uint32_t schema_version;
uint32_t reserved;
uint64_t runtime_app_constructor_attempts;
uint64_t surface_constructor_attempts;
uint64_t manual_io_surface_constructor_attempts;
uint64_t embedded_pty_surface_constructor_attempts;
uint64_t pty_master_open_attempts;
uint64_t pty_master_allocations;
} ghostty_process_census_s;
GHOSTTY_API ghostty_process_census_s ghostty_process_census_snapshot(void);
// Emits a bounded com.cmux.ghostty.process-census Instruments snapshot and
// returns the same values. A snapshot overflow marker makes verification fail
// closed instead of truncating a large counter.
GHOSTTY_API ghostty_process_census_s
ghostty_process_census_emit_signpost_snapshot(void);

// cmux fork: retire the surface from Ghostty app routing and begin bounded
// child-process termination without joining or freeing native surface state.
// After this call, the embedder must make no other surface API calls and must
Expand Down
1 change: 1 addition & 0 deletions include/ghostty/vt.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ extern "C" {
#include <ghostty/vt/focus.h>
#include <ghostty/vt/formatter.h>
#include <ghostty/vt/render.h>
#include <ghostty/vt/render_scene.h>
#include <ghostty/vt/terminal.h>
#include <ghostty/vt/grid_ref.h>
#include <ghostty/vt/grid_ref_tracked.h>
Expand Down
11 changes: 11 additions & 0 deletions include/ghostty/vt/key/event.h
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,17 @@ typedef enum GHOSTTY_ENUM_TYPED {
GHOSTTY_KEY_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
} GhosttyKey;

/**
* Translate an AppKit NSEvent.keyCode to Ghostty's physical key enum.
*
* This uses Ghostty's canonical Chromium-derived macOS table. It is safe to
* call from any process and does not depend on the current keyboard layout.
* Unknown and unsupported native codes return GHOSTTY_KEY_UNIDENTIFIED.
*
* @ingroup key
*/
GHOSTTY_API GhosttyKey ghostty_key_from_macos_keycode(uint32_t keycode);

/**
* Create a new key event instance.
*
Expand Down
Loading