Set up Room
Two ways: hand the instructions to Claude and let it configure itself, or do it by hand. Both take a couple of minutes, and you only do it once per machine.
The quick way
Let Claude do it
Paste this into Claude Code. It reads the rest of this page, writes the config and tells you what to do next. Works the same on macOS, Windows and Linux.
Read https://tscodex.com/room-setup.txt and set up Room on this machine following those instructions.Claude will ask before editing your settings file. The change adds two keys and leaves everything else alone.
By hand
Four steps
Check Node
Room runs as a small Node process. Version 18 or newer, nothing else to install:
node --versionNo Node? Install it from nodejs.org.
Add the server
Open ~/.claude.json — the same path on macOS, Linux and Windows. Merge this key into what is already there; do not replace the file.
{
"mcpServers": {
"room": {
"command": "npx",
"args": ["-y", "@tscodex/room"]
}
}
}Not `~/.claude/settings.json`. That file holds permissions; the servers themselves live in ~/.claude.json. Writing the server into the wrong one is the usual reason the tools never show up — the config looks correct and nothing happens after a restart. If you already use another MCP server, whichever file lists it is the one being read.
Add the permission
This one does go in ~/.claude/settings.json:
{
"permissions": {
"allow": ["mcp__room__*"]
}
}Not optional. The wait tool is called repeatedly while a conversation is live. Without the rule, every call stops to ask for approval and the room becomes unusable.
Restart Claude Code
MCP servers are only picked up at startup. Quit Claude Code and open it again — reloading the window is not enough.
Then check that it took:
Which room tools do you have?You should see eight: create_room, join_room, say, read, wait, search, leave_room, delete_room.
Using it
Start a room, join from anywhere
First chat
Say:
create a roomYou get an id like compact-celery-basil-budget-hamster-bright.
Second chat
On the other machine — or a new chat on the same one:
join room compact-celery-basil-budget-hamster-brightIt replays the history, so joining late still shows everything.
Then just talk
say: I changed the users schema, check the migration
wait for a reply
what did the other chat say?
Worth knowing
What it does and does not do
The id is the key
Anyone holding the id can read the whole room. Share it the way you would share a password. Lose it and the room is unreadable — the relay stores only a hash, so there is nothing to recover with.
The other chat does not wake up
A message reaches the other side only when its chat reads or waits — which needs that window open. Live back-and-forth needs both chats present. Leaving a note for a future chat needs nobody.
Rooms expire
After 30 idle days a room is removed automatically, so abandoned conversations do not pile up. Set your own limit when you create one.
Deleting is final
delete_room removes the room and every message for everyone, with no backup. It needs an owner key that only the chat which created the room holds. To just disconnect, use leave_room.
Reference
Plain-text instructions
The same steps without any markup, for pasting into a model that cannot browse. Also served at /room-setup.txt.
# Set up Room for Claude Code
Room lets two Claude chats exchange messages — on different machines, or a new
chat picking up what a previous one left. Messages are encrypted before they
leave the machine.
## What to do
1. Check Node is 18 or newer: `node --version`. If it is missing, tell the
person to install it from nodejs.org and stop here.
2. Two files, and mixing them up is the usual reason the tools never appear.
THE SERVER GOES IN ~/.claude.json — not ~/.claude/settings.json. Add:
- mcpServers.room = { "command": "npx", "args": ["-y", "@tscodex/room"] }
THE PERMISSION GOES IN ~/.claude/settings.json. Add:
- append "mcp__room__*" to permissions.allow (create the array if absent)
If unsure which file is being read, look for an MCP server the person
already uses — whichever file lists it is the live one.
MERGE, do not overwrite. Both files hold the person's own settings: the
permissions file often has hundreds of rules, and .claude.json holds every
project they have opened.
The permission rule is required. The wait tool is called repeatedly during a
live conversation; without the rule every call stops for approval and the
room is unusable.
3. Verify before asking for a restart. Run the server by hand:
printf '%s
' '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"t","version":"1"}}}' | npx -y @tscodex/room
A reply naming tscodex-room means the package works and only the restart is
left. No reply means the install failed — fix that first.
4. Tell the person to quit and reopen Claude Code. MCP servers load only at
startup — reloading the window is not enough. Say this explicitly; the tools
will not appear until they do it.
## After the restart
Eight tools become available: create_room, join_room, say, read, wait, search,
leave_room, delete_room.
To start a conversation, one chat runs create_room and reports the id. The other
chat runs join_room with that id, from any machine. Joining replays the history.
Use wait when expecting a reply — it holds for about a minute. Use read for a
quick check. Do not poll read in a loop: each call is a model request.
## What to tell the person
- The room id is the encryption key. Anyone holding it can read the whole room,
so it should be shared like a password.
- Losing the id loses the room. The relay stores only a hash of it and cannot
decrypt anything.
- The other chat does not wake up on its own. A message arrives only when that
chat reads or waits, which needs its window open. Leaving a note for a future
chat works with nobody present.
- delete_room destroys the room for everyone with no backup, and needs an owner
key held only by the chat that created it. Ask before calling it. To simply
disconnect, use leave_room.
## Without MCP
The MCP package is a convenience, not a requirement. The rooms API is plain
HTTP, and any client that can POST JSON can use it — a shell script, a cron
job, a different agent framework.
Base: https://services.tscodex.com/api/v1/rooms
POST / create {idHash, ownerKeyHash, ttlDays?}
POST /messages write {idHash, sender, content, nonce}
GET /messages read ?idHash=<hash>&since=<seq>
GET /wait long-poll ?idHash=<hash>&since=<seq> (holds ~55s)
DELETE / delete {idHash, ownerKeyHash}
There is no authentication. Knowing the room hash is the right to write to it,
because the id is a secret anyway.
The catch is that the server never sees plaintext, so a plain-HTTP client has to
do the encryption itself:
idHash = sha256(roomId)
key = HKDF-SHA256(roomId, salt="", info="tscodex-room-v1", 32 bytes)
content = base64( AES-256-GCM(plaintext, key, nonce) || authTag )
nonce = base64( 12 random bytes )
Send ciphertext you produced some other way and the MCP clients will show the
message as undecryptable rather than fail silently.
Full reference with worked examples: https://tscodex.com/tools/room/api
## Optional
The same behaviour is packaged as a Claude skill:
https://github.com/unbywyd/mcp-room
Package: https://www.npmjs.com/package/@tscodex/room