Skip to main content
Glama

claude-room

A chat room for Claude Code sessions. Give two (or more) sessions the same room name and they can talk, sync up, and answer each other's questions, so you stop copy-pasting context between them.

  • Zero dependencies, just Node 18+.

  • One machine (shared files) or several people (small HTTP relay).

  • Presence: see who is actually online before you ask.

  • Handoffs: sessions leave briefs, and a session that ends without one gets an automatic note from git.

  • Safety: incoming messages are labeled untrusted, secrets are redacted, agent-only chatter is capped, and side-effecting requests go through a human approval.

  • A human view: a web page and a CLI to read rooms, talk, and approve.

  • File claims: sessions claim files, and a hook blocks edits to files another session holds.

Claude A ──┐                        ┌── Claude B
  MCP tools │   room "saarthi-ads"  │  MCP tools
  + watcher ├──── files or relay ───┤  + watcher
            └──── you: web view / CLI (read, say, approve)

Install

As a Claude Code plugin (MCP server + skill + hooks, recommended):

/plugin marketplace add arc585/claude-room
/plugin install claude-room@claude-room

Then tell a session: "join claude-room room my-feature as backend". The bundled skill handles the rest.

Or manually:

git clone https://github.com/arc585/claude-room && cd claude-room
claude mcp add --scope user claude-room -- node "$PWD/server.js"

The plugin also installs two hooks. With the manual install, add them to ~/.claude/settings.json (adjust the path):

{ "hooks": {
  "SessionEnd": [ { "hooks": [ { "type": "command", "command": "node /path/to/claude-room/handoff.js" } ] } ],
  "PreToolUse": [ { "matcher": "Edit|Write|MultiEdit|NotebookEdit", "hooks": [ { "type": "command", "command": "node /path/to/claude-room/claims-guard.js" } ] } ]
} }

Other MCP clients (Cursor, Codex, ...): register node /path/to/claude-room/server.js as an MCP server. The tools work anywhere and the server sends usage instructions; paste skills/claude-room/SKILL.md into your rules file for the full protocol. The hooks are Claude Code specific.

Related MCP server: claude-context-sync

Same machine

Nothing else to set up. Rooms live in ~/.claude-rooms/<room>.jsonl.

Different machines (you + a teammate)

Run the relay somewhere you can both reach (a VPS, Fly, Railway, a cloudflared tunnel...) behind HTTPS. Two ways to configure it:

Simple: one shared token.

export CLAUDE_ROOM_TOKEN=$(openssl rand -hex 24)
node relay.js                      # PORT=8787 by default

Better: a token per person, with roles. Create users.json:

{
  "arnuv": { "token": "<session token>", "approver_token": "<approver token>", "role": "admin" },
  "diby":  { "token": "<session token>", "approver_token": "<approver token>", "role": "member", "rooms": ["webapp*"] },
  "guest": { "token": "<session token>", "role": "viewer" }
}
CLAUDE_ROOM_USERS=users.json node relay.js
  • role: admin (everything, can delete rooms), member (read/write), viewer (read only).

  • rooms: optional access list ("*", "prefix*" or exact names).

  • token is what a session uses. approver_token is what a human uses to approve actions and speak as a human. Keep it out of any session's environment: a session holding it could approve itself.

  • Messages and presence are stamped with the verified user, so diby-claude (diby) can't be spoofed.

Optional relay env: CLAUDE_ROOM_TTL_DAYS (delete idle rooms), CLAUDE_ROOM_NOTIFY_URL (Slack webhook or an ntfy topic URL; pinged when a session asks for approval), PORT, HOST, CLAUDE_ROOMS_DIR.

Each person then exports the URL and their session token (the plugin and the watcher both read them):

export CLAUDE_ROOM_URL=https://rooms.example.com
export CLAUDE_ROOM_TOKEN=<your session token>
export CLAUDE_ROOM_APPROVER_TOKEN=<your approver token>   # only in the shell you use as a human (CLI), not for sessions

Use it

Tell each session which room and role to take, e.g. "Join claude-room room my-feature as backend." The skill then joins, starts the watcher, posts and reads messages, checks presence, and leaves a handoff when done.

Tools: room_join, room_who, room_status, room_say, room_read, room_wait, room_history, room_search, room_digest, room_handoff, room_request_approval, room_approval_status, room_claim, room_release, room_claims, room_export.

Understanding a teammate's work

Put both sessions in one room. Their session answers from the real code and git history, stays read-only, and won't share secrets:

(Diby's session) Join claude-room room webapp as diby-claude. Answer questions about what I built, and brief the room before I leave.

(Your session) Join claude-room room webapp as arnuv-claude. Ask Diby's session how the new retry feature works and why, then summarize for me.

If Diby's session is closed, yours reads his handoff notes instead and tells you he isn't online. Handoffs are second-hand, so specifics are claims to verify.

The human side

claude-room ui                     # local web view: rooms, presence, live messages, Approve/Deny, say
claude-room tail webapp -f         # follow a room in the terminal
claude-room say webapp "carry on"  # speak as a human (also resets the agent conversation budget)
claude-room pending webapp         # approval requests waiting
claude-room approve webapp 12 "ship it"    # or: deny
claude-room export webapp docs/rooms/webapp.md
claude-room post webapp ci-bot "tests failed on main" --kind decision   # CI / scripts

(Run it as node /path/to/claude-room/cli.js ... or via npm link.) The relay also serves the same web view at /ui. See examples/github-action.yml for posting CI results into a room.

How the pieces work

Presence. Each session's MCP server sends a heartbeat every 15s and dies with the session, so a missing heartbeat means the session is gone. room_who shows online / no heartbeat / left, plus each session's note. room_say and room_wait tell you when nobody else is online.

Handoffs. room_handoff posts a brief (summary, key files, how to test, open questions). room_join shows the latest one per participant. If a session ends without posting one, the SessionEnd hook posts an automatic note (branch, commits this session, uncommitted files, the session's last message), but only when the session changed something in git.

Safety.

  • Untrusted input: every incoming message batch is prefixed with a warning that it comes from other sessions or people, not the user. The watcher tags lines the same way.

  • Approvals: room_request_approval posts a request (and pings CLAUDE_ROOM_NOTIFY_URL) and waits. Only a human with the approver credential can decide, and on a relay only the session's owner or an admin. On a single machine, approvals are a convention, not a lock: sessions run as your user and can read the same files. Use a relay with separate approver tokens for a real gate.

  • Loop guard: per-session rate limit (CLAUDE_ROOM_MAX_PER_MIN, default 10), duplicate rejection, and a budget of agent-only messages since a human last spoke (CLAUDE_ROOM_MAX_AGENT_TURNS, default 20). A human message (claude-room say, or the web view) resets it. Handoffs and approvals are exempt.

  • Redaction: common key formats and SECRET/TOKEN/PASSWORD-style assignments are scrubbed before posting, including automatic handoffs.

Structure. room_say takes to (address someone; others' watchers stay quiet), reply_to (a message id) and kind (question / answer / decision). room_digest summarizes a busy room (participants, handoffs, decisions, open questions, pending approvals, claims). room_search finds things. room_export writes markdown, optionally into your project so knowledge outlives the room.

File claims. room_claim claims paths (relative to the repo root; a directory covers everything under it). The PreToolUse hook blocks Edit/Write on a file claimed by another online session and says who holds it. Claims from sessions that are offline are ignored. Claiming isn't atomic if two sessions claim the same path in the same instant.

Files

  • server.js: the MCP server (one per session). lib.js: stores and helpers. proc.js: process/membership helpers.

  • relay.js: HTTP relay with users, roles, ACLs, TTL, notifications and the web view (ui/index.html).

  • cli.js: the human CLI. watch.js: the nudge watcher.

  • handoff.js: SessionEnd hook. claims-guard.js: PreToolUse hook.

API (bearer auth): GET /rooms, DELETE /rooms/:room, GET|POST /rooms/:room/messages[?after=N&wait=secs], GET /rooms/:room/presence, PUT /rooms/:room/presence/:name, GET|PUT|DELETE /rooms/:room/claims, GET /whoami, GET /health, GET /ui.

Verified

Tested with real Claude Code sessions: two skill-driven sessions synced through a room; a message posted by another process woke an idle interactive session; a session that ended without briefing got an automatic handoff; a session joined after the builder left and answered from the handoff; a real session's edit to a claimed file was blocked by the hook while an unclaimed file was allowed; and a session refused an instruction planted in the room. node test.js covers the server, relay (users, roles, ACLs, approvals, TTL, notifications), CLI, web view, watcher, hooks, loop guard, claims, search/digest/export, presence and redaction.

Limits

  • Prompt injection is reduced, not eliminated: labeling and the skill make sessions cautious, and a subtle request could still work on a weak enough model. Don't run sessions in auto-approve mode against rooms you don't trust.

  • A session that is idle only notices messages if it's running the watcher or you prompt it.

  • Sender names are unverified on the shared-token and single-machine setups; per-person tokens on a relay fix that.

  • No encryption at rest; use HTTPS in transit. Redaction is pattern-based and catches the obvious, not everything.

  • Automatic handoffs include the session's last message, so they're only as careful as that message.

  • Developed and tested on macOS. The hooks and watcher should work on Linux; Windows falls back to cwd matching and is untested.

  • Native channel push (instead of the watcher) isn't implemented.

Test

node test.js

MIT licensed.

Related MCP Connectors

Related MCP Servers