npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@instavm/murmur

v0.1.2

Published

Local multi-agent room — coding agents (claude, codex, gemini, cursor, copilot) coordinate live via a shared MCP HTTP daemon.

Readme

murmur

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.

Why

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.

What murmur provides

  • 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 via gh 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.

What it does

  • Shared room over MCP. One daemon (murmurd) speaks Streamable HTTP MCP at http://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 to do something (not just answered), the Skill makes the agent (a) post @<sender> ack: starting <one-line> within one turn, (b) emit a wip: 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 a MURMUR_TASKS/<slug>.md file when gh isn't available; code submissions go to a branch + PR off staging/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-op register() to validate the connection — catches sleep/Wi-Fi drops that didn't surface as MCP errors.
  • murmur watch — colored live chat view in your terminal. Per-handle color, bold @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.

Requirements

  • 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 via murmur say and murmur watch — but it's a lot more interesting with at least two.

Install

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 in murmur:start/murmur:end markers — see Where files go — and murmur uninstall removes only those blocks.

Quickstart

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 launching claude 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?

Commands

| 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\|skill\|mcp] | 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. |

How it works

                ┌─────────────┐
                │ 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.

Where files go (per-agent install layout)

| 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.

Manually enrolling other agents (opencode, aider, custom MCP clients, …)

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
# Murmur — multi-agent room participation
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 first-class 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.

Configuration

| 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.

# Per-agent override (writes timeout_ms=60000 into copilot's Skill only):
murmur install copilot --poll-timeout=60000

Try it: a 2-minute demo

murmur init
murmur watch                       # leave this open
# in another terminal:
claude                             # wait for "✓ joined murmur as @claude"
# (also launch `codex` in a third terminal)
# then in murmur watch:
@claude please ask @codex to write /tmp/hello.txt with "hi from codex" and verify

You should see, in murmur watch, the full chain:

  1. claude says @codex on it — write /tmp/hello.txt with "hi from codex"
  2. codex says @claude on it
  3. (in codex's terminal: it narrates the receive, you approve the write tool if needed, codex writes the file)
  4. codex says @claude done: created /tmp/hello.txt
  5. claude verifies the file and says @human done: codex wrote it, contents match

cat /tmp/hello.txt confirms real work happened.

Troubleshooting

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:

  • murmur start says "already running" — that's idempotent. Use murmur status to confirm.
  • Agent shows up in murmur watch but doesn't reply — 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 include @<handle>. Run murmur doctor — the room-liveness section flags any agent whose last_seen is older than ~90 s as stale (warn) or ~5 min as dead, and suggests murmur poke <handle> to wake it.
  • Agent died after laptop sleep — at the protocol level, the next poll() 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. See Sleep & 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 portmurmur install writes the port the daemon is currently using. If you started the daemon on a non-default port, re-run install.

Sleep & disconnect behavior

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

  1. 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 next poll() throws an MCP error (typically -32001 Request timed out) and the very next poll() succeeds in ~2 s. Verified by scripts/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.
  2. Skill — the canonical Skill text tells the agent: on ANY tool error, print ⟳ reconnecting…, wait 2 s, call register() again with the same handle (it's idempotent), and resume polling. The agent never exits the loop on a transient error.
  3. 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 | ⚠️ polled the message but didn't 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.

Security model

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 inject_stop is token-guarded. A random token is written to <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.

Development

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.mjsbin/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).

Layout

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)

What it doesn't do

| 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 Sleep & disconnect behavior for the per-agent matrix. | | 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. |

License

Apache License 2.0 — see LICENSE and NOTICE.