Edit the same file together, on a server you run.
Your editor, their editor or a browser tab, all in the same file. No third party's cloud holds the room.
- Sealed
- Specified
- Path-scoped
- No account
Try → Run
Try it in the browser, then run your own.
Every room runs on a server. The demo is one; the commands below start the same server, and the web client in front of it, on a machine you control.
01Try
LiveHost a folder in desktop Chrome or Edge. Firefox and Safari can join from an invite link; use an editor to host instead.
02Run
selvaged + selvage-webTwo containers: the server that holds the room, and the web client a guest joins in a browser. Rooms live in memory, so a restart ends them.
Try the local Docker setup03Rent a server
Not available yetWe run the server, you open rooms.
Hosted servers
Start a room
Edit together on the demo.
Open the demo in desktop Chrome or Edge. Use a small, disposable text folder: anyone with the invite can edit files on your disk.
01
Share a folder
Enter Your name, choose Share a folder… and allow read/write access. Open a text file.
02
Send the invite
Choose Copy invite link and send the complete link, including everything after #, to someone you trust.
03
Type in the same file
Your guest opens the link, enters their name, chooses Join and opens the same file. Try typing in both windows.
04
End the room
Keep the host tab open; don't reload it. To finish, choose Leave and end the room, then Leave anyway.
Run it yourself
Test locally with Docker.
Run these three commands in order, then open http://127.0.0.1:8080/ and follow the same folder-sharing steps. This setup is local-only: it binds to 127.0.0.1, so its invite won't reach another machine. Test a guest in another browser window on this machine.
To invite someone on another machine, use the demo or follow the remote deployment guide for a reachable server with TLS and deployment hardening.
Create the network
$ docker network create selvage
Start the reference server
$ docker run -d --rm --name selvaged --network selvage ghcr.io/selvage-protocol/selvaged
Start the web client
$ docker run -d --rm --name selvage-web --network selvage -p 127.0.0.1:8080:8080 -e SELVAGE_SERVER=http://selvaged:8080 ghcr.io/selvage-protocol/selvage-web
When you're done
Stopping the containers ends their rooms. The startup commands use --rm, so Docker removes the containers when they stop. Then remove their network.
Stop both containers
$ docker stop selvage-web selvaged
Remove the network
$ docker network rm selvage
Get it working
One server, any client.
The extension, the two plugins, the browser page and an agent over MCP are clients, not a server: each one connects to a selvaged you run.
The server carries bytes it cannot read
Documents, cursors, the file listing and the roles the host signs travel sealed, under keys the invite link carries in the part a browser never sends to a server.
- documents
- cursors
- the file listing
- the roles the host signs
What the server can still see
- that a room exists
- who is in it and their names
- sizes and timing of what moves
It can drop, delay or end a room. The host is a peer's signed claim: the server cannot seat a host, prove one, or take the role.
See it working
Your folder, open in their editor.
Anyone with the link is in
There is no approval step and no account to create. Treat an invite the way you would treat a password.
Everyone's caret, in one file
You see where each person is typing, and their caret and selection travel with their edits.
Guests only see the folder you shared
The room never adds, renames or removes a file in your working copy.
Clients share one protocol
The session layer is written down rather than glued into each editor, so any client that speaks it can share the room.
Why a spec
The session layer is written down.
Which rooms exist, who is in one, which documents are open, where the carets are: every collaborative tool decides those for itself, so a tool from one cannot join a room from another.
Selvage writes that layer down: prose, a canonical byte form for a frame, JSON Schema, and a corpus of conformance vectors, replayed byte for byte against a real server. The specification's own validator, specification/schema/validate.py, prints the corpus's counts, so a reader can check the current figures. It is written to be implemented on its own, without reading the server's code.
The JetBrains plugin is a separate implementation, written in Kotlin from the specification. The other clients share one TypeScript engine.
Read the specification- specificationProse, schema, vectorssource of truth
- reference_serverselvagedavailable
- vscode_clientVS Code extensionavailable
- nvim_clientNeovim pluginavailable
- jetbrains_clientJetBrains IDE pluginavailable
- web_clientThe browser pageavailable
- mcpAn agent over MCPavailable