kittui

kittwm

A window manager that lives in a terminal

kittwm tiles and floats panes inside one terminal, and a pane can be almost anything: a shell, a headless browser, an X11 or Wayland app on another machine, or a native macOS or Windows window. Everything is scriptable, from one keystroke to a typed event stream.

Everything becomes a pane

Everything becomes a paneSix kinds of source feed kittwm: native terminals, a headless Chrome browser, remote X11 and Wayland windows, native macOS windows and native Windows windows. Each implements the same surface contract with declared capabilities: capture, input, exact bytes, focus and surface events, resize, title and restore. The runtime lays them out as panes and draws them with the ANSI or kitty graphics renderer. It is controlled from keys, the kittwm command and its socket, typed SDK events and semantic snapshots. term native PTY browser headless Chrome remote-x11 over SSH remote-wayland over SSH macos-window ScreenCaptureKit windows-window HWND capture surface contract capture · input exact bytes · events resize · title restore kittwm runtime panes · layouts · floating ANSI or kitty renderer sessions · events control keys · kittwm socket SDK events · semantics
One contract.Every source declares what it can do, and kittwm routes input, resizing and capture by those declarations rather than by source type.
kittwm add --helpkittwm add <source> [args] — add a window from any sourcesources:  term           [  ready]  native PTY terminal (bare `add term` runs your login shell; `add term CMD...` runs CMD)  browser        [  ready]  headless-Chrome browser surface (`add browser URL`)  remote-x11     [  ready]  remote X11 window captured into a pane (`add remote-x11 HOST[:app]`)  remote-wayland [  ready]  remote Wayland window captured into a pane (`add remote-wayland HOST[:app]`)  xquartz        [pending]  local XQuartz X11 window (`add xquartz [app]`)  macos-window   [  ready]  native macOS app window, e.g. Edge (`add macos-window <app|title>`; needs a macOS --features quartz build + Screen Recording permission)  windows-window [  ready]  native Windows app window over SSH/WSL stdio (`add windows-window HOST <id|title>`)

Panes and keys

Start kittwm for a clean workspace, then Ctrl+A Enter for a terminal. The built-in cheat sheet is the best map:

kittwm cheatIN SESSION  C-a Enter    terminal     C-a g launcher   C-a ? help  C-a t float  C-a f full   C-a e split-toggle  C-a % split columns       C-a - split rows  C-a x close  C-a Tab focus next        C-a b balance     C-a +/- resizePANE CONTROL  kittwm spawn htop         kittwm focus native-2  kittwm close              kittwm layout rows  kittwm move last          kittwm nudge focused 3 -2  kittwm reset-position     kittwm resize focused +2  kittwm balance            kittwm rename focused editor

Layouts are columns, rows or a grid, with weighted sizes and floating panes nudged by cells. Terminal panes use a real terminal emulator core, and the clipboard is bridged between panes. Each pane's frame is drawn either with ANSI characters or, with KITTWM_NATIVE_RENDERER=kitty, with kittui graphics.

Backends and capabilities

Each backend implements the same surface contract. Parity tests enforce the declared capabilities, comparing capture hashes against golden results:

SurfaceCaptureInputExact bytesResizeTitle
Terminal (PTY)yesyesyesyesyes
Browser (headless, DevTools)yesyesnoyesyes
X11 (Xvfb capture)yesyesnoyesyes
Wayland (waypipe, wlroots)yesyesnoyesyes
macOS (ScreenCaptureKit)yesyesnonoyes
Windows (window capture)yesyesnonoyes
kittui scene, compositeyesnononoyes

Neither native-window backend resizes the source window: on macOS the operating system owns window size, and on Windows the backend deliberately leaves your desktop alone, so arranging panes never rearranges it. Windows capture tries Windows Graphics Capture, then DXGI duplication, then PrintWindow, carried over SSH by a small window host. The full PTY terminal also emits focus and title events; no surface yet saves restore metadata. The Windows backend keeps its system calls thin and puts key mapping, mouse flags and pixel conversion in pure functions that are tested on every platform. A deterministic in-memory backend stands in for real displays in tests.

Semantic surfaces

Pixels show an app but say nothing about it. Semantic surfaces add a tree of components, each with a role, value, state and actions, alongside the pixels rather than instead of them, so an agent or a screen reader can find a button and press it. Browser pages publish semantic snapshots from the DOM and accessibility tree through DevTools:

kittwm-browser --semantic-snapshot https://example.com

Semantic focus and actions go through DevTools as real clicks, focus changes and edits, and sensitive or cross-origin fields stay conservative by default. An adapter for native apps through macOS Accessibility and Linux AT-SPI is designed but not yet built; until then those apps are pixels, with full input.

Automation

Pane actions have commands, and commands have socket equivalents, so scripts and agents drive kittwm the way a person does:

kittwm spawn htop                        # new terminal panekittwm line focused 'cargo test'         # type a line and press Enterkittwm wait focused 'Finished'           # block until the text appearskittwm read-json focused                 # the pane's text, as JSONkittwm events 1000                       # a bounded stream of typed eventskittwm --save-session session.json       # layout, focus, order, titles, commands, weights

Event streams start with a status envelope, carry pane, focus, layout, input, frame, semantic and surface events, and end with END. kittwm info, kittwm panes, kittwm --chrome-json and kittwm-top --json inspect a running session.

Across machines

If a remote machine has kittwm, run it there over SSH and it uses that machine's displays and graphics. If not, local helpers discover what the remote can do and forward over pooled SSH:

kittwm remote host status --x11              # check trusted X11 forwardingkittwm apps --remote host --filter firefox --launch-firstkittwm add remote-x11 host:xterm            # run it in Xvfb there, tunnel it, attach a panekittwm-terminal --remote host