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.
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 | What it does |
|---|---|
| ls | Dump every window, tab and pane as JSON — ids, titles, working directories, process ids, grid size, and any user variables. |
| get-text | Return a pane's on-screen text. --extent all includes scrollback; --ansi preserves colours and attributes as escape sequences. |
| get-colors | Return a pane's full palette — foreground, background, cursor, and all 256 indexed colours. |
| screenshot | Render any pane to a PNG (--output PATH) — visible or not, sized from its own grid. Pixel-accurate, no window capture. |
| Command | What it does |
|---|---|
| send-text | Type text into a pane's input, with C-style escapes (\n \t \e \xNN). |
| send-key | Send key chords by name — enter, ctrl+c, up, f5, alt+x, … |
| Command | What it does |
|---|---|
| launch / new-tab | Open a new tab, optionally in a given --cwd and running a command. |
| new-window / split | Split the focused pane (--axis vertical|horizontal). |
| focus-tab / focus-pane | Move focus to a tab or pane by index or matcher. |
| close-tab / close-pane | Close a tab or a single pane. |
| resize-pane | Grow or shrink a split by an --increment. |
| resize-os-window | Resize the OS window itself (--width, --height). |
| Command | What it does |
|---|---|
| set-colors | Recolor a pane live — foreground, background, cursor, or any colorN. |
| set-tab-color | Give a tab an accent colour in the tab bar. |
| set-tab-title / set-window-title | Rename a tab or a pane. |
| set-font-size | Set the active tab's font size (absolute or +n/-n). |
| set-spacing | Adjust padding around the grid. |
| set-background-opacity | Set window background transparency (0.0–1.0). |
| disable-ligatures | Turn ligature shaping on or off. |
| scroll-window | Move the scrollback view — top, bottom, page-up, page-down, or by N lines. |
| Command | What it does |
|---|---|
| signal-child | Send a signal (SIGTERM, SIGINT, SIGKILL, …) to a pane's process. |
| run | Run a command and capture its output and exit code. |
| env | Set environment variables for future shells. |
| set-user-vars | Attach arbitrary key/value metadata to a pane — surfaced in ls and usable as a match target. |
| load-config | Reload settings from the config file. |
| goto-layout / action | Switch layout (e.g. maximize the focused pane) or trigger a built-in action (next tab, clear, scroll home, …). |
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
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.
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.
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
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
#!/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