Attyx: tiny and fast GPU accelerated terminal emulator

Published: (February 28, 2026 at 02:37 PM EST)
6 min read
Source: Dev.to

Source: Dev.to

Neovim, tmux, git, SSH — that’s my whole day. I’ve used every terminal emulator out there: iTerm2, Alacritty, Kitty, Ghostty. All great.

But I never understood what actually happens inside one. Bytes come out of a shell, escape sequences get parsed, characters appear on screen. What does ESC[38;2;255;100;0m do to the internal state? How does a key press travel through a pseudoterminal and come back as text? I had no clue.

The only way I know how to learn something is to build it.

So I built Attyx — a GPU‑accelerated terminal emulator, from scratch, in Zig. Started on a Saturday. Five days later I was daily‑driving it. I’m still daily‑driving it.

Why Though

“We don’t need another terminal emulator.”
Sure. But I didn’t build it because the world needed one. I built it for two selfish reasons.

1. I wanted to learn Zig

Not from docs and tutorials — from a real project that would punch me in the face with systems‑programming problems. Terminal emulators hit everything: parsing, GPU rendering, font rasterization, Unicode, PTY management, platform APIs. Perfect.

2. I needed a testable terminal core

I build TUI apps. I made Glyph — a React renderer for the terminal. Flexbox, components, hooks, the whole deal, but rendering to your terminal instead of a browser. On top of it I built Aion (Calendar TUI) and Epist (an email client with vim keybindings). Real apps I use every single day.

Problem: how do you test what a TUI app actually looks like? You can test component state, you can test logic, but the final output — the grid of characters and styles after the terminal interprets your escape sequences — is a black hole. Screenshot diffing? Fragile. Asciinema recordings? Not automated. Unit‑testing raw escape codes? Doesn’t catch interpretation bugs.

What I wanted was dead‑simple — feed bytes into a terminal engine, get a deterministic grid back, assert against it. No terminal app existed that let me do that. So I built one where the core is pure from the ground up.

var engine = try Engine.init(allocator, 24, 80);
engine.feed(my_app_output);
const cell = engine.state.grid.getCell(0, 0);
try expectEqual('A', cell.char);
try expect(cell.style.bold);

Enter fullscreen mode
Exit fullscreen mode

No GPU. No window. No PTY. Just bytes in, state out. That’s the testing primitive I’ve wanted for years.

What You Get

  • GPU‑accelerated rendering — Metal on macOS, OpenGL 3.3 on Linux.
  • Full VT100/xterm compatibility. True‑color, 256‑color, the works.
  • Mouse tracking, Kitty graphics protocol for inline images, hyperlinks, alternate screen buffer, scroll regions, cursor shapes.
  • 20 000‑line scrollback with reflow on resize.
  • Popup terminals that float over your session.
  • Search.
  • TOML config with hot‑reload.

All under 5 MB.

The whole thing — GPU rendering, VT parser, font handling, platform code — lives in a tiny binary. That’s what happens when you write Zig with minimal deps, use native platform frameworks instead of bundling a GUI toolkit, and let the compiler strip dead code. No runtime. No GC. No Electron. Just a Zig binary talking to the OS.

Under the Hood (Without Boring You to Death)

I wrote a deep technical dive on the Semos blog if you want all the details. But here’s the gist.

Everything flows through a pipeline:

Raw bytes → Parser → Actions → State → Grid

Enter fullscreen mode
Exit fullscreen mode

  • Parser – an incremental state machine. One byte at a time it spits out actions like “print H”, “move cursor to row 3 col 5”, “set foreground to red”. Fixed‑size buffers, zero heap allocations, handles partial sequences across read() boundaries. The whole parser struct is stack‑sized.

  • Grid – a flat array of cells. Each cell stores a Unicode codepoint, two combining‑mark slots (for diacritics), a style, and a hyperlink ID. One allocation on init. Scroll regions are memcpy on contiguous memory. No linked lists, no indirection.

  • Damage tracking – keeps rendering fast. 256‑bit dirty bitset (four u64s). The state machine flips a bit when it touches a row. The renderer only redraws dirty rows. Most frames that’s one or two rows.

  • Two threads, no locks – PTY thread reads bytes and fills a shared cell buffer. Main thread renders at vsync. A seqlock (just an atomic generation counter) prevents torn reads. If the renderer catches the PTY mid‑write, it skips a frame. You’ll never notice a dropped frame. You will notice mutex contention.

  • GPU rendering – turns each character into a textured quad. Glyphs are rasterized on demand into an atlas that lives in GPU memory. Drawing 10 000 cells costs about the same as drawing 100 — that’s the whole point of offloading to the GPU. The CPU does parsing and state; the GPU does pixels. Each does what it’s good at.

The Semos Stack

Attyx is part of Semos — the collection of dev tools I’ve been building. It fits into a stack that’s been growing over the past few months:

  • Glyph – the React terminal renderer. Write terminal apps with JSX, flexbox, hooks — the same DX you know from the web, but painting to a terminal.
  • Aion and Epist – apps built on top of Glyph (calendar and email).
  • Attyx – closes the loop. Glyph apps needed a testable terminal. Attyx needed real‑world apps to stress‑test against. They push each other forward.

Give It a Shot

brew install semos-labs/tap/attyx

Enter fullscreen mode
Exit fullscreen mode

Or build from source:

git clone https://github.com/semos-labs/attyx
cd attyx
zig build -Doptimize=ReleaseFast

Enter fullscreen mode
Exit fullscreen mode

Or download it from the website if you happen to be on a Mac. You will also get auto‑updates in this case.

Config goes in ~/.config/attyx/attyx.toml — fonts, colors, keybindings, opacity, blur. Change it, hit Ctrl+Shift+R, done. No restart.

Open source, MIT licensed.

Is it as mature as Ghostty or Kitty? Not yet. But I understand every line in it, I use it every day, and the whole thing fits in under 5 MB. That counts for something.

0 views
Back to Blog

Related posts

Read more »

Ghostty – Terminal Emulator

Article Ghostty – Terminal Emulatorhttps://ghostty.org/docs Discussion - Comments: Hacker News threadhttps://news.ycombinator.com/item?id=47206009 – 411 points...