Documentation
TUI client
One binary, two clients — toowl on the desktop is GPU-rendered; on a headless server it draws ANSI through your existing terminal.
The same toowl binary ships two front-ends. On a desktop with a
display, it boots the GPU-rendered GUI. On a headless server, or whenever
you launch toowl through SSH, it boots a crossterm-rendered TUI
client that paints into your existing terminal. Both clients talk
to the same toowld daemon, so your workspaces survive
regardless of which one you're using.
How toowl picks GUI vs TUI
A bare toowl invocation runs through a small selector:
- Explicit flags win.
--guior--tuiforces the choice. - Some subcommands force TUI.
up,ls,a,new, andkill-sessionalways land in the TUI. - Server-only build? When the
guiCargo feature wasn't compiled in, only the TUI is available. - Display detection. macOS and Windows go GUI. Linux uses GUI if
$DISPLAYor$WAYLAND_DISPLAYis set; otherwise TUI.
Build flavors
| Command | Result |
|---|---|
cargo build --release | Default — both clients, full desktop binary. |
cargo build --release --no-default-features --features tui | TUI-only. No wgpu, no winit, no cosmic-text — ideal for headless Linux servers. |
cargo build --release --no-default-features --features gui | GUI-only. |
The TUI-only build skips system deps like libwayland-dev and
libGL, so it installs cleanly on minimal server images.
scripts/install-server.sh wraps the right flags for you.
Server install:
bash scripts/install-server.sh
Or grab a prebuilt toowl-linux-x86_64-server.tar.gz /
toowl-linux-aarch64-server.tar.gz from
Releases.
What it looks like
The TUI is tmux-shaped on purpose. A thin status bar at the bottom shows the workspace name, tab list, and any unread bell counts. The body splits into panes following the workspace's layout. Borders and titles paint through ANSI, every pane has its own VT parser, and dirty-row tracking keeps redraws cheap even on slow links.
- Per-pane parsing. Every pane runs the same VT parser as the GUI — OSC 7 cwd, OSC 8 hyperlinks, OSC 133 prompt marks, WRAPPED reflow, alt-screen all carry over.
- Daemon-driven. Bytes arrive from
toowld, get fed through the parser, marked dirty — the compositor walks dirty rows and paints with crossterm. - Resize-aware. Terminal resize repaints the layout against the new dimensions.
Daemon auto-start
The first invocation on a machine spawns toowld if it's not
already running. The daemon is detached with setsid() —
it survives SSH disconnect and parent SIGHUP, which is what
keeps your workspaces alive between sessions. Logs land in
~/.local/state/toowl/toowld.log and
toowld doctor reads from the same path.
If two clients race to spawn the daemon, the loser's socket bind fails and both clients connect to the winner. Same pattern tmux uses.
Keybindings
The TUI uses a tmux-style prefix — Ctrl+B by default. Press
the prefix, then the chord. Anything unprefixed passes through to the
focused pane's PTY.
| Chord | Action |
|---|---|
C-b d | Detach client. The session keeps running on the daemon. |
C-b c | New tab |
C-b n / C-b p | Next / previous tab |
C-b 1…9 | Switch to tab N |
C-b " | Split horizontal |
C-b % | Split vertical |
C-b x | Close active pane |
C-b h / j / k / l | Focus pane left / down / up / right (arrows also work) |
C-b m | Remote machines picker |
C-b s | Session picker |
C-b $ | Rename session |
C-b z | Toggle zoom on the active pane |
C-b : | Command palette |
C-b ? | Auto-generated help overlay |
C-b C-b | Send a literal Ctrl-B to the pane |
Tab / Shift+Tab | Cycle focus — no prefix needed |
Override the prefix with [tui] prefix = "C-a" in
~/.config/toowl/config.toml. The chord parser is the same
KeyCombo grammar the GUI uses.
Workspaces from the TUI
Open a named workspace from any shell on the server:
toowl up pm2
The TUI reads ~/.config/toowl/workspaces/<name>.toml,
asks the daemon to bring up the workspace, and starts rendering.
C-b d detaches without killing anything; rerunning the same
command reattaches.
See Workspaces for the TOML schema.
Remotes from the TUI
Press C-b m to open the remote-machines picker. Entries come
from ~/.config/toowl/remotes.toml — the same file the GUI
and web client read. Pick a remote and the TUI rebinds to that daemon;
pick Local to drop back to your machine.
See Remote machines for the schema and transport options.
Transport
Under the hood, the TUI talks to toowld through a generalized
Transport trait. The default is a Unix socket on the local
box. C-b m swaps in an SSH-stdio or WebSocket transport so the
same renderer lights up against a remote daemon — no separate client,
no second binary.
Survival tips for the headless flow
- Disconnects are safe. The daemon owns the panes. Close your laptop, kill the SSH session — nothing dies. Reattach with
toowl up <name>ortoowl a -t <name>. - Check the daemon.
toowld doctorverifies the socket, the log file, and PID. Logs live at~/.local/state/toowl/toowld.log. - Detach, don't quit.
C-b ddetaches cleanly. Quitting your terminal also detaches — the daemon keeps the panes.
Keep going
- Workspaces — named, persistent windows you can open from any client.
- Remote machines — connect to other servers without leaving the client.
- Configuration — the rest of
config.toml, including[tui].
Hit a snag installing on a server distro?
File an issue on GitHub with the output of
toowld doctor.