CODEREX

CLI reference

coderex is a thin JSON-RPC client over a local socket. Anything the app can do — list tabs, read a screen, type into a shell, start an agent — a script or another agent can do too.

Install

The CLI ships inside the desktop app — installing Coderex puts coderex on your PATH. Grab the signed .dmg, or use Homebrew:

$ brew install --cask jtrasmon/coderex/coderex

On a server, or anywhere you want the daemon and CLI without the GUI, install the headless build instead. Same binary, no app:

$ brew install jtrasmon/coderex/coderex

Verify it's wired up:

$ coderex ping
$ coderex --help # every command

Quick start

Start an agent, tell it what to do, and read what it said back:

$ SID=$(coderex agent start claude)
$ coderex send --surface "$SID" "fix the flaky test in auth"
$ coderex read --surface "$SID"

agent start opens a new tab, launches the agent in it, and prints that tab's surface id — which is why command substitution works. Every later command takes that id via --surface.

How it works

The app (or the headless coderex serve daemon) listens on a unix socket. The CLI sends one JSON-RPC request per invocation and prints the result.

The socket path resolves in this order:

Every terminal Coderex opens gets $CODEREX_SOCKET_PATH and its own ids injected into the environment. A script running inside a tab can therefore call coderex with no flags at all — it already knows which tab it is. See Environment.

Inspect

coderex ls

Prints the workspace → pane → tab → surface tree.

coderex status

Reports each tab as idle, running (a foreground program is live in it), or attention — the tab rang BEL, which is the signal coding agents emit when they're blocked on you.

FlagScope
(none) Every workspace across all windows, plus a totals line.
--workspace <id> One workspace's rollup, with a per-tab breakdown.
--surface <id> A single tab. Mutually exclusive with --workspace.

On a terminal you get the readable view:

$ coderex status
My Workspace 1 1 needs you 2 running 3 idle
My Workspace 2 2 idle
 
1 needs you 2 running 5 idle

Pipe it anywhere and you get the raw JSON-RPC result instead — same for every command. See Output & exit codes.

coderex read

Prints a tab's current screen. --ansi keeps the colour escapes; without it you get plain text.

coderex history

Prints a tab's scrollback. --lines <n> limits it to the last n lines.

coderex screenshot

FlagMeaning
--format png (default), json, or ansi.
--out <path> Write the PNG to a file instead of stdout.

Drive a tab

coderex send

Types text into a tab's shell and presses Enter. Pass --no-enter to leave the line uncommitted.

$ coderex send --surface "$SID" "npm test"
$ coderex send --no-enter "git commit -m "

Everything after the flags is passed through verbatim, so hyphens and quotes survive.

Agents

Supported tools: claude, codex, gemini, opencode.

coderex agent start <tool>

Opens a new tab, launches the agent, prints the new surface id. Flags after the tool name are handed to the agent itself:

$ coderex agent start codex --yolo --search
$ coderex agent start --workspace "$WS" claude
FlagMeaning
--workspace <id> Where to open the tab. Defaults to $CODEREX_WORKSPACE_ID, else the selected workspace. Must come before the tool name.
--no-check Skip the pre-flight "is this agent installed?" check. Also goes before the tool name.

coderex agent stop

Terminates the agent's foreground process; the tab stays open. Defaults to $CODEREX_SURFACE_ID.

coderex agent update <tool>

Runs the agent's own self-update in a new tab and prints its surface id.

Workspaces & tabs

$ coderex workspace new --title "Acme"
$ coderex workspace delete --workspace "$WS"
$ coderex tab new --workspace "$WS"
$ coderex tab close --surface "$SID"

workspace delete and tab close do not prompt — confirmation dialogs are GUI-only. Scripts get exactly what they asked for.

Notifications

coderex notify raises a notification in the app, attributed to the calling tab automatically. Put it at the end of a long job and your phone lights up.

$ npm test && coderex notify "tests green"
$ coderex notify --title "Deploy" --body "shipped v2"
$ coderex notifications # list
$ coderex notifications clear

notifications accepts --workspace and --surface to filter.

Resources & usage

coderex resources

System, GPU, and per-process usage. Narrow it with --workspace or --surface.

coderex usage

AI-agent model and context usage. Claude reports per tab; Codex, Gemini, and OpenCode report their newest session. --json gives the raw payload instead of the formatted view; --surface limits Claude to one tab.

coderex watch

Subscribes to the event stream and prints each event as it arrives. Useful as the input to a supervisor loop.

Daemon

Terminals are hosted by an engine. On macOS the desktop app runs it in-process by default; turning on Remote Control moves it into a background daemon so your sessions keep running with the window closed. On a server you run the daemon directly:

$ coderex serve # headless engine + socket
$ coderex serve --remote # also join the E2E-encrypted relay
$ coderex login # link this machine to your account

Manage a running daemon from anywhere:

$ coderex daemon start | stop | restart | status

daemon stop ends every agent the daemon owns. The coderex binary is GUI-free and builds on any platform, including a headless Linux box.

Output & exit codes

Commands print human-readable output when stdout is a terminal and the raw JSON-RPC result when it isn't. So this is for you:

$ coderex status

…and this is for your script, with no flag to remember:

$ coderex status | jq '.windows[].workspaces[] | select(.attention > 0) | .title'

Exit status is 0 on success and 1 on failure.

Error codeMeaning
parse_errorThe request wasn't valid JSON.
invalid_requestMalformed request envelope.
invalid_params A parameter was missing or unparseable — e.g. a bad surface id.
not_found The workspace or surface doesn't exist.
internalThe app failed to handle it.

If the app isn't running you get coderex: could not reach app at <path> on stderr and exit 1.

Environment

Coderex injects these into every terminal it opens, so scripts running inside a tab are self-locating.

VariableMeaning
CODEREX_SOCKET_PATH Overrides the socket location. Read by both the app and the CLI.
CODEREX_SURFACE_ID The calling tab. Used when --surface is omitted by send, read, history, screenshot, tab close, and agent stop.
CODEREX_WORKSPACE_ID The calling workspace. Used when --workspace is omitted by tab new, workspace delete, and agent start.
CODEREX_PANE_ID The calling pane.
CODEREX_WINDOW_ID The calling window.

coderex status deliberately ignores the $CODEREX_* fallback, so the bare form is always the every-workspace aggregate rather than "whichever tab I happen to be in".

Recipes

Which agents are blocked on me?

$ coderex status | jq -r '.windows[].workspaces[].tabs[] | select(.status=="attention") | .title'

Nudge every idle agent

$ coderex status | jq -r '.windows[].workspaces[].tabs[] | select(.status=="idle") | .surface_id' \
  | while read -r sid; do
    coderex send --surface "$sid" "continue"
  done

Ping me when the agent finishes

Run this inside the tab — no ids needed, the environment supplies them:

$ npm run build && coderex notify "build done" || coderex notify "build FAILED"

Archive a tab's output

$ coderex history --surface "$SID" --lines 500 > run.log
$ coderex screenshot --surface "$SID" --out run.png