marsh

A shell for composing agents.

marsh adds sandboxed agent commands and filesystem branching to a Bash-compatible shell. Use Claude, Codex, and Pi or register your own, then connect their work with pipes and parallel branches.

brew install docker/tap/sbx mcavage/tap/marsh
First run →

Split work at the prompt

Each branch is a shell command or pipeline running on its own copy of your files. Here, Claude works on the API while Codex works on the CLI.

Example shell session
~/events $ marsh
marsh$ split {
>   api: claude -p \
>     "Add cursor pagination." &&
>     make test
>   cli: codex exec \
>     "Add --json output." &&
>     make test
> } | join --keep
# join prints each branch's results and patch path
marsh$ less \
> .marsh/split/ID/out/api/diff.patch
marsh$ git apply \
> .marsh/split/ID/out/api/diff.patch
marsh$ make test
marsh$

In the shell

Your working tree Uncommitted changes included
api Private copy Claude + make test
cli Private copy Codex + make test
api/diff.patch cli/diff.patch Each branch's changes
Keep the changes you want

Read the diff before running git apply.

Fan work out in parallel, give editing branches their own files, and pipe the results into the next stage.

A sandbox for every agent call

Each call runs in a fresh nonroot container inside a Docker Sandbox VM. marsh keeps a warm VM per agent Kit, so repeated and concurrent calls share its boot and memory costs.

macOS copy-on-write clones let project branches share unchanged file data on supported filesystems. If cloning is unsupported, marsh makes a regular copy.

Your agents get filesystem branching

Inside a job, registered commands, marsh split, and marsh fanout are on PATH. An agent can use its existing shell tool to start sandboxed children and work on private copies of its project.

The agent reads the results and patches on stdout. It needs no new delegation API or changes to its own code.

Agents running agents →
Inside an agent’s shell tool
marsh split -n \
  ::: api claude -p \
    'Add cursor pagination.' \
  ::: cli codex exec \
    'Add --json output.' \
  | marsh join --keep

See and control what runs

Jobs run as nonroot users inside containers and sandbox VMs, without your Mac home or Docker/SBX control sockets. Kit policies filter network access, and you can restrict which commands an agent may start and set resource limits.

Provider keys stored with Docker Sandboxes are added by its proxy, so jobs don't receive the key values. Logins saved in the shared guest home remain readable by other jobs that use it.

marsh jobs --tree shows who started each call, and marsh results records its exit status and container cleanup. Ctrl-C cancels the foreground tree, including jobs the agents started themselves.

The included agents run with permission prompts disabled, so a direct call can edit your working tree immediately. Use split to give registered agent calls private project copies. Ordinary commands in a shell branch, such as make test, can still write outside that copy within your session's Linux VM.

Security model →

Open a shell in your project

You'll need an Apple Silicon Mac and Docker Sandboxes (sbx) 0.47.0 or newer. Install marsh →