{
  "markdown": "# agent-comm\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n[![Node.js](https://img.shields.io/badge/node-%3E%3D20.11-brightgreen)](https://nodejs.org/)\n[![Tests](https://img.shields.io/badge/tests-288%20passing-brightgreen)]()\n[![MCP Tools](https://img.shields.io/badge/MCP%20tools-7-purple)]()\n[![REST Endpoints](https://img.shields.io/badge/REST-29%20endpoints-orange)]()\n\n**Agent-agnostic intercommunication system.** Lets AI coding agents — Claude Code, Codex CLI, Gemini CLI, Aider, or any custom tool — talk to each other, share state, and coordinate work in real time.\n\n| Light Theme                                | Dark Theme                                     |\n| ------------------------------------------ | ---------------------------------------------- |\n| ![Overview](docs/screenshots/overview.png) | ![Dark Theme](docs/screenshots/dark-theme.png) |\n\n## Why\n\nWhen you run multiple AI agents on the same codebase — code review in one terminal, implementation in another, testing in a third — they have no idea the others exist. They duplicate work, create merge conflicts, and miss context.\n\n|                   | Without agent-comm                   | With agent-comm                                      |\n| ----------------- | ------------------------------------ | ---------------------------------------------------- |\n| **Discovery**     | Agents don't know others exist       | Agents register with skills, discover by capability  |\n| **Coordination**  | Edit the same file, create conflicts | Lock files/regions, divide work                      |\n| **Communication** | None — each agent works blind        | Messages, channels, broadcasts                       |\n| **State sharing** | Duplicate work, missed context       | Shared KV store with atomic CAS                      |\n| **Visibility**    | No idea what's happening             | Real-time dashboard + activity feed shows everything |\n\n**agent-comm** gives them a shared communication layer:\n\n- Agents **register** with a name, capabilities, and skills so others can discover them\n- They **discover** each other by skill or tag for dynamic task routing\n- They exchange **messages** (direct, broadcast, or channel-based) to coordinate, with importance levels (`low`/`normal`/`high`/`urgent`) and optional ack\n- They **poll** their inbox with a blocking wait (`comm_poll`) so mid-flight peer signals are consumed without busy-looping\n- They share **state** (a key-value store with atomic CAS) for locks, flags, and progress\n- They log **activity events** (commits, test results, file edits) to a shared feed\n- They detect **stuck agents** — alive (heartbeat OK) but not making progress\n- They **serialize file edits** via the system-layer `file-coord` hook (see below) so parallel agents on shared files cannot clobber each other\n- A **web dashboard** shows everything in real time, including an Activity Feed tab\n\nIt works with any agent that supports [MCP](https://modelcontextprotocol.io/) (stdio transport) or can make HTTP requests (REST API).\n\n### Why hooks, not just MCP tools\n\nThe MCP tools (`comm_state`, etc.) give agents the _primitives_ to coordinate, but they don't _enforce_ coordination — the agent has to remember to call them. Our [bench](bench/README.md) measured what happens when you rely on the model's discretion: **even with strict procedural prompting, Claude follows the protocol on the first claim cycle then drifts back to \"be helpful, finish the task.\"** Soft coordination is unreliable.\n\nThe fix is a pair of `PreToolUse` hooks shipped in `scripts/hooks/`: **`file-coord`** intercepts every `Edit`/`Write`/`MultiEdit` and claims the file via REST `POST /api/state/file-locks/<path>/cas` (blocks the edit if another agent holds the lock); **`bash-guard`** intercepts `git commit`, `git push`, `npm install`, `npm test`, builds, migrations, and dev-server starts and blocks/warns when they would conflict with another session's WIP. **The protocol becomes infrastructure, not a prompt the agent might ignore.**\n\nThe bench's headline pilot is **`multi-term-commit`** — directly modeling the daily pain of two terminal sessions on the same project. Session A edits two files but doesn't commit. Session B then edits two other files and runs `git commit -am \"my work\"`. Without the hook, B's commit silently includes A's WIP. With the hook, B's commit is blocked at the bash layer with an actionable message, and B reacts (selective staging, restore, or coordinate). Bench result:\n\n|               | naive (no hook)                            | **with hooks**            |\n| ------------- | ------------------------------------------ | ------------------------- |\n| Commit purity | **MIXED** — bar.js, baz.js, foo.js, qux.js | **PURE — baz.js, qux.js** |\n| Wall time     | 91.0s                                      | **78.8s (-13%)**          |\n| Total cost    | $0.774                                     | **$0.591 (-24%)**         |\n| Outcome       | A's WIP silently committed under B's name  | clean commit, no clobber  |\n\nThe hook is **faster AND cheaper**, not just safer. Reason: when agents lack coordination on shared workspaces, they read stale state, get confused mid-task, retry, and re-think. Serializing access and surfacing the conflict early removes that wasted thinking. Run `npm run setup` to install both hooks automatically; see [Setup → File Coordination](docs/SETUP.md#pretooluse--posttooluse--scriptshooksfile-coordmjs) for manual install on Claude Code, OpenCode, or any custom MCP client. See [bench/README.md](bench/README.md) for the measurement methodology.\n\n### How agent-comm fits together\n\n`agent-comm` is a single Node process that exposes three transports — MCP stdio (for AI hosts), REST + WebSocket (for hooks, dashboards, custom scripts) — backed by a SQLite database in WAL mode. Hooks installed in your Claude Code (or other host) settings call the REST endpoint at `localhost:3421` to claim file locks, query who-edited-what, and broadcast presence. The dashboard UI at the same port is a live view of every agent, message, channel, and shared-state entry. Multiple AI hosts can connect simultaneously and see the same world.\n\n```mermaid\ngraph TD\n    A[\"Agent A<br/>(Claude Code)\"] -->|MCP stdio| COMM\n    B[\"Agent B<br/>(Codex CLI)\"] -->|MCP stdio| COMM\n    C[\"Agent C<br/>(Custom script)\"] -->|REST API| COMM\n    HK[\"PreToolUse hooks<br/>(file-coord, bash-guard)\"] -->|REST cas| COMM\n\n    subgraph COMM[\"agent-comm\"]\n        D[\"Agents<br/>Register, discover, heartbeat\"]\n        E[\"Messages<br/>Direct, broadcast, channels, threads\"]\n        F[\"State<br/>Namespaced KV with CAS\"]\n        G[\"Events<br/>Real-time pub/sub\"]\n        D --> DB[\"SQLite DB<br/>WAL mode, FTS5 search\"]\n        E --> DB\n        F --> DB\n        DB --> WS[\"WebSocket\"]\n    end\n\n    WS --> UI[\"Dashboard UI<br/>http://localhost:3421\"]\n```\n\n## Quick start\n\n### Install from npm\n\n```bash\nnpm install -g agent-comm\n```\n\n### Or clone from source\n\n```bash\ngit clone https://github.com/keshrath/agent-comm.git\ncd agent-comm\nnpm install\nnpm run build\n```\n\n### Option 1: MCP server (for any MCP-compatible AI host)\n\nagent-comm runs as a stdio MCP server, so any MCP-compatible host can use it.\nTested hosts include Claude Code, Cline, OpenCode, Cursor (read-only state),\nWindsurf, Codex CLI, Aider, and Continue.dev. Adapter recipes for each are in\n[docs/SETUP.md](docs/SETUP.md#client-setup).\n\nGeneric MCP config:\n\n```json\n{\n  \"mcpServers\": {\n    \"agent-comm\": {\n      \"command\": \"npx\",\n      \"args\": [\"agent-comm\"]\n    }\n  }\n}\n```\n\nAdd this to your host's MCP config file (the path varies by host —\n`~/.claude.json` for Claude Code, `~/.config/opencode/config.json` for\nOpenCode, `~/.cursor/config.json` for Cursor, etc. — see the per-host\nsections in `docs/SETUP.md`).\n\nThe dashboard auto-starts at http://localhost:3421 on the first MCP connection\nregardless of which host is connected.\n\n### Option 2: Standalone server (for REST/WebSocket clients)\n\n```bash\nnode dist/server.js --port 3421\n```\n\n### Option 3: Automated setup (Claude Code)\n\n```bash\nnpm run setup\n```\n\nRegisters the MCP server in `~/.claude.json`, installs the [hook scripts](docs/SETUP.md#hooks) (lifecycle + file-coord + bash-guard), and configures permissions. **Other hosts**: see [docs/SETUP.md](docs/SETUP.md#client-setup) for the per-host integration recipes — every host that supports pre-tool-call hooks can use the same `file-coord.mjs` script unchanged.\n\n## MCP tools (7)\n\n| Tool            | Description                                                                                                |\n| --------------- | ---------------------------------------------------------------------------------------------------------- |\n| `comm_register` | Register with name, capabilities, metadata, skills, and auto-join channels                                 |\n| `comm_agents`   | Agent management — actions: `list`, `discover`, `whoami`, `heartbeat`, `status`, `unregister`              |\n| `comm_send`     | Send messages — direct (`to`), channel, broadcast, reply (`reply_to`), forward (`forward`)                 |\n| `comm_inbox`    | Read inbox (direct + channel messages, unread filter, `importance` filter, thread view via `thread_id`)    |\n| `comm_poll`     | Block until a new inbox message arrives (supports `timeout_ms` and `importance` filter)                    |\n| `comm_channel`  | Channel management — actions: `create`, `list`, `join`, `leave`, `archive`, `update`, `members`, `history` |\n| `comm_state`    | Shared key-value state — actions: `set`, `get`, `list`, `delete`, `cas`                                    |\n\n## REST API\n\nAll endpoints return JSON. CORS enabled. See [full API reference](docs/API.md) for details.\n\n```\nGET  /health                              Server status + uptime\nGET  /api/agents                          List online agents\nGET  /api/agents/:id                      Get agent by ID or name\nGET  /api/agents/:id/heartbeat             Agent liveness (status + heartbeat age)\nGET  /api/channels                        List active channels\nGET  /api/channels/:name                  Channel details + members\nGET  /api/channels/:name/members          Channel member list\nGET  /api/channels/:name/messages         Channel messages (?limit=50)\nGET  /api/messages                        List messages (?limit=50&from=&to=&offset=)\nGET  /api/messages/:id/thread             Get thread\nGET  /api/search?q=keyword                Full-text search (?limit=20&channel=&from=)\nGET  /api/state                           List state entries (?namespace=&prefix=)\nGET  /api/state/:namespace/:key           Get state entry\nGET  /api/feed                              Activity feed events (?agent=&type=&since=&limit=50)\nGET  /api/overview                        Full snapshot (agents, channels, messages, state)\nGET  /api/export                          Full database export as JSON\n\nPOST   /api/messages                      Send a message (body: {from, to?, channel?, content})\nPOST   /api/state/:namespace/:key         Set state (body: {value, updated_by})\nPOST   /api/state/:namespace/:key/cas     Atomic compare-and-swap (file-coord hook uses this)\nDELETE /api/messages                       Purge all messages\nDELETE /api/messages                       Delete messages by filter\nDELETE /api/messages/:id                   Delete a message (body: {agent_id})\nDELETE /api/state/:namespace/:key          Delete state entry\nDELETE /api/agents/offline                 Purge offline agents\nPOST   /api/cleanup                       Trigger manual cleanup\nPOST   /api/cleanup/stale                 Clean up stale agents and old messages\nPOST   /api/cleanup/full                  Full database cleanup\n```\n\n## Agent visibility and status\n\n`comm_agents` with `action: \"heartbeat\"` accepts an optional `status_text` parameter, letting agents update their visible status in the same call that keeps them online:\n\n```jsonc\n// MCP call — heartbeat + status update in one\ncomm_agents({ \"action\": \"heartbeat\", \"status_text\": \"implementing auth module\" })\n\n// Clear status text (pass null)\ncomm_agents({ \"action\": \"heartbeat\", \"status_text\": null })\n\n// Plain heartbeat — status text unchanged\ncomm_agents({ \"action\": \"heartbeat\" })\n```\n\n**Hosts that support lifecycle hooks** (Claude Code, OpenCode, future Cursor/Codex when they ship hook APIs) get automatic heartbeats, registration, and status via the lifecycle hook scripts shipped in `scripts/hooks/`. Subagents spawned by the Agent tool inherit the same registration via `SubagentStart`, so they appear on the dashboard alongside the main session. **Hosts without hook support** (Cursor, Windsurf, Aider as of 2025) can still use the MCP tools — agents must call `comm_register` and `comm_agents heartbeat` from the host's instructions file. **Custom MCP clients or scripts** can call the REST endpoints or use `comm_heartbeat` directly to show live progress.\n\nThe REST endpoint `GET /api/agents/:id/heartbeat` returns agent liveness info (status, heartbeat age in ms/s, status text) for external monitoring.\n\n## Communication patterns\n\n### Direct messaging\n\n```mermaid\nsequenceDiagram\n    participant A as Agent A\n    participant S as agent-comm\n    participant B as Agent B\n\n    A->>S: comm_send(to B, content review PR 42)\n    Note over S: Store in SQLite, emit event\n    B->>S: comm_inbox()\n    S-->>B: message from A\n    B->>S: comm_reply(message_id 1, LGTM merging)\n```\n\n### Shared state with CAS (distributed locking)\n\n```mermaid\nsequenceDiagram\n    participant A as Agent A\n    participant S as agent-comm\n    participant B as Agent B\n\n    A->>S: comm_state(action cas, key deploy-lock, new agent-a)\n    S-->>A: swapped true\n    B->>S: comm_state(action cas, key deploy-lock, new agent-b)\n    S-->>B: swapped false\n    Note over B: Lock held by agent-a, back off\n```\n\n## Dashboard\n\n![Messages View](docs/screenshots/messages.png)\n\nThe web dashboard auto-starts at **http://localhost:3421** and shows agents, messages, channels, shared state, and the activity feed in real time. See the [Dashboard Guide](docs/DASHBOARD.md) for all views and features.\n\n---\n\n## Testing\n\n```bash\nnpm test              # 288 tests across 16 files\nnpm run test:watch    # Watch mode\nnpm run test:e2e      # E2E tests only\nnpm run test:coverage # Coverage report\nnpm run check         # Full CI: typecheck + lint + format + test\n```\n\n## Environment variables\n\n| Variable                    | Default | Description                                |\n| --------------------------- | ------- | ------------------------------------------ |\n| `AGENT_COMM_PORT`           | `3421`  | Dashboard HTTP/WebSocket port              |\n| `AGENT_COMM_RETENTION_DAYS` | `7`     | Days before auto-purge of old data (1-365) |\n\n## Documentation\n\n- [Setup Guide](docs/SETUP.md) — installation, client setup (Claude Code, OpenCode, Cursor, Windsurf), hooks\n- [Architecture](docs/ARCHITECTURE.md) — source structure, design principles, database schema\n- [Dashboard](docs/DASHBOARD.md) — web UI views and features\n- [Changelog](CHANGELOG.md)\n\n## License\n\nMIT — see [LICENSE](LICENSE)\n",
  "bytes": 15147,
  "sha": "11209f3bb98cf63b3b70cd34943f03ebb41ebba86177dd6aef244b5798ae3ba4",
  "repo_slug": "keshrath/agent-comm",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/plg_keshrath_agent_comm_agent_comm_d9971d90/readme"
}