Content
# collabor-AI-te
**A shared room where humans and their AI coding assistants collaborate on one repo, safely.**
[](LICENSE)
[](https://code.visualstudio.com/)
[](https://workers.cloudflare.com/)
[](https://modelcontextprotocol.io/)
collabor-AI-te is a VS Code extension plus a tiny Cloudflare backend that puts every
developer and every AI assistant working on a project into one live room. It adds the
piece that goes missing the moment two people (and two AIs) edit the same repo at once:
**a mutually exclusive write-control switch** so exactly one side can write to the repo
at a time, while every AI keeps full read access throughout.
It is **N participants, no pairing required.** A third developer can join as a pure human
with no AI. Anyone can join with their own AI assistant. Nobody has to.

---
## Why this exists
Two developers pairing with AI assistants hit a coordination problem that ordinary chat
and screen-sharing do not solve: both AIs can read the repo, and if both can also *write*
it, they clobber each other's edits. collabor-AI-te makes write access a single shared
token that is visible to everyone and held by at most one side at a time.
- **Read is always open.** Every AI in the room can read the full repo and the full chat,
always. Understanding is never gated.
- **Write is a token.** Exactly one developer holds the repo write-control switch. Flip it
on and you take the token; the other side's switch goes off. An optional hook turns that
visible switch into a hard block on the other AI's file edits.
- **Everyone sees the same truth.** The switch state, the chat, and the roster all live in
one Cloudflare Durable Object, so there is a single source of truth, not two clients
guessing at each other.
And when a disagreement cannot be talked out, you settle it with a networked **Tron
light-cycle duel**, best of three. The winner is posted to chat as the decision of record.
---
## Features
- **Live chat** between every human and AI in the room, with clear attribution
(`You`, `Your AI · AI`, and `system` lines for joins, leaves, and control changes).
- **Repo write-control switch.** Each developer has a switch both sides can see. Exactly one
can be ON at a time; the Durable Object is the single source of truth. Whoever is green
holds repo **write** control. Both AIs always keep full **read** of the repo and chat.
- **Optional hard lock.** A drop-in `PreToolUse` hook blocks an AI's `Write`/`Edit` calls
whenever the *other* developer holds the switch. The switch goes from a convention to an
enforced lock, per AI, opt-in.
- **Fuse Inference.** Two or more developers in a room can join their AIs into one
coordinated unit. The single most capable model across the machines becomes the **lead**
(the one voice in chat) and offloads declarative sub-tasks to the peer's model, which
reviews the plan. The AIs do not merge into one model; this is coordination, not shared
inference. Every repo write still passes through the same write-control switch, and the room
executes nothing on your behalf.
- **Name your AI.** A panel field names your assistant; the name is shared with your MCP
server so your AI posts to the room under it.
- **One-command teammate invite.** The **+ Invite** button copies a single command. Your
teammate runs it and the room itself installs the extension, wires their AI, and connects
them. No manual setup walkthrough.
- **Tron tiebreaker.** A networked light-cycle duel (best of three, arrow keys or WASD) for
settling disagreements you cannot talk out. Each round gives you a **4-second boost
reserve**: double-tap the direction you are already heading to engage double speed, spend
it in increments. The result posts to chat as the settled decision.
- **Expandable composer.** Drag to resize, auto-grows as you type, or hit ⤢ for a big box.
- **The LOL gate.** Your display name must start with `LOL` (it gets stripped) or you are
auto-named **Franny**. Forget the handshake, become Franny. It also keeps two people who
both skip naming from silently colliding on the same identity.
- **Model-agnostic.** The AI side is a standard Model Context Protocol (MCP) server, so any
MCP-capable assistant can join the room, not just one vendor's.
- **Zero-dependency extension.** The VS Code panel is pure VS Code and browser APIs, no npm
dependencies to audit or update.

---
## How it fits together
| Piece | What it is | Who runs it |
|---|---|---|
| `room/` | A Cloudflare Worker + Durable Object: the chat log (DO SQLite), live roster, the write-control lock, and the authoritative Tron simulation, fanned out over WebSocket. Plain HTTP endpoints let MCP servers post, read, and check control without a long-lived socket. | Deployed once, or run locally. |
| `extension/` | The `collabor-AI-te` VS Code panel. Zero npm dependencies, pure VS Code APIs. | Each developer, in their VS Code. |
| `mcp/` | The MCP server: `post_message`, `get_messages`, `get_control`, `take_control`, `release_control`, `list_participants`, `whoami`. | Each developer who wants their AI in the room. |
| `hooks/` | An optional `PreToolUse` guard, `control-guard.py`, that hard-blocks `Write`/`Edit` when the *other* developer holds the token. | Opt-in, per AI. |
**Config flow.** The panel writes your settings to `~/.collab-chat/config.json`. The MCP
server and the hook read that same file, so you configure once in the panel and your AI and
the lock both pick it up.
```
VS Code panel ──writes──► ~/.collab-chat/config.json ◄──reads── MCP server
│ ▲ │
│ └────────reads────── control-guard hook
│ │
└──────────────── WebSocket / HTTP ────────────────► Cloudflare room ◄──── HTTP
(Worker + Durable Object)
```
---
## Requirements
- **VS Code** 1.85 or newer.
- **Node.js** 20 or newer recommended. The MCP server runs on Node 18+; the local Cloudflare
room uses Wrangler 4, whose toolchain expects a current Node LTS (20+).
- A **Cloudflare account** only if you want a deployed, cross-machine room. Local
single-machine use needs no account (it runs in `wrangler`'s built-in `miniflare`).
- An **MCP-capable AI assistant** only if you want an AI in the room. Joining solo as a
human needs none.
---
## Quick start (local, one machine, no Cloudflare account)
**1. Start the room.**
```bash
cd room
npm install
npm run dev # serves http://localhost:8787 in miniflare
npm run smoke # (another terminal) posts + reads back to prove it works
```
**2. Build and install the panel.**
```bash
cd extension
npx @vscode/vsce package
code --install-extension collabor-ai-te-0.6.0.vsix
```
Reload VS Code. Click the **collabor-AI-te** icon in the activity bar, open **Settings**, and
set: your name (for example `LOLAda`), your AI's name (for example `Ada's Claude`, or leave
blank if solo), Room URL `http://localhost:8787`, Room ID `main`, key blank. Click **Save**
and you should see `connected · main`.
**3. Add your AI.**
```bash
cd mcp
npm install
claude mcp add collabor-ai-te -- node "$(pwd)/src/server.js"
```
Save your panel settings first, and run `claude mcp add` *between* assistant sessions if your
client caches its prompt. Then ask your AI things like *"check the room"*, *"post to the
room: ready"*, or *"do I have repo write-control?"*.
> `claude mcp add` is the [Claude Code](https://modelcontextprotocol.io/) form. Any MCP
> client can register `node /abs/path/mcp/src/server.js` as a stdio server instead.
**4. (Optional) Turn the switch into a hard lock.** Add to your assistant's
`.claude/settings.json`:
```json
{ "hooks": { "PreToolUse": [ {
"matcher": "Write|Edit|MultiEdit|NotebookEdit",
"hooks": [ { "type": "command", "command": "python3 /ABS/PATH/hooks/control-guard.py", "timeout": 15 } ]
} ] } }
```
Now your AI's edits are blocked whenever the other developer holds the switch. The room being
down never blocks you (the hook defers on any failure). Set `COLLAB_STRICT=1` to also block
when *no one* holds the token.
---
## Deploy for real cross-machine use
```bash
cd room
npm install # first time (installs wrangler)
npm run deploy # bundles the joiner payload, then deploys
npx wrangler secret put ROOM_KEY # set the shared room secret
```
`npm run deploy` runs `build-join.mjs` first, which embeds the current extension `.vsix`, the
MCP server, and the hook into the Worker so it can serve a one-command joiner at `/join`
(bash) and `/join.ps1` (PowerShell).
Re-run it after changing the extension. The deploy prints your room URL, of the form
`https://collabor-ai-te-room.<account>.workers.dev`. Point your panel at that URL and key.
> Without `ROOM_KEY` the room runs **OPEN** (no auth), which is fine on one machine but never
> for a shared deployed URL. The Worker logs a warning when the key is unset.
### Invite a teammate (the one-command way)
With your panel pointed at the deployed URL, click **+ Invite** and pick your teammate's OS
(Linux / macOS or Windows). It copies one command to your clipboard.
Linux / macOS:
```bash
curl -fsSL https://collabor-ai-te-room.<account>.workers.dev/join | bash -s -- --room main --key <ROOM_KEY>
```
Windows (paste into a PowerShell window):
```powershell
$s = irm 'https://collabor-ai-te-room.<account>.workers.dev/join.ps1'; & ([scriptblock]::Create($s)) -Room 'main' -Key '<ROOM_KEY>'
```
Send it to your teammate over a private channel (it contains the room key). When they run it,
the room serves a script that installs the extension, drops in the MCP server and hook, writes
their config, and connects them. They reload VS Code and run the printed `claude mcp add`
line. They join as "Franny" until they set their name in the panel.
> These are piped installers (`curl | bash` and the PowerShell equivalent), appropriate for a
> trusted teammate. The payload is only the public extension and MCP code, never the key (the
> key is passed as an argument you control). Read the
> [security notes](#security-and-threat-model) before sharing widely.
### Manual alternative
Linux/macOS, from a checkout:
```bash
./setup-linux.sh --url <URL> --key <KEY> --name LOLFranny --ai "Franny's Claude"
```
Run `./setup-linux.sh --help` for all flags (`--room`, `--no-ext`, `--no-mcp`).
Windows needs no checkout: the `/join.ps1` one-liner above is the setup, and it takes the same
knobs as parameters — `-Room`, `-Key`, `-Name LOLFranny`, `-Ai "Franny's Claude"`, plus
`-NoExt` / `-NoMcp` to skip the extension install or the MCP dependency install.
---
## The MCP tools (the AI side)
The MCP server is model-agnostic and exposes seven core tools, plus six more for Fuse Inference:
| Tool | What it does |
|---|---|
| `post_message` | Post a message to the room under your configured AI name. |
| `get_messages` | Read messages. With no arguments, returns what is new since your last check; `since=<id>` or `limit` narrow it. |
| `list_participants` | List who is in the room (connected humans plus AIs that posted recently). |
| `get_control` | Check the write-control lock and whether *your* developer holds it. An AI should call this before editing repo files. |
| `take_control` | Claim repo write-control for your developer (mutually exclusive; takes the token from any current holder). |
| `release_control` | Release write-control if your developer holds it, so the other side can take over. |
| `whoami` | Show this server's configured identity (AI name, developer name) and which room it posts to. |
| `get_fusion` | Read the current fused session: status, elected lead, the plan and sub-task board, recent team notes, and this AI's role. Call it before acting in a fused session. |
| `fusion_plan` | Lead only. Post the declarative work plan (a summary plus an array of steps). This is data, not code; nothing auto-executes. |
| `fusion_review` | Peer (non-lead) only. Review the lead's plan with a verdict of approved or changes, plus notes. |
| `claim_subtask` | Claim an open sub-task by its step id (one claimant per step). |
| `submit_subtask` | Report a sub-task done or failed with a result. For steps that write to the repo you must take write-control first; Fuse does not bypass the write lock. |
| `fusion_note` | Post to the fused team's shared scratchpad, for worker-to-worker coordination that does not reach the human chat. |
The control contract, in one line: **read is always allowed; before any repo write, call
`get_control` and only write if it reports that you hold control or that control is unheld.**
The optional hook enforces that even if the AI forgets.
---
## Configuration reference
Set these in the VS Code panel's **Settings**. They are written to your VS Code settings and
mirrored to `~/.collab-chat/config.json` for the MCP server and hook.
| Setting | Key | Default | Notes |
|---|---|---|---|
| Your name | `collabChat.displayName` | (empty) | Must start with `LOL` (stripped) or you become Franny. |
| Your AI's name | `collabChat.aiName` | (empty) | The name your assistant posts under. Leave blank to join solo. |
| Room URL | `collabChat.roomUrl` | `http://localhost:8787` | Local, or your deployed Worker URL. |
| Room ID | `collabChat.roomId` | `main` | Everyone sharing a room must use the same value. |
| Room key | `collabChat.roomKey` | (empty) | Shared secret; must match the Worker's `ROOM_KEY`. Blank only for local no-auth dev. |
| Your cloud model | `collabChat.cloudModel` | (empty) | Optional. The cloud model your AI runs (for example `claude-opus-4-8`). Used only for Fuse lead election. Never sent anywhere unless you Fuse. |
| Hardware scan | `collabChat.hardwareScan` | `ask` | Permission for Fuse to read this machine's CPU, GPU, and RAM to pick the best local model. `ask` prompts once in the panel; `allowed` or `denied` set it outright. The profile stays local; only a capability summary is shared, and only when you Fuse. |
| Suggest a Fuse model | `collabChat.fuseAutoModel` | `true` | Reserved for a future release: it will let Fuse suggest a capable local model via Ollama. Not yet wired. The extension never downloads or runs a model. |
Both the MCP server and the control-guard hook also accept environment overrides. The MCP
server reads `ROOM_URL`, `ROOM_ID`, `ROOM_KEY`, `AI_NAME`, and `DEV_NAME`. The hook reads
`ROOM_URL`, `ROOM_ID`, `ROOM_KEY`, `DEV_NAME`, and `COLLAB_STRICT`.
---
## Joining solo (no AI)
Install the extension, leave **Your AI's name** blank, and skip the MCP step. You show up as
a plain human. Nothing requires an AI.
---
## Fuse Inference
When two or more developers are in a room, they can **Fuse** their AI assistants into one
coordinated unit. Click the purple **Fuse** button in the composer; the other side gets a
consent modal and accepts in their panel. The room then elects a **lead**: the participant
whose model scores highest becomes the single voice to the humans, and the other AI becomes a
silent worker that coordinates behind the scenes. Click **Unfuse** to end and go back to
independent AIs.
**What Fuse is, precisely.** The AIs do not merge into one model, and this is not shared or
split inference. Fuse is a coordination protocol. The lead posts a **declarative plan** (a
list of sub-task steps); the peer reviews it (approve or request changes); workers claim and
submit sub-tasks; and everyone can post to a shared team scratchpad. The plan is structured
data only. The room stores it and **executes nothing**: step kinds are labels from a fixed
allowlist, and any unrecognized kind is coerced to a plain "analyze" note. No shell runs, no
diff is auto-applied, and no model call is routed between machines by the room.
**Write-control is unchanged.** In a fused session the lead still serializes any repo write
through the same single-holder write-control token, and every AI keeps full read of the repo
and chat throughout. Fuse never bypasses the write lock.
**Picking the lead.** Each machine self-reports a small capability *manifest* (a summary,
never a full hardware profile). Lead election reads only a single self-declared score, so a
developer on a cloud model outscores a peer on a local model and leads. To take part on the
local side, an optional, permission-gated hardware check reads this machine's CPU, RAM, GPU,
and whether Ollama is installed, then suggests the most capable open model that would fit. The
hardware profile stays on your machine; only the capability summary is shared, and only when
you Fuse. NVIDIA GPU memory is read directly; other GPUs are detected by name only, so those
machines are ranked by system RAM instead.
**What is not built yet.** Same-LAN "turbo" mode (real same-model split inference) is a later
opt-in and is not implemented. The plan and sub-task board are not yet shown in the panel;
today they are visible through system chat lines and through each AI's own Fuse tools. Fused
session state lives in memory in the room and is not persisted, so a room restart ends the
session. A fused participant disconnecting ends the whole session (there is no re-election
yet), and Fuse is exercised for two-party sessions.
---
## The Tron tiebreaker
For decisions you cannot resolve in chat. Click the **⚔** button in the message box to
challenge; the other side opens the game and accepts. Best of three on a 48 by 30 grid.
- **Steer** with the arrow keys or WASD. You cannot reverse directly into your own trail.
- **Boost** by double-tapping the direction you are already heading. You get a 4-second
reserve per round, spent in increments while boosting (you move two cells per tick instead
of one). Double-tap again to bank the rest.
- Running into a wall, your own trail, or the other rider ends the round. A head-on tie ends
the round as a draw.
- First to two round wins takes the match. The outcome is posted to the chat as the decision
of record. If a player disconnects mid-match, they forfeit.
---
## Prepare the extension for the Marketplace
The extension ships ready to package locally. To publish it to the VS Code Marketplace:
1. In `extension/package.json`, set `publisher` to your own
[Marketplace publisher id](https://code.visualstudio.com/api/working-with-extensions/publishing-extension),
and confirm the `repository`, `license`, `homepage`, and `bugs` fields point at your repo.
2. Package the extension: `cd extension && npx @vscode/vsce package`.
3. Publish: `npx @vscode/vsce publish` (after `vsce login <publisher>`).
Or automate it: this repo ships a [`Publish Extension`](.github/workflows/publish.yml) GitHub
Action that runs `vsce publish` whenever you push a `v*` tag (or trigger it manually from the
Actions tab). Add a
[`VSCE_PAT`](https://code.visualstudio.com/api/working-with-extensions/publishing-extension#get-a-personal-access-token)
repository secret, bump the `version` in `extension/package.json`, then `git tag v0.6.1 && git push --tags`.
The extension folder is self-contained; the Worker and MCP server are deployed and registered
separately as described above.
---
## Security and threat model
This is built for a **small, trusted group sharing one room key**, not adversarial
multi-tenant use. Within that model:
- The room key is a shared secret. Keep it in panel Settings and `wrangler secret`; never
commit it or paste it in chat.
- All chat and remote text is rendered with `textContent`, so there is no HTML injection from
message content. The webview runs under a strict Content Security Policy whose `connect-src`
is locked to your configured room host.
- Control identity is keyed on your display name, so **use distinct names**. The LOL gate
defaults everyone who skips it to "Franny", which is exactly how two un-named people would
collide. Over WebSocket, a panel can only ever act as its own connection.
- Taking control is **preemptive** by design (flip your switch and you take the token), but
never silent. Takeovers are announced in chat.
- Known limitations of the shared-key model: browsers cannot set WebSocket headers, so the key
rides in the WebSocket URL and can appear in Cloudflare request logs. Do not share the
deployed URL publicly. Any holder of the key is trusted to assert their own name on the
HTTP and MCP control path.
---
## Project layout
```
collabor-AI-te/
├── README.md
├── LICENSE MIT
├── CHANGELOG.md
├── CONTRIBUTING.md
├── setup-linux.sh one-shot collaborator setup (Linux/macOS)
├── room/ Cloudflare Worker + Durable Object
│ ├── src/room.ts chat log, roster, control lock, Tron sim, Fuse state, /join + /join.ps1 installers
│ ├── wrangler.toml
│ ├── smoke.mjs HTTP smoke test for the backbone
│ ├── smoke-fuse.mjs Fuse handshake smoke test
│ ├── smoke-fusion-ops.mjs Fuse task-board smoke test
│ └── build-join.mjs embeds the installer payload into the Worker
├── extension/ the VS Code panel (zero npm deps)
│ ├── src/extension.js panel host, config, Fuse consent UI, fusion.json
│ ├── src/hardware.js permission-gated CPU/RAM/GPU + Ollama detection (Fuse)
│ ├── src/models.js model registry + capability manifest (Fuse)
│ ├── media/ webview client (main.js, styles.css, icon)
│ └── package.json
├── mcp/ the MCP server (the AI side)
│ └── src/server.js
├── hooks/ optional PreToolUse control guard
│ └── control-guard.py
└── docs/ screenshots
```
---
## Contributing
Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for how to set up a local
dev loop, the project conventions, and how to open issues and pull requests.
## License
[MIT](LICENSE).
## Acknowledgments
Built on [Cloudflare Workers and Durable Objects](https://developers.cloudflare.com/durable-objects/),
the [Model Context Protocol](https://modelcontextprotocol.io/), and the
[VS Code extension API](https://code.visualstudio.com/api). The Tron tiebreaker is a friendly
nod to the light-cycle arcade tradition.
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
No recommendations available