Getting started

June 4, 2026 · View on GitHub

Hollow is a terminal emulator for Windows with a Lua-configurable runtime and Ghostty's VT core. This page gets you from zero to a running window with your own overrides.

What ships today

  • A Windows-native terminal with tabs, split panes, floating panes, maximized panes, and workspaces
  • A Lua configuration layer; reload the config without restarting
  • A Lua API for UI, events, keymaps, and shell-to-host integration
  • A native hollow cli … subcommand for host-side automation
  • An optional WSL PTY bypass helper that skips ConPTY for WSL shells

The primary validated target is Windows. WSL is a first-class shell domain. Linux and macOS are not part of the supported matrix yet; see Platforms.

Install a release

The latest release is on GitHub: Releases.

A Windows release contains three executables that belong next to each other:

FileRole
hollow.exeCLI launcher and hollow cli … host
hollow-gui.exeConsole-less GUI shim
hollow-native.exeActual GUI process
hollow-cliPython HTP client (optional, OSC over tty)
wsl/hollow-wsl-bypassLinux-side WSL helper (optional)

Debug symbols (.pdb files) are not bundled in releases. For crash symbolication, see Packaging → Crash reports.

If you want the WSL PTY bypass, also install hollow-wsl-bypass inside your WSL distro. See WSL → Bypass helper.

Write a personal config

Hollow resolves one base config and one override config. The base config is the shipped default in conf/init.lua. Your override is what you actually own; it merges on top of the base.

Default override locations:

  • Windows: %APPDATA%\hollow\init.lua
  • Non-Windows hosts: $XDG_CONFIG_HOME/hollow/init.lua or $HOME/.config/hollow/init.lua

You can also pass --config path/to/init.lua on the command line, which takes precedence over the default path.

Minimal override:

local hollow = require("hollow")

hollow.config.set({
  fonts = { size = 16, family = "Cascadia Mono" },
  scrollback = 128_000_000,
  window_titlebar_show = false,
})

Reload with <leader>uu (the default config binds that to hollow.config.reload() and shows a toast).

See Configuration for the full model.

Mental model

Hollow exposes a single Lua global: hollow. The shipped namespaces are:

NamespacePurpose
hollow.configRead and write configuration
hollow.termTabs, panes, workspaces, text and process helpers
hollow.eventsSubscribe to host events
hollow.keymapBind keys to actions or Lua callbacks
hollow.uiTop bar, sidebars, overlays, widgets
hollow.htpRegister shell-to-host query and emit channels
hollow.fonts, hollow.jsonFont and JSON helpers
hollow.workspace, hollow.asyncWorkspace bootstrap and async
hollow.process, hollow.fsProcess spawning and filesystem
hollow.theme, hollow.util, hollow.platformTheme, utility, and platform
hollow.pluginsPlugin loader
All of the aboveSee Reference for full API

Snapshots returned from hollow.term (tabs, panes, workspaces) are read-only — treat them as values, not live references.

Build from source

The repo builds with Zig 0.15.2 (pinned via .tool-versions). The full toolchain walkthrough lives in Development; the short version:

./scripts/setup.sh   # one-time
./launch.sh          # build and run on Windows from WSL

launch.sh cross-builds x86_64-windows-gnu and copies the executables to the repo root before running hollow.exe.

Next steps