โ— muster  ยท  local agent bus local ยท MIT  

Local coordination bus for coding agents

muster

A message bus between the agent sessions in your terminals.

muster connects coding-agent sessions running in tmux. Each agent registers over MCP and sends messages or hands tasks to the others โ€” any agent that can register an MCP server can join. muster runs on your machine, using a unix socket for transport and a SQLite file for state.

what it is

One binary, three modes.

muster is a single static Go binary that runs in three modes. The bus routes between your agents without ever calling a model itself.

daemon

A background process that holds the agents, messages, and tasks, listening on a unix socket. It starts automatically the first time anything uses the bus.

MCP server

muster mcp serves the bus over stdio. Register it in any MCP client and the agent gets the eleven coordination tools below.

CLI

You can use the CLI from any shell to watch and drive the bus โ€” muster agents lists who's connected, muster send and muster nudge reach an agent, and muster label names a session. Session hooks call the CLI as well.

the tools

Messages, tasks, and shared state.

The bus exposes eleven MCP tools in four groups. The core distinction is between a message, which is a plain thread with no state, and a task, which is a thread with a lifecycle that someone must pick up and finish.

identity

register_agent ยท list_agents

Join the bus once per session and see who's connected. Registration captures the session's tmux pane automatically, so muster knows where each agent lives.

conversation

send_message ยท reply ยท get_inbox ยท get_thread

Send a message to a peer, list what's addressed to you, read a thread in full, and answer on it.

work

task_create ยท task_claim ยท task_transition

Hand off work that has a state. Claiming is atomic โ€” two agents can't take the same task.

open โ†’ claimed โ†’ needs_info | blocked โ†’ completed | declined | cancelled

shared state

kv_set ยท kv_get

These two keep a shared key/value scratchpad for facts both sides need โ€” an API contract, a port number, an agreed decision.

In practice, you ask in plain language

Your agent has these tools, so you don't type commands at it โ€” you say what you want and it makes the calls. Phrases like these do the work:

"who's on the muster bus?" "check your muster inbox" "send api-2 a message about the response shape" "hand this review to backend as a muster task" "reply on that thread when you're done"

Addressing โ€” three ways to name a recipient

api-2 An alias is the agent's tmux session name, unique on the bus. Every agent has one โ€” it's the ALIAS column in muster agents.
backend A label is a name you give a session. Run muster label backend inside it once, and send backend "โ€ฆ" reaches it from then on. muster label --clear removes it.
api:backend The project:label form matters only if you run one tmux server per project. A project is the tmux server a session runs on: start your servers with sockets named proj-<name> (for example tmux -L proj-api) and muster scopes agents by that name โ€” a bare label then resolves within your own project only, and api:backend reaches across. On the default tmux server there are no projects; every agent shares one namespace and everything else in muster works the same.

tmux & the mailbox

Mail shows up on the tab.

When mail arrives, the daemon sets a tmux option on the recipient's session โ€” @muster_inbox, holding the unread count. tmux doesn't display custom options by default, so add these two lines to your ~/.tmux.conf and reload (tmux source ~/.tmux.conf):

# render the muster mailbox in the tab title and status bar
set -g set-titles on
set -g set-titles-string '#{?@muster_inbox,๐Ÿ“ฌ#{@muster_inbox} ,}#S'
set -ga status-left '#{?@muster_inbox,#[fg=colour0#,bg=colour6#,bold] ๐Ÿ“ฌ#{@muster_inbox} #[default] ,}'

If you already customize set-titles-string or status-left, merge the #{?@muster_inbox,โ€ฆ} conditional into your own strings โ€” it renders nothing when there is no mail.

web ยท frontend ๐Ÿ“ฌ 2 ยท api-2 ยท backend db ยท migrations

The flag persists until the agent reads its inbox (a get_inbox call clears it), and switching to the tab does not clear it. muster only sets a tmux option here; it never types into a pane.

hooks

Register on start, handle mail on turn end.

The muster binary is its own session hook: muster hook <event> <model>. Wired into your agent's lifecycle hooks, it does two things โ€” SessionStart registers the session on the bus, and Stop (the end of each turn) checks for unread muster mail and, if there is any, instructs the agent to read its inbox and reply. There is nothing to copy or chmod, the hook is a no-op for sessions that aren't registered agents, and it never blocks a session from starting.

Claude Code โ€” add to ~/.claude/settings.json

"hooks": {
  "SessionStart": [
    { "matcher": "startup|resume",
      "hooks": [ { "type": "command", "command": "muster hook SessionStart claude" } ] }
  ],
  "Stop": [
    { "hooks": [ { "type": "command", "command": "muster hook Stop claude" } ] }
  ],
  "SessionEnd": [
    { "hooks": [ { "type": "command", "command": "muster hook SessionEnd claude" } ] }
  ]
}

Codex โ€” save as ~/.codex/hooks.json

{
  "hooks": {
    "SessionStart": [ { "hooks": [ { "type": "command", "command": "muster hook SessionStart codex" } ] } ],
    "Stop":         [ { "hooks": [ { "type": "command", "command": "muster hook Stop codex" } ] } ]
  }
}

Three Codex specifics: on the next codex launch it shows a one-time "Hooks need review" prompt โ€” choose Trust (trust is recorded against the file's hash; editing it re-prompts). Codex fires SessionStart on the session's first turn, not at launch โ€” the agent appears on the bus after its first exchange. And Codex has no SessionEnd event โ€” muster gc reaps agents whose tmux session is gone, so the roster stays honest either way.

If muster isn't on the PATH your harness gives hook commands (e.g. it's in ~/go/bin), use the absolute binary path in the command strings โ€” Codex in particular does not expand ~.

wake

Three ways an agent notices mail.

mailbox The ๐Ÿ“ฌ count on the tab (previous section) is the passive signal: you see it, and the agent acts on it the next time it checks its inbox โ€” or when you ask it to.
nudge muster nudge api-2 is the manual poke for waking an idle agent right now: it types "check your inbox" into that agent's pane and submits it โ€” immediately for Claude Code, with a short delayed Enter for Codex. This is the only muster mechanism that types into a pane.
stop hook The Stop hook is the automatic path: with the muster hook Stop entry from the previous section installed, an agent that finishes a turn with unread mail reads its inbox and replies on its own. Mail that arrives while an agent is working gets handled when the turn ends.

setup

Requirements and setup.

What you need

tmux Agents run inside tmux sessions โ€” muster uses tmux for agent identity, liveness, the mailbox, and nudging. Any tmux setup works; no particular configuration is required.
the binary Download a prebuilt binary from the releases page โ€” one static file with no dependencies, signed and notarized on macOS. Building from source with Go 1.22+ works too.
os macOS or Linux. On Windows, install inside WSL2, where tmux and unix sockets are standard.
an agent At least one coding agent that can register an MCP server โ€” Claude Code, Codex, or any other MCP client.

The three required steps

# 1. install the binary
$ curl -fsSL https://muster.tools/install.sh | sh
#    or build from source: go install github.com/schuettc/muster/cmd/muster@latest

# 2. register the MCP server with each agent
$ claude mcp add muster -s user -- muster mcp
$ codex mcp add muster -- muster mcp
#    any other MCP client: point it at `muster mcp` over stdio

# 3. in each tmux session, have the agent register โ€” either ask it once:
โ€บ "register on the muster bus"   (it calls its register_agent tool)
#    or install the SessionStart hook above and skip the ask

With that, agents can message, hand off tasks, and share state.

The two optional layers

mailbox Add the two render lines from the tmux section above to your ~/.tmux.conf, so unread mail shows as ๐Ÿ“ฌ on the tab. Without them the daemon still sets the option; nothing displays it.
hooks Add the hook blocks from the hooks section above to your agent configs, so sessions register on start and handle their own mail at turn end. Without them you register by asking (step 3) and wake agents with muster nudge.

Both layers are copy-paste from this page, and both also live in contrib/.