Detente docs
Everything in one place: how Detente catches a break, how to run it, every command and chat phrase, and what it can't do yet.
localhost on the tower machine, or its TOWER_ADDR from any other laptop. Every command and link below uses it.

How it works
Agents on different laptops can't see each other's unpushed work, and file locks only catch two edits to one file. Detente sits in your team's chat as the tower, compares what each agent is changing, and holds both before a break is pushed.
File a flight plan
FLIGHT PLAN task: add a timeout to sessions edit: auth/session.py changes: create_session
Before it edits anything, an agent posts what it will change in the tower room.
Get cleared
[o_o] CLEARED lay-claude · auth/session.py
Detente clears the plan, and warns when it overlaps someone else's.
Gates enforce it
No clearance for billing/models.py. File a flight plan in the tower room.
A Claude Code hook refuses edits, and a git hook refuses commits, for any file not cleared. Shell commands are checked for files they changed.
Squawks report the code
lay-claude auth/session.py
def create_session(user, ttl)
a-codex billing/refunds.py:42
create_session(user)A daemon on each laptop sends the signatures that changed and the calls being made in unpushed work. Detente compares them across laptops with Python's ast, and fetches main every 10 seconds while there's unpushed work.
A break holds both
Holding for conflict-create-session-3f1a. A person decides in that room.
When one agent's change breaks code the other is writing, Detente holds both flights and opens a conflict room with both people and both agents.
A person picks A or B
lay: A [^_^] DECIDED by lay (A): pass a ttl in billing/refunds.py. a-codex makes the edit. [^_^] RESOLVED conflict-create-session-3f1a: the code fits again. 0 open collisions.
The holds lift, the agent you picked makes the fix, and Detente archives the room once the code fits again.
Play the runWhat Detente says
lay-claude changed a function. a-codex, on another laptop, is still calling it the old way, in a different file. Nobody has pushed, and no lines overlap.
[O_O]! COLLISION lay-claude changed create_session(user) to create_session(user, ttl) a-codex's billing/refunds.py:42 is missing required argument ttl Nothing pushed. Both flights holding. Opened conflict-create-session-3f1a.
Every decision is deterministic Python. No LLM call decides a clearance.
Run it
One computer runs the
tower. Each laptop gets the
command. People decide in
chat.
| Radar, after you sign in | http://localhost:3100/radar |
|---|---|
| Showcase | http://localhost:3100/showcase |
| Detente's API | http://localhost:8100 |
| Mattermost, for chat | http://localhost:8065 |
| Switch Gateway | http://localhost:3110 |
| Switch's agent API | http://localhost:8110 |
The tower
One machine that stays on. You need Docker, uv and Node 24. This starts Switch with its bundled Mattermost, then Detente and the radar, and makes a sign-in. Switch can use Slack, Discord or Microsoft Teams instead, though Detente has only been tested on Mattermost.
git clone https://github.com/laypatel13/detente cd detente make install make switch-up make setup make up make user NAME=yourname
Let the team's laptops in
Every address answers on this machine only. Add its address on your team's private network, such as its Tailscale address, and restart. Teammates then use it in place of localhost, and Switch's database stays here.
echo "TOWER_ADDR=100.101.102.103" >> .env make switch-up up
Already have a Switch server? Skip make switch-up and run uv run python -m backend.setup --url <agent API URL> --registration-token <token>.
Each laptop
Every computer where an agent works. First, Switch Console, Switch's desktop app, runs the agent and puts it in the team's chat. When it asks for a server, choose Connect to an existing server and enter this address.
http://localhost:8110
Then install the command once, with Python 3.12 or newer. pipx install detente works too; uvx doesn't, because the gates run from wherever the command is installed.
uv tool install detente
Then connect each checkout an agent works in. It asks for anything you leave out, including the pilot token, DETENTE_PILOT_TOKEN in the tower's .env, and checks it with the tower before writing anything.
detente connect --callsign lay-claude --person lay --vendor "Claude Code" --url http://localhost:8100
Keep the watcher running while agents work, and check the setup whenever something seems off.
detente watch detente doctor
Last, set up the agent in Switch Console. Name it exactly the callsign you gave detente connect and point it at this checkout's folder. Under Who can talk to your agent, add a rule for the agent detente: the default, you and your agents, blocks its clearances and holds. Then add it to the tower room, where it learns the flight-plan rules.
connect keeps its .detente file out of git. watch sends the paths, changed lines, signatures and calls of your unpushed work, never whole files, and only to your tower. The CLI sends no telemetry.
Commands
Start
detente- Roger, where you are, and the commands you'll use most.
detente connect- Connects the checkout you're in to your team's tower: the commit gate, Claude Code's edit gate, the callsign and the pilot token.
detente watch- Tells the tower what this checkout's unpushed work changes and calls. While there's unpushed work it also fetches main every 10 seconds. Ctrl+C stops it.
detente doctor- Checks git, the config, both gates, and that the tower answers and takes the token.
detente disconnect- Removes this checkout's gates and config. Other hooks, your code and your commits stay as they are.
The tower
detente status- Flights in the air, open conflicts and the latest messages.
-n 10shows more. detente conflict [name]- One conflict in full: what changed, what it breaks, the fixes on offer and who picked. Leave the name out for the open one.
detente check <file>…- Is this checkout cleared to edit these files? Exits 1 if any isn't. For agents without Claude Code's hooks, and for scripts.
Options and exit codes
--repo PATH, -r PATH- Use another checkout than the one you're in.
--json- The raw result as JSON, for scripts:
doctor,status,conflictandcheck. exit 0- All fine.
exit 1- A finding:
checkrefused a file. exit 2- A usage problem.
exit 3- The setup or the tower:
doctorfound a problem, or the tower didn't answer.
Showcase
detente showcase- The recorded run, in your terminal.
--fastplays it without pauses. uvx detente showcase- The same, with nothing installed but uv.
Accounts, on the tower machine
add <name>- Adds an account. It asks for a password of at least 12 characters.
password <name>- Changes the password and signs that person out everywhere.
remove <name>- Removes the account and ends its sessions at once.
list- Lists accounts.
Run each one after docker compose -p detente exec api .venv/bin/python -m backend.accounts. Five wrong passwords lock that name for five minutes. Sessions last 14 days.
Develop
make test- Everything offline. Fails if the real app imports showcase code.
make bench- 32 scenarios on real git checkouts, in seconds.
make bench-real REPOS="…"- Replays merged PRs from a project's history to count false alarms.
make dev- The API and the web app with live reload.
make test-live- Real Switch, Mattermost, git worktrees, gates and squawk daemons. Needs Switch and Detente running.
make test-crash- Kills Detente mid-collision to prove holds survive a crash. Needs make api.
make record- Flies both choices on real Switch and rewrites the showcase's recordings.
Talk to Detente
Decisions happen in Switch, where both people and both agents see them. The CLI never picks a fix. Detente checks that the sender is a person before it acts.
| Says | Who | What happens |
|---|---|---|
| @detente ground stop | A person | Every gate closes until resume. |
| @detente resume | A person | Gates reopen. |
| @detente land <callsign> | A person | Clears that flight and stops comparing its unpushed work, for an agent that died or a break you accept. |
| A or B | A person | In a conflict room, picks the fix. |
| FLIGHT PLAN | An agent | Files a plan. |
| LANDED | An agent | Closes its flight. Its work still counts, unpushed or just pushed. |
The benchmark
18 of 20
real breaks stopped from the code, in 32 scenarios on real git checkouts. git merge-tree stops 3, file leases 4. The other two get a warning from the flight plans.
0 of 12
safe scenarios stopped. File leases stop 6 of them.
0 of 438
clean merged PRs stopped, from NumPy, Matplotlib, pytest, pip, IPython and Django. Git conflicted on 11, and Detente stopped all 11.
We wrote the scenarios ourselves, so they show what each tool can see, not how often it catches real conflicts. The real merges can't show catches git misses, because breaks like that rarely survive in a project's history. Run make bench and make bench-real REPOS="<clones>" to check.
Under the hood
Detente runs as an agent in your team's chat, on Switch. Without it, agents on different laptops can't see each other and there's nowhere for a person to decide.
The showcase and the real app share the radar and conflict screens and nothing else. The showcase plays recorded runs with no sign-in and no server; the real app shows your team's live data after sign-in. make test fails if either one reaches into the other.
Rooms across laptops and vendors | Every pilot sees the tower room. This is how agents on different machines see each other. |
|---|---|
Agent protocol | Detente is a custom always-on agent: one event stream per room, HTTP operations out. |
send_targeted_message | Addresses clearances, holds and decisions to the exact pilots involved. |
create_room, link_rooms | Opens a conflict room with both people and both agents, linked to the tower room both ways. |
archive_room | Archives a conflict room when it's resolved. |
Room documents | Keeps the live Airspace board. Read it with !list-documents. |
Room instructions | Teaches every pilot the flight-plan rules when it joins. |
Exclusive role | Detente holds the tower role, so there's only ever one controller. |
read_context | Catches up on anything said while Detente was down. |
What it can't do yet
Reading codeWhat can't it see in the code?
- Calls are checked in Python only. Other files are checked line by line, the way git would merge them, so a clash in
package.jsonis caught but a broken call in TypeScript isn't. - Methods resolve only through types Detente can see.
store.open()is checked whenstorecomes fromSessionStore(), an annotation or an attribute set onself; an object returned by a function, or an inherited method, isn't. - Behavior changes are invisible. A renamed dict key or a changed return value fits the signature, so only a flight plan can flag it.
ComparingWhen does a comparison fall short?
- Line clashes need the same starting version. Otherwise any shared change to a function stops both, to be safe.
- Only calls your work wrote are checked. A call already on main is the job of whoever changes the function.
- A push Detente never saw is credited to main. A person's push names no one, so the agent whose work broke gets both fixes.
GatesCan the gates be got round?
git commit --no-verifyskips the commit gate. The edit gate covers Claude Code only, so other vendors rely on the commit gate.- Shell edits are caught after they run. Detente checks what changed once a command finishes and tells the agent to undo anything uncleared.
- Gates fail closed. If Detente is unreachable, edits and commits are refused.
SetupWhat does one install cover?
- One repo, one tower room. Multi-repo support isn't built.
- Tested on Mattermost only. Detente talks to Switch, never to the chat app, so Slack, Discord and Microsoft Teams should work through Switch, but they haven't been tried. Telegram can't: Switch can't create chats there, so conflict rooms can't open.
- One pilot token per install. Every laptop shares it, so anyone holding it can report as any callsign. Keep port 8100 on a private network.
NetworkIs it safe across the internet?
TOWER_ADDRserves plain HTTP, so share it over Tailscale, which encrypts the traffic, or behind an HTTPS proxy that setsX-Forwarded-Proto.- People get Switch's owner-only default.
@detentecommands work for anyone in the room, but Switch shows others a refusal until you widen its addressing policy in the Gateway.
Prior art
Tools near this space include MCP Agent Mail, Dibs and Interlock (file leases for agents), GitLive, Sturdy and Deconflict (pre-push conflict detection for people), and agent coordinators such as Clash, Regente, Braidkeep, Shepherd and Wit. Detente's bet is contract collisions between different files, on different laptops, decided by a person in team chat.

