Documentation

Remote machines

Connect to remote toowld daemons over SSH or WebSocket. One config, three clients.

A remote is a toowld daemon running on another host. Define it once in ~/.config/toowl/remotes.toml and the same entry surfaces in the GUI Perch, the TUI picker, and the web client. Workspaces, panes, and scrollback live on the remote daemon — the client just renders.

Define a remote

Create ~/.config/toowl/remotes.toml with one [[remote]] table per machine:

# ~/.config/toowl/remotes.toml

[[remote]]
name = "idrl"
host = "idrl.example.com"
transport = "ssh"
port = 22
user = "ubuntu"

[[remote]]
name = "lan-box"
host = "192.168.1.20"
transport = "ws"
port = 7113

[[remote]]
name = "prod"
host = "api.example.com"
transport = "wss"
port = 7113
auth = { token_env = "TOOWL_PROD_TOKEN" }

Schema reference

FieldRequiredNotes
nameyesUnique identifier. Shown in the Perch, palette, and window-title badge. Must not collide with another remote.
hostyesHostname or IP. Must not start with - — that's an SSH option-injection guard.
transportyesssh, ws, or wss.
portnoDefaults to 22 for SSH and 7113 for ws / wss.
usernoSSH user. Must not start with -.
auth.token_envnoName of an env var holding the bearer token for wss. The token itself never lives in the config file.
remote_toowld_binnoOverride the toowld path on the SSH-side host. Whitelisted to filename-safe characters.

Transports

SSH stdio

The primary path today. toowl spawns ssh <host> [-l user] toowld --serve-stdio and tunnels JSON-RPC over the SSH connection. No port forwarding, no extra daemon config — if you can SSH into the box and it has toowld installed, you can use it as a remote.

  • Auth — whatever your SSH config does. Keys, agents, jump hosts all work.
  • Survives disconnect — the remote daemon was started with setsid(); it keeps running across SSH drops, so your workspaces survive.
  • Defense in depth — toowl rejects host and user values starting with - and constrains remote_toowld_bin to filename-safe characters so a hostile config can't smuggle SSH options.

WebSocket (ws)

Plain WebSocket. LAN-only — there's no transport-level encryption. Use this for a box on the same trusted network where SSH is overkill.

Secure WebSocket (wss)

TLS WebSocket with optional bearer-token auth. Set auth.token_env to the name of an environment variable holding the token; toowl reads it at connect time:

export TOOWL_PROD_TOKEN="…"
toowl

Heads up. wss and ws transports complete the TLS / WS handshake but the daemon's JSON-RPC endpoint is still landing. SSH is the primary path for now; ws and wss will light up automatically once the daemon adds /v1/rpc.

The Remotes Feather

The Feather is a one-tap switcher for the active window's daemon. Open the Perch with Ctrl+Shift+B, find Remote Machines, and click a remote to rebind the current window. The window title picks up the @ host badge, panes you spawn from the palette land on the remote daemon, and the Workspaces Feather starts listing the remote's workspaces.

Click Local to drop back to your own machine.

Three clients, one config

ClientHow to open the picker
GUIClick Remote Machines on the Perch.
TUIType the prefix and mCtrl+B m by default.
WebNavigate to /remotes on the daemon's HTTP gateway. SSH remotes are hidden — browsers can't initiate SSH.

All three read the same ~/.config/toowl/remotes.toml. Edits are hot — the Feather watches the file and refreshes its list when you save.

Driving a remote from the command line

Prefix any toowl command with @<name> to target a remote instead of your local daemon. name is a [[remote]] entry from the config above; @local forces the local daemon (handy to override an inherited TOOWL_REMOTE).

toowl @idrl                     # interactive TUI, attached to idrl
toowl @idrl ls                  # list the remote's sessions
toowl @idrl roost ws list       # list the remote's workspaces
toowl @idrl roost snapshot build --ansi    # dump a session's screen
toowl @idrl roost new -s build -- cargo build   # start a session on idrl

toowl ls                        # no @ = your local daemon

Over SSH the remote daemon auto-spawns on first connect, so there's nothing to start by hand. Anything that works locally works behind @host — with one exception: toowl up <name> reads a workspace file from your local disk, so it stays local-only. Build remote workspaces with toowl @host roost ws new or interactively in the TUI.

Equivalent env var. @host is shorthand for setting TOOWL_REMOTE=<name>; if you prefer, export it once in your shell and drop the prefix. The flag wins when both are set.

Connection lost

Sessions live on the daemon, not the client — so a dropped SSH/WS link never loses your work. The TUI detects the drop, shows reconnecting…, and re-attaches automatically with capped backoff. The GUI window gains a (connection lost) title suffix and flips the pane chrome dots red; reconnect by clicking the remote again in the Remotes Feather (or re-running toowl @<name>). Either way the daemon kept the panes alive, so you reattach to the same live state.

Setting up the remote box

Install the server-flavored build on the remote machine:

# On the remote host
bash scripts/install-server.sh

# Verify the daemon launches on demand
toowld doctor

See TUI client for the headless build flags and SSH-friendly install notes.

Security notes

  • Tokens live in env vars, not on disk. auth.token_env only names the env var; the token value never round-trips through the config file.
  • SSH option-injection guards. Hosts and users starting with - are rejected at config load, before they reach ssh.
  • Duplicate names are rejected. The loader refuses to start if two [[remote]] tables share a name.

Keep going

  • Workspaces — named windows you can open on local or remote daemons.
  • TUI client — run toowl over SSH on a server with no display.
  • Configuration — the rest of config.toml.

Edge case or feature request? File it on GitHub.