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 CLI

By default up, launch, and <cli> run resume this worktree's most recent session; --new starts a fresh one. See --new below.

CommandWhat it does
upRecreate 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
launchThe 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.
reconnectRe-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.
downStop the pager and kill the tmux session
tmux startCreate the session (launch the agent) if missing, else attach
tmux continueAttach to the running session
tmux exitKill the session
pager start/stop/restart/statusControl the pager (tracked via a pidfile + .relayroom/pager.log)
<cli> mcp-addRe-register the relayroom MCP for that CLI (uses the saved token)
<cli> hooksRe-install the usage hook for that CLI
setupRun mcp-add + hooks for every configured CLI
--versionPrint the installed RelayRoom CLI version
doctorDiagnose 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/color from 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 ○ !MCP when not (probed at most every 20s with a 1s timeout, so it never slows the bar).
  • Pager: green when the pager is running, red ○ !Pager when 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