{
  "markdown": "# cc-dm\n\n[![npm version](https://img.shields.io/npm/v/cc-dm.svg)](https://www.npmjs.com/package/cc-dm)\n[![license](https://img.shields.io/npm/l/cc-dm.svg)](https://github.com/Akram012388/cc-dm/blob/main/LICENSE)\n\nPeer-to-peer direct messaging between Claude Code sessions.\n\n## What it does\n\nRunning multiple Claude Code sessions in parallel — a planner, a backend worker, a test runner — means context constantly needs to move between terminals. The default workflow is copy-paste: pull text from one session, switch windows, paste into another, lose formatting, lose thread.\n\ncc-dm lets any session DM any other session on the same machine. Messages are delivered as native `<channel>` events within 500ms via the Claude Code Channels protocol, landing directly in the receiving session's context window.\n\n## How it works\n\n```\n  Session A (planner)  ──┐\n  Session B (backend)  ──┼──→  ~/.cc-dm/bus.db  (SQLite WAL)\n  Session C (tests)    ──┘          ↑\n                               500ms poll per session\n                               → <channel> event pushed into context\n```\n\nEach session spawns a cc-dm channel server via stdio. The server connects to a shared SQLite database at `~/.cc-dm/bus.db`. When a session sends a message, it writes a row to the bus. Every other session's server polls the bus every 500ms, picks up messages addressed to it, and pushes them as `<channel>` events into its parent session. No daemon, no ports, no network. Just a shared file and a poll loop.\n\n## Requirements\n\n- **Claude Code** v2.1.80 or later\n- **claude.ai login** — Channels requires cloud authentication, not API key auth\n- **Bun** runtime ([bun.sh](https://bun.sh))\n- **macOS** — primary supported platform\n\n## Quick Start\n\nStart a new Claude Code session and enter the following commands:\n\n```\n/plugin marketplace add cc-dm-marketplace\n/plugin install cc-dm\n```\n\nRestart Claude Code. The cc-dm tools and skills will be available in all sessions.\n\n## Install (alternative methods)\n\n**Via npm** (requires [Bun](https://bun.sh)):\n\n```bash\nnpm install cc-dm\n```\n\nThe npm package contains the full plugin source. After installing, follow the [Quick Start](#quick-start) above to register the plugin with Claude Code.\n\n> **Note:** cc-dm is a Claude Code channel plugin, not a standalone library. The npm package exists for discoverability and as a distribution mirror — the primary install method is the plugin marketplace above.\n\n**Via curl:**\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/Akram012388/cc-dm/main/install.sh | bash\n```\n\n## Quick alias\n\nAdd this to your `~/.zshrc` or `~/.bashrc`:\n\n```bash\nalias cc-dm='claude --dangerously-skip-permissions --dangerously-load-development-channels plugin:cc-dm@cc-dm-marketplace'\n```\n\nThen launch sessions with:\n\n```bash\nCC_DM_SESSION_NAME=planner CC_DM_SESSION_ROLE=orchestrator CC_DM_SESSION_PROJECT=myapp cc-dm\n```\n\nOr just `cc-dm` and register interactively via `/cc-dm:register`.\n\n> **Note:** `--dangerously-skip-permissions` bypasses all tool permission prompts for the session, not just cc-dm's. Use with awareness.\n\n## Usage\n\nStart a session without the alias:\n\n```bash\nCC_DM_SESSION_NAME=planner CC_DM_SESSION_ROLE=orchestrator CC_DM_SESSION_PROJECT=myapp \\\nclaude --dangerously-load-development-channels plugin:cc-dm@cc-dm-marketplace\n```\n\nOnce inside, use natural language:\n\n> \"Register this session as planner\"\n\n> \"DM the backend session: auth spec is ready\"\n\n> \"Who is active in cc-dm?\"\n\n> \"Broadcast to all sessions: wrapping up in 10\"\n\n## Multi-session orchestration\n\nOpen two or more terminals and launch Claude Code with different session identities:\n\n**Terminal 1 — Planner:**\n```bash\nCC_DM_SESSION_NAME=planner CC_DM_SESSION_ROLE=orchestrator CC_DM_SESSION_PROJECT=myapp claude --dangerously-load-development-channels plugin:cc-dm@cc-dm-marketplace\n```\n\n**Terminal 2 — Backend:**\n```bash\nCC_DM_SESSION_NAME=backend CC_DM_SESSION_ROLE=worker CC_DM_SESSION_PROJECT=myapp claude --dangerously-load-development-channels plugin:cc-dm@cc-dm-marketplace\n```\n\nOr skip the env vars and register interactively using `/cc-dm:register` after launch.\n\nSessions can now message each other directly, broadcast to all, and coordinate work across terminals.\n\n## Session identity\n\nSet these environment variables before launching:\n\n- `CC_DM_SESSION_NAME` — your display name (e.g. `planner`, `backend`, `tests`)\n- `CC_DM_SESSION_ROLE` — your role (e.g. `orchestrator`, `worker`, `reviewer`)\n- `CC_DM_SESSION_PROJECT` — optional project tag (e.g. `myapp`, `api-server`)\n\nSee also: [Message metadata](#message-metadata), [Permission relay](#permission-relay), [Access control](#access-control) for optional env vars that enable advanced features.\n\nIf not set, Claude will ask you to register via the `/cc-dm:register` skill on first interaction. Each session gets an auto-generated internal ID (`session-<random hex>`) used for message routing. Sessions send a heartbeat every 30 seconds. A session with no heartbeat for 60 seconds is automatically deleted from the roster. Undelivered messages expire after 15 seconds. No manual cleanup needed.\n\n> **Recommended naming convention:** Use `[project]-[name]` for session names, e.g. `myapp-planner`, `myapp-backend`, `myapp-tests`. Keep the prefix consistent across all workers in the same project and ensure it matches the `CC_DM_SESSION_PROJECT` value. This makes `who` output immediately scannable and helps Claude associate sessions with their project context at a glance.\n\n## Project-scoped messaging\n\nWhen working across multiple projects or worktrees, both broadcasts and DMs can be scoped to a project. Sessions with a `project` tag can only message other sessions with the same tag. Sessions without a project can message anyone (global, the default).\n\n```bash\n# Terminal 1 — frontend worker on myapp\nCC_DM_SESSION_NAME=frontend CC_DM_SESSION_ROLE=worker CC_DM_SESSION_PROJECT=myapp cc-dm\n\n# Terminal 2 — backend worker on myapp\nCC_DM_SESSION_NAME=backend CC_DM_SESSION_ROLE=worker CC_DM_SESSION_PROJECT=myapp cc-dm\n\n# Terminal 3 — worker on a different project\nCC_DM_SESSION_NAME=api-dev CC_DM_SESSION_ROLE=worker CC_DM_SESSION_PROJECT=api-server cc-dm\n```\n\nA broadcast from `frontend` reaches `backend` but not `api-dev`. A DM from `frontend` can reach `backend` (same project) but not `api-dev` (different project). A session without a project tag can broadcast and DM any active session — project scoping only restricts outbound messages from sessions that have a tag set.\n\nYou can also set the project interactively via `/cc-dm:register` — the skill shows active project tags so you can pick an existing one.\n\n> **Note:** Project scoping is an opinionated default designed for structured multi-project workflows. You can override it at any time — use `/cc-dm:register` or say \"register\" to change a session's project tag, clear it for global access, or scope it to a different project. This lets you mix isolation styles: keep most workers scoped to their project while leaving a coordinator session global, or temporarily remove a session's project tag when it needs to reach across boundaries.\n\n## Message metadata\n\nThe `dm` and `broadcast` tools accept optional metadata fields that are delivered as attributes on the `<channel>` tag:\n\n- **`priority`** — `urgent`, `normal`, or `low`\n- **`message_type`** — `task`, `question`, `status`, or `review`\n- **`thread_id`** — any string (max 64 chars) to group related messages into a conversation thread\n\nThese are purely informational — they don't change delivery behavior. The receiving session's Claude uses them to prioritize, filter, or group messages contextually. If omitted, messages work exactly as before.\n\n> **Example:** `dm(to=\"backend\", content=\"deploy is broken\", priority=\"urgent\", message_type=\"status\")` delivers with `priority=\"urgent\"` and `message_type=\"status\"` visible in the channel event attributes.\n\n## Permission relay\n\nEnables one session to remotely approve or deny tool calls for another session, using the Claude Code Channels `claude/channel/permission` protocol capability. Completely opt-in — off by default.\n\n**Setup:** Add these env vars when launching a worker session that needs remote approval:\n\n```bash\nCC_DM_PERMISSION_RELAY=1 \\\nCC_DM_PERMISSION_APPROVER=orchestrator \\\nCC_DM_SESSION_NAME=worker CC_DM_SESSION_ROLE=worker CC_DM_SESSION_PROJECT=myapp \\\nclaude --dangerously-load-development-channels plugin:cc-dm@cc-dm-marketplace\n```\n\n**How it works:**\n1. Worker wants to run a tool (e.g., `Bash rm -rf dist/`)\n2. Instead of showing a local approval dialog, cc-dm relays the request to the `orchestrator` session\n3. Orchestrator sees: *\"Session worker wants to use Bash... Reply with `yes abcde` or `no abcde`\"*\n4. Orchestrator replies with the verdict — worker's tool call is approved or denied\n\nIf `CC_DM_PERMISSION_APPROVER` is not set, the request broadcasts to all project sessions — first response wins. The local terminal approval dialog is always available as a fallback.\n\n| Env var | Required? | Purpose |\n|---------|-----------|---------|\n| `CC_DM_PERMISSION_RELAY=1` | Yes | Enables the relay; without this, nothing changes |\n| `CC_DM_PERMISSION_APPROVER` | No | Name of the session that approves (omit for broadcast) |\n\n## Access control\n\nOptional sender-side restrictions on who can broadcast and who you can DM. All env vars are parsed at session startup — no runtime changes.\n\n```bash\n# Only orchestrators and architects can broadcast from this session\nCC_DM_BROADCAST_ALLOWED_ROLES=orchestrator,architect\n\n# This session can only DM these specific sessions\nCC_DM_DM_ALLOWLIST=planner,reviewer\n\n# OR: this session can DM anyone EXCEPT these (mutually exclusive with allowlist)\nCC_DM_DM_BLOCKLIST=intern\n```\n\n| Env var | Purpose |\n|---------|---------|\n| `CC_DM_BROADCAST_ALLOWED_ROLES` | Comma-separated roles allowed to broadcast. Empty = no restriction. |\n| `CC_DM_DM_ALLOWLIST` | Comma-separated session names this session can DM. Empty = no restriction. |\n| `CC_DM_DM_BLOCKLIST` | Comma-separated session names this session cannot DM. Empty = no restriction. |\n\n`CC_DM_DM_ALLOWLIST` and `CC_DM_DM_BLOCKLIST` are mutually exclusive — setting both causes a fatal error at startup. If neither is set, the session can DM anyone in its project (the default behavior).\n\n> **Note:** Access control is sender-side only. It restricts what THIS session can send, not what it can receive. A session blocked by your allowlist can still DM you.\n\n## Remote access\n\nClaude Code has a built-in `/remote-control` feature that lets you access any session from the Claude iOS app. This pairs naturally with cc-dm — run multiple named sessions locally, drop into any one from your phone, and use cc-dm to coordinate between them.\n\n## Live stream viewer\n\n[cc-dm-stream](https://github.com/Akram012388/cc-dm-stream) is a companion TUI that renders session registrations, messages, broadcasts, and lifecycle events in real time. Run it in a separate terminal to observe the cc-dm bus without joining as a session.\n\n```bash\ncc-dm-stream                      # watch all traffic\ncc-dm-stream --project myapp      # filter by project\n```\n\nInstall from within Claude Code using `/cc-dm:install-stream`, or see the [cc-dm-stream repo](https://github.com/Akram012388/cc-dm-stream) for manual install options.\n\n## Bus inspection\n\nInspect the SQLite bus directly at any time:\n\n```bash\nbun -e \"\n  import { Database } from 'bun:sqlite';\n  const db = new Database(process.env.HOME + '/.cc-dm/bus.db');\n  console.log(db.query('SELECT * FROM sessions').all());\n  console.log(db.query('SELECT * FROM messages').all());\n\"\n```\n\n## Releases\n\n| Version | Date | Highlights |\n|---------|------|------------|\n| [v1.3.1](https://github.com/Akram012388/cc-dm/releases/tag/v1.3.1) | 2026-03-27 | Ghost name theft fix, register skill improvements, lifecycle docs |\n| [v1.3.0](https://github.com/Akram012388/cc-dm/releases/tag/v1.3.0) | 2026-03-27 | Message metadata, permission relay, role-based access control |\n| [v1.2.0](https://github.com/Akram012388/cc-dm/releases/tag/v1.2.0) | 2026-03-27 | Compaction resilience, heartbeat self-heal |\n| [v1.1.0](https://github.com/Akram012388/cc-dm/releases/tag/v1.1.0) | 2026-03-24 | Project-scoped messaging, [npm package](https://www.npmjs.com/package/cc-dm) published |\n| [v1.0.0](https://github.com/Akram012388/cc-dm/releases/tag/v1.0.0) | 2026-03-22 | Production release — duplicate delivery guard, same-name protection, stronger session IDs |\n| [v0.3.0](https://github.com/Akram012388/cc-dm/releases/tag/v0.3.0) | 2026-03-22 | Fix MCP server path resolution for plugin marketplace installs |\n| [v0.2.0](https://github.com/Akram012388/cc-dm/releases/tag/v0.2.0) | 2026-03-21 | 44-test suite, clean shutdown, bus hardening |\n| [v0.1.0](https://github.com/Akram012388/cc-dm/releases/tag/v0.1.0) | 2026-03-21 | Initial release |\n\nSee [CHANGELOG.md](CHANGELOG.md) for full details.\n\n## Known limitations\n\n**System sleep recovery:** When a laptop sleeps for more than 60 seconds, all cc-dm sessions are marked stale and deleted from the bus by the next cleanup cycle. The heartbeat self-heals automatically — each session re-registers within ~30 seconds of waking. During that window, the session is unreachable via DM or broadcast but the MCP server process continues running. No manual intervention is needed.\n\n## Development status\n\nBuilt on Claude Code Channels (research preview, v2.1.80+). The `--dangerously-load-development-channels` flag is required until cc-dm is submitted to and approved by the official Channels marketplace. Breaking changes possible as the Channels protocol matures toward GA. Track: https://code.claude.com/docs/en/channels-reference\n\n## Built by\n\nShaikh Akram Ahmed — architect turned builder, Muscat, Oman.\nhttps://github.com/Akram012388 · https://x.com/CodeAkram\n\n## Privacy\n\ncc-dm operates entirely on your local machine. All data is stored in a local SQLite file (`~/.cc-dm/bus.db`). No data is transmitted over the network, no telemetry is collected, and no external services are contacted.\n\n## License\n\nMIT\n",
  "bytes": 14062,
  "sha": "1ecc7e0cc7e3e6ea07d0b2d406d631867ea62c547dcc3014e9302303dea25d79",
  "repo_slug": "akram012388/cc-dm",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/plg_akram012388_cc_dm_cc_dm_3f2bfe00/readme"
}