Documentation

Architecture

29 focused crates, a dirty-driven GPU frame loop, and a per-host daemon any client can attach to.

toowl is a Cargo workspace of 29 focused crates (edition 2024, no dependency cycles, nothing depends on toowl-app). It splits into two tiers: the client — a GPU desktop app or a crossterm TUI — and the daemon (toowld) that owns your workspaces and long-running sessions.

<80ms
Cold start
First frame on Apple Silicon
~80MB
Idle memory
No always-on redraw
120fps
Smooth-glide cursor
Where the display allows; 0fps when idle
1 binary
GUI + TUI
Auto-detects desktop vs headless
29
Focused crates
No cycles, edition 2024
17
Built-in themes
Plus your own in config.toml

Clients, transports, and the daemon

Any client reaches a per-host toowld over the Transport trait — a Unix socket locally, SSH-stdio for a remote box, or a WebSocket for the browser. The daemon owns a tree of workspaces → sessions → PTYs; closing a window detaches, reopening reattaches, and the shells underneath never stop.

Clients Desktop GUI wgpu · native chrome TUI client crossterm · over SSH Browser roost-web · scoped URL Transport Unix socket SSH-stdio WebSocket / WSS Host toowld per-host workspace & session owner Workspace: dev @host Session — attached PTY → $SHELL (zsh) Session — detached, still running PTY → claude · pm2 · build
One daemon per host owns your workspaces; any client attaches over a transport.

The frame loop (and why it's fast)

A dedicated thread reads each PTY into a channel. Once per frame, tick() drains every pane's channel, feeds the bytes through the vte parser into the grid, and marks changed rows dirty. The renderer then runs one GPU pass per pane (cell background → underline → glyph → cursor) plus a single chrome pass for tabs and overlays.

  1. PTY thread reads bytes
  2. channel crossbeam
  3. tick() drain + parse
  4. grid dirty rows
  5. render 1 pass/pane + chrome
  6. present wgpu surface
PTY bytes to pixels — buffers are pre-allocated, so resizing never reallocates.
The freeze-fix law: never always-redraw. toowl paints a frame only when the grid actually changed or something explicitly requested a repaint. That's why the cursor glides at your display's refresh rate while you type but the app sits at ~80 MB and near-zero CPU when you're just reading. The flip side: whenever a window returns to the foreground (app-switch, un-occlusion, regained focus) toowl forces one fresh repaint, so what you see is always current — not stale until you click.

The 29 crates

Each crate's lib.rs re-exports only what its consumers need, so the public surface stays small and the dependency graph stays acyclic.

App & render core
toowl-app

The binary — event routing, action dispatch, window + plugin host.

toowl-render

wgpu renderer: glyph atlas, one pass per pane + a chrome pass.

toowl-widgets

Panel trait + palette, settings, search, context menu.

toowl-input

The Action enum (feature dictionary), keymaps, key parsing.

Terminal & grid
toowl-vt

vte parser → SGR/cursor/erase, OSC 7/8/133, Kitty graphics.

toowl-grid

Cells, scrollback, selection, reflow-on-resize, command marks.

toowl-pty

Portable PTY wrapper with a dedicated read thread.

Config, theme & type
toowl-config

TOML schema + state.json, atomic save, 150ms hot-reload watcher.

toowl-theme

6 flagship themes + by_name lookup.

toowl-font

cosmic-text + swash CPU rasterizer, lazy face loading.

Platform
toowl-macos

AppKit runloop, Liquid Glass titlebar, cwd lookup.

toowl-windows

DWM Mica/Acrylic, rounded corners, dark title bar.

Feathers (plugins)
toowl-plugin

Plugin trait, View tree, HostApi, PluginEvent.

toowl-plugin-claude

The Claude Feather: session list + crash banner.

toowl-plugin-nest

cwd-synced file browser Feather.

toowl-plugin-mcp

MCP Hub — hot-start Model Context Protocol servers.

toowl-plugin-scout

Web search Feather.

toowl-plugin-subprocess

JSON-RPC subprocess adapter + crash-restart watchdog.

toowl-plugin-remotes

Remote Machines Feather — host switcher.

toowl-plugin-workspaces

Workspaces Feather — open/save named workspaces.

toowl-plugin-roost

Daemon-aware Feather surface.

Daemon, remote & TUI
toowl-roost-daemon

The toowld daemon: per-host workspace + session owner.

toowl-roost-proto

Typed wire protocol shared with clients.

toowl-roost-client

Unix-socket + SSH-stdio + WebSocket Transport impls.

toowl-tui

crossterm client — talks to toowld via Transport.

toowl-cli

toowl up <name> dispatcher + singleton-IPC shim.

Updates & Aviary
toowl-updater

GitHub-Releases-driven in-app updater.

toowl-aviary-format

Signed Feather package format.

toowl-aviary-client

Aviary registry client.

Two clients, one binary

The same source builds two ways. A desktop build pulls in wgpu and winit; a server build drops them entirely:

# Desktop (GUI + TUI)
cargo build --release

# Headless server (TUI only, no GPU deps)
cargo build --release --no-default-features --features tui

At runtime the toowl binary auto-detects: a GPU window where there's a display, a tmux-style crossterm client over SSH or on a headless host. Both share the exact same vte parser and grid, so terminal behavior is identical everywhere.

Feathers (the plugin tier)

Extensions are Feathers. A plugin implements the Plugin trait, describes its UI as a View tree, and talks to the host through HostApi. Feathers hot-start when you open the Perch (so they cost nothing at launch) and can be stopped and started without a restart. In-workspace first-party Feathers — Claude, Nest, MCP Hub, Scout — ship in the binary; signed third-party Feathers install from the Aviary.

Go deeper