Multi-agent sessions
moat join launches a second agent inside an already-running container, reusing its workspace, grants, and credential context. No new container is created and no new proxy registration is issued.
How it works
A moat join session is an exec child of the existing container. The original agent owns the container lifecycle: stopping the run (via moat stop) tears down the container and terminates any joined agents. Joined agents share the run’s proxy token, so their network requests are logged to the same run’s network.jsonl and attributed to the same audit chain.
Console output is split: the primary agent writes to logs.jsonl; each joined agent writes to logs.<index>.jsonl.
Quick start
In a first terminal, start a claude run:
moat claude
# note the run ID printed in the status footer, e.g. run_a1b2c3d4e5f6
In a second terminal, join it:
moat join run_a1b2c3d4e5f6 claude
The second terminal opens an interactive claude session in the same workspace. The status footer on the join shows joined · 1; the primary’s footer shows primary +1.
Headless join
Use --prompt / -p to run a join non-interactively and exit when done:
moat join run_a1b2c3d4e5f6 claude -p "print the current git branch"
The output streams to the terminal and the command exits with claude’s exit code.
Session flags
| Flag | Effect |
|---|---|
-c, --continue | Continue the most recent conversation |
-r, --resume ID | Resume a specific session by ID |
-p, --prompt TEXT | Run non-interactively with this prompt |
--continue and --resume are mutually exclusive.
Status footer
| Session | Footer display |
|---|---|
| Primary, no joins | (no session segment) |
| Primary, N joins active | primary +N before the run ID |
| Joined session (index N) | joined · N before the run ID |
Lifecycle
The original run owns the container. Joined agents are exec children:
moat stop <run>stops the container, which terminates all joined agents.- A joined agent exiting (or being interrupted) does not affect the primary or other joins.
moat destroyremoves the run after it is stopped; joined log files (logs.N.jsonl) are removed with the run.
v1 constraints
v1 supports same-agent joins only. The agent argument must match the agent the run was created with:
# Works: joining claude into a moat claude run
moat join run_a1b2c3d4e5f6 claude
# Error: run has no codex configuration
moat join run_a1b2c3d4e5f6 codex
Cross-provider join (e.g. running codex inside a claude run) and container-side worktree joins (moat join … --wt) are not supported in v1.
Relationship to moat exec
moat join and moat exec both exec a command into an existing container:
moat execruns an arbitrary command you supply.moat joinresolves an agent provider by name and constructs its standard invocation (equivalent to whatmoat claudewould run inside the container).
Use moat exec for shell commands and scripts; use moat join to start a full interactive agent session.