CLI Reference
Complete command-line reference for TUIOS
Complete command-line interface reference for TUIOS.
Every command below accepts --help, which is authoritative. This page documents what the binary actually does, including the places where the flags and the runtime options disagree.
Installation
See Getting Started for installation instructions.
Basic Usage
tuios [flags]
tuios [command] [flags]Global Flags
Only --debug, --cpuprofile, and --pprof are persistent flags accepted everywhere. The interface flags below are registered only on the commands that draw a TUI (tuios, tuios attach, tuios new, tuios ssh, tuios tape play). Passing --theme to tuios ls is an error, not a no-op.
Four more are local to a bare tuios and are rejected on every subcommand: --list-themes, --preview-theme, --skill, and --standalone.
--theme
Set the color theme.
tuios --theme dracula
tuios --theme nord
tuios --theme tokyonightThe default is empty, not a named theme. With no --theme and no theme in the config file, TUIOS uses your terminal's own 16 ANSI colors rather than overriding them.
--list-themes
List all available themes. 342 ship with the binary, plus any custom themes you have added.
tuios --list-themes--preview-theme
Preview a theme's colors.
tuios --preview-theme draculaCombine with fzf for interactive selection:
tuios --theme $(tuios --list-themes | fzf --preview 'tuios --preview-theme {}')--debug
Enable debug logging.
tuios --debug--ascii-only
Use ASCII characters instead of Nerd Font icons.
tuios --ascii-only--show-keys
Show pressed keys overlay (for demos and recordings).
tuios --show-keys--border-style
Set window border style.
Values: rounded, normal, thick, double, hidden, block, ascii, outer-half-block, inner-half-block
tuios --border-style thick
tuios --border-style hidden--dockbar-position
Set dockbar position.
Values: bottom, top, hidden
tuios --dockbar-position top
tuios --dockbar-position hiddenset-config --help lists values that do not exist
The flag and the runtime appearance.dockbar_position option take the same three values. tuios set-config --help still prints top, bottom, left, right for it. That list is wrong: left and right are rejected. Trust tuios list-options appearance.dockbar_position, which reads the registry the validator uses.
--hide-window-buttons
Hide window control buttons.
tuios --hide-window-buttons--scrollback-lines
Set scrollback buffer size (100-1000000).
tuios --scrollback-lines 20000--no-animations
Disable window animations for instant transitions.
tuios --no-animationsWhen enabled, windows will instantly snap to their positions without animated transitions. Useful for lower-end hardware or users who prefer instant feedback.
--confirm-quit
Always show the quit confirmation dialog, even when no foreground processes are running.
tuios --confirm-quitBy default, TUIOS only shows the confirmation dialog if there are active foreground processes that would be killed on exit. This flag makes it always ask before quitting.
--window-title-position
Set window title position.
Values: bottom, top, hidden
tuios --window-title-position top
tuios --window-title-position hiddenWhen set to hidden, window titles are not displayed and the rename keybinding (r) is disabled.
--hide-clock
Hide the clock overlay. Deprecated: the clock is hidden by default, so this flag is a no-op kept for compatibility. Use --show-clock to opt in instead.
tuios --hide-clockThe clock still appears during tape recording (red background) or when prefix mode is active.
--show-clock
Show the clock overlay.
tuios --show-clock--show-cpu
Show CPU usage indicator in the dockbar.
tuios --show-cpu--show-ram
Show RAM usage indicator in the dockbar.
tuios --show-ram--shared-borders
Enable shared borders between adjacent tiled windows for a more compact layout.
tuios --shared-borders--hide-scrollbar
Hide the scrollbar thumb drawn on the window border.
tuios --hide-scrollbar--zoom-max-width
Cap the width, in cells, that zoom mode expands a window to. 0 means fullscreen.
tuios --zoom-max-width 120Useful on ultrawide displays where a fullscreen zoom produces unreadably long lines.
--window-button-style
Draw the window controls as a filled pill or as macOS traffic lights.
Values: pill (default), dots
tuios --window-button-style dots--window-button-position
Which end of the title bar the window controls sit on.
Values: right (default), left
tuios --window-button-position left--standalone
Run a standalone session without the daemon, overriding startup.daemon. Accepted on a bare tuios only.
tuios --standaloneThis matters only when you have set startup.daemon = true, which makes a bare tuios attach to a daemon-backed session. --standalone is the way back out, so a daemon that will not start never leaves you without a way in. TUIOS_NO_DAEMON=1 does the same thing for a whole shell.
--skill
Print the agent skill for driving TUIOS from a pane, then exit. Accepted on a bare tuios only.
tuios --skill > ~/.claude/skills/tuios/SKILL.mdThe document is a Markdown file with YAML frontmatter, written for a coding agent running inside a pane. It covers finding out where you are running, reading and writing other panes, opening panes and running work in them, waiting on conditions instead of polling, reporting your own state, and finding, messaging and questioning the other agents alongside you.
It ships inside the binary and is generated in part from the same registries the commands use, so it describes the TUIOS you are actually running.
--cpuprofile
Write a CPU profile to a file, for development.
tuios --cpuprofile cpu.prof--pprof
Serve net/http/pprof on the given address for live profiling.
tuios --pprof localhost:6060This opens an unauthenticated HTTP server that exposes profiling data and the process command line. Bind it to localhost.
-v, --version
Print the version, the VT backend the binary was built with (pure-Go or ghostty), the commit, build date, and builder, then exit.
tuios --versionThere is no tuios version subcommand. tuios version is an error.
Commands
Several commands have aliases:
| Command | Aliases |
|---|---|
attach | a |
new | n |
ls | list-sessions |
resurrect | restore |
keybinds | keys, kb |
Daemon Mode (Session Persistence)
TUIOS supports persistent sessions that continue running in the background, similar to tmux or screen.
new
Create a new persistent session and attach to it. Alias: n.
tuios new [session-name] [flags]Flags:
-d, --detach- Create the session headless, without attaching a client
Examples:
# Create session with auto-generated name
tuios new
# Create named session
tuios new mysession
# Create session with theme
tuios new work --theme dracula
# Create a headless session for scripting
tuios new build --detachA --detach session gets an initial window and is immediately usable by send-keys, run-command, and capture-pane. It is created at a fixed 80x24 until a client attaches, and the appearance flags are ignored because there is no client to apply them to. See Headless Sessions.
attach
Attach to an existing session. Alias: a.
tuios attach [session-name] [flags]Flags:
-c, --create- Create session if it doesn't exist
Examples:
# Attach to most recent session
tuios attach
# Attach to named session
tuios attach mysession
# Attach or create if doesn't exist
tuios attach mysession -cls
List all TUIOS sessions. Alias: list-sessions.
tuios ls [flags]Flags:
--json- Output as JSON--all-hosts- Also list every machine in the[hosts]config table--host <name>- List one host by name.localmeans this machine
Without --json it prints a table of session name, window count, status, creation time, and last activity.
JSON output is a bare array, with no wrapper object:
[
{
"name": "work",
"id": "7f55590c-ecc0-450e-88a3-3cb1ff2573c8",
"created": 1784391188,
"last_active": 1784391188,
"window_count": 3,
"attached": false,
"width": 120,
"height": 40,
"display_name": "Work",
"accent": "mauve",
"current_workspace": 2,
"restored": true
}
]created and last_active are Unix seconds. The last five fields are omitted when unset, so a plain session prints the first eight and nothing more. display_name and accent carry the session's label and accent colour, current_workspace is the workspace it is showing, and restored marks a session rebuilt from saved state that nobody has attached to yet. A windows array of per-window summaries is present when the daemon knows them.
With no daemon running, ls lists the sessions saved on disk instead of printing nothing. Each row is marked saved in the table and carries "saved": true in JSON, and the command exits 3. See Exit Codes.
Across hosts. --all-hosts and --host group the listing by machine, so the output is a different shape: an object with a hosts array rather than a bare array of sessions. A host that does not answer gets a row saying so and never fails the command. See hosts.
resurrect
Restore a session saved to disk after the daemon exited. Alias: restore.
tuios resurrect [session-name]With no argument it lists the sessions that can be restored. With a name it restores that session and attaches to it.
Resurrection restores window structure, not running processes or scrollback. See Session Resurrection for exactly what survives.
kill-session
Kill a specific session.
tuios kill-session <session-name>Destructive. This closes every window in the session and deletes its saved state file, so a killed session cannot be resurrected.
kill-server
Stop the TUIOS daemon.
tuios kill-serverDestructive. Every session's processes are terminated. The daemon does save session structure on its way out and the next daemon restores it, so this is not a way to get a clean slate. Use tuios daemon --no-restore for that.
daemon
Run the daemon in the foreground, for debugging.
tuios daemon [flags]Flags:
--log-level <level>- Debug log level:off,errors,basic,messages,verbose,trace--no-restore- Do not auto-restore saved sessions on start
# Watch every protocol message go by
tuios daemon --log-level messages
# Start clean, ignoring saved session state
tuios daemon --no-restorestart-server
Start the daemon in the background.
tuios start-serverThis command is hidden from tuios --help and is effectively internal. The daemon starts on its own when you create or attach to a session, so you should not need it. It is documented here because it is functional and shows up in shell completion.
logs
View the daemon's logs.
tuios logs [flags]Flags:
-n, --lines <n>- Number of entries to show, default50.0means all--all- Show all stored log entries-f, --follow- Keep printing new entries as they arrive--clear- Clear the logs after viewing
# Last 50 entries
tuios logs
# Last 200
tuios logs -n 200
# Tail the log
tuios logs -f--clear is destructive: it discards the stored log buffer after printing it. Redirect the output somewhere first if you may need it.
The amount of detail in the log depends on the --log-level the daemon was started with.
layout
Manage layout templates (saved window arrangements).
layout list
List all saved layout templates.
tuios layout listlayout delete
Delete a saved layout template.
tuios layout delete <name>Destructive and not undoable. Export the layout first if you might want it back.
layout dir
Show the layout templates directory path.
tuios layout dirlayout export
Export a layout template as a tape script, printed to stdout. The name is required and is the only argument; there is no output-file argument.
tuios layout export <name>Redirect it yourself to save it, and replay it with tuios tape exec:
tuios layout export dev > dev.tape
tuios tape exec dev.tapessh
Run TUIOS as an SSH server.
tuios ssh [flags]Flags:
--port- SSH server port (default:2222)--host- SSH server host (default:localhost)--key-path- Path to SSH host key (auto-generated if not specified)--default-session- Session name every connection lands in--ephemeral- Run standalone, with no daemon
Examples:
# Start on default port
tuios ssh
# Custom port
tuios ssh --port 8022
# Listen on all interfaces
tuios ssh --host 0.0.0.0 --port 2222
# Every client joins the same shared session
tuios ssh --default-session shared
# Each connection gets a throwaway instance, nothing persists
tuios ssh --ephemeral
# Connect from another machine
ssh -p 2222 user@hostnameWith --default-session, connecting clients attach to one named session and see each other's work, which is the pairing setup. With --ephemeral there is no daemon at all, so nothing survives disconnection and none of the session commands (ls, attach, send-keys) can reach the connection.
config
Manage TUIOS configuration.
config path
Print configuration file path.
tuios config pathconfig edit
Edit configuration in $EDITOR.
tuios config editconfig reset
Reset configuration to defaults.
tuios config resetDestructive. This overwrites your config file, including custom keybindings. Copy the file shown by tuios config path first if you want to keep it.
keybinds
View keybinding configuration. Aliases: keys, kb.
keybinds list
List all keybindings.
tuios keybinds listkeybinds list-custom
List only customized keybindings.
tuios keybinds list-customkeybinds doctor
Audit the effective bindings: keys claimed twice inside TUIOS, keys TUIOS takes from the pane, and which of those a common program wants. Every finding carries an evidence tier: certain comes from TUIOS routing, observed was read from a live pane, reference comes from a curated list of program defaults.
tuios keybinds doctor
tuios keybinds doctor --json
tuios keybinds doctor --guest nvimkeybinds explain
Everything one key does: every scope it acts in, whether the pane's program would receive it, and which common programs bind it. Same --json and --guest flags as doctor.
tuios keybinds explain ctrl+bThe same analysis is available inside the app as the keybind manager, on Ctrl+B k.
tape
Manage and run tape automation scripts.
tape play
Run a tape file in interactive mode. This always starts a visible TUI and plays the script inside it, so you can watch the automation happen. Press Ctrl+P to pause and resume.
tuios tape play <file.tape>This subcommand has no flags of its own; only the global flags apply. There is no headless or --visible option. To run a script without a new TUI, use tape exec against a daemon session.
tape validate
Validate tape file syntax.
tuios tape validate <file.tape>tape list
List all saved tape recordings.
tuios tape listtape dir
Show tape recordings directory path.
tuios tape dirtape show
Display contents of a tape file.
tuios tape show <name>tape delete
Delete a tape recording.
tuios tape delete <name>Destructive. The file is removed from the tape directory. Check tuios tape show <name> first.
tape exec
Execute a tape script against a running TUIOS session (remote execution).
tuios tape exec <file.tape> [flags]Flags:
-s, --session <name>- Target session (default: most recently active)
This allows you to run tape scripts without starting a new TUIOS instance. The script runs against an already-running daemon session. See Remote Tape Execution for details.
Remote Control Commands
Control a running TUIOS session from external scripts and tools. These commands require a daemon session to be running. They all take -s/--session and default to the most recently active session when it is omitted.
These are a convenience layer over the daemon's JSON control protocol. If you are writing more than a few calls, go to the protocol directly. tuios --skill prints the agent skill built into the binary, which documents this whole surface with examples that are tested against the command tree.
Beyond the commands documented in detail below, the layer now covers window arrangement and naming: send-text (literal text, no token splitting), new-window (with --workspace, --cwd, --no-focus, or an argv to exec), split-window, focus-window, move-window, set-window, select-workspace, list-workspaces, set-layout, list-options, wait-for, set-session-name, set-session-accent, set-workspace-name, and the agent-state group (set-agent-state, get-agent-state, explain-agent-detect, explain-agent-screen). list-themes lists every theme the daemon can apply, filterable and with --json, and import-theme converts a kitty, ghostty, alacritty, or wezterm colour scheme into a TUIOS theme file. Each accepts --help, and tuios list-verbs describes the protocol-level schema behind it.
send-keys
Send keystrokes to a TUIOS session.
tuios send-keys <keys> [flags]Flags:
-s, --session <name>- Target session (default: most recently active)-w, --window <name|id>- Target window by name or ID (default: focused window)-l, --literal- Send keys directly to terminal PTY (bypass TUIOS)-r, --raw- Treat each character as a separate key
Key Format (default mode, not --literal):
- Single keys:
i,n,Enter,Escape,Space - Key combos:
ctrl+b,alt+1,shift+Enter. Case-insensitive - Sequences: separated by a space or a comma,
"ctrl+b q"or"ctrl+b,q" - Modifiers:
ctrl,alt,shift,super,meta - Special keys:
Enter,Return,Space,Tab,Escape,Esc,Backspace,Delete,Up,Down,Left,Right,Home,End,PageUp,PageDown,F1throughF12
The PREFIX token. $PREFIX and PREFIX both expand to the configured leader key, ctrl+b by default. Use it so scripts keep working when someone rebinds their prefix:
tuios send-keys "$PREFIX q"In bash and zsh, $PREFIX inside double quotes is expanded by the shell before TUIOS sees it. Use single quotes, or the bare PREFIX spelling, to pass it through:
tuios send-keys 'PREFIX q'Window targeting. --window resolves its argument in this order, first match wins:
- Exact full ID
- The index
list-windowsprints (an all-digit target in range) - Unique ID prefix, any length
- Custom name (a name set with
RenameWindow), then window title
Names come last, so an index or ID always wins over a window that happens to be named 2. Use a full or prefixed ID when you need certainty.
--literal and --raw both disable key parsing: the string is written to the PTY as-is. tuios send-keys --literal Enter types the six letters Enter rather than pressing the key. Send the text with --literal --raw, then send Enter in a second call without those flags.
Where the keys go also depends on whether a client is attached. With a TUI attached, keys are routed through it so window-manager bindings like the prefix are honored. On a headless session there is no window manager to consult, so the parsed bytes go straight to the target PTY and prefix sequences do nothing.
Examples:
# Enter terminal mode
tuios send-keys i
# Send key combo
tuios send-keys "ctrl+b q"
# Send to specific session
tuios send-keys -s mysession Escape
# Send literal text to terminal (use --raw to prevent space splitting)
tuios send-keys --literal --raw "echo hello"
# Target a window by name, then by ID prefix
tuios send-keys --window "Server" --literal --raw "echo hello"
tuios send-keys --window a1b2c3d4 --literal "ls"capture-pane
Capture the content of a terminal pane to stdout.
tuios capture-pane [flags]Flags:
-s, --session <name>- Target session-w, --window <name|id>- Target window by name or ID-S, --scrollback- Include full scrollback history (not just visible screen)--ansi- Preserve ANSI escape codes (colors, styles)
Examples:
# Capture focused window
tuios capture-pane
# Capture specific window with scrollback
tuios capture-pane -w mywindow --scrollback
# Pipe to file with colors
tuios capture-pane --ansi > pane.txtscreenshot
Render a pane to a styled image file. Where capture-pane gives you the text, screenshot gives you the picture.
tuios screenshot [flags]The image is drawn from the pane's own cells, so colours, styles and links are exact. A frame is drawn around it: padding, a wash derived from the theme, rounded corners, a shadow and a title bar. Every part of that frame is a [screenshot] config option, and each has a flag here that overrides it for one call. See the screenshot table.
The daemon renders the file, so this works on a detached session with nobody attached.
Flags:
-s, --session <name>- Target session-w, --window <name|id>- Target window by name or ID-f, --format <format>-png,svg,ansi,htmlortxt--frame <style>- Dressing around the capture:window,plainornone--theme <name>- Render in this theme instead of the session's-o, --out <path>- Write here instead of a generated name-S, --scrollback- Put the pane's history above the screen--lines <n>- Bound the history to the last N rows--cursor- Draw the cursor cell--copy/--no-copy- Try, or do not try, to copy the image to the clipboard--json- Output result as JSON
Examples:
# The focused window, as a PNG under screenshot.directory
tuios screenshot
# A named window on a named session, detached is fine
tuios screenshot -s work -w build
# With history above the screen
tuios screenshot --scrollback --lines 200
# An SVG for a README
tuios screenshot --format svg --out demo.svg
# Re-render in another palette
tuios screenshot --theme catppuccin_mochapng and svg carry the frame. ansi and txt are the bare stream, and the frame options do not apply to them.
Basic colours are a guess without a theme
With no theme set, basic and indexed colours fall back to the xterm defaults, because only your terminal knows its own palette. The result says so. Use --theme to render in a named palette instead.
The --json object carries path, host, format, cols, rows, bytes, copied, and a warnings array.
run-command
Execute a TUIOS command (same commands available in tape scripts).
tuios run-command <command> [args...] [flags]Flags:
-s, --session <name>- Target session (default: most recently active)--json- Output result as JSON--list- List all available commands
Verb names are PascalCase and tuios run-command --list always prints the set the installed binary supports. The table below is that list.
Windows:
| Command | Arguments | Description |
|---|---|---|
NewWindow | [name] | Create a new terminal window |
CloseWindow | [name] | Close a window. With no name, closes the focused one |
NextWindow | Focus the next window | |
PrevWindow | Focus the previous window | |
FocusWindow | <name> | Focus a window by name |
RenameWindow | <name> or <old> <new> | Rename the focused window, or a named one |
MinimizeWindow | [name] | Minimize the focused or named window |
RestoreWindow | [name] | Restore the focused or named window |
CloseWindow <name> closes every window that matches the name, not just the first. Two windows both titled zsh are both closed. Pass no argument to close only the focused window.
Modes and layout:
| Command | Arguments | Description |
|---|---|---|
TerminalMode | Switch to terminal mode | |
WindowManagementMode | Switch to window management mode | |
ToggleTiling | Toggle tiling mode | |
EnableTiling | Enable tiling mode | |
DisableTiling | Disable tiling mode | |
SnapLeft | Snap the focused window to the left half | |
SnapRight | Snap the focused window to the right half | |
SnapFullscreen | Snap the focused window to fullscreen | |
Split | horizontal or vertical | Split the focused window |
RotateSplit | Rotate the split direction | |
EqualizeSplits | Reset all split ratios to equal |
Workspaces:
| Command | Arguments | Description |
|---|---|---|
SwitchWorkspace | <1-9> | Switch to workspace N |
MoveToWorkspace | <1-9> | Move the focused window to workspace N |
Appearance:
| Command | Arguments | Description |
|---|---|---|
EnableAnimations | Enable UI animations | |
DisableAnimations | Disable UI animations | |
ToggleAnimations | Toggle UI animations | |
SetDockbarPosition | top, bottom, left, right | Change dockbar position |
SetBorderStyle | <style> | Change window border style |
SetTheme | <theme-name> | Change the color theme |
ShowNotification | <message> [type] | Show a notification. Type is info, success, warning, or error |
Queries:
| Command | Arguments | Description |
|---|---|---|
ListWindows | Same data as tuios list-windows | |
GetWindow | [id-or-name] | Same data as tuios get-window |
GetSessionInfo | Same data as tuios session-info |
The three query verbs are what the dedicated list-windows, get-window, and session-info commands call internally. Use the dedicated commands; they are the same request with a shorter spelling.
The two verb vocabularies are not the same. run-command takes PascalCase verbs (NewWindow, SwitchWorkspace). The daemon's JSON control protocol takes kebab-case verbs (new-window, capture-pane), and the two sets are not one-to-one. A protocol verb name will not work here, and a run-command verb name will not work there.
Examples:
# List all available commands
tuios run-command --list
# Create a new window
tuios run-command NewWindow "my-terminal"
# Get JSON output with window ID
tuios run-command --json NewWindow "dev"
# Switch workspace
tuios run-command SwitchWorkspace 2
# Split and equalize
tuios run-command Split vertical
tuios run-command EqualizeSplits
# Target specific session
tuios run-command -s mysession ToggleTilingJSON output. --json prints a result envelope with the verb's own result fields merged into the top level. There is no data wrapper:
{
"success": true,
"message": "command executed",
"window_id": "79d10b84-414e-44cf-a0f3-20ac2c1fcc48",
"name": "dev"
}So a new window's ID is at .window_id, not .data.window_id. Branch on .success, not on .message; the message is human-readable text and its wording is not a stable interface. On failure the object is {"success": false, "error": "..."} and the exit code is 1.
set-config
Change TUIOS configuration at runtime.
tuios set-config <path> <value> [flags]Flags:
-s, --session <name>- Target session (default: most recently active)
Available paths: every path in the option registry, which is well over a hundred of them. They are dotted paths under the config table they belong to, for example appearance.border_style or screenshot.format. An [appearance] option also answers to its bare name, so border_style and appearance.border_style are the same path. A path the registry does not know is refused rather than silently recorded, and the error names the nearest real path.
Do not learn the list from this page. Ask the binary, which is always in step with itself:
# Every settable path, with its type, default and accepted values
tuios list-options
# One group
tuios list-options --section sidebar
# Everything under a path
tuios list-options appearance.sidebar.
# Machine-readable, for a script or an agent
tuios list-options --json | jq -r '.options[].path'The same registry drives the in-app settings page, so an option an agent can set is an option a person can reach.
Examples:
tuios set-config appearance.dockbar_position top
tuios set-config appearance.border_style rounded
tuios set-config appearance.animations_enabled false
tuios set-config appearance.sidebar.enabled trueThe command's own help is out of date
tuios set-config --help lists four paths and gets two of them wrong. It says dockbar_position takes left and right, which it does not, and it names animations with a toggle value, which is not a registry path at all. The real option is appearance.animations_enabled, and it is a plain boolean. Those four are also not the whole set. tuios list-options is the accurate surface.
Four things set-config cannot reach, because they are maps of named tables rather than scalars with a single settable value: [keybindings], [hooks], [hosts], and the [dock] component lists. Those are file edits. dock.clock.format is the one [dock] key that is a scalar, and it is in the registry.
get-config
Read back a session option previously set with set-config.
tuios get-config <path> [flags]Flags:
-s, --session <name>- Target session (default: most recently active)
tuios get-config border_styleOptions are stored in daemon-owned state, so this works whether or not a TUI client is attached. It reports the option's recorded value, which is not necessarily what a running client is drawing if the client was started with a conflicting flag.
list-verbs
List the JSON control-protocol verbs the daemon supports, with their parameters and an example call.
tuios list-verbs [verb] [flags]Flags:
--json- Output as JSON
# Every verb with its parameters
tuios list-verbs
# Just one verb
tuios list-verbs capture-pane
# Machine-readable, for a script or an agent
tuios list-verbs --jsonThese are the kebab-case protocol verbs, a different set from the PascalCase run-command verbs above. The output is generated from the daemon's own verb registry, so it describes the binary you are running rather than a document that can drift. See Control Protocol.
list-options
List every configuration path set-config accepts, with its type, default, accepted values and description, grouped by section.
tuios list-options [prefix] [flags]Flags:
-s, --session <name>- Target session--section <name>- Only options in this group, for examplesidebarordock--json- Output as JSON
# Everything that can be set
tuios list-options
# One group
tuios list-options --section sidebar
# Everything under a path
tuios list-options appearance.sidebar.
# Machine-readable, for an agent or a script
tuios list-options --json | jq -r '.options[].path'Use it to find a path instead of guessing one. Where the session carries an override, the override is shown beside the default. Each JSON row has path, type, section, description and default, plus accepted, min, max, deprecated and session_value where they apply.
list-glyphs
List the glyph sets, and describe one. A glyph set decides the shape of the chrome the way a theme decides its colour. See Glyph sets.
tuios list-glyphs [set] [flags]Flags:
-s, --session <name>- Target session--json- Output as JSON
# Every set, and where custom ones live
tuios list-glyphs
# What this set actually draws
tuios list-glyphs heavy
# The roles a set asked for and did not get
tuios list-glyphs mine --json | jq -r '.problems[]?'With no argument it lists the sets, the active one, the glyphs directory, and every role name. With a set named, it prints role by role what the set names and what is drawn for it, so an inherited or dropped glyph is visible.
Inspection Commands
Query the state of a running TUIOS session. These commands are designed for scripting and return structured data.
No TUI Required: Inspection commands (list-windows, get-window, session-info) query the daemon's stored state directly and work even when no TUI client is attached to the session. This makes them ideal for background scripting and monitoring.
list-windows
List all windows in a TUIOS session. The table prints index, ID, name, workspace, size, and the detected agent, and the index it prints is accepted by -w everywhere a window target is taken.
tuios list-windows [flags]Flags:
-s, --session <name>- Target session (default: most recently active)--json- Output as JSON
Examples:
# Table format
tuios list-windows
# JSON for scripting
tuios list-windows --json
# Query specific session
tuios list-windows -s mysession --jsonJSON Output:
{
"success": true,
"message": "command executed",
"windows": [
{
"window_id": "79d10b84-414e-44cf-a0f3-20ac2c1fcc48",
"index": 0,
"title": "Terminal 79d10b84",
"display_name": "dev",
"custom_name": "dev",
"workspace": 1,
"focused": true,
"minimized": false,
"x": 0,
"y": 0,
"width": 120,
"height": 40,
"pty_id": "5643204f-ec1d-49d9-9385-ded247ba75cb"
}
],
"total": 1,
"focused_index": 0,
"focused_window_id": "79d10b84-414e-44cf-a0f3-20ac2c1fcc48",
"current_workspace": 1,
"workspace_windows": [1, 0, 0, 0, 0, 0, 0, 0, 0]
}Notes on the shape:
- The identifier field is
window_id, a full UUID. There is noid. - The top-level focused pointer is
focused_window_id. There is nofocused_id. custom_nameis present only on windows that have been renamed.display_nameis always present and is the custom name when set, the title otherwise.workspace_windowsis a per-workspace window count, indexed from workspace 1 at position 0.successandmessageare the result envelope every remote command shares.
get-window
Get detailed information about a specific window.
tuios get-window [id-or-name] [flags]Arguments:
id-or-name- Window ID or custom name. If omitted, returns the focused window.
Flags:
-s, --session <name>- Target session (default: most recently active)--json- Output as JSON
Examples:
# Get focused window
tuios get-window --json
# Get specific window by name
tuios get-window dev --json
# Get window by ID
tuios get-window a1b2c3d4 --json
# Query specific session
tuios get-window -s mysession --jsonJSON Output: the same window object list-windows emits, flattened into the result envelope rather than nested.
{
"success": true,
"message": "command executed",
"window_id": "79d10b84-414e-44cf-a0f3-20ac2c1fcc48",
"index": 0,
"title": "Terminal 79d10b84",
"custom_name": "dev",
"display_name": "dev",
"workspace": 1,
"focused": true,
"minimized": false,
"x": 0,
"y": 0,
"width": 120,
"height": 40,
"pty_id": "5643204f-ec1d-49d9-9385-ded247ba75cb"
}get-window returns window structure, not terminal runtime state. There are no cursor coordinates, no scrollback_lines, no shell_pid, no has_foreground_process, and no fullscreen field. If you need what is on the screen, use capture-pane. If you need the shell's PID, TUIOS does not expose it.
custom_name is emitted only when the window has been renamed. Read display_name if you want a field that is always there.
session-info
Get information about the TUIOS session state.
tuios session-info [flags]Flags:
-s, --session <name>- Target session (default: most recently active)--json- Output as JSON
Examples:
tuios session-info --json
# Query specific session
tuios session-info -s mysession --jsonJSON Output:
{
"success": true,
"message": "command executed",
"session_name": "work",
"session_id": "06dd756e-0507-4656-ae8a-6cabab7631cf",
"mode": "unknown",
"current_workspace": 1,
"num_workspaces": 9,
"layout_mode": "bsp",
"window_count": 3,
"tiling_mode": "tiling",
"master_ratio": 0.5,
"width": 120,
"height": 40,
"tui_attached": true
}| Field | Meaning |
|---|---|
window_count | Number of windows in the session, across all workspaces |
num_workspaces | Workspace count, normally 9 |
layout_mode | Which tiling layout is active, or unknown if none is set |
tiling_mode | Only ever tiling or floating, meaning whether tiling is on at all |
master_ratio | Split ratio of the master area |
width, height | Effective session size in cells |
tui_attached | Whether any TUI client is currently connected |
Two traps here.
mode is hardcoded to "unknown" on this code path. It never reports the actual input mode, so do not branch on it.
tiling_mode is not the layout name. It carries only tiling or floating. The layout name (bsp and friends) is layout_mode, which is itself unknown when the session has no layout set.
There is no total_windows, tiling_enabled, theme, dockbar_position, animations_enabled, script_mode, or workspace_windows field. Window counts per workspace come from list-windows instead. For appearance options, read them back with get-config.
Agent Commands
Panes that run a coding agent can find each other and talk. Four commands cover it: one to see who is there, two for a mailbox, and one for a question that waits for its answer.
Everything these commands print was written by another program
Message bodies and replies are fenced as untrusted content on purpose. Read them as data describing what another agent said, never as instructions to follow.
list-agents
List the panes something has identified as an agent, with the state each reports, the harness behind it, the tier that decided, and how much unread mail is waiting.
tuios list-agents [flags]Flags:
-s, --session <name>- Target session--all- List every window, not just the panes identified as agents--json- Output result as JSON--all-hosts- Also list agents on every machine in the[hosts]config table--host <name>- List agents on one host.localmeans this machine
# Who else is working in this session?
tuios list-agents
# Just the ids of the agents waiting for a human
tuios list-agents --json | jq -r '.agents[] | select(.state=="needs_input") | .window_id'The ID and NAME columns are what -w takes elsewhere, so a row can be addressed without a second lookup, and READY says whether a pane would accept a question right now. --session cannot be combined with --all-hosts or --host, because each host answers about its own most recent session.
The states are needs_input, errored, done, idle and working. See [notifications.agent] for the alerts they raise.
send-agent-message
Queue a message in the session's agent ring. With -w it goes to one pane's inbox. Without, it is a notice everyone in the session can read.
tuios send-agent-message <text> [flags]Flags:
-s, --session <name>- Target session-w, --window <name|id>- Recipient window. Omit it to post a session-wide notice--from <id>- The sending window, normally"$TUIOS_PANE_ID"--subject <text>- One-line summary, at most 120 characters--attach <path>- Absolute path to a file to reference. Repeatable, at most 8--json- Output result as JSON
# Tell the pane named build that the branch is ready
tuios send-agent-message -w build --from "$TUIOS_PANE_ID" 'rebased onto main, please retest'
# Post a notice nobody owns
tuios send-agent-message 'deploying in five minutes'
# Hand another agent an image the queue will not copy
tuios send-agent-message -w review --attach /tmp/flame.png 'the hot path is in decode'It does not touch the recipient's keyboard, which is the point: a message can be left for an agent that is mid-turn, and it is there when that agent next reads its inbox. Nothing delivers it for you, so the recipient has to be one that checks. For an agent that does not, use ask-agent.
The ring is bounded and it is not durable
Messages die with the daemon. A full ring drops its oldest. A message to a window that has since closed reads back undeliverable rather than being handed to whatever pane takes its name.
read-agent-messages
Read the session's agent ring.
tuios read-agent-messages [flags]Flags:
-s, --session <name>- Target session-w, --window <name|id>- Read this window's inbox, normally"$TUIOS_PANE_ID"--unread- Only messages nobody has read yet--notices- Include session-wide notices in an inbox read--peek- Read without marking anything read--limit <n>- Return at most this many, newest last. Default 20--json- Output result as JSON
# My unread mail
tuios read-agent-messages -w "$TUIOS_PANE_ID" --unread
# Everything said in this session lately, without marking anything read
tuios read-agent-messages --limit 50
# Look at my inbox without consuming it
tuios read-agent-messages -w "$TUIOS_PANE_ID" --peekWith -w it reads that pane's inbox and marks what it returns as read. Without, it reads everything and marks nothing, so looking around never empties someone else's mailbox.
ask-agent
Wait until the target agent is not mid-turn, type the question into its pane, wait until it has dealt with it, and print what the pane produced in between.
tuios ask-agent <text> [flags]Flags:
-s, --session <name>- Target session-w, --window <name|id>- The agent to ask.list-agentsfinds it--from <id>- The asking window. Omitting it gives up loop detection--ready-timeout <ms>- Wait this long for the target to stop working. Default 30000--settle <ms>- Silence that counts as finished, for a pane that reports no state. Default 2000--timeout <ms>- Wait this long for the answer overall. Default 300000--lines <n>- Cap the reply to this many lines. Default 200--force- Send without waiting for the target to be ready--json- Output result as JSON
# Ask the reviewer pane a question and wait for it
tuios ask-agent -w review --from "$TUIOS_PANE_ID" 'does the retry path look right to you?'
# A slow question, with a longer overall budget
tuios ask-agent -w review --timeout 900000 'please review the whole diff and summarise the risks'This is the difference between typing at a pane and asking an agent a question. The honest signal that a message landed is the target's state returning to rest, so that is what is waited on. A pane that reports no state falls back to going quiet for --settle. The answer says which of the two ended the wait.
Two things it will not do. It will not type at an agent that is working, which is what --force overrides, at the cost of interleaving with whatever the target is doing. And it will not open an ask that closes a loop with one already in flight, so B cannot ask A back while A is still blocked on B.
Remote Hosts
TUIOS can ask other machines what they are running. This is the first stage of federation and it is deliberately small.
Listings only
Nothing on another machine can be started, changed or stopped from here. You cannot create a session on a remote host, attach to one, send it keys, or kill it. The daemon has no verb that would let it. To work on another machine, ssh to it and run TUIOS there.
hosts
List the machines in the [hosts] config table and the state of each link.
tuios hosts [flags]Flags:
--json- Output as JSON
The daemon holds one ssh link to each configured host. This command shows what state each link is in, which TUIOS version the far side runs, and which control protocol it speaks.
| Status | Meaning |
|---|---|
up | The link is open and the remote daemon answers |
no_daemon | The machine is up and no TUIOS daemon runs on it |
unreachable | The last attempt failed. The line below the table says why |
incompatible | The remote daemon speaks a control protocol this build does not serve. Upgrade TUIOS on one of the two machines |
connecting | The first attempt has not finished yet |
To add a host, edit the config file and restart the daemon. See the hosts table.
[hosts.build]
addr = "gaurav@buildbox"The daemon runs ssh with BatchMode on, so a link never asks for a password and never asks about a host key. Ssh to the host once by hand to accept its key.
Once a host is configured, ls and list-agents take --all-hosts and --host.
# Every session on every machine
tuios ls --all-hosts
# The agents on one machine
tuios list-agents --host buildupdate
Replace this TUIOS with the newest published release.
tuios update [flags]Flags:
--check- Report what would be installed and change nothing--pre- Count a prerelease as the newest release
# See whether there is a newer release, without installing it
tuios update --check
# Install it
tuios update
# Include prereleases
tuios update --check --preThis only updates a binary that came from a release archive, which is what the install script downloads. Every other way of installing TUIOS has something that owns the file: a package manager, Homebrew, the Nix store, or the Go tool. update refuses to write over those and prints the command that does update them, because overwriting one leaves its records describing a file that is no longer there.
tuios-web is updated at the same time when it sits beside tuios. The two talk to one daemon and it compares their versions, so they move together or not at all.
Every download is checked against the release's published checksum. A file that does not match is discarded and nothing is installed.
The daemon keeps running the old build until it is restarted. The command says what to do about that when it finishes.
completion
Generate shell completion scripts.
tuios completion [bash|zsh|fish|powershell]Examples:
# Bash
tuios completion bash > /etc/bash_completion.d/tuios
# Zsh
tuios completion zsh > "${fpath[1]}/_tuios"
# Fish
tuios completion fish > ~/.config/fish/completions/tuios.fish
# PowerShell
tuios completion powershell > tuios.ps1Scripting Examples
The remote control and inspection commands are enough for shell scripting. Three field names carry most of the mistakes: window IDs are .window_id, the focused window is .focused_window_id, and the window count is .window_count.
Create a Development Layout
#!/bin/bash
set -euo pipefail
# Create windows and capture their IDs. run-command --json flattens result
# fields to the top level, so the ID is .window_id and not .data.window_id.
EDITOR_ID=$(tuios run-command --json NewWindow "editor" | jq -r '.window_id')
TERM_ID=$(tuios run-command --json NewWindow "terminal" | jq -r '.window_id')
LOGS_ID=$(tuios run-command --json NewWindow "logs" | jq -r '.window_id')
# Enable tiling. EnableTiling is idempotent; ToggleTiling is not
tuios run-command EnableTiling
# Send commands to each window in turn
tuios run-command FocusWindow "$EDITOR_ID"
tuios send-keys --literal --raw "nvim ."
tuios send-keys Enter
tuios run-command FocusWindow "$LOGS_ID"
tuios send-keys --literal --raw "tail -f /var/log/system.log"
tuios send-keys Enter
tuios run-command FocusWindow "$TERM_ID"Prefer EnableTiling and DisableTiling over ToggleTiling in scripts. A toggle depends on the state you happened to start in, so rerunning the script produces the opposite result.
Interactive Window Selector with fzf
#!/bin/bash
WINDOW=$(tuios list-windows --json | \
jq -r '.windows[] | "\(.display_name)\t\(.window_id)"' | \
fzf --with-nth=1 | \
cut -f2)
if [ -n "$WINDOW" ]; then
tuios run-command FocusWindow "$WINDOW"
fiWait for Window Count
#!/bin/bash
while true; do
WINDOW_COUNT=$(tuios session-info --json | jq '.window_count')
if [ "$WINDOW_COUNT" -ge 3 ]; then
echo "Ready with $WINDOW_COUNT windows"
break
fi
sleep 0.5
doneA poll loop like this one is what the control protocol's wait-for verb exists to replace. If you are writing anything that has to wait on session state, do it over the control protocol instead of sleeping.
Beyond the CLI
Each CLI invocation opens its own connection to the daemon, runs one request, and exits. That is fine for a handful of calls and wasteful for a loop. It also flattens almost every failure into exit code 1, with the reason only in text on stderr. Only a missing daemon gets a code of its own.
For anything larger, talk to the daemon directly. It speaks a line-oriented JSON protocol on the same socket, with structured error codes, blocking waits, and a subscribable event stream. See Control Protocol, and run tuios list-verbs to get the schema from the binary itself.
Environment Variables
TUIOS_DEBUG_INTERNAL
Enable internal debug logging (same as --debug flag).
export TUIOS_DEBUG_INTERNAL=1
tuiosEDITOR / VISUAL
Set editor for tuios config edit.
export EDITOR=vim
tuios config editXDG_CONFIG_HOME
Override config directory location.
export XDG_CONFIG_HOME=~/.custom_config
tuios config pathCOLORTERM
Enable true color support (usually set automatically).
export COLORTERM=truecolorGraphics Environment Variables
Control graphics protocol support (experimental features):
# Kitty graphics protocol
export TUIOS_KITTY_GRAPHICS=1 # Force enable
export TUIOS_KITTY_GRAPHICS=0 # Force disable
# Sixel graphics protocol
export TUIOS_SIXEL_GRAPHICS=1 # Force enable
export TUIOS_SIXEL_GRAPHICS=0 # Force disable
# Debug logging for graphics
export TUIOS_DEBUG_CAPS=1 # Log capability detection to /tmp/tuios_caps.logExperimental
Graphics support is experimental. Bugs are expected. Use environment variables to force enable/disable if auto-detection doesn't work correctly for your terminal.
Exit Codes
0- Success1- Error: command failed, invalid arguments, session or window not found3- No daemon is reachable
There are two failure codes, and only one of them is specific. 3 means the command needed a daemon and could not find one. Every command that talks to the daemon returns it, and tuios ls uses it deliberately: with no daemon it lists the sessions saved on disk, marks them saved, and exits 3, so a script can tell a stopped daemon from a running daemon holding nothing, which exits 0 with an empty list.
tuios ls --json > sessions.json
case $? in
0) echo "daemon up" ;;
3) echo "daemon down, listing is from disk" ;;
*) echo "failed" ;;
esacls is also the only command that still prints valid JSON on the no-daemon path. Every other command fails before it reaches its own --json branch, so it writes a plain-text explanation to stderr and exits 3 even when you asked for JSON.
Everything else is 1. The CLI does not distinguish "no such session" from "bad argument" by exit status, and with --json the reason is in the error field rather than the status. If your script needs to tell those cases apart, use the control protocol, which returns structured error codes.
Examples
Run with custom theme and border
tuios --theme dracula --border-style thickDaemon mode workflow
# Create a new session
tuios new work
# ... do some work, then detach with Ctrl+B d ...
# List sessions
tuios ls
# Reattach later
tuios attach work
# Kill when done
tuios kill-session workStart SSH server for remote access
tuios ssh --host 0.0.0.0 --port 2222Run tape automation
# In a fresh TUI you can watch
tuios tape play examples/demo.tape
# Against a session that is already running
tuios tape exec examples/demo.tapeEdit configuration
tuios config editList custom keybindings
tuios keybinds list-custom