⬑ void
Void β grid-first terminal Β· Ghostty hard fork Β· NΓM tiling as a core surface Β· beta: grid mode only
grid-mode Β· tiling-surface Β· terminal Β· pty Β· tool-call-stream Β· perf-first Β· zig Β· swift Β· gtk Β· metal Β· opengl
Void is a hard fork of Ghostty where an NΓM pane grid is a first-class rendering surface β not a window-manager bolt-on, not a tmux-style multiplexer process. When cell count N changes the layout auto-rebalances (cols = ββNβ, rows = βN/colsβ, cols β₯ rows), each cell carries its own cwd/env, and input can broadcast to all cells. It inherits Ghostty's engine (SIMD parser, Metal/OpenGL, per-terminal threads) unchanged. Zig shared core, native Swift on macOS, GTK on Linux.
Beta status β grid mode is the only implemented direction. Two further directions are planned, not yet built: a structured agent I/O channel alongside PTY (roadmap P3) and a per-PR perf budget vs the Ghostty baseline (roadmap P4). They are described below as roadmap, not as shipped features.
[!NOTE] Part of the dancinlab n = 6 family β hexagonal icon, sibling to NEXUS, Anima, N6, and HEXA-LANG. Void is a UX divergence from Ghostty, not a drop-in replacement; upstream syncs are selective cherry-picks only and full Ghostty history/credit is preserved.
At a glance
spawn a pane with cmd+ctrl+1..9 β the grid auto-rebalances
N = 2 N = 4 N = 6 N = 9
ββββββ¬βββββ ββββββ¬βββββ βββββ¬ββββ¬ββββ βββββ¬ββββ¬ββββ
β 1 β 2 β β 1 β 2 β β 1 β 2 β 3 β β 1 β 2 β 3 β
β~/p β~/w β ββββββΌβββββ€ βββββΌββββΌββββ€ βββββΌββββΌββββ€
ββββββ΄βββββ β 3 β 4 β β 4 β 5 β 6 β β 4 β 5 β 6 β
β~/l β~/r β β~/rβ~/sβ~/tβ βββββΌββββΌββββ€
2 Γ 1 ββββββ΄βββββ βββββ΄ββββ΄ββββ β 7 β 8 β 9 β
2 Γ 2 3 Γ 2 βββββ΄ββββ΄ββββ
3 Γ 3
cols = ββNβ rows = βN/colsβ cols β₯ rows Β· per-cell cwd Β· no manual resize handles Β· no tmux
void # launch terminal
cmd+g # toggle grid mode <-> tab mode
cmd+ctrl+1..9 # spawn a tab in grid slot 1..9 (auto-rebalances)
cmd+ctrl+shift+1..9 # cycle tabs within a grid slot
cmd+ctrl+0 # broadcast input to all cells
Why void
Three things upstream Ghostty treats as explicit non-goals β Void forks to take exactly these bets.
1. Grid mode β a first-class tiling surface
cells = N on add / remove the whole grid
ββββββββββββββββββββββββββββββ re-balances to equal splits:
N = 2 β 2 Γ 1 cols = ββNβ
N = 4 β 2 Γ 2 rows = βN/colsβ
N = 6 β 3 Γ 2 cols β₯ rows (wider before taller)
N = 9 β 3 Γ 3 (no manual resize handles)
The NΓM grid is a new renderer path, not a patch on the single-surface renderer and not a multiplexer process. Per-cell cwd / env, shared input routing, broadcast. No tmux, no prefix key, no config DSL to learn. This is the headline β the other two directions sit on top of it.
2. Ghostty hard fork β performance inherited, not rebuilt
Void did not rebuild a terminal. It hard-forks a fast one and changes three things. The SIMD parser, Metal (macOS) / OpenGL (Linux) renderers, and per-terminal render/read/write threads come straight from Ghostty. 4698 files were renamed Ghostty β Void at commit 964c9e32e; upstream history and contributor credit are preserved (cherry-pick only, no clean merges).
3. AI-native I/O and a perf budget (roadmap β not yet implemented)
shell process βββββ PTY βββββββββΆ traditional byte stream
β β
βΌ βββββ AGENT βββββββΆ structured tool-call events
libvoid layer βββββ€ token stream w/ boundaries
β² βββββ META ββββββββΆ cwd, exit-code, span marks
β
agent process (no wrapper process required)
Neither of these is built yet β the beta is grid-only. The plan: a structured agent channel alongside PTY (tool-call events and token-stream boundaries as a data model, not heuristic-parsed from stdout) β roadmap P3, deliberately not the headline since Void is grid-first, not an "AI overlay" terminal. And a perf budget where every PR reports a delta against the Ghostty baseline with a β₯ 2 % regression blocking merge β roadmap P4, the harness is not wired yet. Both are described here as intent, not as shipped behaviour.
Highlights
| β¦ | Grid mode (implemented) β NΓM pane grid as a core surface, auto-layout (cols = ββNβ, rows = βN/colsβ), per-cell cwd, broadcast |
| ⬑ | Ghostty-grade performance (inherited) β SIMD parser, per-terminal render/read/write threads, Metal on macOS, OpenGL on Linux |
| β | Native UI (inherited) β SwiftUI on macOS (AppIntents, Shortcuts), GTK on Linux (systemd, cgroup isolation) |
| β‘ | Perf budget (roadmap P4 β not built) β plan: every PR reports Ξ against the Ghostty baseline; β₯ 2 % regression blocks merge |
| β | AI-native I/O (roadmap P3 β not built) β plan: agent protocol alongside PTY; structured tool-call / token-stream channels, no wrapper |
| β» | Session restore (implemented) β per-pane mmap'd ring of raw PTY bytes; auto-replay on void/macOS crash restores scrollback + colors + cursor (no upstream Ghostty equivalent) |
| β¬’ | dancinlab branding β hexagonal icon, n = 6 family (NEXUS Β· Anima Β· N6 Β· HEXA Β· Void) |
Architecture
ββββββββββββββββββββββββββββββββββββββββββββ
β macOS App (Swift) β
β SwiftUI Β· AppIntents Β· CoreText β
β Metal renderer Β· native menu β
ββββββββββββββββ¬ββββββββββββββββββββββββββββ
β
ββββββββββββββββΌββββββββββββββββββββββββββββ
β libvoid (Zig) β core β
β parser Β· terminal state Β· renderer β
β grid engine (agent I/O: roadmap) β
ββββββββββββββββ¬ββββββββββββββββββββββββββββ
β
ββββββββββββββββΌββββββββββββββββββββββββββββ
β Linux App (GTK) β
β systemd Β· OpenGL Β· FreeType β
ββββββββββββββββββββββββββββββββββββββββββββ
Zig-based shared core with platform-native shells. Core is C-ABI-compatible so it can be embedded in third-party projects (Ghostty's libghostty pattern β renamed to libvoid in this fork).
Install
# 1. Install hexa-lang (gives you `hexa` + `hx` package manager)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/dancinlab/hexa-lang/main/install.sh)"
# 2. Install void
hx install void
Or build from source β see HACKING.md. Default branch on the fork is void/main, not main.
Run
void # launch terminal
void +show-config # print active config
void +list-keybinds # list keybindings
void +crash-report # list crash reports
Keybindings (default)
| Keys | Action |
|---|---|
cmd+g |
toggle grid mode β tab mode |
cmd+ctrl+1..9 |
spawn new tab in grid slot 1..9 (stacks β repeated presses add tabs to the same slot) |
cmd+ctrl+shift+1..9 |
cycle tabs within grid slot |
cmd+ctrl+0 |
broadcast input to all cells |
cmd+opt+return |
find next (relocated from cmd+g) |
cmd+shift+opt+return |
find previous (relocated from cmd+shift+g) |
cmd+t / cmd+n |
new tab / new window |
cmd+d / cmd+shift+d |
split pane right / down |
cmd+, |
open settings |
All keys are rebindable via config β nothing is hardcoded.
Fork status
| Upstream | ghostty-org/ghostty β cherry-picks only, no merges |
| Fork date | 2026-04-21 (from upstream commit c3c8572f7) |
| Default branch | void/main |
| L3 rename | complete β 4698 files renamed Ghostty β Void at commit 964c9e32e |
| CI | .github/workflows/build-fork.yml on GitHub-hosted macos-15 runners (ad-hoc codesign) |
| Icon | hexagonal, dancinlab n = 6 family |
See VOID_FORK.md for the full fork rationale, non-goals, and upstream policy.
Roadmap
Checkpoints (done):
| # | Milestone | Date |
|---|---|---|
| C0 | project-init β hexa scaffold | 2026-04-21 |
| C1 | fork-base β Ghostty β Void rebrand | 2026-04-21 |
Phases:
| # | Phase | ETA | Status |
|---|---|---|---|
| P1 | Grid mode + new-tab keybinding β auto-grid, slot-spawn, mode toggle | 2026-05-18 | β |
| P2 | Stack analysis β map void renderer/apprt/terminal/font internals | 2026-05-05 | β¬ |
| P3 | AI-native I/O protocol β structured agent channel alongside PTY | β | β¬ |
| P4 | Perf baseline β capture benches, set void regression budgets | β | β¬ |
| P5 | Diverge / upstream strategy β decide what feeds back vs stays void | β | β¬ |
P1 (grid mode) is complete: surface rendering, NΓM auto-layout (cols = ββNβ), cmd+ctrl+1..9 slot-spawn, broadcast, and per-cell cwd all landed. P4 (perf baseline) is next β capturing the Ghostty-baseline benches before further divergence accumulates.
Non-goals
- Not a drop-in Ghostty replacement β Void will diverge in UX.
- Not a shell β Void drives shells, it does not replace them.
- Not an "AI terminal" β grid mode is the headline and the only thing built; agent I/O is an unimplemented roadmap direction, never an overlay.
Crash reports
Void inherits Ghostty's crash reporter. Reports are saved to $XDG_STATE_HOME/void/crash (default ~/.local/state/void/crash) and are not sent off your machine. Use void +crash-report to list. Reports use the Sentry envelope format with extension .voidcrash.
[!WARNING] Crash reports contain full stack memory per thread at the time of the crash and can include sensitive data.
Session restore β survive abnormal termination
When void or macOS dies abnormally, void re-opens with the previous terminal contents (scrollback, colors, cursor) restored β not just the window layout. The mechanism is fork-only (no upstream Ghostty equivalent); see docs/design/sighup-resistant-session.md for the full design.
Two failure modes, one experience
| Scenario | Event | What survives |
|---|---|---|
| A: void only dies | segfault, OOM, jetsam SIGKILL |
grid + per-pane terminal content |
| B: macOS dies | kernel panic, hard shutdown, power loss | same (bounded β€ 1s loss) |
How it works
ββββββββββββββββββββββββββββββββββββββββββββ
β macOS NSWindowRestoration (existing) β β grid topology + per-surface UUID
β TerminalRestorable.swift β survive force-quit / crash
ββββββββββββββββ¬ββββββββββββββββββββββββββββ
β uuid round-trips via Codable
ββββββββββββββββΌββββββββββββββββββββββββββββ
β PersistRing (mmap, 4 MB / pane) β β raw PTY byte stream β disk
β ~/.void/sessions/by-uuid/<uuid>.ring β memcpy + msync(MS_ASYNC) every 1s
ββββββββββββββββ¬ββββββββββββββββββββββββββββ
β on relaunch
ββββββββββββββββΌββββββββββββββββββββββββββββ
β Termio.init replay β processOutput β β bytes (ANSI + colors + cursor)
β BEFORE io read thread starts β fed back through SIMD parser
ββββββββββββββββββββββββββββββββββββββββββββ
- Write side β
Termio.processOutputappends every PTY byte to an mmap'd ring (memcpy, ~0Β΅s, lock-free per pane).msync(MS_ASYNC)fires every 1s β kernel page cache + dirty-page flush bound Scenario B loss to β€ 1 second. Scenario A loses nothing because mmapMAP_SHAREDpage cache survives process death. - Read side β at surface init, if a ring exists at the UUID-keyed path,
PersistRing.replay()extracts up to 4 MB of most-recent bytes, andTermio.processOutputLockedfeeds them through the parser before the io read thread spawns. The new shell still starts fresh underneath; the visual scrollback is reconstructed via ANSI replay.
Enable
# void config
window-save-state = always # macOS NSWindowRestoration (already documented)
persist-bytes-mmap = true # opt-in: enable per-pane ring buffer
What's restored / what isn't
| β Restored | β Not restored |
|---|---|
| scrollback text | running processes (PTY child is fresh) |
| colors + text attributes (via ANSI escapes in byte stream) | live cursor position from a long-running TUI |
grid topology + per-pane cwd (via existing TerminalRestorable) |
environment variables that diverged at runtime |
| focused pane, tab color, title overrides | sub-process state (vim buffers, REPL history, etc.) |
Apple Terminal.app's "Tab Contents v2" mechanism is plain-text-only (no colors); void's ring is raw bytes including ANSI sequences, so attributes round-trip.
Manual recovery
If auto-replay doesn't trigger (e.g. UUID lost, ring schema changed), the byte stream is still on disk:
tool/void-session-replay.sh --list # enumerate ring files
tool/void-session-replay.sh --latest # dump most recent ring to stdout
tool/void-session-replay.sh --all # dump every ring
tool/void-session-replay.sh <path-to-ring> # dump a specific ring
Pipe to less -R, cat, or save to a file.
Storage layout
~/.void/sessions/by-uuid/
<uuid>.ring # 4 MB mmap'd ring buffer per pane
...
Ring files are not garbage-collected automatically β rm -rf ~/.void/sessions/by-uuid is safe between sessions when you want to start fresh.
Status
- Beta β grid mode is the only implemented direction. P1 (grid mode + new-tab keybinding) complete (2026-05-18): surface rendering, NΓM auto-layout, slot-spawn, broadcast, per-cell cwd
- Inherited from Ghostty (not Void-built): SIMD parser, Metal/OpenGL renderers, per-terminal threads, native Swift/GTK shells, crash reporter
- Void-only support infra (shipped, not a "direction"): session-restore via per-pane mmap byte ring β see Session restore
- Not yet implemented: AI-native I/O (roadmap P3) Β· perf-budget harness (roadmap P4) β described in this README as intent, not shipped behaviour
- Fork date: 2026-04-21 (from upstream commit
c3c8572f7); default branchvoid/main(notmain) - L3 rename complete β 4698 files renamed Ghostty β Void at commit
964c9e32e - Next: P4 perf baseline (capture Ghostty-baseline benches), then Show HN / r/commandline launch
- CI:
.github/workflows/build-fork.ymlon GitHub-hostedmacos-15runners (ad-hoc codesign)
Repo layout
void/
βββ README.md
βββ AGENTS.md / AGENTS.tape project ops manual + machine-readable companion
βββ VOID_FORK.md fork rationale + non-goals + upstream policy
βββ HACKING.md / CONTRIBUTING.md dev + contribution guides
βββ LICENSE MIT
βββ build.zig / build.zig.zon Zig build entry + manifest
βββ src/ libvoid (Zig core) β parser Β· terminal state Β· renderer Β· grid (agent I/O: roadmap)
βββ macos/ Swift app (SwiftUI Β· AppIntents Β· Metal Β· CoreText)
βββ linux/ + gtk/ GTK app (systemd Β· OpenGL Β· FreeType)
βββ pkg/ vendored package wrappers
βββ include/ C-ABI headers for libvoid embedders
βββ images/ icon + brand assets (hexagon n=6 family)
βββ docs/ reference docs + logo.svg
βββ conformance/ terminal protocol conformance tests
βββ bench/ perf budget harness β roadmap P4 (Ξ vs Ghostty baseline)
βββ nix/ + flake.nix Nix build entry
βββ .github/workflows/ CI (build-fork.yml on macos-15 runners)
Contributing
- Contributing to Void β CONTRIBUTING.md
- Developing Void β HACKING.md
- Fork rationale & upstream policy β VOID_FORK.md
Credits
Void is a hard fork of Ghostty by Mitchell Hashimoto and the Ghostty team. All Ghostty contributors are credited in upstream history, which is preserved in this repo. Divergent work β grid mode (implemented), plus the planned AI-native I/O and perf-harness directions β is Void-only.
License
MIT β same license as upstream Ghostty. All Ghostty contributors are credited in upstream history (preserved in this repo); divergent work (grid mode implemented; AI-native I/O and perf-harness planned) is Void-only.
⬑ Terminal as substrate. Grid as primitive. · Based on Ghostty · dancinlab