kolu
Docs

the terminal

A real terminal, not a preview.

A tile is a full terminal, not a preview — a real xterm.js instance with everything you’d expect from a native one. The title bar carries the same repo monogram and a short colour spine as the dock, so identity agrees everywhere you look.

A maximized tile: Claude Code asking permission to create a file, with the dock docked as a sidebar.
Maximized: the tile takes the screen and the dock becomes a sidebar.

Splits and tabs

Split a bottom pane with Ctrl + </kbd>, add tabs with <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>. On the canvas, every descendant of a tile — a direct split, or a split of a split created from the shell or by an agent (kolu create --parent <id>) — shows as a flat tab in that tile’s bottom strip. Nested depth is allowed in the data; the canvas just does not invent a second visual language for it. In the Dock, the same terminals keep their true tree: every split is an indented entry beneath its real parent, and clicking it lands the keyboard in that pane. Every sub-entry shows the same status indicator as a top-level dock row — shell identity for a plain shell, agent brand mark and attention colour when an agent is running. An externally-created split opens the same way — the pane expands and the new split is selected, no click needed (unless you’re already working in another split of that tile, which it won’t yank you off).

In a split, the pane that does not have focus recedes slightly, so the one your keystrokes are going to always reads as the foreground.

Font zoom

Zoom the font with Cmd/Ctrl + + / - — it zooms only the focused tile and persists per terminal, so two tiles can be aligned to the same size.

Rendering

  • WebGL rendering with a canvas fallback, kept on your whole working set of terminals at once so switching between them never churns GPU contexts.
  • Clickable URLs — a long URL that wraps across lines survives resizes and always opens whole.
  • Unicode 11 and inline images (sixel, iTerm2, kitty).

Output keeps flowing

The terminal defends itself against the ways live output can silently stall: a heartbeat detects a dead connection (a sleeping laptop, a Wi-Fi roam) and reconnects on its own; reconnecting re-asks for everything the old connection was carrying, so a pane cannot be left waiting on an answer that can no longer come; a repaint queued while the window was in the background runs the instant you return; and when a flooding terminal outruns its view, it re-attaches and repaints from a fresh snapshot rather than freezing. You should never need a keypress or a reload to see output that already happened. And a pane whose feed keeps coming back empty — reopened, but never delivering anything — says so rather than sitting there blank: a message names the pane and tells you kolu is still retrying, and it keeps retrying at a gentle cadence until output reaches the pane again.

A terminal’s screen is drawn for one specific width and height, so a pane waits until it has actually been measured before it asks for anything, and asks for the screen at its own size. That matters most for a split you open later — a collapsed panel, or a tab that was in the background when the page loaded. It has no size on screen to measure yet, so rather than guess one and paint a screen drawn for the wrong width, it stays empty until you reveal it and then paints once, correctly. You should never have to nudge the divider to fix a split’s rendering.

On touch devices

A mobile key bar sends the keys soft keyboards lack — Esc, Tab, arrows, Ctrl+C — with two sticky modifiers you tap to arm. The full story is in kolu on a Phone.

Next