CLI Commands

This page lists every public rex command and flag. See The CLI for how to use them. Anything tagged Snapshot is on the snapshot channel and not yet in preview.

Common Commands

rex new [LABEL] [-- COMMAND...]

Create a session.

FlagDescription
-c, --cwd stringWorking directory for the terminal.
--keep-openKeep the terminal open after its command exits.
--shell SHELLRun COMMAND through SHELL’s login environment (none starts it directly).
--interactiveAlso read the shell’s interactive startup files, such as ~/.zshrc.
--window stringLabel for the first window.
--jsonOutput the created session as JSON.

rex ls

List sessions.

FlagDescription
--jsonOutput sessions as JSON.
-q, --quietPrint IDs only, one per line.
--shortShow short IDs (--short=false shows full IDs). Defaults to true.

rex run [flags] -- COMMAND...

Run a command in a new block.

Run a command in a new terminal block.

COMMAND runs through your login shell’s environment but not its interactive configuration, so profile variables and PATH apply and aliases do not. Use --interactive to read that configuration too, such as ~/.zshrc, for a program whose directory is added to PATH there. Use --shell to pick another shell, or --shell=none to start COMMAND directly.

By default, Rex places the block in a new window. Use --split to place it beside an existing block. Use --focus=false to preserve the active window. With --wait, Rex writes the creation result, then waits and returns the terminal child’s exit status.

FlagDescription
--split DIRECTIONPlace the new block in DIRECTION relative to the anchor (right, left, above, or below).
--ratio PCTGive the new block PCT percent of the split. Defaults to 50.
-b, --block BLOCKUse BLOCK as the split anchor (defaults to focused).
-s, --session stringScope to session SESSION.
-w, --window stringScope to window WINDOW.
-c, --cwd stringWorking directory for the terminal.
--keep-openKeep the terminal open after its command exits.
--shell SHELLRun COMMAND through SHELL’s login environment (none starts it directly).
--interactiveAlso read the shell’s interactive startup files, such as ~/.zshrc.
--label TEXTSet the new block label to TEXT.
--focusFocus the new block. Defaults to true.
--jsonOutput the creation result as JSON.
--waitWait and return the terminal child’s exit status.
rex run -- htop
rex run --wait -- go test ./...
rex run --split=below --ratio 30 -- tail -f app.log
rex run -b editor --split=left -- lazygit
rex run -s build -- make
rex run --interactive -- opencode
rex run --shell=none -- /opt/tool/bin/x

rex split [flags] [-- COMMAND...]

Split the focused block.

Create a terminal block for a shell or command.

A COMMAND runs through your login shell’s environment but not its interactive configuration. Use --interactive to read that configuration too, --shell to pick another shell, or --shell=none to start COMMAND directly.

By default, Rex splits the focused block and places the new block on its right. Use -b BLOCK to select another anchor or --split to choose another direction. Use --focus=false to preserve the current focus. With --wait, Rex writes the creation result, then waits and returns the terminal child’s exit status. Use rex run to place the block in a new window.

FlagDescription
--split DIRECTIONPlace the new block in DIRECTION relative to the anchor (right, left, above, or below). Defaults to right.
--ratio PCTGive the new block PCT percent of the split. Defaults to 50.
-b, --block BLOCKUse BLOCK as the split anchor (defaults to focused).
-s, --session stringScope to session SESSION.
-w, --window stringScope to window WINDOW.
-c, --cwd stringWorking directory for the terminal.
--keep-openKeep the terminal open after its command exits.
--shell SHELLRun COMMAND through SHELL’s login environment (none starts it directly).
--interactiveAlso read the shell’s interactive startup files, such as ~/.zshrc.
--label TEXTSet the new block label to TEXT.
--focusFocus the new block. Defaults to true.
--jsonOutput the creation result as JSON.
--waitWait and return the terminal child’s exit status.
rex split
rex split --split=below
rex split -b editor --split=left -- lazygit
rex split --wait -- make
rex split -- htop

rex do (ACTION | SCRIPT | -e CODE) [KEY=VALUE...]

Perform an action or run a Lua script.

Perform an action by name, or run a Lua script.

A name without a dot is an action init.lua defines with rex.action. A name that starts with a client prefix, such as pane.split, is performed by the targeted client. A name that starts with a block type’s creator name, such as com.superlogical.terminal.reset, is a block action or method. Run “rex actions” to list them.

To run a Lua script instead, give its path. The first argument is a script path when it contains a slash (or a backslash on Windows) or ends in .lua. Use - to read the script from stdin, or -e to give it on the command line. A script can call the same API as init.lua. Its return value prints the same way as an action’s result. In a script, rex.invoke runs the actions the script defines and asks the server to run any others.

A script can also call the hosts that “rex hosts” lists. rex.servers() returns their labels, and rex.server(LABEL) returns the same API helpers as rex, with calls going to that host. rex do connects to a host on the script’s first call to it, and stays connected until the script ends. --server chooses only the server that rex itself calls.

With --action NAME, rex do runs the script, then runs the action the script defines as NAME and prints that action’s result. Pairs are typed against that action’s schema. Use this to try an action in init.lua before the server reloads it.

A script that registers rex.on handlers keeps running after its last line, and runs its handlers as events arrive, one at a time. It hears the session that -s, -b, or the environment names, or every session if none is named. --all makes it hear every session, including ones created later. While it runs, rex.session.attach and rex.session.detach change what it hears.

Such a script runs until it calls rex.stop(CODE), and rex do exits with CODE, or 0 if it is left out. The script also stops, with status 0, when --for DURATION has passed, or when the last session it hears is destroyed, unless it hears every session. Ctrl-C stops it with status 130. A failed handler is reported and the script keeps going. With --fail-fast, the first failure exits with status 1.

Any script can pause. rex.sleep(SECONDS) waits for time to pass, and rex.wait(EVENT, FILTER, TIMEOUT) waits for an event, such as the exit of a command the script started. Nothing else in the script runs meanwhile. --for does not interrupt a pause at the top level of the script.

Arguments are KEY=VALUE pairs typed against the action’s schema. Use --args to pass a JSON object instead, or @FILE to read one, or - for stdin. A script reads its arguments from rex.args. Scripts have no schema, so each value’s type comes from how it is written: n=2 is a number and name=x is a string.

A client action needs a client. Use -C to name one, or REX_CLIENT. With neither, the app client is used when exactly one is connected. An init.lua action’s queued client actions go to the same client, and so do a script’s calls to rex.client.queue.

FlagDescription
--args JSONPass the arguments as a JSON object (@FILE, or - for stdin).
-s, --session stringScope to session SESSION.
-b, --block BLOCKApply the action to BLOCK (default: the focused block).
--origin ORIGINReport the origin as ORIGIN: key, palette, api, or cli. Defaults to cli.
-e, --eval CODERun CODE as a Lua script.
-a, --action NAMERun the action NAME that the script defines.
--allListen for events from every session.
--for DURATIONStop listening for events after DURATION.
--fail-fastExit at the first rex.on handler that fails.
--jsonPrint the result as JSON.
rex do dev_layout branch=main
rex -C studio do pane.split direction=right
rex do com.superlogical.terminal.reset
rex -C studio do client.tab.goto index=2 --json
rex do ./layout.lua branch=main
rex do - < script.lua
rex do -e 'return rex.call("session.list")' --json
rex do notify.lua --args '{"title":"done"}'
rex do watch.lua --all --for 10m
rex do ~/.config/rex/init.lua --action dev_layout branch=main

rex send [TEXT]

Send input to a terminal

FlagDescription
-b, --block stringSend to block BLOCK.
-s, --session stringScope to session SESSION.
-w, --window stringScope to window WINDOW.
rex send 'make test'
rex send -b logs $'\003'
printf 'y\n' | rex send
rex send -s build -w 2 'ls'

rex send-key KEY...

Send key presses to a terminal

Each KEY uses Rex’s key binding syntax. Join modifiers with +, as in ctrl+c or shift+left. A bracketed name such as [Slash] selects a physical key. By default, Rex sends a press followed by a release for each key. Use --action to send one action instead.

Rex interprets printable keys using a US keyboard layout because send-key does not receive physical keyboard input. The generated text and physical key may differ on other layouts. Use rex send when exact text matters.

FlagDescription
-b, --block stringSend to block BLOCK.
-s, --session stringScope to session SESSION.
-w, --window stringScope to window WINDOW.
--action ACTIONSend one ACTION for each key: press, release, or repeat.
rex send-key enter
rex send-key ctrl+c
rex send 'make test' && rex send-key enter
rex send-key -b logs ctrl+c
rex send-key shift+left shift+left
rex send-key --action release ctrl+[KeyQ]

rex capture

Print a terminal’s screen and scrollback.

Print the screen and scrollback of a terminal block.

When --block is omitted, Rex uses REX_BLOCK if it names a live block. Otherwise, it uses the focused block of the default window. Text is the default format. HTML preserves rendered styling. VT preserves terminal control sequences. Output always ends with a newline.

A terminal keeps about 64 MiB of scrollback. That is roughly 100,000 lines of plain text at 80 columns, and fewer in a wider terminal or with styled output. Once the limit is reached, the oldest lines are dropped.

FlagDescription
-b, --block BLOCKSelect block BLOCK.
-s, --session stringScope to session SESSION.
-w, --window stringScope to window WINDOW.
--format FORMATOutput FORMAT: text, html, or vt. Defaults to text.
--trimRemove trailing blank lines.
--unwrapJoin soft-wrapped lines.
rex capture
rex capture -b logs --trim > screen.txt
rex capture --format=html > screen.html
rex capture -s build -w 2

rex kill SESSION...

Kill sessions.

Layout

rex focus TARGET|DIRECTION

Focus a block or window.

The directions left, right, up, and down move between blocks by position. Next and prev move through the blocks in layout order. Focus stops at the edge of the layout or the end of the order. Use --wrap to continue from the other side.

A target can be a block or window ID, label, or ID suffix. A positive integer selects a window by its one-based position. If a target matches both a block and a window, use a full ID to select the intended resource.

FlagDescription
-s, --session stringScope to session SESSION.
-w, --window stringScope to window WINDOW.
--wrapContinue from the other side at the edge.
rex focus left
rex focus left --wrap
rex focus next --wrap
rex focus 2
rex focus logs
rex focus -s build editor

rex zoom [BLOCK]

Zoom a block to fill its window.

Zoom changes only how the block is displayed. It does not change the underlying window layout. Without --on or --off, the command toggles the current zoom state. Use --on or --off to set the state explicitly.

BLOCK may be passed as an argument or with --block. If BLOCK is omitted, Rex uses REX_BLOCK when it identifies a live block. Otherwise, Rex uses the focused block in the default window.

FlagDescription
-b, --block BLOCKSelect block BLOCK.
-s, --session stringScope to session SESSION.
-w, --window stringScope to window WINDOW.
--onEnable zoom.
--offDisable zoom.
rex zoom
rex zoom --off
rex zoom -b logs --on

rex move [BLOCK] DIRECTION ANCHOR

Move a block next to another.

Move a block next to an anchor block.

DIRECTION selects BLOCK’s new position relative to ANCHOR. It must be right, left, above, or below. The two blocks may be in different windows, but both must be visible and belong to the same session.

If BLOCK is omitted, Rex uses REX_BLOCK when it identifies a visible block. Otherwise, Rex uses the focused block in the default window. The --ratio flag sets the percentage of the resulting split assigned to BLOCK. PCT must be between 1 and 99.

If a block label is also a direction word, identify the block by its full block ID or a hexadecimal ID suffix.

FlagDescription
--ratio PCTGive the moved block PCT percent of the split. Defaults to 50.
-s, --session stringScope to session SESSION.
-w, --window stringScope to window WINDOW.
rex move below editor
rex move logs right editor --ratio 30
rex move c2a9f3 above 1bc2a9 -s work

rex swap BLOCK OTHER

Swap two blocks.

Swap the layout positions of two visible blocks.

The blocks may be in different windows, but they must belong to the same session. Rex resolves both block arguments before changing the layout. The surrounding layout is unchanged.

FlagDescription
-s, --session stringScope to session SESSION.
-w, --window stringScope to window WINDOW.
rex swap editor logs
rex swap c2a9f3 1bc2a9

rex resize [BLOCK]

Resize a block.

Resources

rex session

Manage sessions.

rex session new [LABEL] [-- COMMAND...]

Create a session.

FlagDescription
-c, --cwd stringWorking directory for the terminal.
--keep-openKeep the terminal open after its command exits.
--shell SHELLRun COMMAND through SHELL’s login environment (none starts it directly).
--interactiveAlso read the shell’s interactive startup files, such as ~/.zshrc.
--window stringLabel for the first window.
--jsonOutput the created session as JSON.

rex session ls

List sessions.

FlagDescription
--jsonOutput sessions as JSON.
-q, --quietPrint IDs only, one per line.
--shortShow short IDs (--short=false shows full IDs). Defaults to true.

rex session inspect [SESSION]

Inspect a session.

FlagDescription
--jsonOutput session information as JSON.

rex session rename [SESSION] LABEL

Rename a session.

rex session move [SESSION] (--before S | --after S | --index N)

Move a session to a new place in the session order.

The session order is the order that session ls prints. It also decides which session a number names, so after a move, “rex session inspect 1” shows whichever session is now first.

Exactly one of --before, --after, or --index is required. Positions count from one. An index past the end moves the session last. Moving a session to where it already is does nothing and succeeds.

If SESSION is omitted, Rex uses REX_SESSION when it is set. Otherwise, Rex uses the default session.

FlagDescription
--before SMove immediately before session S.
--after SMove immediately after session S.
--index NMove to one-based position N.
rex session move logs --before work
rex session move 3 --after 1
rex session move --index 1
rex session move build --index 99

rex session kill SESSION...

Kill sessions.

rex window

Manage windows.

rex window new [-s SESSION] [LABEL] [-- COMMAND...]

Create a window in the selected session. The new window becomes active by default. Use --focus=false to keep the active window and focused block unchanged. If the session has no active window, the new window becomes active even with --focus=false.

FlagDescription
-s, --session stringScope to session SESSION.
-c, --cwd stringWorking directory for the terminal.
--keep-openKeep the terminal open after its command exits.
--shell SHELLRun COMMAND through SHELL’s login environment (none starts it directly).
--interactiveAlso read the shell’s interactive startup files, such as ~/.zshrc.
--focusMake the new window active (--focus=false leaves the current window active). Defaults to true.
--jsonOutput the created window as JSON.
rex window new
rex window new logs -- tail -f app.log
rex window new logs --focus=false -- tail -f app.log
rex window new -s build tests

rex window ls

List windows.

FlagDescription
-s, --session stringScope to session SESSION.
-A, --allList windows in every session.
--jsonOutput windows as JSON.
-q, --quietPrint IDs only, one per line.
--shortShow short IDs (--short=false shows full IDs). Defaults to true.

rex window inspect [WINDOW]

Inspect a window.

FlagDescription
-s, --session stringScope to session SESSION.
--jsonOutput window information as JSON.

rex window focus [WINDOW|next|prev]

Focus a window by ID, label, position, or ID suffix.

If WINDOW is omitted, focus the window containing REX_BLOCK when available. Otherwise, focus the active window in the default session. Use next or prev to move through window order.

FlagDescription
-s, --session stringScope to session SESSION.
--wrapWrap next and prev at the ends.

rex window move [WINDOW] (--before W | --after W | --index N) [-s SESSION]

Move a window within its session’s tab order.

Exactly one of --before, --after, or --index is required. Window positions are numbered from one in the same order shown by window ls. An index past the end moves the window last.

If WINDOW is omitted, Rex uses the window containing REX_BLOCK when available. Otherwise, Rex uses the active window in the default session.

FlagDescription
--before WMove immediately before window W.
--after WMove immediately after window W.
--index NMove to one-based position N.
-s, --session stringScope to session SESSION.
rex window move logs --before editor
rex window move 3 --after 1
rex window move --index 1
rex window move -s work build --index 99

rex window rename [WINDOW] LABEL

Rename a window.

FlagDescription
-s, --session stringScope to session SESSION.

rex window close WINDOW...

Close windows.

FlagDescription
-s, --session stringScope to session SESSION.

rex block

Manage blocks.

rex block new FLAVOR

Create a block.

rex block ls

List blocks.

FlagDescription
-s, --session stringScope to session SESSION.
-w, --window stringScope to window WINDOW.
-A, --allList blocks in every session.
--jsonOutput blocks as JSON.
-q, --quietPrint IDs only, one per line.
--shortShow short IDs (--short=false shows full IDs). Defaults to true.

rex block inspect [BLOCK]

Inspect a block.

FlagDescription
-s, --session stringScope to session SESSION.
-w, --window stringScope to window WINDOW.
--jsonOutput block information as JSON.

rex block focus [BLOCK]

Focus a block by ID, label, or ID suffix.

If BLOCK is omitted, focus the block named by REX_BLOCK when available. Otherwise, focus the current block in the default window.

FlagDescription
-s, --session stringScope to session SESSION.
-w, --window stringScope to window WINDOW.

rex block types

List block types.

FlagDescription
--jsonOutput block types as JSON.

rex block send [TEXT]

Send input to a terminal

FlagDescription
-b, --block stringSend to block BLOCK.
-s, --session stringScope to session SESSION.
-w, --window stringScope to window WINDOW.
rex send 'make test'
rex send -b logs $'\003'
printf 'y\n' | rex send
rex send -s build -w 2 'ls'

rex block send-key KEY...

Send key presses to a terminal

Each KEY uses Rex’s key binding syntax. Join modifiers with +, as in ctrl+c or shift+left. A bracketed name such as [Slash] selects a physical key. By default, Rex sends a press followed by a release for each key. Use --action to send one action instead.

Rex interprets printable keys using a US keyboard layout because send-key does not receive physical keyboard input. The generated text and physical key may differ on other layouts. Use rex send when exact text matters.

FlagDescription
-b, --block stringSend to block BLOCK.
-s, --session stringScope to session SESSION.
-w, --window stringScope to window WINDOW.
--action ACTIONSend one ACTION for each key: press, release, or repeat.
rex send-key enter
rex send-key ctrl+c
rex send 'make test' && rex send-key enter
rex send-key -b logs ctrl+c
rex send-key shift+left shift+left
rex send-key --action release ctrl+[KeyQ]

rex block capture

Print a terminal’s screen and scrollback.

Print the screen and scrollback of a terminal block.

When --block is omitted, Rex uses REX_BLOCK if it names a live block. Otherwise, it uses the focused block of the default window. Text is the default format. HTML preserves rendered styling. VT preserves terminal control sequences. Output always ends with a newline.

A terminal keeps about 64 MiB of scrollback. That is roughly 100,000 lines of plain text at 80 columns, and fewer in a wider terminal or with styled output. Once the limit is reached, the oldest lines are dropped.

FlagDescription
-b, --block BLOCKSelect block BLOCK.
-s, --session stringScope to session SESSION.
-w, --window stringScope to window WINDOW.
--format FORMATOutput FORMAT: text, html, or vt. Defaults to text.
--trimRemove trailing blank lines.
--unwrapJoin soft-wrapped lines.
rex block capture
rex block capture -b logs --trim > screen.txt
rex block capture --format=html > screen.html
rex block capture -s build -w 2

rex block zoom [BLOCK]

Zoom a block to fill its window.

Zoom changes only how the block is displayed. It does not change the underlying window layout. Without --on or --off, the command toggles the current zoom state. Use --on or --off to set the state explicitly.

BLOCK may be passed as an argument or with --block. If BLOCK is omitted, Rex uses REX_BLOCK when it identifies a live block. Otherwise, Rex uses the focused block in the default window.

FlagDescription
-b, --block BLOCKSelect block BLOCK.
-s, --session stringScope to session SESSION.
-w, --window stringScope to window WINDOW.
--onEnable zoom.
--offDisable zoom.
rex block zoom
rex block zoom --off
rex block zoom -b logs --on

rex block move [BLOCK] DIRECTION ANCHOR

Move a block next to another.

Move a block next to an anchor block.

DIRECTION selects BLOCK’s new position relative to ANCHOR. It must be right, left, above, or below. The two blocks may be in different windows, but both must be visible and belong to the same session.

If BLOCK is omitted, Rex uses REX_BLOCK when it identifies a visible block. Otherwise, Rex uses the focused block in the default window. The --ratio flag sets the percentage of the resulting split assigned to BLOCK. PCT must be between 1 and 99.

If a block label is also a direction word, identify the block by its full block ID or a hexadecimal ID suffix.

FlagDescription
--ratio PCTGive the moved block PCT percent of the split. Defaults to 50.
-s, --session stringScope to session SESSION.
-w, --window stringScope to window WINDOW.
rex block move below editor
rex block move logs right editor --ratio 30
rex block move c2a9f3 above 1bc2a9 -s work

rex block swap BLOCK OTHER

Swap two blocks.

Swap the layout positions of two visible blocks.

The blocks may be in different windows, but they must belong to the same session. Rex resolves both block arguments before changing the layout. The surrounding layout is unchanged.

FlagDescription
-s, --session stringScope to session SESSION.
-w, --window stringScope to window WINDOW.
rex block swap editor logs
rex block swap c2a9f3 1bc2a9

rex block stream BLOCK [DATA_REF]

Stream block data.

rex block call METHOD [ARGS]

Call a block method.

Call one method exposed by a block.

METHOD is the block method name. ARGS must be a JSON object. Pass the object directly, use @path to read it from a file, or use - to read it from stdin. When ARGS is omitted, the request sends no arguments.

When --block is omitted, Rex uses REX_BLOCK if it names a live block. Otherwise, it uses the focused block of the default window.

Method results are JSON. Output written to a terminal uses two-space indentation. Redirected output stays on one line for use in scripts. Use rex block inspect to list methods and rex block inspect --json to view their schemas.

FlagDescription
-b, --block BLOCKSelect block BLOCK.
-s, --session stringScope to session SESSION.
-w, --window stringScope to window WINDOW.
rex block call process
rex block call -b c2a9f3 write '{"data":"ls\n"}'
rex block call -b logs format @request.json
echo '{"format":"text","trim":true}' | rex block call format -

rex block rename [BLOCK] LABEL

Rename a block.

FlagDescription
-s, --session stringScope to session SESSION.
-w, --window stringScope to window WINDOW.

rex block close BLOCK...

Close blocks.

FlagDescription
-s, --session stringScope to session SESSION.
-w, --window stringScope to window WINDOW.

rex client

Manage clients.

Inspect the clients connected to the server.

A client is one program connected to the server, such as Rex.app or this command. Each client says what it is when it connects, and a person may give it a label.

rex client ls

List clients.

List the clients connected to the server.

Each client says what it is when it connects. The label is the name a person gave it, and two clients may share one. Command line clients such as this one are hidden unless --all is given. With --json, the output is the server’s full reply, including command line clients. Use -s to list only the clients attached to one session.

FlagDescription
-s, --session stringScope to session SESSION.
--allInclude command line clients.
--jsonOutput clients as JSON.
-q, --quietPrint IDs only, one per line.
--shortShow short IDs (--short=false shows full IDs). Defaults to true.
rex client ls
rex client ls -s work
rex client ls --all
rex client ls -q

rex client inspect [CLIENT]

Inspect a client.

Show one client and the actions it offers.

CLIENT is a client ID, label, or ID suffix. With no CLIENT, -C or REX_CLIENT names the client, and otherwise the app client is used when exactly one is connected.

FlagDescription
--jsonOutput the client and its actions as JSON.
rex client inspect studio
rex client inspect 3f9a
rex client inspect --json

Automation

rex events

Stream server events as they occur.

Without --session, events follows session creation, removal, state changes, and server connectivity for the whole server. Use --session to follow one session, including custom events emitted by its blocks. Use --all to follow every server event, including clients joining, leaving, and changing.

The default format writes one human-readable line per event. With --json, each line contains the same event JSON object sent by the server, compacted onto one line. Output is flushed after every event so pipelines can process events as they arrive.

The command runs until interrupted or the server disconnects. --timeout limits connecting and starting event delivery. It does not limit how long events are streamed.

FlagDescription
-s, --session stringScope to session SESSION.
--allFollow every server event, including clients joining, leaving, and changing.
--jsonOutput events as newline-delimited JSON.
rex events
rex events -s build
rex events --all
rex events --json | jq -c 'select(.type == "session_created")'

rex wait TARGET

Wait for a block, window, or session to end.

For a terminal block, wait returns the child process’s exit status. It does not wait for the block itself to close, so it also works with terminals created with --keep-open. Waiting for any other block, a window, or a session succeeds when that resource closes or is destroyed. If a terminal closes before reporting a child exit, wait returns 1.

By default, wait runs until the target ends or the server disconnects. Use --for to limit the wait. The global --timeout still limits connections and individual API requests, but it does not limit event delivery. With --json, the command writes the payload that ended the wait as one line of JSON.

If Rex cannot determine a terminal child’s exit status, wait returns 1. Statuses above 255 are reduced modulo 256 to match shell behavior.

Targets may be IDs, labels, ID suffixes, or a window’s one-based position. If a target matches more than one resource kind, use a full ID to select the intended resource.

FlagDescription
-s, --session stringScope to session SESSION.
-w, --window stringScope to window WINDOW.
--for DURATIONGive up after DURATION.
--jsonOutput the terminating payload as JSON.
rex wait c2a9f3
rex wait build
rex wait 2 -s work
rex wait --for 10m $B || echo timed out

rex api

Inspect and call the server API.

Inspect and call methods exposed by the server’s control API.

Use call to run a method by name. Use list to discover the methods exposed by the connected server, including methods provided by block creators. Use describe to read one method’s schemas, examples, and validation rules.

rex api call server.status
rex api call -s work session.view
rex api list
rex api describe session.new_split

rex api call METHOD [ARGS]

Call a server API method.

Call one method exposed by the server’s control API.

METHOD is the API method name, such as server.status. ARGS must be a JSON object. Pass the object directly, use @path to read it from a file, or use - to read it from stdin. When ARGS is omitted, the request sends no arguments.

Methods that take a session_id require the connection to attach to that session. Use --session to resolve a session by ID or label and attach before the request. The command adds session_id to ARGS when it is missing. If ARGS already contains session_id, the value is preserved and must match the selected session. Without --session, a top-level session_id in ARGS is used for the attachment.

Method results are JSON. Output written to a terminal uses two-space indentation. Redirected output stays on one line for use in scripts.

FlagDescription
-s, --session stringScope to session SESSION.
rex api call server.status
rex api call -s work session.view | jq '.windows | length'
rex api call session.create @layout.json
echo '{"label":"x"}' | rex api call session.create -

rex api list

List server API methods.

List methods exposed by the connected server.

The default output has separate tables for regular API methods and methods provided by block creators. Use --quiet to print only method names, one per line. Use --json to print the complete help document returned by the server.

FlagDescription
-q, --quietPrint method names only.
--jsonOutput the API help document as JSON.

rex api describe METHOD

Describe a server API method.

Describe one method exposed by the connected server.

The default output includes the method’s description and any available schemas, examples, and validation rules. Use --json to print the method’s entry from the server’s help document.

FlagDescription
--jsonOutput the method description as JSON.

rex actions

List the actions a client or the server offers.

List the actions that a client or the server offers.

With -C or REX_CLIENT, this lists the actions that client offers, as it most recently reported them to the server. Otherwise it lists the actions the server offers: those that init.lua defines with rex.action, followed by those of every block type. A key binding can name any action in either list.

The ARGS column lists each action’s arguments. An argument followed by ? is optional.

FlagDescription
--jsonOutput actions as JSON.
rex actions
rex -C studio actions
rex actions --json

Server

rex server

Manage the Rex server.

rex server run

Run a foreground server.

FlagDescription
--listen ENDPOINTListen on ENDPOINT (defaults to the local Rex Unix socket).
--extra-listen ENDPOINTAlso listen on unix, http, tailnet, tailnet-serve, or login-server ENDPOINT (repeatable).
--socket-mode MODESet Unix socket permissions to MODE (owner and group bits only). Defaults to 0600.
--allow-anonymousAdmit anonymous callers on plain TCP listeners (every connection gets full access).
--tailnet-allow-identifiedAdmit every identified caller through the host’s tailscaled (default: node owner).
--tailscaled-socket PATHUse the tailscaled LocalAPI socket at PATH (default: platform socket).
--tailscale-allow-tailnet-membersAllow any tailnet member permitted by ACLs to reach Rex.
--exit-emptyStop when no sessions or control connections remain.
--websocket-origin-pattern PATTERNAllow browser WebSockets from cross-origin PATTERN (repeatable).
--block-dir DIRDiscover executable block plugins in DIR (repeatable).
--block-plugin-reloadReload block plugins after source changes.
--state-dir DIRStore persistent server state below DIR.
--restoreRestore the saved sessions (false starts without them and saves nothing). Defaults to true.
--config PATHRead the config file at PATH (default: REX_CONFIG, else rex/init.lua in the config directory).
--max-sessions NRefuse new sessions once the server holds N (0 for no limit). Defaults to 64.
--max-blocks NRefuse new blocks once the server holds N across all sessions (0 for no limit). Defaults to 1024.
--max-windows NRefuse new windows once a session holds N (0 for no limit). Defaults to 64.
--max-panes NRefuse new panes once a window holds N (0 for no limit). Defaults to 64.
--tailscaleAlso serve the API over the tailnet as an embedded tsnet node.
--tailscale-hostname NAMETailnet device NAME for --tailscale. Defaults to rex.
--tailscale-control-url URLRegister the tailnet node with the control server at URL, such as Headscale.
--tailscale-auth-key-file FILEEnroll --tailscale with the one-time auth key read from FILE (’-’ for stdin).
--tailscale-advertise-tag TAGAdvertise ACL TAG (tag:name) when --tailscale enrolls the node (repeatable).
--log-format FORMATWrite server logs as FORMAT: text or json. Defaults to text.

rex server start

Start a persistent server.

Start is idempotent. Start options apply only when a new server is launched. An existing server retains its active configuration until explicitly restarted.

The log size limit applies only to the file created for a detached server. Rex clears that file before a write would exceed --log-max-size.

FlagDescription
--extra-listen ENDPOINTAlso listen on unix, http, tailnet, tailnet-serve, or login-server ENDPOINT (repeatable).
--socket-mode MODESet Unix socket permissions to MODE (owner and group bits only). Defaults to 0600.
--allow-anonymousAdmit anonymous callers on plain TCP listeners (every connection gets full access).
--tailnet-allow-identifiedAdmit every identified caller through the host’s tailscaled (default: node owner).
--tailscaled-socket PATHUse the tailscaled LocalAPI socket at PATH (default: platform socket).
--websocket-origin-pattern PATTERNAllow browser WebSockets from cross-origin PATTERN (repeatable).
--block-dir DIRDiscover executable block plugins in DIR (repeatable).
--block-plugin-reloadReload block plugins after source changes.
--state-dir DIRStore persistent server state below DIR.
--restoreRestore the saved sessions (false starts without them and saves nothing). Defaults to true.
--config PATHRead the config file at PATH (default: REX_CONFIG, else rex/init.lua in the config directory).
--max-sessions NRefuse new sessions once the server holds N (0 for no limit). Defaults to 64.
--max-blocks NRefuse new blocks once the server holds N across all sessions (0 for no limit). Defaults to 1024.
--max-windows NRefuse new windows once a session holds N (0 for no limit). Defaults to 64.
--max-panes NRefuse new panes once a window holds N (0 for no limit). Defaults to 64.
--tailscale-allow-tailnet-membersAllow any tailnet member permitted by ACLs to reach Rex.
--tailscaleAlso serve the API over the tailnet as an embedded tsnet node.
--tailscale-hostname NAMETailnet device NAME for --tailscale. Defaults to rex.
--tailscale-control-url URLRegister the tailnet node with the control server at URL, such as Headscale.
--tailscale-auth-key-file FILEEnroll --tailscale with the one-time auth key read from FILE.
--tailscale-advertise-tag TAGAdvertise ACL TAG (tag:name) when --tailscale enrolls the node (repeatable).
--log-format FORMATWrite server logs as FORMAT: text or json. Defaults to text.
--log-max-size SIZELimit the active detached log to SIZE by clearing old contents (0 disables). Defaults to 50MiB.
--env NAMEPass environment variable NAME or NAME=VALUE to a new server (repeatable).
--jsonOutput server information as JSON.

rex server status

Show server status.

FlagDescription
--jsonOutput server information as JSON.

rex server logs

Show detached server logs.

Show logs captured for a server launched by rex server start.

Servers started by a service manager such as systemd or launchd log through that manager instead. For a personal server run by the systemd user unit that the Linux packages and the home-manager module install, run journalctl --user -u rex. For the shared server that the Linux packages and the NixOS module install, run journalctl -u rex.service.

On Unix, rename/create rotation must send SIGHUP to the server after creating the replacement file. Windows uses copy-truncate or --log-max-size. --follow continues across log rotation.

FlagDescription
--followFollow appended log output until the server stops.
--state-dir DIRRead server logs below DIR.
-n, --lines NShow the newest N log lines. Defaults to 200.
--allShow the entire available detached log.

rex server tailscale

Manage the server’s Tailscale node.

rex server tailscale on

Serve the API over the tailnet.

On is idempotent and runtime-only: a restarted server returns to its start flags. A node enabled for the first time begins Tailscale’s normal authentication flow; the login URL appears in the server log and in rex server status.

A one-time auth key enrolls a new node without that browser flow: pass --auth-key-file with a path, or ’-’ to read the key from stdin. There is deliberately no way to pass the key itself on the command line, where it would be visible in the process list. The key is needed only for a node’s first enrollment — the enrolled identity is kept on the server — and is ignored while the node is already enabled. ACL tags given with --advertise-tag are applied the same way: only when this call enrolls the node for the first time.

--control-url registers a node this call starts with another control server, such as Headscale. Each control server keeps its own saved login, so a node moved to a new one signs in again. To move a node that is already on, turn it off first. The server’s --tailscale-control-url is used when this flag is left out.

FlagDescription
--hostname NAMETailnet device NAME when this call starts the node (defaults to the server’s configured name).
--allow-tailnet-membersAllow any caller admitted by the tailnet instead of only this node’s owner.
--auth-key-file FILEEnroll a new node with the one-time tailscale auth key read from FILE (’-’ for stdin).
--advertise-tag TAGAdvertise ACL TAG (tag:name) when this call enrolls a new node (repeatable).
--control-url URLRegister a node this call starts with the control server at URL, such as Headscale.
--jsonOutput the resulting state as JSON.

rex server tailscale off

Stop serving the API over the tailnet.

Running ‘off’ more than once succeeds. Tailnet connections close while sessions keep running. Keeps you signed in. The next ‘on’ reconnects without signing in. Use ‘logout’ to forget this device.

FlagDescription
--jsonOutput the resulting state as JSON.

rex server tailscale logout

Sign out of Tailscale and stop tailnet serving.

Sign out of the enabled Tailscale node and stop tailnet serving. The next ‘on’ must sign in again. If already off, this leaves the saved login unchanged.

FlagDescription
--jsonOutput the resulting state as JSON.

rex server tailscale login

Request a Tailscale sign-in link.

Request a sign-in link for the enabled Tailscale node. Tailscale can take a few seconds to produce the link. If none is shown, run the command again or check rex server status.

FlagDescription
--jsonOutput the resulting state as JSON.

rex server tailscale rename NAME

Rename the enabled Tailscale node without restarting or signing in again. NAME must be one DNS label of 1 to 63 ASCII letters, digits, or hyphens, with no leading or trailing hyphen. The new DNS name may appear after this command returns.

FlagDescription
--jsonOutput the resulting state as JSON.

rex server tailscale pair

Show a QR code to pair another device.

Show the server’s tailnet address as a QR code to scan with Rex on another device.

The code holds only the address, not a credential. The other device must be on the same tailnet. Tailscale must be on and its HTTPS address ready.

FlagDescription
--jsonOutput the address as JSON.

rex server stop

Stop the server.

Stopping the server ends every program running in its sessions.

With --if-idle, the server stops only if it has no sessions and no other client is connected. Otherwise it keeps running, and the command says what is using it and exits with status 1. A client that connects at the same moment is refused, so it never starts work that the stop would end.

With --discard, the command also deletes the server’s saved sessions once it has stopped, so the next start begins with none. If no server is running, it only deletes them. If the stop is refused, nothing is deleted. Pass --state-dir if the server was started with one.

--if-idle needs a server recent enough to support it. With an older server, the command leaves the server running and exits with status 4. Without --if-idle, rex server stop works with a server of any version.

FlagDescription
--discardDelete the saved sessions once the server has stopped.
--if-idleStop only if the server has no sessions and no other connected clients.
--state-dir DIRFind the saved sessions for --discard below DIR.

rex config

Work with Rex’s config file.

Rex reads one configuration file per account, init.lua. It binds keys with rex.bind and takes them away with rex.unbind.

The file is REX_CONFIG when that variable is set. Otherwise it is rex/init.lua in the account’s configuration directory, which is $XDG_CONFIG_HOME/rex or ~/.config/rex on macOS and Linux, and %AppData%\rex on Windows.

rex config check [PATH]

Load the config file and report what it found.

Load the config file and report where it is, whether it is there, how many keys it binds and unbinds, how many modes it uses, how many actions it defines, and everything loading it had to complain about. Without PATH the account’s own init.lua is used.

Only loading happens here. Some mistakes take more than the file to see, such as binding an action that neither this file nor the client has, or unbinding a key that nothing was bound to. Those depend on which client is asking, and “rex keymap” reports them.

The file is loaded by this rex binary, so it is checked against the functions and fields this version of Rex knows. A server running a different version may read it differently. “rex keymap” asks the running server instead.

The exit status is 1 when any complaint is an error.

FlagDescription
--jsonOutput the result as JSON.

rex config reload

Make the server read the config file again and tell every client connected to it that their keys may have changed.

The generation counts the times this server has read the file. A client compares it against its own to notice that its keymap is out of date. It advances on every read, including one that failed.

A read that fails keeps the keys of the last one that worked. Only the file’s own complaints are reported here. For the ones that take a client’s own bindings to find, use “rex keymap”.

This runs on the server’s own machine, over its local socket. Whoever can edit the file is already there, and a remote caller is refused.

The exit status is 1 when any complaint is an error.

FlagDescription
--jsonOutput the result as JSON.

rex keymap

Show what each key does, as the server resolves it. The answer is the config file’s bindings stacked over the bindings the asking client ships with, and under the shortcuts recorded in that client’s own settings.

Without --request this command sends no layers and declares no actions of its own. The output is then the config file’s bindings alone, and a binding that names an action is not checked against any client’s list of actions. Pass a client’s own request to see the keymap that client receives. If that request sets server_actions, the output lists the same actions the client receives.

Bindings are listed with the top of each key’s stack first, which is the order a client tries them in. A binding in a mode is listed as the config file writes it, such as resize/left, and applies only while a client has that mode active. When there are modes, a table of them follows the bindings. The exit status is 1 when any complaint is an error.

FlagDescription
--request FILESend the client.keymap request in FILE (”-” reads stdin).
--jsonOutput the response as JSON.
rex keymap
rex keymap --request client.json
rex keymap --json | jq '.bindings[] | select(.keys[0] == "cmd+d")'

rex login-server

Run the multi-account login server.

The login server runs as root. It identifies each caller, selects an operating system account through the accounts file, and starts or reuses a Rex server for that account. It proxies each accepted connection to the selected server. Clients select an account with https://ACCOUNT@host:port. Tailnet listeners admit every identified caller because the accounts file controls authorization. Local users use sudo to request another account. Send SIGHUP to reload the accounts file. Reloading closes revoked connections but leaves account servers and sessions running.

FlagDescription
--listen ENDPOINTListen on the root-only Unix ENDPOINT (default: unix://RUNTIME-ROOT/login-server.sock).
--extra-listen ENDPOINTAlso listen on unix, http, tailnet, or tailnet-serve ENDPOINT (repeatable).
--allow-anonymousAdmit anonymous callers on plain TCP listeners (every connection gets full access).
--tailscaled-socket PATHUse the tailscaled LocalAPI socket at PATH (default: platform socket).
--accounts FILEMap callers to accounts with the HuJSON FILE (default /etc/rex/accounts.jsonc, or /usr/local/etc/rex/accounts.jsonc on FreeBSD).
--runtime-root DIRKeep the socket and accounts/ below DIR (default: $REX_RUNTIME_DIR, else /run/rex, or /var/run/rex on FreeBSD).
--pamOpen PAM sessions and run PAM account checks (default true; --pam=false uses shadow-based checks and no login session).
--pam-service NAMEUse the PAM policy for service NAME (default rex-login-server).
--log-format FORMATWrite server logs as FORMAT: text or json. Defaults to text.

rex home

Show or choose your home server.

Show or choose your home, the server this device follows for hosts and shortcuts.

Your home is this machine unless you choose another. Any Rex server can be a home. A server is not told that it is someone’s home, and admits you the same way either way.

Without a command, connect to your home and show what it reports about you. Your choice is kept in home.json in Rex’s state directory. Setting REX_HOME chooses a home for one environment and takes precedence over the file. The --server option and REX_SERVER choose the server other commands talk to. They do not change your home.

FlagDescription
--jsonOutput the home and your identity as JSON.

rex home set ENDPOINT

Follow ENDPOINT for hosts and shortcuts.

Make the server at ENDPOINT your home. ENDPOINT takes the same forms as --server.

The server is asked for its status first. If it cannot be reached, your home is not changed, so a mistyped address or a server that is down never becomes your home. The home is named by --label, or by the endpoint’s host or socket name if no label is given.

Your choice is written to home.json in Rex’s state directory, along with the host ID the server reports. rex home uses the host ID to warn you if the address later leads to a different machine. This command fails while REX_HOME is set, because that variable takes precedence over the file.

FlagDescription
--label NAMECall the home NAME in output.

rex home unset

Follow this machine again.

Forget the home you chose, so this machine’s own server is your home again. This removes home.json. It succeeds if no home was chosen.

This command fails while REX_HOME is set, because that variable takes precedence over the file.

rex hosts

List and change the hosts you connect to.

List and change your hosts, the other Rex servers you connect to by label.

Your home keeps your hosts, so every device that follows the same home sees the same list. The hosts of this machine’s own server always count too, whatever your home is. If a host of this machine and a host of your home have the same label, this machine’s host wins.

A new host goes to your home. A change to a host goes to the server the host came from. If your home is away, the change is held on this machine and sent the next time rex hosts reaches your home. Until then, the list shows the hosts your home had when it was last reached.

To use a host, give its label to --server, as in “rex -S studio session ls”.

Without a command, list your hosts. The --server option and REX_SERVER do not change which servers this command talks to.

FlagDescription
--jsonOutput the hosts as JSON.

rex hosts list

List your hosts.

List the hosts your home keeps, including changes held for it, and the hosts of this machine’s own server.

FROM says which server a host came from, and is left out when your home is this machine. SOURCE is the init.lua line that declares a host, “stored” for a host added with rex hosts, or “held” for a host not yet sent to your home.

If your home is away, the list shows the hosts it had when it was last reached, and says how long ago that was. Warnings go to standard error.

FlagDescription
--jsonOutput the hosts as JSON.

rex hosts add LABEL ENDPOINT...

Add a host to your home.

Add a host called LABEL, reached at each ENDPOINT in turn. An endpoint takes the same forms as --server.

A socket path, such as unix:///tmp/rex.sock, works only on a device where the path exists, such as the local end of an ssh -L forward. Other devices skip it and try the next endpoint.

The host goes to your home, so every device that follows your home sees it. No other host of yours may have the same label, ignoring case.

If your home is away, the host is held on this machine and listed at once. It is sent the next time rex hosts reaches your home.

FlagDescription
--icon NAMEShow the icon NAME next to the host.

rex hosts edit LABEL

Change a host.

Change the host called LABEL, ignoring case. Give at least one option. --endpoint replaces all of the host’s endpoints, and may be given more than once.

The change goes to the server the host came from: your home, or this machine. Editing a host declared in init.lua stores a host that takes the declaration’s place. The line stays in the file, but no longer has an effect.

If the host is your home’s and your home is away, the change is held on this machine and sent the next time rex hosts reaches your home.

FlagDescription
--label NEWRename the host to NEW.
--endpoint ENDPOINTReach the host at ENDPOINT (repeatable, replaces all endpoints).
--icon NAMEShow the icon NAME next to the host (empty removes it).

rex hosts remove LABEL

Remove a host.

Remove the host called LABEL, ignoring case, from the server it came from: your home, or this machine.

Removing a host declared in init.lua hides it. The line stays in the file, but no longer has an effect.

If the host is your home’s and your home is away, the removal is held on this machine and sent the next time rex hosts reaches your home.

rex hosts check [LABEL...]

Check which hosts can be reached from here.

Try to reach each of your hosts, or only the hosts called LABEL, ignoring case. All hosts are tried at once, and each one has up to --timeout to answer.

STATUS is one of:

reachable a Rex server answered at ENDPOINT not reachable from here nothing answered, but the host may work from another network or device down a machine answered, but not a Rex server

DETAIL says why a host could not be reached. For a reachable host, it says when the address now leads to a different machine than the one you added.

The check succeeds whatever it finds. Commands that connect to a host try the address that answered first.

FlagDescription
--jsonOutput the results as JSON.

rex whoami

Show your identity, server, and Rex location.

FlagDescription
--jsonOutput identity, server, and location as JSON.

Other

rex completion

Generate shell completion scripts for Rex.

rex completion bash

Generate Bash completion.

Load it with source <(rex completion bash), or install it in a bash-completion directory.

rex completion zsh

Generate Zsh completion.

Install it with rex completion zsh > "${fpath[1]}/_rex".

rex completion fish

Generate Fish completion.

Install it with rex completion fish > ~/.config/fish/completions/rex.fish.

rex completion powershell

Generate PowerShell completion.

Add the output of rex completion powershell to your PowerShell profile.

rex completion nu

Generate Nushell completion.

Add the output of rex completion nu to your config.nu.

rex terminfo

Set up and report Rex’s terminal type.

Rex carries its own terminfo entry, xterm-rex, describing what its terminals support.

A terminal claims it wherever this account is set up for it, unless REX_TERM names another entry. Run “rex terminfo setup” once per account, and “rex terminfo status” to see what this machine would decide.

rex terminfo status

Report the TERM a new terminal would be given, and why.

Report the TERM a new terminal would be given, what was examined to decide it, and, when this account is not set up, which command fixes it.

A server claims xterm-rex wherever that is safe and keeps xterm-256color everywhere else. Naming an entry in REX_TERM overrides that and gives every terminal that name, which makes REX_TERM=xterm-256color the off switch. The value “auto” asks for the rule the server already follows.

The report covers the terminfo entry, the ssh client, both guard files, the hosts that have been recorded, and which configuration is responsible for what ssh would actually send.

Nothing of yours is changed and no host is contacted. The one file written is a throwaway copy of Rex’s guard, used to ask ssh what that guard would do on its own.

FlagDescription
--jsonOutput the report as JSON.

rex terminfo setup

Install Rex’s terminfo entry and ssh guard.

Install xterm-rex where programs find it, and configure ssh so that the name never reaches a host that has never heard of it.

Three things happen. The entry is installed in ~/.terminfo. A guard is written to Rex’s configuration directory. One Include line is added at the top of ~/.ssh/config. ssh is then asked what it would send to a host without the entry, and the answer is reported.

If your ssh configuration already includes a guard, as it does when home-manager manages it with Rex’s module, the guard and the Include line are skipped, because they would add nothing.

The guard needs OpenSSH 7.8 or later, because an older ssh refuses any configuration that contains it. With an older ssh, only the entry is installed, and the command fails with a message that says why.

With --system the entry goes into /usr/share/terminfo and the guard into /etc/ssh/ssh_config.d/50-rex.conf, so that every account on this machine has both, root included. That needs root, and it is what makes programs started through sudo and su find the entry. On FreeBSD, where /etc/ssh/ssh_config reads no other files, it also adds an Include line for the guard’s directory to the top of that file.

Run this once per account. Repeating it is harmless.

Two flags are meant for a program that sets an account up on someone’s behalf. --entry-only installs the entry and leaves ssh configuration alone, which is the half that needs no permission. --json reports what the run did as one object instead of the lines a person reads.

Installing the entry is not the whole story. A terminal claims the name once the guard is in place as well, and REX_TERM can name another entry instead. “rex terminfo status” reports what this machine would do.

FlagDescription
--entry-onlyInstall the entry alone, for a program that adds the guard later (the name is claimed only once the guard is in place too).
--dry-runReport what would change without writing anything.
--systemInstall the entry and the guard for every account on this machine.
--jsonOutput what the run did as JSON.

rex terminfo remove

Remove the ssh guard, leaving the terminfo entry installed.

Remove Rex’s ssh guard and the Include line that puts it into effect, so that ssh goes back to forwarding whatever TERM it is given.

With --system the machine-wide guard /etc/ssh/ssh_config.d/50-rex.conf goes instead. On FreeBSD, so does the Include line the setup added to /etc/ssh/ssh_config. That needs root.

The terminfo entry stays where it was installed, in both cases. Shells that are already running with TERM=xterm-rex stop working the moment the entry disappears, so there is no command that deletes it. Remove the files by hand if you really want them gone.

--json reports what the run did as one object instead of the lines a person reads, in the shape the setup uses.

FlagDescription
--dry-runReport what would change without writing anything.
--systemRemove the guard that every account on this machine shares.
--jsonOutput what the run did as JSON.

rex terminfo show

Print the terminfo source.

Compile it on another machine with: rex terminfo show | tic -x -

rex terminfo host

Install Rex’s terminfo entry on other machines.

Install xterm-rex on a remote host and record that it is there, so that ssh stops announcing xterm-256color to it.

A record is compared, exactly, against the destination as ssh resolves it, so one machine can be recorded under more than one spelling.

rex terminfo host install DESTINATION [-- SSH_OPTIONS...]

Install Rex’s terminfo entry on a remote host.

Install xterm-rex on DESTINATION over ssh, and record the host so that ssh stops announcing xterm-256color to it.

The entry’s source is piped to the remote tic, which compiles it into ~/.terminfo there. Nothing else on the remote host is touched, and no interactive session is started. Options after — are passed to ssh, so “— -p 2222” and “— -J jump.example.com” work as usual.

The entry lands in the home directory of the account you connect as, while the record is kept per host. Another account on that host will not have the entry. Use “rex terminfo host forget” to undo a record.

What gets recorded is the spelling you typed, because that is what the guard compares against. When your ssh config rewrites it with HostName, that name is recorded as well, because a machine-wide guard sees the rewritten one. Either way, other spellings of the same machine keep the old terminal type until you install to them too.

rex terminfo host forget HOST

Forget that a host has Rex’s terminfo entry.

Remove HOST from the hosts file, so that ssh goes back to announcing xterm-256color to it.

Use this when the entry is gone from that host, or when you connect to it as an account that does not have it.

HOST is the spelling that was recorded. Run “rex terminfo host ls” to see them.

rex terminfo host ls

List the hosts recorded as having Rex’s terminfo entry, one per line, in the order they were added.

Each line is compared, exactly, against the destination as ssh resolves it. One machine can appear under more than one spelling, and each spelling is its own record.

FlagDescription
--jsonOutput the list as JSON.

rex skill

Set up agents to use Rex.

Set up agents such as Claude Code and Codex to use Rex.

Rex installs two things into each agent. A skill teaches the agent how to use the rex command. A hook, in agents that support hooks, tells the agent at the start of each session which Rex session and terminal it is running in. Both get their text from the rex command each time the agent uses them, so upgrading Rex also updates what agents are told.

Run “rex skill setup” once per account, and “rex skill status” to see what is installed.

rex skill status

Report whether Rex’s skill and hooks are installed.

Report, for each agent Rex knows, whether the agent was found on this machine and whether Rex’s skill and hooks are installed in it. Nothing is changed.

Each item is reported as one of:

current installed and up to date outdated installed by an older Rex, or edited since missing not installed foreign a file of the same name that Rex did not install unreadable the file could not be read unsupported the agent cannot hold the item here

FlagDescription
--projectReport on the current repository instead of your account.
--jsonPrint the report as JSON.

rex skill setup

Install Rex’s skill and hooks into agents.

Install Rex’s skill and hooks into the agents found on this machine, or into the agents named with --agent. If no agent is found, the skill alone goes into the shared ~/.agents/skills directory that most agents read.

The skill goes into each agent’s skill directory. Some agents share a directory, and it is written once. Hooks are added to each agent’s settings file, and the rest of the file is left as it was. Some agents ask you to approve a new hook before they run it, and the output says how.

Run this once per account. Running it again is safe, and updates anything an older Rex installed.

Pass --session-naming to have agents name the session after their task. A new setup leaves that off, and running setup again keeps the choice already installed unless you pass the flag.

If a skill named rex is already installed and Rex did not install it, it is left alone and reported as a conflict. Use --force to replace it.

FlagDescription
--agent AGENTUse only AGENT, which is claude, codex, opencode or pi (repeatable).
--projectSet up the current repository instead of your account.
--dry-runReport what would change without changing anything.
--forceReplace a skill named rex that Rex did not install.
--session-namingTell agents to name the session after their task (omit to keep the installed choice).
--jsonPrint the result as JSON.

rex skill remove

Remove Rex’s skill and hooks from agents.

Remove Rex’s skill and hooks from every agent Rex knows, or from the agents named with --agent. Agents that are no longer installed are included, so nothing Rex installed is left behind.

Only files and hooks that Rex installed are removed, including older copies of the skill in other directories the agent reads. Other skills, hooks and settings are left as they were.

FlagDescription
--agent AGENTUse only AGENT, which is claude, codex, opencode or pi (repeatable).
--projectRemove from the current repository instead of your account.
--dry-runReport what would change without changing anything.
--jsonPrint the result as JSON.

rex skill show

Print the guide that Rex’s skill gives agents.

An agent with the skill installed reads the guide through the skill. An agent without it can run this command to read the same guide.

rex version

Print version information.

FlagDescription
--jsonOutput version information as JSON.

Global Options

Every command accepts these.

FlagDescription
--autostartStart a missing local server. Defaults to true.
-C, --client CLIENTAct on client CLIENT, given as a label or ID.
--color WHENSet color WHEN to auto, always, or never. Defaults to auto.
-S, --server SERVERConnect to SERVER, a host’s label or a server address (a value with a port is always an address).
--timeout DURATIONLimit each connection and nonstreaming request to DURATION. Defaults to 10s.
-v, --verbose countIncrease diagnostic verbosity (repeatable).