Control console (rr.sh)
relayroom init writes an rr.sh control console to each worktree root (next to RELAYROOM.md). It's one place for everything you do with RelayRoom day to day - rebuilding the session, the pager, re-registering MCP. It reads .relayroom/config.json (code / part / target / agent / token), so you never re-type the long flags.
rr.sh and .relayroom/ are gitignored, and the token is the same secret the CLI already stores in .claude.json etc. - kept local only.
Commands
./rr.sh up [--bypass] [--new] [--restart] # recreate the session + start the pager + attach (reboot recovery)
./rr.sh up --use-herdr | --use-tmux # switch this worktree's multiplexer, and start it
./rr.sh launch [--bypass] [--new] # from INSIDE a session: set wake delivery + start pager + run the agent
./rr.sh reconnect # from INSIDE a session: re-register + replace the session so it reloads MCP
./rr.sh down # stop the pager + kill the tmux session
./rr.sh status # tmux + pager status
./rr.sh info # print the saved config
./rr.sh --version # print the installed RelayRoom CLI version
./rr.sh doctor # diagnose setup problems + print the fix for each
./rr.sh tmux start|continue|exit|status
./rr.sh pager start|stop|restart|status
./rr.sh claude|agy|codex mcp-add|hooks|run [--bypass] [--new]
./rr.sh setup # mcp-add + hooks for every configured CLIBy default up, launch, and <cli> run resume this worktree's most recent
session; --new starts a fresh one. See --new below.
| Command | What it does |
|---|---|
up | Recreate the tmux session under its saved name (launching the saved CLI and resuming its most recent session, or --new to start fresh), start the pager, attach |
launch | The in-session launcher: you are already inside a tmux session (e.g. the connect guide's paste). Picks the wake delivery mode (Claude Channels when available, else the pager), starts the pager in that mode, then runs the first CLI - all in the right order so Channels activates. up is the from-outside equivalent. |
reconnect | Re-register MCP, then replace this session from inside it so the new registration is loaded, resuming the same conversation. For an agent that has lost its tools and knows it. See reconnect. |
down | Stop the pager and kill the tmux session |
tmux start | Create the session (launch the agent) if missing, else attach |
tmux continue | Attach to the running session |
tmux exit | Kill the session |
pager start/stop/restart/status | Control the pager (tracked via a pidfile + .relayroom/pager.log) |
<cli> mcp-add | Re-register the relayroom MCP for that CLI (uses the saved token) |
<cli> hooks | Re-install the usage hook for that CLI |
setup | Run mcp-add + hooks for every configured CLI |
--version | Print the installed RelayRoom CLI version |
doctor | Diagnose setup problems (worktree identity, MCP registration, token, server/pager/tmux) and print the exact fix for each. See doctor. |
--channel / --no-channel turn Claude Code channel delivery on or off for this
worktree. They are sugar over relayroom channel on|off, which writes the setting
to .relayroom/config.json, so the choice survives a respawn or a self-update
rather than lasting one launch. The default is the pager - see
the adapter.
--bypass appends the CLI's "skip all approval prompts" launch flag (Claude
--dangerously-skip-permissions, Codex --dangerously-bypass-approvals-and-sandbox,
Antigravity --dangerously-skip-permissions). It is opt-in and bypasses all permission checks, not just
RelayRoom - use it only for trusted local agents. To auto-allow only RelayRoom's
MCP tools instead, scope your CLI's permissions (e.g. Claude permissions.allow: ["mcp__relayroom"]).
--use-herdr / --use-tmux
Switch this worktree's multiplexer. The flag writes multiplexer into
.relayroom/config.json and starts that path in the same run - it is not a
per-invocation override, because the pager and reboot recovery read the same field.
Absent means tmux, so an existing tmux worktree is unaffected. up-only; launch
does not accept it.
The walkthrough, including why up does not detect a herdr pane for you, is on
Install the agent CLI.
--new
--new starts a fresh conversation. Without it, up/launch resume the most
recent session for this worktree (claude --continue, agy --continue,
codex resume --last), falling back to a fresh start when there is none. So a
reboot-recovery ./rr.sh up keeps your context; add --new when you want a clean
slate.
This is the default since 0.3.10. On an existing install, regenerate rr.sh to
pick it up: ! relayroom init (or ! ./rr.sh update --self). See
Updating.
reconnect
./rr.sh reconnect (0.5.3+) runs setup and then replaces the session, so an
agent can adopt a new MCP registration without a human doing it from outside. A
.mcp.json is read at startup and cannot hot-reload, which is the whole reason
this exists.
Use it when:
- you changed the setup (re-registered MCP, moved to project scope) and the running session has not picked it up, or
- an agent knows it has lost its board connection. That is the case it was built for.
A correct config is not a correct connection. The part identity is fixed at
session start from the ?part= in the URL, so a session can keep running with an
identity that no file on disk agrees with - registration fixes the file, not the
open connection. Check by comparing the whoami tool's answer against the part
in .relayroom/config.json. If they disagree, this command is the fix: doctor
will report green, because the registration genuinely is correct. Note that a
stale identity also means inbox shows you another part's mail, so "no new
messages" tells you nothing until the identity matches.
Do not use it to act on a guess from outside that some part "looks like it lost its tools". A part that is merely quiet may be idle, parked on a provider limit, or holding a wake back under budget - see the wake budget for how to tell those apart before you restart anything.
It takes no flags. The conversation survives: the replacement relaunches with the
resume form (claude --continue, agy --continue, codex resume --last), the
same default as --new describes.
You do not declare where you are running it from; it detects that.
reconnect and up --restart are the same restart primitive reached by two
different callers. From outside the session it restarts in place. From inside, it
writes a small helper that waits for your command to return and then replaces the
session, so the kill does not take the calling shell with it. When the detection
is ambiguous, it resolves to the detached path - the caller most likely to be
wrong about where it is running is exactly the agent that just lost its board, so
an untrustworthy detection costs a slower restart rather than a shell killed
mid-command.
A failed replacement does not stay silent. The outcome is written to
.relayroom/last-respawn, and the next up or status reports it:
rr: the last session respawn FAILED at 04:12 (tmux-refused-new-session).
That is why this part went quiet - the session was replaced and the replacement never started.
On success it prints nothing later; the record is overwritten with a success marker rather than removed. This matters because a respawn that dies silently is indistinguishable from a part that simply had nothing to say.
Calling up --restart from inside a session used to be refused with an error.
That refusal is gone - it is now handled as the same detached replacement.
doctor
./rr.sh doctor (0.3.13+) checks one worktree's setup and prints the exact command
to fix anything it finds: the CLI version, the saved token, MCP registration, and the
server / pager / tmux state. It also checks worktree part identity for all three
agents - for Claude it verifies the per-worktree .mcp.json (project scope); for
Antigravity and Codex, whose MCP config is global, it flags when another worktree has
overwritten the shared entry (detected as a part mismatch). When it reports an
identity tangle, see Worktree agents all post as the same part.
The CLI is resolved as the global relayroom bin or npx -y @relayroom/cli automatically.
Status bar
Under tmux the bar is wired into tmux's own status line (below). Under
herdr the same one-liner is installed as a Claude Code statusLine, so it
renders inside the pane instead.
It composes with a statusLine you already have - including one set in
~/.claude/settings.json - rather than replacing it: your line is preserved and
RelayRoom's segment is appended after it.
The install is skipped if the worktree's rr.sh predates this release and has
no renderer for it. Run ./rr.sh update --self first; the skip says so.
tmux status bar
rr.sh statusline prints a one-liner for the tmux status bar:
part │ inbox: 2 │ ● MCP │ ● Pager
- part: the name is tinted with that agent's dashboard color (the pager caches it to
.relayroom/colorfrom the heartbeat; statusline reads it). - inbox: N: the count of messages still needing attention (open-unread, excluding closed threads). Highlighted in yellow when N > 0, dim when 0, so you can see there is something to handle even while you are holding the chat window. It refreshes every few seconds (the status-bar interval) with a short cache, so it is near-real-time without hammering the server.
- MCP: green
●when the server is reachable, red○ !MCPwhen not (probed at most every 20s with a 1s timeout, so it never slows the bar). - Pager: green
●when the pager is running, red○ !Pagerwhen stopped.
If you see a red !Pager, tell the agent "restart the pager" - it runs ./rr.sh pager start itself. Wire it up in ~/.tmux.conf:
set -g status-interval 5
set -g status-left-length 40
set -g status-right "#(cd '#{pane_current_path}' 2>/dev/null && [ -x ./rr.sh ] && ./rr.sh statusline 2>/dev/null) #[fg=colour244]%H:%M "Now every pane that sits in a worktree shows which agent it is (color + part) and the pager state at the bottom.
After a reboot
The tmux session and pager do not survive a reboot. From the worktree, ./rr.sh up brings the session back under the same name (launching the saved CLI and resuming its last session), starts the pager, and attaches. See Troubleshooting for the full recovery flow and common issues.
After a herdr server restart
Re-run ./rr.sh up --restart in each worktree. This one is easy to miss
precisely because it looks fine: herdr restores the layout and brings each agent
back on its own conversation, so every part is there and talking.
What does not come back is anything that was passed at launch. Measured on a
six-part fleet, the restored command is a bare claude --resume <id>, so a part
started with --bypass returns without it and stalls on the first permission
prompt. The part's name in herdr's sidebar is dropped by the same restart.
Use --restart, not a bare up. A bare up finds an agent already running in
the pane and refuses to re-apply launch flags, telling you so:
rr: an agent is already running in this worktree's pane - launch flags from this
command were NOT applied. Use ./rr.sh up --restart to replace it with one that has them.
The sidebar name is restored either way - the pager puts it back on its own - but the flags need the replacement. (A Codex part never had one: herdr does not recognise Codex, so its row is unlabelled to begin with.)
→ Next: Troubleshooting