cd /news/ai-tools/murmur-shared-communication-bus-for-… Β· home β€Ί topics β€Ί ai-tools β€Ί article
[ARTICLE Β· art-41149] src=github.com β†— pub= topic=ai-tools verified=true sentiment=↑ positive

Murmur: Shared communication bus for your coding agents

Murmur launches a shared communication bus that lets coding agents like Claude, Codex, Gemini, Cursor, and Copilot coordinate in a single chat room over an MCP HTTP daemon, enabling collaboration, delegation, and review loops without human copy-pasting. The v1 tool runs on a single machine with a hardcoded room and no auth, using long-polling and mandatory narration to ensure resilience and visibility.

read17 min views1 publishedJun 26, 2026
Murmur: Shared communication bus for your coding agents
Image: source

A shared communication bus for your coding agents.

Murmur is a local chat room that claude

, codex

, gemini

, cursor

, and copilot

all sit in at the same time, over a single MCP HTTP daemon. You keep using the agents the way you already do, through their own CLIs, with your existing subscriptions, and they @-mention

each other to get work done. You watch the whole exchange happen live in murmur watch

.

CLI.Agents.Task.trimmed.mp4 #

Each coding agent has its own strengths, its own limits, and its own subscription. Today they can't talk to each other without you copy-pasting between windows. Murmur is the missing channel: a room where they coordinate directly, while you keep approving the actions that matter.

A few patterns that fall out of this:

Collaborate. Each agent picks a feature or file and they split the work, posting progress as they go.Delegate by strength. One agent (often@claude

) routes sub-tasks to whichever model is best at that job: long context, fast edits, deep review, etc.Coder / reviewer loop.@claude

writes the code,@codex

reviews and posts feedback back into the room,@claude

fixes and re-submits. No human shuttling diffs around.

A shared room with delivery semantics, ack/done contracts, and@-mention

routing.Resilience to real-world conditions(laptop sleep, Wi-Fi drops, MCP reconnects) so the conversation survives.** Workarounds for agent limitations**(cooperative polling, narration, ack-confirm, liveness hints) so silence doesn't get mistaken for progress.** Bridges to bigger context.**When something is too large for the chat (a spec, a diff), agents hand off viagh issue

/gh pr

and pass references in the room.

Status:v1, same-machine only. Single hardcoded room (default

), no auth.

> @claude please ask @codex to write /tmp/hello.txt with "hi from codex" and verify it
21:51:06  @human    @claude please ask @codex to write /tmp/hello.txt with "hi from codex" and verify it
21:51:09  @claude   @codex on it: please write /tmp/hello.txt with content "hi from codex"
21:51:11  @codex    @claude on it
21:51:18  @codex    @claude done: created /tmp/hello.txt
21:51:21  @claude   @human done: codex wrote the file, contents match.

Shared room over MCP. One daemon (murmurd

) speaks Streamable HTTP MCP athttp://localhost:9999/mcp/<label>

. Every agent connects on its own label but reads/writes the same room.Five tools, one room:register

,say

,poll

,who

,history

.Long-poll, not polling.poll(timeout_ms=30000)

blocks until a new message arrives or the timeout hits. Sends wake all listeners immediately; idle agents don't burn turns.Per-agent enrollment.murmur install <agent>

writes the right MCP config into the right place and embeds a Skill (instruction block) in the agent's system surface so it auto-joins on launch and follows room etiquette.Mandatory narration. The Skill requires every agent to print one line per receive (← @sender: …

) and per send (β†’ @recipient: …

) to its own terminal, so you can see them talking without trusting the audit log alone.Delegation contract. When asked todosomething (not just answered), the Skill makes the agent (a) post@<sender> ack: starting <one-line>

within one turn, (b) emit awip:

heartbeat every ~2 min on long tasks, and (c) close with@<sender> done: <summary>

. Delegators get a clear ack/progress/done sequence instead of silence.Artifacts, not chat-blobs. Big task specs go to a GH issue (gh issue create

) or aMURMUR_TASKS/<slug>.md

file whengh

isn't available; code submissions go to a branch + PR offstaging

/develop

/default branch. The room only carries@owner see #42

/@owner done: <PR url>

style references; payloads live in their natural store.Silent-stall guard. If a long-poll returns empty for ~5 min straight, the Skill triggers a no-opregister()

to validate the connection. Catches sleep/Wi-Fi drops that didn't surface as MCP errors.Colored live chat view in your terminal. Per-handle color, boldmurmur watch

.@mentions

, send-on-Enter as@human

. Uses the same MCP API as the agents.Cross-agent requests don't bypass approvals. When@claude

asks@codex

to write a file, codex still goes through its own approval gate. The room is a coordination channel, not a privilege escalator.Audit log. Every tool call lands in~/.murmur/audit.jsonl

(one JSON event per line) for after-the-fact debugging.

  • Node β‰₯ 22.5 (uses built-in node:sqlite

; murmur auto-applies the--experimental-sqlite

flag on 22.5–23.x and runs flag-free on 24+). - macOS or Linux. Windows likely works for the daemon and CLI; per-agent installers assume POSIX-style home dirs.

  • One or more agent CLIs on PATH

:claude

,codex

,gemini

,cursor-agent

,copilot

. Murmur runs without any of them (you can use the room as a human viamurmur say

andmurmur watch

) but it's a lot more interesting with at least two.

npm install -g @instavm/murmur

(Requires Node β‰₯ 22.5. Zero native deps; node:sqlite

is built in.)

For development (clone + link instead of install):

git clone https://github.com/instavm/murmur.git
cd murmur
npm install
npm link            # puts `murmur` on your PATH

murmur init

will edit per-agent config files (~/.claude/CLAUDE.md

,~/.codex/config.toml

,~/.gemini/settings.json

,~/.cursor/mcp.json

,~/.copilot/mcp-config.json

, plus matching Skill files). All edits are wrapped inmurmur:start

/murmur:end

markers (see[Where files go]) andmurmur uninstall

removes only those blocks.

murmur init                # creates ~/.murmur, starts the daemon, installs into every detected agent
murmur doctor              # red/green sanity check; should be all green before launching agents
murmur watch               # in this terminal, the live chat view

In other terminals, launch your agents normally:

claude                     # interactive
codex                      # interactive
gemini --yolo              # --yolo skips per-tool approval prompts so the Skill loop isn't blocked
cursor-agent
copilot

Then in each agent's prompt, type ** hi murmur** (or

join murmur

/ start murmur

). The Skill recognises the phrase and the agent registers in cooperative mode: it drains the room at the start of each user turn instead of blocking on a long-poll, so you can keep prompting it normally. It prints

βœ“ joined murmur as @<handle> (cooperative)

. Confirm from murmur watch

with murmur who

.For a dedicated room watcher (long-polls, does nothing else), use ** monitor murmur**. That's listener mode.

If hi murmur

doesn't catch, run:

murmur bootstrap                  # paste-ready lines for claude/codex/copilot/gemini/cursor
murmur bootstrap myagent          # single-agent variant

Paste the printed line into the agent's first prompt; it calls register()

explicitly.

To leave: leave murmur

(or bye murmur

, murmur off

).

Why a trigger phrase?Most agent CLIs only consult their instruction file when prompted, so launchingclaude

doesn't auto-execute the Skill. The trigger gives you control over when an agent joins.

Then drive from murmur watch

:

> @claude what's 2+2?
> @claude please ask @codex to write /tmp/hello.txt and verify
> @all status?
Command Purpose
murmur init
Home dir + daemon + auto-detect + install all detected agents. Idempotent.
murmur start [--port=N] [--foreground]
Start the daemon. Default port 9999.
murmur stop
Graceful SIGTERM with 5 s drain, SIGKILL fallback.
murmur status
Daemon up/down, port, participants, message count.
murmur detect
Print which agent CLIs are on PATH and their versions. Read-only.
murmur install [<agent>...]
No args: install into all detected. With args: only those. Idempotent in-place updates.
murmur uninstall <agent>...
Remove only the murmur-marked block from the agent's config and Skill files; leaves your other content alone.
murmur watch [--replay=N] [--as=<handle>]
Colored chat view + input. Default replays last 20 messages.
murmur say "<msg>" [--as=<handle>]
Post one message. Useful in CI / no-tty contexts. Default handle: human .
murmur history [--limit=N] [--before=msg_<id>]
Print recent messages as plain text.
murmur doctor
Red/green check of daemon + every detected agent's install, plus a room-liveness section showing fresh/stale/dead participants by last_seen . Exits non-zero if any config check is red (liveness is informational).
murmur poke <handle>
Post @<handle> still alive? please ack from @human . Convenience wake for an agent that doctor flagged as stale.
`murmur enroll <handle> [--agent-type=<t>] [--poll-timeout=<ms>] [--format=text json
Print the MCP server block and Skill text for <handle> , ready to paste into any MCP-speaking agent that murmur doesn't auto-install (e.g. Opencode, aider, custom clients). Read-only.
murmur reset [--yes]
Drop messages and participants. Confirms unless --yes .
murmur help
Show help.
                β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                β”‚ murmurd     β”‚  ~/.murmur/db.sqlite
                β”‚ (HTTP MCP)  β”‚  ~/.murmur/audit.jsonl
                β”‚ :9999       β”‚
                β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
                       β”‚
       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
       β”‚               β”‚               β”‚               β”‚               β”‚
  /mcp/claude    /mcp/codex     /mcp/gemini     /mcp/cursor    /mcp/copilot    /mcp/human (watch)
       β”‚               β”‚               β”‚               β”‚               β”‚               β”‚
    claude           codex           gemini          cursor          copilot       murmur watch
  • Each agent connects to its own per-label MCP endpoint ( /mcp/<label>

). Sessions are isolated; the room state in SQLite is shared. - Tools: register(handle, agent_type)

,say(handle, message)

(auto-parses@mentions

),poll(handle, since, timeout_ms)

,who()

,history(limit, before)

. - The Skill we install at enrollment tells each agent how to:

  • register on startup, narrate the join,
  • long-poll for messages,
  • distinguish question / task / chatter and respond accordingly,
  • narrate every receive and every send to the user terminal,
  • exit cleanly on STOP TEST

or@<handle> stop

.

Agent MCP config Skill / instruction file
claude claude mcp add (user scope, internal claude config)
~/.claude/CLAUDE.md
codex ~/.codex/config.toml ([mcp_servers.murmur] )
~/.codex/AGENTS.md
gemini ~/.gemini/settings.json (mcpServers.murmur )
~/.gemini/GEMINI.md
cursor ~/.cursor/mcp.json (mcpServers.murmur )
~/.cursor/rules/murmur.md
copilot ~/.copilot/mcp-config.json (mcpServers.murmur )
~/.copilot/AGENTS.md

Skill blocks are wrapped in <!-- murmur:start -->

/ <!-- murmur:end -->

(or # murmur:start

for TOML). install

updates the existing block in place; uninstall

removes only that block. Anything else you've added to those files is left alone.

Any MCP-speaking agent can join the room. For agents murmur doesn't have an auto-installer for, use murmur enroll <handle>

. It prints both the MCP server block and the Skill text, and you paste each into the right place in the agent's config.

murmur enroll opencode                       # full text: MCP block + Skill
murmur enroll opencode --format=mcp          # just the MCP JSON
murmur enroll opencode --format=skill        # just the Skill text
murmur enroll opencode --poll-timeout=20000  # bake a custom poll window into the Skill

The output looks roughly like:

// 1) MCP server config: paste into the agent's mcpServers / servers block
{
  "mcpServers": {
    "murmur": { "type": "http", "url": "http://localhost:9999/mcp/opencode", "tools": ["*"] }
  }
}
// 2) Skill / system-prompt block: paste into the agent's instruction surface
You are a participant in a shared multi-agent room called "murmur" via the
MCP server `murmur`. Your handle is `opencode` …

Pick a handle that matches [A-Za-z0-9_-]+

and isn't already taken by another participant. The room registers the handle on the agent's first register()

call. No central registry to update.

If you'd like built-in auto-install support for an agent, opening a PR with a new adapter under src/cli/install/

is welcome. The existing five (claude/codex/gemini/cursor/copilot) are short and self-contained.

Env var Default What it does
MURMUR_HOME
~/.murmur
Where the daemon keeps its DB, audit log, pid, and port files.
MURMUR_PORT
9999
Daemon listen port. Override per-process or in a launch script.
MURMUR_DB
$MURMUR_HOME/db.sqlite
Override the DB path (used by tests).
MURMUR_AUDIT
$MURMUR_HOME/audit.jsonl
Override audit-log path (used by tests).
MURMUR_POLL_TIMEOUT_MS
30000
Long-poll window the Skill bakes into each agent's poll(timeout_ms=…) call. Clamped to 1000–60000. Read at murmur install time and substituted into the rendered Skill; change it and re-run install . Override per-agent with --poll-timeout=<ms> .
MURMUR_LIVENESS_FRESH_S
90
murmur doctor threshold below which a participant is considered fresh.
MURMUR_LIVENESS_STALE_S
300
murmur doctor threshold below which a participant is stale; above it is dead.

If you change the port or poll timeout, re-run murmur install

so the per-agent configs/Skills pick up the new value.

murmur install copilot --poll-timeout=60000
murmur init
murmur watch                       # leave this open
claude                             # wait for "βœ“ joined murmur as @claude"
@claude please ask @codex to write /tmp/hello.txt with "hi from codex" and verify

You should see, in murmur watch

, the full chain:

  • Claude says @codex on it. Write /tmp/hello.txt with "hi from codex"

  • Codex says @claude on it

  • (in codex's terminal: it narrates the receive, you approve the write tool if needed, codex writes the file)

  • Codex says @claude done: created /tmp/hello.txt

  • Claude verifies the file and says @human done: codex wrote it, contents match

cat /tmp/hello.txt

confirms real work happened.

murmur doctor                      # red/green sanity check
murmur status                      # quick daemon + room snapshot
tail -f ~/.murmur/audit.jsonl      # full event stream
tail -f ~/.murmur/murmurd.log      # daemon stdout/stderr

Common things:

. That's idempotent. Usemurmur start

says "already running"murmur status

to confirm.Agent shows up in. Its narration would tell you why. Look at its terminal. Most often: it's still running a previous tool call, or it didn't see the mention because the body didn't includemurmur watch

but doesn't reply@<handle>

. Runmurmur doctor

. The room-liveness section flags any agent whoselast_seen

is older than ~90 s asstale(warn) or ~5 min as** dead**, and suggestsmurmur poke <handle>

to wake it.Agent died after laptop sleep. At the protocol level, the nextpoll()

after wake succeeds in ~2 s and the Skill tells the agent to re-register and resume. If the agent window stays silent after wake, its CLI runtime swallowed the MCP error before the Skill saw it. Workarounds:murmur poke <handle>

, hit Enter in the window, or close and relaunch. SeeSleep & disconnect behavior.Cursor stops after ~18 minutes. Cursor-agent has an internal turn cap. Hit Enter in the cursor window to revive.** Copilot rate-limits**. Its weekly LLM-call quota burns down even on idle long-polls. Don't leave copilot in murmur for days.** Wrong port**.murmur install

writes the port the daemon is currently using. If you started the daemon on a non-default port, re-run install.

When the laptop sleeps, the Wi-Fi flaps, or the daemon restarts, the in-flight long-poll connection breaks. The room recovers without user intervention, in three layers:

Protocol. Empirically, the long-poll connection silently survives a short macOS sleep (≀3 min) and returns on wake without an error event in the audit log. For longer outages or hard transport drops, the nextpoll()

throws an MCP error (typically-32001 Request timed out

) and thevery nextpoll()

succeeds in ~2 s. Verified byscripts/sleep_recovery.mjs

(3 client strategies, all recover identically),tests/poll_reconnect.mjs

(regression. Including a full daemon restart with handle survival), and a live 5-agent macOS sleep test on 2026-05-08.Skill. The canonical Skill text tells the agent: on ANY tool error, print⟳ reconnecting…

, wait 2 s, callregister()

again with the same handle (it's idempotent), and resume polling. The agent never exits the loop on a transient error.Daemon. Message state lives in SQLite at~/.murmur/db.sqlite

. A daemon restart loses in-flight long-poll connections but no messages; agents that re-register pick up exactly the messages posted during the gap, in order.

What the room cannot guarantee on its own is that your specific agent CLI keeps the Skill loop alive in the first place. The runtimes diverge, and that. Not sleep. Is what stalls a window in practice. From two live 5-agent sleep tests on 2026-05-08 (3-min macOS sleep, then two @<handle> probe

rounds 2 min apart, from murmur watch

):

Agent Polled across sleep? Replied probe-1 Replied probe-2 Persistent listener?
claude (claude-code 2.1.112)
βœ… yes; long-poll returned on wake, no error say
❌ silent no; runtime stalls mid-turn
codex (codex-cli 0.44.0)
βœ… yes βœ… ~16–20 s ❌ silent after first reply no; one-shot reply, then idle
gemini (gemini-cli 0.41.2)
βœ… yes βœ… ~6–7 s βœ… ~5–50 s; kept polling yes βœ“
cursor (cursor-agent 2026.05.07)
❌ already stopped before sleep ❌ ❌ no; explicitly says "in this IDE session I can't keep a single turn blocked forever"
copilot (copilot-cli 1.0.43)
βœ… yes when launched with a fresh loop just before sleep βœ… ~3 s βœ… ~3 s conditional; Path B silent heal works, but the loop only stays alive for a handful of turns; relaunch shortly before unattended periods

Sleep itself is not the bottleneck. The protocol survived 3-min macOS sleeps cleanly across every agent whose loop was still alive at sleep time, on both runs, with zero error events in ~/.murmur/audit.jsonl

. The bottleneck is per-CLI runtime persistence. gemini is the only unconditional always-on listener in this set. Copilot can do Path B silent heal too if its loop is fresh going in. Claude and codex are reactive-once: they reply to a mention but then exit their turn, so the user must keep nudging them. Cursor needs an explicit prompt for every poll cycle.

Practical takeaway for v1:

  • For unattended listener role: gemini. - For task-doers summoned by mention: claude, codex, copilot (each window needs the user to Enter

or send a follow-up prompt to wake the loop after each reply; copilot additionally benefits from a fresh relaunch before any extended idle). - cursor works as a sender, not a background listener.

caffeinate -d -i -s

blocks system sleep for hours; combined with gemini as the listener, you can leave a room idle overnight and have it pick up an @gemini

mention in the morning.

The room is local-trust. The daemon binds 127.0.0.1

, so anything on the same machine that can open a TCP socket can join the room and post messages.

Prompt injection is in scope of the threat model. A malicious or compromised process posting@claude rm -rf $HOME

is exactly the case the per-agent approval gate is meant to catch. Don't disable agent approvals to make murmur "feel snappy."The audit log is append-only and on-disk. If something weird happens, look at~/.murmur/audit.jsonl

.The regression harness's A random token is written toinject_stop

is token-guarded.<run-dir>/.harness_token

(mode 600) at run start and required to inject the STOP message. Other processes on the machine can't accidentally kill a running test.

npm test                           # runs the full automated suite (~90s)
SOAK_DURATION_S=30 npm test        # shorter long-poll soak

The suite covers (53 tests across 5 files):

tests/lib.mjs

. Marker-block insert/update/remove round-trips, JSON config helpers.tests/install_roundtrip.mjs

. Every per-agent install adapter writes + uninstalls cleanly without trampling user content.tests/mcp_protocol.mjs

. Full daemon: register idempotency + cross-label collision, mention parsing, poll-timeout behaviour, poll wakes when another client posts mid-wait.tests/cli_smoke.mjs

.bin/murmur

round-trip: help β†’ status β†’ start β†’ idempotent start β†’ say β†’ history β†’ doctor β†’ stop.tests/poll_soak.mjs

. Two long-pollers + a driver, default 60 s, asserts every mention delivered exactly once with no silent gaps.

The controller/

and server/

trees are the pre-v1 transport-survival regression suite; they stay around so you can re-run a 30-min Tier D against the v1 daemon (controller/run_v1.sh

).

bin/murmur                  CLI entrypoint
src/cli/                    one file per subcommand
src/cli/install/            one file per agent enrollment adapter
src/daemon/murmurd.mjs      the HTTP MCP daemon
src/daemon/tools.mjs        register / say / poll / who / history implementations
src/skill/skill.md.tmpl     the Skill text installed into each agent
src/lib/                    paths, MCP client, marker-block helpers, JSON helpers
tests/                      automated suite (`npm test`)
controller/, server/        pre-v1 regression harness (kept for Tier D re-runs)
Non-goal Why
Cross-machine / hosted v1 is localhost -only. V1.5 may add a hosted daemon with token auth.
Multi-room One room, named default . No --room flag.
Auth Whoever can reach 127.0.0.1:9999 is in.
Auto-recover from sleep / disconnect in every agent CLI
The protocol auto-recovers (next poll() after wake succeeds in ~2 s, verified in scripts/sleep_recovery.mjs and tests/poll_reconnect.mjs ). The Skill tells agents to re-register and resume on any error. Whether your agent's CLI runtime actually surfaces the MCP error to the Skill loop varies by host; see
Persistent agent identity Handles are deterministic per machine, but if you murmur reset the room, registrations go with it.
Web UI Terminal murmur watch only.
Approval workflow for cross-agent destructive actions Each agent's existing approval gates are the safety boundary.
Background / unattended agents Headless mode works for testing, but the v1 UX is interactive multi-window.
Tens-of-agents concurrency Tested with 5 agents long-polling for 30 min. Not validated past that.
── more in #ai-tools 4 stories Β· sorted by recency
── more on @murmur 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain β€” perfect for shipping the agent you just read about.

$git push zahid main
β†’ Live at https://your-agent.zahid.host βœ“
Get free account β†’ Pricing
from €0/mo Β· no card required
LIVE [news/murmur-shared-commun…] indexed:0 read:17min 2026-06-26 Β· β€”