OdyTTY

A GPU-backed terminal emulator, written from scratch in Rust — documenting itself.

host odytty.unfinished-works.com render wgpu/Vulkan theme odyssey visual crt
visual layer: off by default in OdyTTY — hit plain for the crisp shipped look

$ man odytty — overview

OdyTTY is a terminal emulator we're building from scratch, in Rust. It's GPU-backed (wgpu/Vulkan) and meant to be quick, sturdy, and pleasant enough to live in all day.

The unusual part is what's underneath: we wrote the whole stack ourselves. Every byte — from the pseudo-terminal all the way to the pixel on your screen — runs through our own code instead of someone else's library.

Full byte-path ownership

The PTY layer uses rustix directly for openpt/grantpt/unlockpt and session-leader spawn. The VT parser is a clean-room two-layer pipeline built from primary specifications (vt100.net, ECMA-48, xterm ctlseqs) — not derived from vte or any other terminal's source. vte, portable-pty, and crossterm are not in the dependency tree. External crates handle only font rasterization, the GPU API, windowing, and clipboard transport — the same boundary mature independent terminals draw.

  • written inRust
  • renderersingle-pass forward, wgpu / Vulkan
  • platformLinux today · macOS & Windows on the way
  • licenseGPL-3.0-only
  • built-in themes53

Where it runs

We're building on Linux first, but OdyTTY isn't meant to stay there.

Linux available now Wayland, or X11 via XWayland
macOS actively targeted a first-class goal as development continues
Windows planned on the roadmap for a future release

$ odytty --features

A few things most terminals don't do — or at least, not all at once, and not on top of their own code.

🎨 Live color emoji

Full cluster rendering via swash: ZWJ family sequences, flag pairs, skin-tone modifiers, keycap sequences, and VS15/VS16 variation-selector policy. Noto Color Emoji CBDT/CBLC bitmaps in a dedicated premultiplied-RGBA atlas. Emoji pixels are never SGR-tinted.

🖼 Kitty graphics + Sixel

The full Kitty APC graphics surface (actions t/T/p/d/q, RGB/RGBA + PNG, direct / file / shared-memory transports, placements, z-index, crop, cell scaling) plus a complete Sixel data language with the VT340 palette and DECSDM.

⌨ Kitty keyboard protocol

Progressive enhancement as a negotiated overlay: disambiguation, event types (press/repeat/release), alternate keys, report-all, associated text. Bounded stack; RIS/DECSTR resets it. At flags 0 the output is byte-identical to legacy key encoding.

🖱 SGR-pixel mouse (1016)

End-to-end pixel mouse reporting: DECSET/DECRST/DECRQM wired, native pixel-to-cell seam closed, reports emitted as CSI < Cb ; Px ; Py M|m with true physical pixel coordinates.

🌈 Theme-driven palette

A full 16-color ANSI palette plus semantic roles (cursor, selection, search, border). 53 contrast-validated built-ins, OSC-4 / OSC-10/11/12 dynamic overrides with correct precedence, and a dependency-free .theme file format for your own.

✨ Optional ambient layer

An off-by-default visual treatment — minimum-contrast lift, stem darkening, focus dimming, bloom, and a CRT pass (scanlines + vignette) — all gated behind explicit settings. Readability first; atmosphere on request.

Compatibility, in brief

Comprehensive VT coverage: SGR (256-color + truecolor, colon and semicolon forms), cursor movement and position reports, scroll regions (DECSTBM/DECOM), alternate screen (47/1047/1048/1049), mouse modes 9/1000/1002/1003 with encodings 1005/1006/1015/1016, focus reporting (1004), DECSCUSR, OSC 0/2 titles, wide-character handling, rectangle ops (DECCRA/DECFRA/DECERA/DECCARA), XTGETTCAP, DECRQSS, and bracketed paste. See protocols.

$ odytty --install — build & run

Building OdyTTY takes Cargo and a Vulkan-capable GPU. For now that means Linux — Wayland, or X11 through XWayland.

build & launch
# clone, then from the repo root:
cargo build --release
cargo run -- --native
quick launch examples
# larger text with the Odyssey theme
ODYTTY_FONT_SIZE=18 ODYTTY_THEME=odyssey cargo run -- --native

# a custom font family
ODYTTY_FONT_FAMILY="DejaVu Sans Mono" cargo run -- --native

# RGB subpixel antialiasing
ODYTTY_SUBPIXEL=rgb cargo run -- --native
headless introspection (print and exit — no window)
odytty --list-themes   # stable name / appearance / family rows
odytty --show-config   # effective merged config as key=value lines

Configuration resolves defaults → ~/.config/odytty/odytty.conf → environment; environment variables always win. The native app polls the config file about once per second for live reloads. See config for the full knob reference.

$ man odytty.conf — runtime knobs

Most of the time you won't come here — OdyTTY is configured from an in-app settings panel, so you pick options and watch them take effect rather than editing a file by hand. But everything that panel touches is also a plain key = value setting (and an environment variable), and this is the complete list. It's generated straight from OdyTTY's docs/runtime-knobs.md, so it never drifts from the real thing.

Loading the knob reference…

$ odytty --list-themes — wear any era

OdyTTY ships 53 built-in themes, each a full appearance profile: default fg/bg, the window clear color, the 16-color ANSI palette, and semantic roles. Click any theme to wear it — the whole page reskins live, including the CRT field's hue. That is the same data the terminal loads; the gallery is generated from the real .theme files.

The .theme file format

A theme is a plain text file of key = value lines. Drop one in ~/.config/odytty/themes/ and select it with theme = myname or point ODYTTY_THEME at a path. A bad or missing theme never prevents startup — OdyTTY falls back to plain and logs a warning.

~/.config/odytty/themes/example.theme
name = example
appearance = dark

foreground = #d6def4
background = #0c1224
clear      = #070b18

cursor    = #86c1ff
selection = #243352
search    = #4a4018

color0  = #12182a   # ANSI black
color1  = #e06b74   # red
# … color2 – color15 …

$ odytty --keys — bindings

The default keyboard surface. You can rebind any of it from the settings panel, or via ODYTTY_KEYBINDS / the keybinds config key (e.g. ctrl+shift+y=copy;ctrl+shift+p=paste).

ChordAction
Ctrl+Shift+FScrollback search (next/prev, match highlights)
Ctrl+Shift+TTheme picker — arrow to preview, Enter to keep, Esc to restore
Ctrl+Shift+,In-app settings panel (font, theme, cursor, all knobs)
Ctrl+S (in panel)Write changed rows back to odytty.conf (preservation-first)
Ctrl+Shift+YCopy selection (default; rebindable)
Ctrl+Shift+PPaste (default; rebindable)
Double-clickSelect word · Triple-click selects line
Ctrl+ClickOpen OSC 8 hyperlink via xdg-open (scheme allowlist)

$ odytty --protocols — support matrix

What OdyTTY understands on the wire, for reference. Everything ticked here is verified by the test suite.

Graphics & images

  • Kitty graphics protocol — actions t/T/p/d/q
  • RGB/RGBA (f=24/f=32) & PNG (f=100)
  • Transports: direct, file, temp-file, shared memory
  • Placements, z-index, source crop, cell scaling, offsets
  • Sixel (DCS q) — RGB/HLS, repeat, raster attrs, VT340 palette, DECSDM

Input & mouse

  • Kitty keyboard protocol (progressive enhancement)
  • Mouse modes 9 / 1000 / 1002 / 1003
  • Encodings 1005 / 1006 / 1015 / 1016 (SGR-pixel)
  • Focus reporting (DECSET 1004)
  • Bracketed paste with sanitization

OSC & dynamic color

  • OSC 0/2 window title
  • OSC 8 hyperlinks (hover underline, Ctrl+click, allowlist)
  • OSC 7 working directory (advisory, localhost-only)
  • OSC 52 clipboard write (read opt-in)
  • OSC 4 / 10 / 11 / 12 + resets (104/110/111/112)

Rendering & text

  • SGR 256-color + truecolor (colon & semicolon)
  • Extended underlines (4:04:5) + underline color (58/59)
  • Subpixel AA (dual-source) with grayscale fallback
  • Synchronized output (DEC 2026, 150 ms timeout)
  • XTGETTCAP, DECRQSS capability queries

$ man odytty — FAQ & colophon

Is OdyTTY actually a CRT terminal?

No. OdyTTY renders crisp by default — its plain theme is xterm-exact and all CRT/bloom/ambient effects are off until you enable them. The CRT look on this site is OdyTTY's own opt-in visual layer, turned up as a showpiece. Hit plain in the visual-layer control to strip it back to the shipped appearance.

What makes it different from other terminals?

Two things, mostly. First, it's menu-driven: you set it up from an in-app settings panel and a live theme picker — pick an option, watch it apply — instead of hunting through a config file in another window. (There's still a config file underneath, and the panel writes to it, so power users keep everything they'd want; you just rarely have to touch it.)

Second, it owns its whole stack — the pseudo-terminal layer, the parser, the model, the renderer, the shaders — rather than wrapping an existing library like vte or portable-pty. That, together with live color emoji, Kitty graphics and Sixel, the Kitty keyboard protocol, pixel-precise mouse reporting, and 53 built-in themes, is a combination you don't often see in one place.

What does it run on?

Today, Linux with a Vulkan-capable GPU (Wayland natively, X11 via XWayland). macOS support is a first-class goal we're actively working toward, and Windows is on the roadmap for a future release.

How do I report issues or contribute?

OdyTTY is GPL-3.0-only and uses a DCO sign-off workflow (see CONTRIBUTING.md in the repository).

This page is a static site (Vite → Cloudflare Pages). The CRT field is a raw WebGL shader; the theme gallery and knob table are generated from OdyTTY's real .theme files and runtime-knobs.md by a small awk pipeline. It steals its tube from its sibling, unfinished-works.com — same workshop, different machine.