gwae logo

gwae

niri's scrolling tiling, for your CLI agents, in any terminal.
An infinite 2D grid of strips where panes never shrink.
No daemon. No compositor. One process.

curl -fsSL https://raw.githubusercontent.com/hongnoul/gwae/main/scripts/install.sh | bash
1 process. No daemon, no socket, no attach
~0.05 ms full 300×80 repaint
0 agent instrumentation: standard OSC 133 only
columns right, strips down. None ever shrink

Onboarding

Install → Guided setup → Spawn agents → Hold ⌥ to triage

curl -fsSL https://raw.githubusercontent.com/hongnoul/gwae/main/scripts/install.sh | bash
gwae                  # one strip, one quarter-width pane
gwae init             # guided setup: theme, layout, chrome (live preview)
gwae run "claude"     # your agent in column 0
gwae doctor           # config + theme validity, layout smoke

Why

Every terminal multiplexer divides a fixed screen: more agents means smaller panes, until nothing is readable. niri solved this on the desktop with scrolling tiling — columns keep their size, the viewport moves. gwae brings that model into the terminal you already use.

For coding agents

gwae hosts ordinary PTYs, so every agent works out of the box: Claude Code, Jcode, Codex, OpenCode, Gemini CLI, anything you can launch from a command line. Status tracking speaks the standard OSC 133 protocol only, with a quiet-heuristic fallback for shells without integration.

»  working          command running
!  wants attention  idle with output / prompt waiting
✓  done             exited 0
✗  failed           non-zero exit

⌥+g jumps to the pane that needs you most: failed beats wants-attention beats done, nearest first, crossing strips and following with the scroll.

Compared

Project Layout In a terminal? Detach? Platforms
tmux plane tiling yes yes (server) macOS/Linux/*BSD
Zellij plane tiling + floating yes yes macOS/Linux/Windows
Séance niri strip (GUI) no socket Linux (GTK)
tairi niri strip (GUI) no workspaces macOS
gwae 2D niri strip grid yes no (--resume) macOS/Windows/Linux

Philosophy

Usage

⌥+h/j/k/l        focus left / down / up / right (crosses strips)
⌥+Shift+hjkl     move column / carry pane
⌥+Enter          new column right of focus
⌥+;              spawn agent column
⌥+s              split: new pane below
⌥+r              cycle column width 1/3 → 1/2 → 1/4
⌥+f              toggle full width
⌥+↑/↓            scrollback (typing snaps back to live)
⌥+1..9           jump to column N
⌥+g              smart-jump to the pane that needs you
⌥+t              live theme picker
⌥+/              cheat-sheet HUD

All other keys pass through to the focused pane. Full table in the README.

Architecture

gwae (one process)
├── Layout core (rows/strips/columns/panes) — pure, no I/O
├── Pane tasks (one per PTY: bytes → parse → grid + OSC 133)
├── Composer (coalesce damage → single 2D cell buffer)
├── Render (diff buffer → batched ANSI, sync-update markers)
├── Input (raw mode: decode keys, route to pane or ⌥)
└── Minimap / smart-jump (per-pane status → chrome)

Layout invariants are proptest properties; E2E tests drive the real binary through a live PTY. See ARCHITECTURE.md and the normative LAYOUT-SPEC.md.