Scriptable

rbterm API

Drive a running rbterm from the shell. Open tabs, split panes, type into a session, read the screen back as text or with full colour, recolor, resize, screenshot, and automate it all — over a private local socket, or an in-band escape sequence that needs nothing but the terminal itself, so it works even across SSH. Off by default; opt in when you want it.

What it is

Every running rbterm can expose a control channel. A tiny client built into the same binary — rbterm @ <command> — sends JSON commands to it and prints the reply. Commands are executed on the terminal's own main thread, so a scripted action is exactly as safe as a keystroke. The result: your terminal becomes a programmable surface you can wire into shell scripts, editor plugins, build tools, dashboards, and test suites.

# enable it once (Settings → Window → Scripting), then:
rbterm @ ls                                  # list windows / tabs / panes as JSON
rbterm @ send-text 'make && ./run\n'         # type a command into the active pane
rbterm @ get-text                            # read the pane's text back
rbterm @ screenshot --output ~/shot.png      # save a PNG of a pane
rbterm @ split --axis horizontal             # split the focused pane
rbterm @ launch --cwd ~/src htop             # new tab running a command

Enable it in Settings → Window → Scripting, or launch with --listen-on unix:/tmp/rb.sock. When enabled, rbterm exports RBTERM_LISTEN_ON into every shell it opens, so rbterm @ … inside a pane just targets its own window.

Command referenceEverything the API can do, grouped by what it touches.

Read & inspect

CommandWhat it does
lsDump every window, tab and pane as JSON — ids, titles, working directories, process ids, grid size, and any user variables.
get-textReturn a pane's on-screen text. --extent all includes scrollback; --ansi preserves colours and attributes as escape sequences.
get-colorsReturn a pane's full palette — foreground, background, cursor, and all 256 indexed colours.
screenshotRender any pane to a PNG (--output PATH) — visible or not, sized from its own grid. Pixel-accurate, no window capture.

Input

CommandWhat it does
send-textType text into a pane's input, with C-style escapes (\n \t \e \xNN).
send-keySend key chords by name — enter, ctrl+c, up, f5, alt+x, …

Windows, tabs & panes

CommandWhat it does
launch / new-tabOpen a new tab, optionally in a given --cwd and running a command.
new-window / splitSplit the focused pane (--axis vertical|horizontal).
focus-tab / focus-paneMove focus to a tab or pane by index or matcher.
close-tab / close-paneClose a tab or a single pane.
resize-paneGrow or shrink a split by an --increment.
resize-os-windowResize the OS window itself (--width, --height).

Appearance

CommandWhat it does
set-colorsRecolor a pane live — foreground, background, cursor, or any colorN.
set-tab-colorGive a tab an accent colour in the tab bar.
set-tab-title / set-window-titleRename a tab or a pane.
set-font-sizeSet the active tab's font size (absolute or +n/-n).
set-spacingAdjust padding around the grid.
set-background-opacitySet window background transparency (0.01.0).
disable-ligaturesTurn ligature shaping on or off.
scroll-windowMove the scrollback view — top, bottom, page-up, page-down, or by N lines.

Process & environment

CommandWhat it does
signal-childSend a signal (SIGTERM, SIGINT, SIGKILL, …) to a pane's process.
runRun a command and capture its output and exit code.
envSet environment variables for future shells.
set-user-varsAttach arbitrary key/value metadata to a pane — surfaced in ls and usable as a match target.
load-configReload settings from the config file.
goto-layout / actionSwitch layout (e.g. maximize the focused pane) or trigger a built-in action (next tab, clear, scroll home, …).

Targeting panesA boolean matcher picks exactly which panes a command hits.

Pass -m / --match to any command. Match on id, title, cwd, pid, num (tab index), state, or a user var — and combine them with and, or, not, and parentheses. Without a matcher, commands act on the focused pane.

rbterm @ get-text   -m '(title:vim or id:3) and not cwd:/tmp'
rbterm @ send-text  -m 'all' '\x03'          # Ctrl-C every pane
rbterm @ set-colors -m 'cwd:/var/log' background=#2a0000
rbterm @ signal-child -m 'pid:34521' SIGTERM

Two ways to connectPick automatically — no setup for the common case.

Local socket

For external scripts and other programs. rbterm listens on a per-process Unix socket with owner-only permissions. Point the client at it with --to unix:/path, or let it inherit RBTERM_LISTEN_ON. Requests and replies are length-prefixed JSON.

In-band escape sequence

For driving the terminal from inside one of its own panes — and, crucially, over SSH. The request rides a terminal escape sequence in the pane's output stream; the controlling rbterm intercepts it and writes the reply straight back. No socket, no port, nothing to forward.

The client chooses for you: it uses the socket when one is reachable, and otherwise falls back to the in-band channel of the terminal it's running in. A reader thread parses the framing; every command that touches tabs, panes or the renderer runs on the main loop — so remote commands are as safe as keypresses, and a flood of them can't corrupt state.

Encrypted & authenticatedLock the control channel to a password — end to end.

By default the control socket is owner-only and rbterm only opens it when you opt in. For anything stronger, set a remote-control password. rbterm then refuses every plain command and accepts only authenticated, encrypted ones: an ephemeral X25519 key exchange derives a shared key (hashed with SHA-256), and each command is sealed with AES-256-GCM. The password and a timestamp travel inside the encrypted payload, with a five-minute replay window and a constant-time check.

rbterm --rc-password 'hunter2'                  # or set it in the config file

# the client encrypts automatically when it has the password + key:
export RBTERM_RC_PASSWORD=hunter2
export RBTERM_PUBLIC_KEY=...                  # rbterm prints this on startup
rbterm @ ls                                   # → encrypted; plain commands are rejected
Key exchange
X25519 (ECDH)
Cipher
AES-256-GCM
Key derivation
SHA-256 of the shared secret
Replay guard
5-minute timestamp window

Test your terminal with itThe same API is rbterm's end-to-end test harness.

Because the API can both drive a pane and read it back, it doubles as a way to test the terminal itself. The bundled suite (make test) launches rbterm, feeds escape sequences through send-text, and asserts on get-text — verifying colour and attribute rendering, cursor positioning, screen erase, auto-wrap, scrollback, split/close behaviour, and live recolouring. Your own scripts can do the same.

rbterm @ send-text 'printf "\\033[1mBOLD\\033[0m\\n"\n'
rbterm @ get-text --ansi      # assert the bold SGR is present

A small exampleSpin up a working layout from a script.

#!/bin/sh
# open a build pane and a log pane side by side, then tail the log
rbterm @ launch --cwd ~/project
rbterm @ split --axis vertical
rbterm @ send-text -m 'cwd:~/project' 'make watch\n'
rbterm @ send-text -m 'all' '\n'
rbterm @ set-tab-title 'build'
rbterm @ screenshot --output ~/build-layout.png