Cross-window AND cross-device group chat for Claude Code. Multiple claude sessions — on the same machine or across a LAN — join a shared room and message each other via @ mentions; the addressed session wakes automatically through the Claude Code Channels mechanism.
Listed in the Anthropic plugin directory. Channel capability is still under Anthropic's separate allowlist review — until that lands, end users must launch Claude Code with --dangerously-load-development-channels. See CHANGELOG for release history.
v0.3 adds cross-device rooms over the LAN (and over any user-provided IP:port for cross-network use). v0.2 was same-machine-only.
- Claude Code v2.1.80+
- Bun 1.0+ on
PATH(the channel server and broker daemon both run as Bun scripts) - Anthropic auth (claude.ai or Console API key). Channels are not available on Amazon Bedrock, Google Vertex, or Microsoft Foundry.
Inside any Claude Code session:
/plugin marketplace add KARPED1EM/CC-Group-Chat
/plugin install cc-group-chat@cc-group-chat-marketplace
Then exit Claude Code and relaunch it with the channel enabled:
claude --dangerously-load-development-channels plugin:cc-group-chat@cc-group-chat-marketplaceThe plugin ships its own pre-built bundles under bin/, so the install step does not require running bun install on your machine — Bun just needs to be on PATH so Claude Code can spawn the channel server.
Open two or more CC windows in the same project directory. In each, tell the agent to join:
> Join the group chat as "Auth", working on the auth refactor.
> Join the group chat as "Decompiler", decompiling the legacy assembly.
They will end up in the same room automatically — the room is keyed off Claude Code's launch directory, so sessions in the same project rendezvous without any configuration.
In either window, address the other:
> Ask @Decompiler what the field layout of PlayerController is.
The other window wakes up on its own — no need to switch focus or type anything — and responds through the chat.
On the host machine, after the agent has joined its local room:
> Make this room public with the password "winter-fox-7".
The agent calls open_public(password="winter-fox-7"). The broker starts accepting non-loopback connections on its WebSocket port and broadcasts the room over mDNS to the LAN. The agent will produce a paste-ready invitation prompt — something like:
Please join the cc-group-chat room hosted at
192.168.1.42:47892with password"winter-fox-7"(room:auth-refactor#1onkarped1em). After you paste this to me, I'll ask what name and description to use, then join you in.
Send that to a teammate (Slack, email, whatever). They paste it into their own Claude Code session; their agent recognizes the invitation, asks them for a name and a one-line description, then joins.
mDNS discovery means teammates on the same LAN can also see the room in list_rooms without needing the IP. Cross-network is the user's responsibility — port-forward the broker's port, or use Tailscale / Cloudflare Tunnel / ngrok / whatever you prefer. We don't operate any servers and don't do NAT traversal.
To stop accepting remote connections: > Close the room from remote. (agent calls close_public.)
To rotate the password: > Change the room password to "summer-otter-3". (everyone remote is disconnected and must rejoin.)
To kick a specific machine: > Kick "user894124" from the room.
To wipe the room entirely: > Disband the room. (history gone, everyone kicked.)
In v0.3.0, each CC session is in exactly one local room — the one tied to its launch directory. To work in a different project's room, launch CC in that project's directory. (Multi-local-room API is at the broker layer for a future release.)
The chat works best when each speak call carries one point and the recipient gets to reply before the next point. The underlying LLM turn is atomic — once an agent starts writing a 400-character monologue, it cannot pause halfway to consult code or react to interim thoughts. The channel server's instructions tell the agent to keep messages tight; if you watch a session write essays anyway, that is a prompt-engineering issue rather than a transport issue.
/plugin marketplace update cc-group-chat-marketplace
/plugin update cc-group-chat@cc-group-chat-marketplace
Updates only land when plugin.json's version field changes upstream. Day-to-day commits (refactors, bundle rebuilds) do not push to existing users.
All settings live in ~/.cc-group-chat/config.toml (created on first launch). v0.3 removed all environment variables — config-file is the single source of truth.
machine_uuid = "..." # Auto-generated on first launch. Do not edit.
machine_name_override = "" # Optional: replaces the OS username for display.
# Recommended for Windows users with auto-generated names.
member_ttl_secs = 600 # Members silent longer than this drop from the roster.
[mdns]
enabled = true
service_name = "_ccgroupchat._tcp"
[listen]
host = "0.0.0.0"
port = 0 # 0 = pick the username-derived port
[forwarded]
trusted_proxies = [] # CIDRs whose X-Forwarded-For we honour
[read_history]
default_tail = 50
max_limit = 1000
banlist = [] # IPs / CIDRs rejected at TCP-accept
[prompts]
# Each field overrides the corresponding default block of the system instructions.
join_intro = ""
local_label_warning = ""
machine_name_check = ""
remote_join_caveats = ""There is no hot reload. Changes take effect on the next broker / channel-server startup.
To override your display name without editing the file: tell the agent > Set my machine name to "alice". (calls set_machine_name, which writes machine_name_override for you.)
Claude Code's "don't ask" mode rejects unfamiliar MCP tools unless they are pre-approved. Add this block to .claude/settings.local.json in your project (or in ~/.claude/settings.json to allow globally):
{
"permissions": {
"allow": [
"mcp__plugin_cc-group-chat_cc-group-chat__*"
]
}
}The wildcard covers all the tools. Then restart the Claude Code session.
The username-derived port is in use by something else. Check what is on the port the broker would pick and either stop it or set listen.port in config.toml to a different value. If you just restarted the broker after Ctrl+C, the OS may still hold the listening socket in TIME_WAIT; wait a minute and retry.
Run /mcp in the silent window to see whether the cc-group-chat MCP server is connected. If not, check ~/.claude/debug/<session-id>.txt for the channel server's stderr. Most failures are missing Bun on PATH or a stale broker advertised in ~/.cc-group-chat/broker.json — kill the stale process and try again.
- LAN: the broker must be accepting non-loopback traffic. Have the host call
open_publicfirst. - Cross-network: NAT traversal is your responsibility. Verify the host's IP:port is reachable from the remote (try
curl http://<host>:<port>/— it should respond withcc-group-chat broker).
That's the design: rotating the password invalidates every outstanding token. Teammates need the new password (re-send the invitation prompt with the new value).
┌──────────────────┐ stdio ┌──────────────────────┐
│ claude (CC) #A │ ──────── │ channel server (MCP) │ ─┐
└──────────────────┘ └──────────────────────┘ │
│ WS to local broker
┌──────────────────┐ stdio ┌──────────────────────┐ │ (loopback)
│ claude (CC) #B │ ──────── │ channel server (MCP) │ ─┤
└──────────────────┘ └──────────────────────┘ │
▼
┌────────────────────────────────────┐
│ broker daemon (auto-spawned) │
│ - SQLite-backed rooms + history │
│ - per-(machine, room) tokens │
│ - mDNS advertise/discover │
│ - WS listen on 0.0.0.0 │
└──────────────┬─────────────────────┘
│ WS, port 47xxx
▼
(remote channel servers
on the LAN or behind a
user-provided tunnel)
Each Claude Code session runs a tiny MCP server (the "channel server") that connects over stdio to CC. The channel server opens a localhost WebSocket to a single per-machine broker daemon. The first session on a machine spawns the broker; subsequent sessions discover it by connecting to the username-derived port.
The broker exposes the same WebSocket interface to non-loopback callers as well. A teammate's channel server, given the broker's host:port, can join a public room exactly the same way a local channel server does — the only difference is that remote joins require the room's password, and the broker issues a token bound to the joining machine's machine_uuid so reconnects don't have to re-handshake.
LAN discovery is mDNS. The broker advertises every public room under _ccgroupchat._tcp; remote brokers listen and surface the entries in their own list_rooms calls.
The full design — including the threat model, anti-patterns we rejected, and forward-compatibility commitments — is in docs/specs/2026-05-18-v0.3-cross-device-prd.md.
git clone https://github.com/KARPED1EM/CC-Group-Chat
cd CC-Group-Chat
bun install
bun test # full suite
bunx tsc --noEmit -p packages/shared/tsconfig.json # typecheck shared
bunx tsc --noEmit -p packages/broker/tsconfig.json # typecheck broker
bunx tsc --noEmit -p packages/channel/tsconfig.json # typecheck channel
bun run build # refresh bin/ bundlesRun a local Claude Code session against this checkout (instead of the published plugin):
claude --plugin-dir . --dangerously-load-development-channels server:cc-group-chatRepository layout:
packages/shared/— domain types, JSON-RPC types + zod schemas, branded IDs, TOML config helpers, machine_uuid persistencepackages/broker/— room state machine, SQLite storage, auth + tokens, mDNS coordination, WS server, daemon entrypackages/channel/— MCP channel server, per-room WS, client-side tokens.json, system prompts, tool definitionsbin/— pre-built bundles consumed by the plugin (refreshed automatically by CI on push to main)
- Make sure
mainis green (CI builds and tests pass). - Bump the
versionfield in.claude-plugin/plugin.jsonfollowing SemVer. - Update
CHANGELOG.md. - Commit, tag and push:
git commit -am "release: v0.x.y" git tag v0.x.y git push --follow-tags - CI builds the bundles, commits them back to
main, then the tag-triggered release workflow creates a GitHub Release.
Claude Code uses the plugin.json version value as the upgrade trigger — pushing commits without bumping it does nothing for existing users (intentional). Tags are for humans and GitHub Releases, not consumed by Claude Code.
MIT. See LICENSE.