ghosdin

May 8, 2026 · View on GitHub

License: MIT Odin Zig raylib Platform

Odin bindings for libghostty-vt — the zero-dependency VT terminal parser/state library from the Ghostty project.

Includes a graphical terminal emulator, an embeddable game dev console, and an idiomatic Odin wrapper.

What's Here

ghosdin/
├── vendor/ghostty_vt/
│   ├── ghostty_vt.odin    Raw C FFI bindings (complete API)
│   └── terminal.odin      Idiomatic Odin wrapper (Term, iterators, helpers)
├── pty/                   Shared POSIX PTY interface (forkpty, non-blocking I/O)
├── render_rl/             Shared raylib helpers (cell render, font, key encoding)
├── console/               Embeddable quake-style dropdown console
├── termview/              Standalone graphical terminal (raylib + PTY)
├── demo/                  Headless demo (bindings smoke test)
├── example/               Example game with embedded console
├── docs/architecture.md   Architecture and data flow
├── justfile               Build commands
└── ghostty/               Ghostty source (cloned, gitignored)

Quick Start

Prerequisites

  • Odin dev-2026-05 or newer (the dev-2026-05 API set is what the bindings target)
  • Zig 0.15.2 — to build libghostty-vt (pinned in .mise.toml; upstream ghostty does not yet support 0.16)
  • just — task runner

Setup

git clone <repo-url> ghosdin && cd ghosdin
git clone --depth 1 https://github.com/ghostty-org/ghostty.git
just dev

Commands

just dev              Build + launch the graphical terminal
just run-demo         Run the headless demo
just run-example      Launch the example game (` to toggle console)
just build            Build everything
just check-all        Type-check all packages
just debug            Build + run in debug mode
just info             Show toolchain and build info
just clean            Clean all artifacts
just update           Pull latest ghostty + rebuild
just test-lib         Run libghostty-vt's test suite

Packages

vendor/ghostty_vt — Bindings

Complete Odin mapping of the libghostty-vt C API, plus an idiomatic wrapper.

Raw bindings (ghostty_vt.odin)

import gvt "vendor/ghostty_vt"

term: gvt.Terminal
opts := gvt.Terminal_Options{cols = 80, rows = 24, max_scrollback = 1000}
gvt.terminal_new(nil, &term, opts)
defer gvt.terminal_free(term)

data := "\x1b[1;32mHello!\x1b[0m\r\n"
gvt.terminal_vt_write(term, raw_data(data), len(data))

Idiomatic wrapper (terminal.odin)

import gvt "vendor/ghostty_vt"

t, err := gvt.term_init(80, 24)
defer gvt.term_destroy(&t)

gvt.term_write(&t, "\x1b[1;32mHello!\x1b[0m\r\n")

title := gvt.term_title(&t)
cx    := gvt.term_cursor_x(&t)

// Render iteration
gvt.term_render_update(&t)
row_it := gvt.term_render_rows(&t)
for row in gvt.render_row_next(&row_it) {
    cell_it := gvt.term_render_cells(&t)
    for cell in gvt.render_cell_next(&cell_it) {
        // cell.codepoint, cell.fg_color, cell.style, etc.
    }
}

API Coverage

ModuleDescription
TerminalCreate terminals, feed VT data, query/set state
Render StateIncremental dirty-tracking for renderers
Screen/Grid RefCell and row access, grapheme clusters, hyperlinks
SGR ParserParse styling escape sequences
OSC ParserParse operating system commands
Key EncoderEncode keyboard events to escape sequences
Mouse EncoderEncode mouse events to escape sequences
FormatterExport content as plain text, VT, or HTML
ModesANSI and DEC terminal mode utilities
Focus/PasteFocus encoding, paste safety + bracketed encoding
SelectionGrid-ref selection ranges
Kitty GraphicsImage storage, placement iteration, render geometry
SysRuntime callbacks (PNG decode, log)
AllocatorCustom memory allocator support
Build InfoQuery compile-time library configuration + version

console — Embeddable Game Dev Console

Drop-in quake-style terminal for raylib games. Press ` to toggle.

import con "ghosdin/console"

// In your game init:
console := con.create()    // or con.create(con.Config{...})
defer con.destroy(&console)

// In your game loop:
con.update(&console)       // handles toggle key + keyboard when open
con.draw(&console)         // renders the overlay (call after your game draws)

// Game input gating:
if !con.is_open(&console) {
    // process game input only when console is closed
}

Features:

  • Spawns a real PTY shell — run any command
  • Smooth slide-in/out animation
  • Configurable: dimensions, colors, opacity, toggle key, font size
  • Captures keyboard when open so game doesn't get stray input
  • Full VT escape sequence support (colors, cursor, modes)

termview — Graphical Terminal

A working terminal emulator in ~300 lines of Odin:

  • Spawns a PTY with $SHELL
  • Feeds output through libghostty-vt
  • Renders the grid with raylib (OpenGL)
  • Keyboard input (printable chars, special keys, ctrl combos)
  • Colors, bold, underline, strikethrough, cursor
just run-termview

Screenshots

  • F12 — save the full window as termview_<timestamp>.png in the working directory.
  • Click and drag — capture a cell-aligned region as termview-region_<timestamp>.png, and copy the underlying text into the system clipboard at the same time.

example — Game + Console Demo

A small raylib game (WASD movement, particles) with the console embedded. Press ` to drop down a terminal overlay.

just run-example

Architecture

PTY ──bytes──> ghostty-vt ──render state──> raylib
 ^                                            |
 └──────────── keyboard input ────────────────┘

See docs/architecture.md for the full writeup.

Roadmap

The vendor/ghostty_vt bindings will eventually be extracted into their own standalone repository as a proper Odin package, making them easy to import without pulling in the full ghosdin project.

License

Bindings and demo code: MIT

libghostty-vt: See Ghostty's license