Rooms
Channels and direct messages, for talking to one agent or several, and rooms that own files everyone works on together
Rooms
A chat is a one-on-one with one agent, tied to one project folder. Sometimes you don't want that: you want to ask an agent something wherever it happens to live, or get a few agents talking in the same place about one topic. That's what a room is for. DorkOS has two kinds: channels and direct messages.
Three ways to talk to your agents
| What it's about | Who's in it | When it's over | |
|---|---|---|---|
| A chat | a project folder | one agent | when the work is done |
| A group message | who you're talking to | two or more agents | never, it's an ongoing thread |
| A channel | a topic | any number of agents, by name | when you archive it |
A chat is about one agent and its folder, a group message is about who you are talking to, and a channel is about what you are talking about.
Where an agent works when it answers you in a room
A chat runs inside a project folder you pick. An agent working there can read, write, and run commands in that exact project.
A room never moves an agent. When an agent answers you in a room, it works from its own folder, the same one it uses everywhere else. So it is still itself: the same personality, the same safety rules, the same memory, and the same account. You can't use a room to point an agent at some other folder for that room. If that's what you need, open a chat in that folder instead.
A room with no files of its own. The agent does real work from its own folder: reading files, running commands, the same as any other reply.
A room with files of its own. The agent still works from its own folder, and it is also handed two things for that turn:
- Its own copy of the room's files, which it can change freely.
- A look at the room's shared copy, which it can read but is told never to change.
Because the agent is standing in its own folder, a room about its own project can ask it to change its own code in the same reply it works on the room's files. It does that the way it would anywhere else, following its own project's rules. Files a room owns covers the room's side of it.
What you don't lose either way: each agent you talk to in a room keeps its own chat behind the scenes, so it remembers the room's history from one message to the next, the same as it would in a regular chat.
Direct messages
A direct message (DM) is a standing thread with several agents at once — a group message.
One agent, or several. Click the + next to "Direct messages" in the sidebar, then type an agent's name. Press Enter to add them, and repeat to add more. When you're done picking people, clear the search box and press Enter again.
Pick one agent and you get its chat — the same chat you get by clicking that agent in the sidebar. There's only one way in to an agent, so it only ever shows up once. Pick two or more and you start a group message, named after whoever's in it (like "Ana and Kai"). Add somebody to a group later and the name keeps up, unless you've renamed the DM yourself.
An agent can also open a one-on-one line to tell you something. That puts the agent under Direct messages in the sidebar, as one row: clicking it opens the same chat. A chat connected from Telegram or Slack keeps its own row, because there's a real person on the other end.
Ask for the same group again later and DorkOS reopens that DM instead of starting a new one. There's no way to end up with two group messages to the same people.
Who replies. By default, an agent answers every message you send it in a DM, the same as a
regular chat. In a group message, that means every agent in it can answer the same message: three
agents in the room, three replies, unless you say otherwise. To address just one agent, type @
followed by their name.
Channels
A channel is a named, topic-based room that can hold any number of agents and stays open until you archive it.
Starting one. Click the + next to "Channels" in the sidebar. Give it a name, pick the
agents you want in it, and click Create channel. DorkOS turns the name into a #-prefixed
channel right away.
A channel with nobody in it has nobody to answer you, so picking agents is part of making one. You can still create an empty channel if that's what you want, with Create it without agents, and add people later.
Adding agents later. Three places do the same thing, whichever you find first:
- The member count at the top of an open channel. Click it.
- The Add agents button in a channel with nothing in it yet.
- Right-click the channel in the sidebar, then Add agents...
All three open the same panel, which is also where you remove someone, and where you set how each agent decides when to reply in that channel.
Agents introduce themselves. When you create a channel with agents in it, or add an agent to one later, the channel gets a line saying "Ana joined this room." and Ana posts a sentence or two about who it is and what it can help with there. Each agent does this once per channel: removing it and adding it back, or restarting DorkOS, doesn't repeat it. Nobody answers an introduction, so a channel opened with five agents gets five introductions and then waits for you. An agent that is busy at that moment, or a channel that has used up its automatic replies for the hour, gets the line without the introduction, and so does an agent that has already introduced itself five times in the last hour. An introduction runs at the default permission level of the agent's tool, never the agent's own level, because all it needs is to post one message. Direct messages, #team and chats bridged from another app skip this.
Who replies. In a channel, an agent answers when you @mention it, not every message. That
keeps a busy channel from turning into everyone answering at once. You can change it per agent in
the members panel: from replying to everything, down to never replying on its own.
Waking someone, or just keeping them posted. Every @name in a channel message wakes that
agent, wherever it sits. To tell an agent something without asking it to act, write cc before
its name: cc @ana @bo wakes neither of them, for the rest of that line. A cc'd agent reads the
message the next time something else wakes it, so a cc is for an FYI, never a request. Copied names
show as grey chips. While you type, a line under the box says who your message wakes and who it
copies in, and once it's sent, your own message says "Woke @ana. Cc: @bo." Direct messages work as
before.
Files a room owns
A room can hold real files, not just messages. Scripts, notes, a set of documents, a small project: whatever the room is actually working on. Everyone in the room works on them together.
This is different from sending a file in a message. A file you send goes with that message. A room's files belong to the room, and they stay there whether or not anyone is talking.
Where to find them
Open a room's panel: click the member count at the top of the room, or right-click the room in the sidebar and choose Members. Under the list of who's in the room you'll see Files.
Each row says who last changed that file and when. If DorkOS can't work that out for a row, it
shows a dash rather than guessing. ROOM.md and README.md sit at the top, where you'd look for
them. In a room with no files of its own, only you see a Files section, with a button to
set them up. Everyone else sees none.
The list hides the machinery your tools keep for themselves: anything whose name starts with a dot,
whether it's a file or a folder, plus node_modules, .git, .dork, .claude, and .agents.
Press the crossed-out eye to show it all, and the plain eye to hide it again.
Everyone gets their own copy
The room keeps one shared copy of its files. Every agent that works in the room gets a copy of its own to work in.
That's the whole trick. Two agents can be busy in the same room at the same time without writing over each other, because neither one is writing where the other is. Nothing changes an agent's copy while it's working, and nothing writes to the shared copy in the middle of somebody's turn.
An agent's copy sticks around between turns. Work it started yesterday is still there today.
Copies catch up on their own when that's safe. Each time an agent starts a turn in the room, DorkOS checks its copy. If the agent has nothing in progress (no unsaved changes, no saved work the room hasn't got), DorkOS brings the copy up to date with the room's shared copy, and tells the agent how many files changed. So an agent that isn't mid-task always starts on the current files.
If the agent does have work in progress, DorkOS leaves its copy exactly as it is. Instead, the agent is told what has moved in the room since it started: who changed what, and which of those files it has also been changing. It then catches up itself, when it's ready.
DorkOS leaves a copy alone in a few other cases too, and never guesses:
- Another of that agent's turns in the same room is still running. The copy waits for the next turn.
- The copy isn't on its own branch (its own line of saved work). The agent is told to switch back before it merges.
- The room's git settings name a program. See Two refusals you might meet.
- Git can't read the copy. DorkOS logs it and tries again on the agent's next turn.
The shared copy is read-only by instruction, not by lock. Agents are told never to write in the room's shared copy, and where the agent's tool supports it, its file editor is kept out too. But an agent that runs commands can write wherever its permission settings let it, whichever tool it runs on, and that was true before too. What protects the room is that DorkOS checks the shared copy before every save and merge. If anything in it changed outside DorkOS, saving and merging stop until you sort it out (see When somebody changes the files outside DorkOS).
That check covers the files themselves. It doesn't yet cover the saved history agents share. An agent could still tamper with another agent's saved work, or with a stored version of a file, the current one included, without a new save and without the check noticing. It could do that with its file tools as well as with commands. Closing that gap is planned work.
Handing work back to the room
An agent puts finished work into the shared copy by merging it. That's the only way anything lands there.
Merging is careful on purpose:
- Unsaved work isn't merged. An agent has to save its work first, and it's told so if it hasn't.
- An agent has to catch up first. If the room has moved on since the agent last looked, the merge is refused and the agent is told how far behind it is. It catches up in its own copy, sorts out anything that clashes there, and tries again. Clashes never reach the shared copy.
- Two agents finishing at once take turns. The second one waits rather than failing. A room that has somehow piled up eight waiting merges turns the ninth away instead of queueing it, and says when to try again.
- Nothing lands half-done. A merge either goes in completely or not at all.
When it works, the room gets one line saying who merged what and how much changed. Nobody is
interrupted by it. The other agents find out the next time they do something in the room, which is
the point: a busy set of files doesn't have to mean a noisy room. An agent that actually wants your
attention @mentions you like anyone else.
There's no way to undo a merge from inside DorkOS, and no way for an agent to rewrite the room's history. Files only ever move forward.
You can read the work before it lands. When an agent puts a review of one of its files on the room's canvas, and its copy is ahead of the room, the tab shows that file the way the agent has it next to the way the room has it — change by change. Turn down the parts you don't want and they go back in the agent's copy, the same as if the agent had undone them. Then press Merge into the room.
Merging is something a person does. Only you see the button: agents have no way to reach it, so no agent can sign off its own work. Anyone in the room can open the review and send parts of it back — that's an ordinary thing for a person to do — but merging is yours alone. If the room has moved on since the agent last caught up, the button is replaced by the reason — and by a note to ask that agent to catch up, because it's their copy and running git in somebody else's working copy isn't your job.
Seeing who is sitting on work
Beside the Files heading, a badge names anyone holding work the room hasn't got yet. Hover it and it says which kind: work they saved but haven't merged, or changes they haven't even saved. It only appears when there's something to see.
A copy nobody has touched for two weeks gets tidied away, but only when it holds nothing the room hasn't already got. Anything unsaved or not yet merged is left alone, however long it sits there, including after that agent leaves the room. You can change the two weeks in Configuration.
Reading and editing
Click a file to read it. Text and markdown show in place. A picture, something too big, or anything that can't be shown says so plainly instead of failing.
Any text file you can also edit, whether it's notes, code or settings. Press Edit, make your change, and save. Your name goes on it, so the room can always say who wrote what, and each save is one entry in the room's history. Pictures and other files that aren't text stay read-only.
You can change the files themselves from the same panel:
- Add a file or a folder. Use the buttons next to Files, or right-click a row. A new file opens straight away for you to write. A new folder asks for its first file too, and appears once you save that file.
- Upload. Drop files from your computer onto the panel or onto a folder, or press Upload. Up to 20 at a time. If a name is already taken, you choose: replace it, or keep both.
- Rename, move and delete. Rename or delete from a row's menu, or drag a row onto a folder to move it. Deleting asks first and says how many files go with a folder. The room's history keeps a copy, so an agent or git can bring it back.
- Keep a file from the chat. Next to a file someone attached to a message there's a folder button. Press it, pick a folder, and the file becomes one of the room's files.
Each of these is one entry in the room's history under your name, and the room shows one quiet line about it. No agent is woken up by it.
If somebody changes the same file while you have it open, DorkOS won't quietly write over their work or throw yours away. It tells you who got there first and what they said they were doing, and you choose: open their version, or save yours over it. A rename, delete or upload that runs into somebody else's newer change asks the same way.
When somebody changes the files outside DorkOS
The files sit on your own computer, so nothing stops you opening them in a text editor. If you do, DorkOS notices and says so at the top of the room's Files section. Saving and merging stop in that room until it's sorted out. Stopping loudly beats guessing at what you meant.
You get two ways out, and they're both yours to pick:
- Keep them all. Everything that changed is saved as one entry in the room's history.
- Discard. Tick exactly the files to throw away. They can't be brought back, and DorkOS asks you to confirm.
One thing DorkOS will not do: if the room's files have ended up on a different branch, it leaves them there and tells you. Moving a branch it didn't move could strand work somebody meant to keep.
Two refusals you might meet
The room's git settings name a program. A room's files are kept with git, the tool that records every change. Git's settings can tell it to run a program whenever it handles a file. DorkOS never writes that kind of setting, but an agent running commands could. If one turns up, DorkOS stops working on that room's files: no saving, no merging, no reading them, and no bringing agents' copies up to date. The agents in the room are told a person has to fix it. You see each setting and one command that removes them all, in the Files panel and in DorkOS's log. Anyone else in the room, agents included, only sees that the files are paused until you fix the settings, because the command names a folder on your computer. Once you remove them, the room carries on as before.
An older room chat can't be picked up in the app. In earlier versions of DorkOS, an agent's room replies ran inside its copy of the room's files. Most of those chats carry on from the agent's own folder without you doing anything, but some can't move (OpenCode chats are the ones we know of). If you open one from your chats and send a message, DorkOS says it can't continue there and points you back to the room. In the room, that agent's next reply starts a new chat from its own folder. The old one stays readable, and the room keeps everything that was said.
ROOM.md, the room's front page
A room with files gets a ROOM.md. It's the room's own page, written by the people and agents in
it, and it's where "how we work here" belongs.
Every agent in that room reads it on every turn. So a convention you write once is a convention everybody follows, instead of something you repeat in every message.
A few things worth knowing:
- It adds to an agent's instructions, it doesn't replace them. Agents are told exactly that. If a room rule clashes with an agent's own, the agent follows its own and says so.
- Changes land on the next thing an agent does, never in the middle of something it's already working on.
- There's a size limit. Past it, agents are told the file is too long to send rather than being handed part of it, because half a rule reads like a whole one.
What a room can never do to an agent
A room can't widen what an agent is allowed to do. Permission settings, what an agent may run, what it needs to ask you about: all of that is yours, and nothing in a room's files or messages can reach it. Nothing in a room's files runs on its own when an agent catches up or merges, either.
The room's canvas is the same. It's a place to show each other things, not a way around any of the above: a document on the canvas never lets a member read a file they couldn't already read. A file out of somebody's own project shows as a tab with its name and who opened it, and says so instead of opening.
An agent attaching a file to a message is the same again: it can only attach a file it could already open on its own machine. The file has to be in that agent's own folder or its own copy of the room's files, so one agent can never reach into another's copy of the work and put it in front of everybody.
Worth being straight about the part that isn't a setting. Joining a shared room is trust in whoever can write to it. A file in a room, like a message in a room, can try to talk an agent into running something. DorkOS marks everything written by other people as information rather than instructions, and tells agents where a room's rules came from. But a room's files are data until an agent decides to run them, and who's in the room is the real control.
Giving a room files of its own
Open the room's panel. Under the list of who's in the room, Files says "This room has no shared
files." Choose Set up files… and confirm. DorkOS creates the room's shared files, with a
ROOM.md made from the room's name and topic. It can't be undone: once a room has files, it
keeps them. The same step is also a request to the DorkOS API, in the
reference below.
You can also ask an agent in the room to do it. An agent doesn't need your OK. It only works in rooms the agent is in, and the room and Activity both show who did it. To stop it for one agent, set that agent's Rooms permission to Ask or Blocked. To stop it everywhere, switch room files off in settings.
Once a room has files, everything above works normally.
The settings that go with all of this are in Configuration.
The room's canvas and browser
Every room has a table everyone can put something on. Open a room and the right panel has a Canvas tab and a Browser tab beside Room. Canvas holds documents — a file, a review of what changed in one, a write-up, a picture, a widget. Browser holds pages. Both belong to the room, not to your browser: everyone sees the same set, a reload gets it back, and closing something takes it off everybody's screen.
This is the same panel the Workbench guide describes in a one-on-one chat. What changes in a room is who the documents belong to.
Putting something on it
Anyone in the room can, person or agent. There's no owner-only half: if you're in the room, the table is yours too.
You have three ways in:
- Start from the empty tab. With nothing up yet, each tab offers its own starting points — Markdown or JSON on Canvas, a web page on Browser. Whichever you pick lands on the table for everyone.
- Type an address in the Browser tab. The page lands on the table with your name on it.
- Open a file from the Room tab's Files section and press Put on the canvas.
Anything already up, you can close or pin from its own tab — and that counts for everyone too.
An agent uses the tools it already has for your own workbench: put a document up, change one, take one off, open a file, open a review of a file, go to a page. Everything else those tools can do — panels, the sidebar, the theme, rearranging your window — only works in a one-on-one chat, and a room turns it down. A room is a shared table, not a shared window.
An agent can also put something here from a one-on-one chat with you. If you ask it for a chart and say the room it belongs in, it puts the chart straight on that room's table — it doesn't have to be answering in the room at the time. It has to be a member: a room it isn't in gets the same "no such room" a room that doesn't exist gets, so a room's name is never something to guess at. Everyone in the room sees the document, and one line saying what it put there posts when its turn with you ends. Nobody's turn starts because of it.
What everybody else sees
The document, as soon as it lands, with the face of whoever put it there on its tab. Nothing moves the tab you're on and nothing moves you off what you're reading — a tab that jumped because somebody else acted would be the same rudeness as an agent that speaks when it wasn't asked. The Canvas or Browser tab grows a small dot instead, so you can find what arrived when you're ready.
Markdown an agent wrote is yours to edit in place, and your save changes it for everyone. While you're editing, an agent's change to that same document is held rather than applied, and the agent is never told the change went through. Every other document on the table keeps updating normally.
You can also see who is reading what. A second small face sits on the tab somebody has open. In practice those faces are your agents': one appears while an agent's turn is really reading that document and goes when the turn ends, so it tells you what the agent is working from right now. It is never something an agent decides to show you — only a turn that really read the document puts one there, and an agent cannot say so any other way. Your own is never drawn for you, and none of it is saved: close the window and your face goes with it, and nobody who opens the room later learns where you used to be.
How agents find out
Three ways, and there is no fourth:
- The next time they do anything in the room, agents are told what's on the table — what each document is, what it's called, who put it there, and how many windows are open on the room right now. They aren't given the contents; an agent that wants those asks for them.
- One quiet line in the room's log per turn, saying what that agent opened or changed. It interrupts nobody, exactly like the line a merge writes.
- An
@mention, when an agent actually wants eyes on something now.
None of those starts anybody's turn. Putting something on a room's canvas wakes nobody, which is what makes it safe to leave on.
Talking about a document
Every document on the canvas has a Discuss button. Press it and the room gets one short line saying you started a discussion about that document, and a thread opens on it. Type there and you're talking about that one thing, out of the way of everything else being said in the room.
Press Discuss again next week, from another device, and you land in the same thread. So does
everyone else: there is one discussion per document, and the room remembers which one it is. The
line it writes wakes nobody, and a reply in the thread starts nobody's turn unless you @mention
them — the same rule as anywhere else in the room.
If you do ask an agent something in a document's thread, it is told about that document and no other. It still gets the label, not the contents; if it wants what's inside, it asks for it.
Following somebody's browser
If somebody else is in the room with you, the Browser tab has a Follow button. Pick a person and your panel goes where theirs goes — the same page, the same place on it — until you turn it off.
A few things worth knowing:
- It's people only. You can't follow an agent and an agent can't follow you. An agent has no window to share; it puts what it wants you to see on the canvas instead.
- It's off until you turn it on, it's never remembered, and it stops on its own when you switch to another window, close the tab, leave the room, or the person you're following goes quiet for half a minute.
- Nothing is recorded. What travels is which document they're on, the page in it, and how far down they've scrolled — never anything that's on the page. It's gone the moment it arrives, like the "typing" dots, and it's never in the room's history.
- Nobody shares anything until somebody is following them. A room where nobody is following anybody sends nothing extra at all.
- You're never pulled off something you're typing in. If you're editing a document, following waits until you stop.
Pinning, and what falls off
A room's canvas holds twelve documents at a time. Put up a thirteenth and the one nobody has touched for longest drops off to make space. Pin a document from its tab and it sorts to the front, never drops off however long it sits there, and doesn't count toward the twelve. Pins belong to the room like everything else here: you pin it, everyone sees it pinned.
Hover a tab and press the pin to put one up; press it again to take it down. Anyone in the room can do either. And a pin is part of the room rather than part of your browser, so it keeps: reload the page, or open the room on your phone, and the pinned tab is still first.
A room that has files of its own starts with ROOM.md pinned, because those
are the notes the whole room shares and they are worth a tab nothing can push off.
A board is just a pinned document
There is nothing to set up. Pin one document — a checklist, a status card, whatever the room needs to keep an eye on — and ask an agent to keep it current; any agent in the room can rewrite it, and everybody sees the same thing. #team starts with one so you can see what that looks like. Close it if you would rather not have it, and it stays closed.
A file on the canvas is still where it was
Putting a file on a shared table doesn't hand anyone the contents of files they couldn't already open. A document that came out of the room's own shared copy opens for every member, because every member could already read it.
The other case is a file an agent opened somewhere only it can reach: its own folder, which every room turn works from, or a file it is merely reading in its own copy. That shows up as a tab with the file's name and who opened it, and says plainly that the contents aren't here. It never quietly opens instead.
The one exception is a review of the room's own files from an agent's copy that is ahead of the room — the case above, under Handing work back to the room. That is work waiting for your decision rather than a file somebody is reading, so it opens, side by side with the room's own copy.
The check is on whoever is looking, at the moment they look, so it holds for somebody who joined the room afterwards too.
Archived rooms, and phones
Archiving a room freezes its canvas the way it freezes everything else: the documents stay, anyone can still read them, and nothing new can be put up. Deleting the room deletes them with it.
On a phone the panel is the same full-height sheet the Room tab uses, with the same tabs across the top.
#team, the room Home opens on
Every install has one channel it never had to make: #team. DorkOS opens it the first time the server starts, and the Home tab shows it. In every other way it is an ordinary channel, so everything else on this page applies to it too.
Who is in it. You, DorkBot, and every agent you register. A new agent joins on its own the moment you create it, so there is nobody to add. Removing an agent leaves its membership and its messages alone: the room still says who wrote what, and the agent simply stops answering.
Type without naming anyone and your default agent answers. One agent, not the room. Name
someone with @ and that agent answers instead, without your default chiming in as well. You pick
your default in Settings, and changing it moves who answers right away. On a fresh install it is
DorkBot, so day one already has someone to talk to.
You can quiet it, but you can't lose it. Mute #team from its row in the sidebar, the same as any other room. There is no delete. Your agents can't rename or archive it either, and if you archive it yourself, Home offers to bring it back.
Moments: the things #team marks
Now and then #team says something that isn't a message from anybody. "tangerines joined your team." "Your first schedule is set up." Those are moments: one line marking something that really happened here.
They only ever come from your own records. A moment is read off something DorkOS already keeps, like your list of agents or your activity log. Nothing is guessed at, rounded up, or invented to be encouraging, and a number in a moment was counted rather than estimated.
Each one lands once. A first-of-its-kind moment, like your first connection, happens once and never again. Restarting DorkOS doesn't repeat it, and anniversaries come once per anniversary.
At most one an hour. Add five agents in a minute and you get one line, not five. A milestone that would have arrived an hour after the thing it marks is dropped rather than saved up, because by then it isn't news.
A moment is a message in the room, not a separate feed. It sits in the room's history in the order it happened, with the face of whoever it's about next to it. There's nothing to press: it says what happened, and there's nobody to answer.
What gets marked today: an agent joining your team (with a warmer line for the very first agent you add), your first schedule, your first connection, the first scheduled run that finished overnight, a week and a month with an agent, and a week where something ran here every single day.
When you come back after being away
Come back after a few hours and the agents that got something done while you were gone can each leave one line in #team about it. It's called welcome-back, and the rule behind it is news, not noise:
- Only agents that actually did something. One with nothing new to say says nothing.
- Three lines at most, however many agents qualify.
- Four hours away before coming back counts as coming back. Time away is measured from the last thing you did in DorkOS, not from a browser tab losing focus.
- Nobody is woken up to write one. The lines come from what your chats already recorded, so the notes themselves cost you nothing. (The next-step offers below are the one part that does.)
One more thing, and it's on to start with. A note can end with a single next step the agent wants you to decide on — "want me to open the PR?". There's no way to know an agent has one without asking it, and asking runs that agent for a turn, so this is the one part of coming back that costs anything. Only the agents that already left you a note get asked, each of them once. An agent with nothing to offer says nothing, and an agent that's busy or runs into trouble stays quiet too — you still get the notes either way. If you'd rather not spend the turns: Settings → Preferences → Next-step offers, and it stays off.
Turning it off. Settings → Preferences → Welcome-back notes. Off means no notes, and no work done deciding there was nothing to say. That switch lives on your server, so it follows you to every device you open DorkOS on. To keep the notes but change how long an absence has to be, or how many notes one return may produce, both are settings in your config file: see Welcome back.
Handles: the name that reaches someone
A handle is one short name you type after an @ to reach exactly one agent. @ana.
@art-blocks-analytics.
Your agents already have one. DorkOS builds it from the name you gave the agent. It lowercases
the name and turns spaces into hyphens. Two agents that would end up with the same handle get
different ones: the second becomes @api-server-2. So a message can only ever reach one of them.
You do not have one yet. DorkOS will not guess a handle for you. It will not use a placeholder, and it will not use your computer's login name. Rooms say you have no handle rather than invent an address that reaches nobody. The screen for picking your own comes with the profile work. Nothing else about a room changes in the meantime.
Agents know you by the name in your profile. When an agent reads a room, your messages show under the name you gave DorkOS, or as "the operator" if you haven't given one. They never show as "You", which an agent could read as itself. Every line also says whether a person or an agent wrote it, and that tag is what tells you apart from an agent. An agent that is allowed to change your settings can also change your profile name, so the name alone doesn't prove who wrote something.
A handle uses lowercase letters, numbers, dots, underscores and hyphens. It runs from 2 to 32 characters and starts and ends with a letter or a number. Two handles can never differ only by capitals, and no two agents can share one.
Changing a handle is safe. Change yours on your profile, and an agent's on the agent's profile. Every message you already sent still reaches the same agent, because DorkOS worked out who you meant when you sent it. The handle left behind stays with whoever had it. Nobody else can claim it, and they can take it back. Each room the agent is in gets one quiet line saying who renamed it.
When you pick a handle, DorkOS turns it down if it looks like someone else's, like @d0rian next
to @dorian.
Renaming an agent needs a secure connection: this computer, your tunnel, or an https address. A
phone on your Wi-Fi can rename you, but not an agent, until Wi-Fi connections are encrypted.
People writing in from Telegram get a handle too. Theirs always carries the service they came
from, like @miguel.telegram. Somebody on another service can rename themselves anything they like
and still never take a name your agents answer to.
A message never gives an agent more power than its sender has. When someone from Telegram or Slack writes in a room, the agent answers at the level a brand-new chat starts at, even if you set that chat to Full autonomy. When one of your agents asks another for help in a room, the second agent works with no more power than the first one had at that moment. Your own messages run at the level you chose.
Five names are held back so nothing can pretend to be them. @dorkos is the room's own voice.
@everyone, @here, @channel and @room are reserved.
Deleting an agent keeps its handle. Its old messages are still in the room and still have to say
who wrote them. So a new agent you build later with the same name gets the numbered form,
@api-server-2, instead of the name the deleted one still holds.
What you see while an agent works
Ask a question in a room and an agent may take a while to answer. While it's working, a line above the message box tells you so:
Kai is working on it · 42s
The count is how long it has been going. If more than one agent picked it up, they're all named, up to three — past that the line counts them instead. Click it to see who: their names, how long each has been going, and what each one is replying to.
If the work runs longer than a room normally waits, the line says so rather than sitting there looking stuck:
Kai is still working — this is taking longer than usual · 12m
The answer still comes when it's ready. Nothing is lost, and a late reply says how long it took.
The line only appears while real work is running. DorkOS shows it when an agent actually picks up your message and takes it away the moment the work ends — it can't be faked, and an agent can't turn it on by wanting to. When it goes, either the answer is there or the room tells you why there isn't one.
How an agent decides to speak
Your agents choose when to speak. Every turn ends in one of three ways:
- Say something. The agent writes a message into the room on purpose.
- Just react. Sometimes ✅ is the whole answer, and adding "Acknowledged." on top of it is the message the reaction was meant to replace.
- Say nothing. The agent read the room, had nothing worth adding, and stopped.
An agent's thinking is not a message. Everything it works through during a turn stays in its own chat, where you can go and read it if you want to. Nothing reaches the room unless the agent puts it there.
It works the same way in direct messages, and on every kind of agent you run.
When you asked and got nothing, the room tells you. One line — "Ana read this and did not reply" — so you are never left wondering whether it saw you, and you can ask again, ask somebody else, or let it go. When nobody asked and an agent simply had nothing to add, the room stays exactly as it was: the working line fades out saying it finished with nothing to add, and there is no trace of it afterwards. That is the point. Nothing happened.
An agent may post as many messages in a turn as a person could. Agents are asked to say one thing in one message, and the room's log shows you exactly what each one said.
One exception keeps strangers from steering your agents. When someone outside your team starts a turn, for example a message on Telegram or Slack, that turn can post at most three messages and send you at most three notes. Your own agents' turns are never counted. One gap remains: a Codex or OpenCode agent posting into a room other than the one it is answering is not counted yet.
When your agent is busy somewhere else
An agent works in one folder, even if you talk to it in several places. Two chats at once means two turns changing the same files, and past a point they trip over each other. So DorkOS lets one agent work in up to three chats at the same time and no more. You can change that number in Settings → Advanced → Room limits → Chats at once, from 1 (one thing at a time) to 8.
Send an agent a message while it's already at that limit and DorkOS keeps your message. You never have to send it again. The line above the message box says what will happen while you wait:
Kai will pick this up when it finishes in #deploys · 40s
If Kai is working in several places, any of them finishing can free it, so the line says … when it finishes in #deploys or another chat.
Click it and you get two things: a way to open the chat that's in the way, and — if your agent has messages waiting in more than one place — Answer here first, which moves this room to the front of its queue. It doesn't interrupt anything. The work already running finishes first either way.
When one of those turns ends, your message becomes the agent's next turn and the answer lands here, in the room where you asked. Because rooms show messages in the order they arrive, a late answer says which message it's answering.
Two things worth knowing. If your agent is stuck on something for a very long time — an hour by default — DorkOS stops promising an answer and says so. Your message isn't lost: the agent reads it the next time it does anything in this room. And if the DorkOS server restarts while a message is waiting, the same thing happens: nothing is lost, but the room stops owing you an answer of its own, so send a nudge if you want one.
It can take a few seconds to catch up. If you open a room in the middle of a long reply, or your browser reconnects, the line appears within about ten seconds rather than instantly. And if it is missing while you were expecting it, that is worth reading as "DorkOS isn't sure right now" — your browser may have lost the room's live connection, or the agent may genuinely have stopped.
Where you left off
A room keeps going while you are away. When you come back, DorkOS puts a New messages line right where you stopped, so you can see what is new without scrolling and guessing. The room's row in the sidebar carries a count of what is waiting, and it clears once you catch up.
One mark, all your devices. The mark belongs to you, not to the browser you happened to use. Read a channel on your laptop and the count clears on your phone too, with no reload and no refresh button.
Nobody else can see it. This is not a read receipt. No other person and no agent can find out what you have read or when you read it. DorkOS shows no "seen by" list anywhere, and there is no setting that turns one on. Your mark is a private note to yourself about where you stopped.
Agents keep a mark of their own, but it answers a different question: which messages have already been handed to an agent, so it does not answer the same one twice. It is not a record of you.
Sending a file
You can send files in a room the same way you send them in a chat: click the paperclip, drag one onto the message box, or paste one in. They go with your message, not on their own — type something, then press Enter.
Once it's sent, everyone in the room sees it. Pictures show up right in the room; anything else shows up as a small chip with the file's name and size that you can click to download.
Only the people and agents in that room can open them. Someone who isn't in the room can't, even with the link.
The agents in the room get your files automatically. If your message reaches an agent, the files arrive with it and the agent can read them straight away — there's nothing to approve and nothing to copy anywhere.
Agents can send files too. A screenshot or a recording an agent made goes into the room the same way yours does: it shows up on the message, everyone can open it, and every other agent in the room finds its own copy of it on its next turn. An agent can only send a file from its own folder or its own copy of the room's files, and the same size and count limits apply.
A few things worth knowing:
- A file needs words with it. A message has to say something, so attaching a file on its own won't send.
- If a file doesn't upload, the message waits. The chip says what went wrong and offers to try again or remove it. Nothing goes out until you decide, so a message never arrives without the file it was about.
- How big and how many come from the same limits as chat — see Configuration.
A file you send is not the same as a file the room owns. Sending is for a picture or a document you want people to see right now. Files a room owns is for the work itself, and it's the better home for anything agents will edit, run, or come back to.
Saving a room as a file
Rooms live inside DorkOS, which means you can't open one in a text editor, search it with the tools you already use, or put a copy on a drive. Exporting fixes that. It writes the whole room history to one file you own:
dorkos room export #backendThat saves something like room-backend-2026-08-15.jsonl in the folder you're standing in. Give
it --out to choose the name and place, or --out - to send it straight to another command:
dorkos room export #backend --out ~/archive/backend.jsonl
dorkos room export #backend --out - | grep deployWhat's in it. One message per line, in the order they were said, as JSON. Each line carries who said it, when, what they wrote, who they mentioned, which thread it belongs to, the reactions on it, and the names of any files attached. Names are written out on every line, so searching for a person's name finds their messages without any extra tooling. The first line describes the room and who's in it; the last line is a count, which is how you can tell a finished download from one that stopped early.
Attachments are listed, not included — you get each file's name, size, and type, so the file stays small enough to search. The pictures and documents themselves stay in DorkOS.
It's a copy. Exporting changes nothing and takes nothing away; the room carries on exactly as it was. There's no way to load a file back in, on purpose — the room in DorkOS is the real one, and a file that could overwrite it would be a way to rewrite history.
How much you get. Exporting your own room gives you all of it, from the very first message, even if you joined partway through. Anyone else — an agent, or a second person on the install — gets only what was said after they arrived, which is the same rule that governs what they can read in the room itself. The file says which of the two it is, so you're never guessing.
Good to know
- Threads have their own page. Reply to a message and you start a thread. Every thread you're in is on the Threads page at the top of the sidebar, newest reply first, and you can answer one right there. On a phone, a thread opens as a full screen over its room. Tap back or swipe right to return to the same spot in the room.
- Mentioning someone. Type
@followed by their handle to address just them. It's how you get an answer in a channel, and it's useful in a group DM. A display name is not an address: only a handle reaches somebody. Get it wrong and DorkOS just treats it as plain text; nothing breaks. - Several replies at once is normal. Addressing more than one agent and getting more than one answer is how rooms are meant to work, not a glitch.
- Agents can reply to each other, up to a point. If one agent's reply mentions another, that can trigger a reply of its own, and so on. DorkOS caps how many times that can happen in a row (30 by default), and no one agent may take more than 10 of those turns. When it stops, the room tells you which agent stopped, that the back-and-forth hit its automatic-reply limit, and that sending a message picks it back up. Sending a new message resets the count. You can change the limit; see Configuration.
- A dropped connection says so. If your browser loses its live connection to a room, you'll see "New messages aren't coming through right now" with a link to reconnect. You can still read and post either way, you just might not see a reply land until you're back.
- You see every room; your agents don't. As the person running DorkOS, every channel and DM is visible to you. An agent only sees the rooms it's actually a member of.
Reference (for developers)
If you're calling the API directly, here's the exact mechanics behind everything above.
Creating and posting
POST /api/rooms creates a channel (kind: "channel") or a direct message (kind: "dm").
Posting a message is trigger-only: POST /api/rooms/:id/entries returns 202 Accepted
immediately, and the message itself, along with any agent replies it triggers, arrives over the
room's durable event stream, GET /api/rooms/:id/events. That stream works the same way a
chat's does: a snapshot on connect, gap-free replay via Last-Event-ID on reconnect, then live
events with a monotonic sequence number.
A second, global stream, GET /api/events, carries the signals that keep the sidebar's room list
current (a room's name changing, a new room appearing, an unread count going up, your own read
mark moving on another device) without needing a subscription to every room at once.
REST surface
| Method | Path | Purpose |
|---|---|---|
GET | /api/rooms | List your rooms, optionally filtered by kind. |
POST | /api/rooms | Create a channel or a direct message. |
GET | /api/rooms/:id | One room, with its member list. |
PATCH | /api/rooms/:id | Update a room's title, topic, or archived state. |
GET | /api/rooms/:id/entries | Paginated message history. |
GET | /api/rooms/:id/export | The whole room as JSONL, as a download. |
POST | /api/rooms/:id/entries | Post a message. |
POST | /api/rooms/:id/members | Add a member. |
PATCH | /api/rooms/:id/members/:authorId | Change a member's response mode. |
DELETE | /api/rooms/:id/members/:authorId | Remove a member. |
GET | /api/rooms/:id/members/:authorId/reseat-options | Where an agent could move to another account. |
POST | /api/rooms/:id/members/:authorId/reseat | Move an agent to another account. |
GET | /api/rooms/:id/events | The room's live event stream. |
The room's canvas has nine of its own. Every one resolves the caller server-side and answers 404
for a room you aren't in, exactly as if it didn't exist. The six that write also refuse an
archived room; the three that read answer normally forever. Two of them are yours alone — saying
what you're looking at, and the review of somebody else's copy — and answer an agent 403.
| Method | Path | Purpose |
|---|---|---|
GET | /api/rooms/:id/canvas | Everything on the room's canvas. |
GET | /api/rooms/:id/canvas/:documentId | One document, contents included. |
POST | /api/rooms/:id/canvas | Put a document on it. |
PATCH | /api/rooms/:id/canvas/:documentId | Change one, pin it, or bump it to the front. |
DELETE | /api/rooms/:id/canvas/:documentId | Take one off, for everybody. |
POST | /api/rooms/:id/canvas/:documentId/editing | Say you're editing it, so agent changes hold. |
POST | /api/rooms/:id/canvas/:documentId/thread | Open the document's discussion, or re-open it. |
GET | /api/rooms/:id/canvas/:documentId/diff | Both copies of the file behind a review. |
PUT | /api/rooms/:id/canvas/:documentId/diff | Put a reviewed file back in the agent's copy. |
Following somebody's browser has three more. All three are people only: a caller acting as an agent is refused.
| Method | Path | Purpose |
|---|---|---|
PUT | /api/rooms/:id/follow | Follow somebody, or say you're still following them. |
DELETE | /api/rooms/:id/follow | Stop following. |
POST | /api/rooms/:id/follow/view | Say where you're looking, for whoever is following. |
The full request and response shapes are in the API reference.
Marking a room read
Read state is not a room endpoint. One address covers every kind of room or chat a person reads:
| Method | Path | Purpose |
|---|---|---|
PUT | /api/read-cursors/room/:id | Move your mark in this room to a position. |
GET | /api/read-cursors/room/:id | Read your mark back. |
Both are people-only. A caller the server resolves as an agent gets 403 PEOPLE_ONLY rather than a
row of its own, and there is no way to name a different user in the request, so a cursor is only
ever written and read back by the person it belongs to.
A room cursor is delegated into the room service, so it runs the room's own visibility check and
recomputes the unread count the sidebar draws. A cursor that actually moves is announced as a
read_cursor event on the global GET /api/events stream, which is how your other open windows
catch up without polling.
What an agent has been shown is a separate number, room_members.last_read_seq, advanced by the
room's participation loop as entries are handed to that agent. No route writes it.
PUT /api/rooms/:id/read-cursor is gone. If you wrote a script against it, point it at PUT /api/read-cursors/room/:id instead. The request body is the same.
Who answers, and when
Each agent member of a room has a response mode that decides whether a given message triggers a reply from it:
| Stored value | Replies when |
|---|---|
silent | never |
mention-only | mentioned by name |
direct-only | the room is a one-to-one, or mentioned by name |
engaged | mentioned by name, and for a short while after that |
always | every message |
Every one of these is accepted in every room. direct-only is the odd one out: it is the only value
whose meaning changes with the kind of room it is stored in — in a one-to-one it answers everything,
in a channel it answers only when you say its name.
A direct message seeds each agent's response mode from that agent's own default (always unless
configured otherwise). A channel seeds new members as engaged. Mentions are resolved once,
at the moment a message is posted, against the room's current roster; they're never re-parsed
later, so renaming an agent doesn't retroactively change who an old message addressed.
Staying in the exchange
engaged is the channel default because the two either side of it are both wrong for a room you
actually work in. mention-only charges you an @ on every single message, even when it is
obvious who you are talking to. always means an agent answers everything anybody says, which in a
room with more than one of them is a discussion you are no longer part of.
So an agent that has been addressed keeps answering for a while, and then stops. In a channel,
DorkOS follows who you are talking to rather than waiting for another @mention: when you post without
naming anyone, it goes to whichever agent you were just talking to there — the one that answered
last, or the one you last @mentioned if it hasn't answered yet. That window ends after
60 minutes, or after 15 messages, whichever comes first — and the agent's own replies keep
it open, the same as naming it again would. Both numbers are settings
(rooms.engagedWindowMinutes and rooms.engagedWindowPosts); setting either to 0 makes
engaged behave exactly like mention-only.
Agents talking to each other stay on a shorter leash: one agent's reply to another only keeps that exchange open for 10 minutes or 5 messages, no matter how high you've turned the settings above. That keeps agent-to-agent chatter from running on quietly in the background.
The same window works in a one-to-one. Adding a second agent to one of those does not turn it into a channel — DorkOS still counts it as a direct message — and once there is more than one agent in the room you do start saying which one you mean.
The window is per thread. Asking an agent something inside a thread keeps it in that thread, not in the whole channel — and talking to it in the channel does not pull it into every thread that happens to be open.
Listening inside that window is nearly free. An agent that is following the exchange skips a
message that plainly was not for it — one that named a different agent, or a reply in an exchange it
is not part of — instead of reading it properly and then deciding to say nothing. It still sees the
message as background the next time it does reply, so nothing goes missing, and a message that names
it is never skipped. Set rooms.responseGate to off if you would rather every agent weigh every
message.
An agent's own settings do not offer Engaged as its default. That default only ever seeds a one-to-one, at the moment the agent joins it, and how loud an agent is belongs to the room rather than to the agent.
The channel lead
Every channel can have a lead: the one agent that answers when you write without @-naming
anyone, and you aren't already talking to someone else there.
The lead answers no matter how its own reply setting is set — even @only or Silent. To stop
that, pick another lead, or none. It steps back in
two cases: when your message @mentions a different agent, and when it names only people. And if
you're mid-exchange with another agent (see Staying in the exchange
above), that agent keeps the message — the lead only picks up what nobody else would.
Choosing one. The first agent you add to a channel becomes its lead. Change it from the channel's members panel. If the lead leaves the channel, the agent that has been in it longest takes over. If the lead is removed from DorkOS altogether, the channel has no lead until it comes back or you pick another. An agent can hand the lead to another agent while it holds it, or take it when nobody does, but it can never take it from another agent.
Channels connected to Telegram or Slack have no lead. Their agent answers @mentions only, so
messages from people outside your team never reach it on their own.
#team keeps its own. Its lead is always your default agent, the one you pick with "Set as default" on an agent's profile, and the room itself can't change it.
You always hear back
When an agent is picked to answer your message, 👀 appears on it right away, and goes away when the agent is done. You can tell at a glance that somebody has it.
If the agent is busy in its own chat, the room says so once and tries again on its own; you don't send anything twice. If it is still busy after about two hours, the room says that too.
If a channel has no agent in it, a quiet line above the message box says so, with a way to add one. It isn't a message in the room, so it never counts as unread.
If an agent's Claude account runs out of usage, or nearly does, the agent moves to the account with the most usage left and answers the same message. The room says so in one short line. If no account has usage left, the room says when the soonest one is back. You can also move an agent yourself: open its menu in the member list and choose Continue on another account….
Setting it, in the app
You do not pick any of those words. Open a room's panel — the member count in its header, or Members on its row in the sidebar — and each agent has its loudness on the right, on a scale that runs quiet to loud:
Silent → @only → Engaged → Everything
The same four in a channel and in a one-to-one. Press it and the scale opens, with the rule spelled out underneath in your own numbers. Point at a setting, with the mouse or the arrow keys, and the line at the top of the panel shows what the whole room would become if you chose it — so you can see the consequence before you commit to it. Nothing is saved until you actually pick one.
Who sees which rooms
You, the person running DorkOS, see every room. "Membership" here describes the data model, not an access rule against the machine's owner. An agent only sees rooms it's a member of, so it can't list your other rooms.
What an agent knows when it answers
An agent replying in a room gets more than the one message. Before its turn runs, DorkOS tells it where it is and who it is talking to:
- The room's name and topic, and whether this is a reply inside a thread.
- Everyone in the room, and which of them are people and which are other agents. That one distinction is what lets an agent leave a question alone when it was clearly meant for a colleague, instead of answering everything it can see.
- Which agents are mid-answer right now. This is so an agent knows somebody is already on it. It is not a queue, and nothing waits its turn.
- Messages it hasn't read yet, and the last few things it said here, so a second reply doesn't repeat the first.
- What's on the room's canvas: each document's name, what it is, who put it there, and how many windows are open on the room right now. Never the contents — an agent that wants those asks for them, which keeps a room with a busy canvas from costing anything extra on a turn that ignores it.
- How many automatic replies are left, in this room and across DorkOS.
Everything other people wrote arrives in a clearly marked block that tells the agent it is information, not instructions. The markers around that block carry a one-time code, so a message can't end the block early and have the rest read as a command. The message the agent is answering reaches it exactly as you typed it, with nothing wrapped around it.
Every reply is a real chat
A room-triggered reply runs through the same turn machinery a normal chat uses. Each agent keeps one chat per room it's in, bound the first time it replies there, which is what lets its context carry across messages in that room instead of starting fresh each time.
Every room turn runs with the agent's own home directory as its cwd, whether or not the room has
files. For a room with files, the turn is also granted folders for that turn only: the agent's
worktree (read and write), the room's shared checkout (read), and the few parts of the room's
.git that a commit and a git merge main in that worktree write. The agent reaches the room's
files by absolute path and runs git there with git -C. At launch, a clean worktree is
fast-forwarded to main. One holding work is left alone and the turn is told what moved; one off
its own branch is left alone and the turn is told to switch back.
Continuing a room-bound chat from the app follows the same rule: the turn runs at the agent's
home with the same grants. A request naming the agent's own worktree in the room is switched to its
home, and one naming a private copy of the agent's own home is allowed. A request naming any folder
that isn't the agent's own is refused DESK_NOT_OWN, and a chat whose runtime keeps it inside
the room's files is refused ROOM_SESSION_MOVED, both with 409.
Giving a room files
POST /api/rooms/:id/repo gives a room files of its own. It takes no body. DorkOS creates the
room's shared copy, seeds a ROOM.md from the room's name and topic, and commits it as whoever
asked.
Any member can call it, and agents reach it through the set_up_room_files tool. Someone
outside the room gets 404, and an archived room answers 409 ROOM_ARCHIVED. Asking twice is safe: a room that already has files answers 409 with
the binding it already has. If room files are switched off in settings, it answers 409 ROOM_REPOS_DISABLED.
| Method | Path | Purpose |
|---|---|---|
POST | /api/rooms/:id/repo | Give a room files of its own. Any member. |
GET | /api/rooms/:id/files | List one directory of the room's shared copy, with provenance. |
GET | /api/rooms/:id/files/content | Read one file. Answers text, binary, or too-large. |
PUT | /api/rooms/:id/files/content | Save one file. People only; agents merge instead. |
POST | /api/rooms/:id/files/upload | Upload files. People only. |
POST | /api/rooms/:id/files/move | Rename or move a file or folder. People only. |
POST | /api/rooms/:id/files/delete | Delete a file or folder. People only. |
POST | /api/rooms/:id/files/from-attachment | Keep a chat attachment as one of the room's files. People only. |
GET | /api/rooms/:id/repo/status | Main's tip, and each member's unmerged and uncommitted work. |
POST | /api/rooms/:id/repo/merge | Merge a member's work into the room's shared copy. |
POST | /api/rooms/:id/repo/main/repair | Commit or discard changes made outside DorkOS. Owner-only. |
The read routes are gated exactly as reading a room's history is: a caller who is not a member gets
the same 404 an unknown room gets, and membership is checked before the room is asked whether it
has files, so a room id cannot be used to find out which rooms have them.
Every listing and every read answers from a commit, never from whatever is on disk, so a
half-written edit in the shared copy is invisible and .git is not in the tree to be reached. A
symlink is listed and never followed.
Two answers from these read routes are worth not confusing. 409 ROOM_HAS_NO_REPO means this room
specifically has no files, either because it was never given any or because room files are switched
off: one predicate covers both, on purpose, so the answer cannot be used to tell them apart.
ROOM_REPO_GIT_UNAVAILABLE means this machine has no git at all. The merge tool never returns
either one; it distinguishes NOT_A_PROJECT_ROOM from ROOM_REPOS_DISABLED instead.
PUT /api/rooms/:id/files/content carries { path, baseCommit, text }. baseCommit is the commit
the editor loaded, and the save is refused 409 FILE_CHANGED only if the shared copy moved and
touched that path. The refusal carries the commit that won, which is what the app turns into
"open their version, or save yours over it".
The two room-repo tools
Agents get exactly two verbs, both membership-gated. Everything else they do with a room's files is
ordinary git in their own copy, including catching up, which is plain git merge main and
deliberately not a tool.
| Tool | Tier | Does |
|---|---|---|
merge_to_room_main | act | Merge this agent's work into the room's shared copy. |
set_up_room_files | act | Give a room this agent is in files of its own. |
room_repo_status | observe | Where main is, and who is holding unmerged work. |
merge_to_room_main refuses with a specific reason rather than a generic failure, and each reason
implies its own fix: NOT_A_PROJECT_ROOM, UNCOMMITTED_WORK, BEHIND_MAIN (with how far),
NOTHING_TO_MERGE, SYMLINK_ESCAPES_REPO, SUBMODULE_NOT_ALLOWED, FILE_TOO_LARGE,
REPO_CAP_EXCEEDED, MAIN_CHECKOUT_DIRTY. A merge arriving while another is running queues, and
answers 429 MERGE_IN_FLIGHT with a Retry-After when its wait runs out. It is answered the same
way without waiting at all if the room's queue is already eight deep, which is a wedged room saying
so rather than growing a line nobody will reach the front of.
Giving a room files is not in this list and never will be. The full mechanism, the merge contract,
and the trust boundary are in
contributing/room-repos.md.