relay
What it does,and what it won't
relay concentrates on four things: warn an agent that its target is already being touched, before the edit lands; count how many commits teammates made since your last one; put irreversible operations through a human decision; and keep every record append-only and hash-chained. It will not merge, rebase, lock ordinary files, resolve conflicts, or store your codebase.
Only four things
relay is a notification service, but it does not notify you about everything. It is scoped to the four failures that actually happen when you run several agents at once.
| What relay concentrates on | Why there | |
|---|---|---|
| 1 | You learn about a clash before you touch the file | Learning after the edit means it is already overwritten |
| 2 | You notice commit lag | By the time you notice unaided, the other side is five commits ahead and merging costs half a day |
| 3 | Irreversible operations pass through a human | A production deploy or a migration is not a decision an agent should take alone |
| 4 | The log cannot be rewritten afterwards | If you cannot prove which agent did what and when, you cannot show it to an auditor |
1. Conflicts, before the edit
The moment an agent is about to open a file — before the write — relay tells it if anyone else is touching that target.
relay: ⚠ same target WORKDIR/src/auth.ts — Bob is about to edit it
❓ unanswered request #128 "may I change the production env?"
Targets are not only files.
| Notation | What it means |
|---|---|
src/auth.ts | the whole file |
src/auth.ts#validateSession | one function in it (no clash with someone editing another function) |
api:/v1/users | an API contract (clashes across files) |
db:users.email | a database column |
env:AUTH_SECRET | an environment variable |
deploy:production migration:users | irreversible operations (see reservations below) |
task:PROJ-142 | an issue. Backlog, Jira or GitHub — inside relay it is one resource |
Stale intents do not rot. If the session that declared an intent goes quiet for 15 minutes it becomes “idle”, after an hour “expired”, and it stops counting as a conflict. A crashed teammate cannot block you forever.
2. Commit lag, as a number
relay does not read your git history. The fact that an agent committed flows in, and the receiving side counts.
Bob has committed 3 times since your last commit
It is sent only for git commit / push / merge / rebase / pull, so ordinary work stays quiet. Merges also record which branch was pulled in.
3. Only irreversible operations are actually blocked
| Target | Behaviour |
|---|---|
| Files, issues, API contracts … | Warning only. The receiving agent and its owner decide |
deploy: migration: | Blocked. If another live session holds an intent on the same resource, relay returns 409 and the hook refuses to run the tool |
A blocked agent can still force through (RELAY_FORCE=1) — and the fact that it forced through is recorded.
Approvals use four of the kinds: ask (please approve) answered by ok (go ahead), ng (there is a problem) or re (conditional, free text). Whether a human decided or the agent auto-approved is always recorded (approved_by). Approvals can be answered from the Claude mobile app.
4. The log cannot be rewritten
Records are hash-chained one by one, so changing a single character of any past entry is detectable.
- target, kind, time, who, which session / folder / branch it came from
- what changed (created, edited, deleted; line numbers; an excerpt before and after; the reason for a deletion; what the change was for)
- who decided (human or agent)
Administrative operations — invitations, deletions, ownership transfers — go to a separate ledger, also hash-chained. Deleting a project does not erase them, because a record that says “this was deleted” is useless if it can be deleted.
No personal data goes into the shared log. Others see only a relay-issued ID, and the ID differs per project, so nobody can correlate a person across projects.
Agents read two things, not everything
Feeding the whole log into an agent bloats its context. The two tools are split by purpose.
| Tool | Returns | When to call it |
|---|---|---|
relay_context | only what relates to the targets you are about to touch (conflicts, relevant commits you have not pulled, requests awaiting an answer, past decisions, modules two or more people touched, a risk level) | before starting work, and when you change targets |
relay_timeline | the flow by day, in prose (who created / edited / deleted what, when they committed, which branch merged where, which branches are unmerged) | when taking over a session |
relay_context { targets: ["src/auth/*", "api:/v1/users"] }
→ ⚠ risk: high — another session is touching the same target
conflicts: Bob [b2c3d4e5] src/auth/session.ts (active write)
relevant_changes: Alice's commit "feat: add session validation" changed src/auth/jwt.ts
pending: #128 "may I change the production env?" (addressed to you, unanswered)
What people look at
Development timeline — who created, edited or deleted what, when they committed, and which branch merged where, as a vertical list. Click a row to see the record behind it: which file, which lines, what changed, and what it was for.
Development knowledge — people, sessions, modules, branches, requests and decisions as a graph. Modules touched by two or more people get a red rim, so you find the tinder before the fire.
Work list — a 24-hour summary (counts, awaiting reply, the recent flow) plus the detail. You can switch to other projects you belong to.
5. Todos survive a crash
A todo added with relay_todo is not auto-cancelled after an hour like an ordinary intent. It survives a crashed session and keeps appearing at the top of every delivery until it is closed.
[relay todos] 2 open (the oldest since 3 hours ago)
#12 tidy the branching in src/pay.ts "keep putting it off" (2 in progress)
#18 write the deploy runbook
Progress accumulates as wip, so how far you got is kept too. Only did (done) and cancel close a todo.
In the work list, a todo left by an expired session is marked “can be taken over” — so the next session sees whose work is unfinished and simply continues it.
Also included
- Handing over files — send the files a session touched to someone who does not use GitHub (2 MB per file, 200 MB per project, deleted after 30 days by default). They land in
relay-inbox/in the recipient’s working folder, and a human decides whether to take them in - Backlog integration — mirror approvals, replies and goal reports into issues, and deliver issue updates back into agent sessions
- Presence and addressing — who is online now (activity within 10 minutes), which sessions are alive. Approvals can be addressed to one session
- One-command setup —
npx -y -p https://relay.h-c.ai/dl/relay-client.tgz relay-setup - Speed — a median of 18.5 ms from sender to the other client (localhost measurement, September 2026)
What relay does not do
These are not “not built yet”. They are decided against.
- automatic merges, automatic rebases, automatic conflict resolution
- enforced locks on ordinary files
- storing your whole codebase (excerpts of changes are kept; a copy of the repository is not)
- semantic conflict detection (it will not discover on its own that two people built the same feature in different places)
- replacing your issue tracker
- a supervisor agent, a central planner, automatic task decomposition, automatic agent creation
relay carries facts only, never commands. There is no channel for instructions, so there is nothing there to hijack. The judgement stays with the receiving agent and with you.
Supported agents
| Status | |
|---|---|
| Claude Code (PC) | Primary. MCP and hooks both run, so warnings arrive before the edit |
| Codex CLI | Works. No hooks, so news arrives when a tool is called |
| Claude mobile app, claude.ai | Remote MCP (OAuth 2.1). Read the work list and answer approvals |
| ChatGPT | Works. News and approval requests are appended when it calls a relay tool. With no hooks, relay cannot interrupt it (its /mcp has no server-initiated stream) |
| Gemini | Planned. Not supported yet |
See pricing, the day-to-day guide, or how relay compares with A2A.
Frequently asked questions
What does relay concentrate on?
Four things: conflict detection before the edit, commit lag, an approval round-trip for irreversible operations, and a tamper-evident log. Everything else is deliberately absent — it never merges or resolves conflicts. It only blocks an agent for a deploy or a migration.
Does it lock files?
Not ordinary files. If someone else is on the same target you get a warning, and the receiving agent and its owner decide. The exception is deploy and migration: there an intent acts as a reservation and relay returns 409 while the first session is alive.
Can it detect conflicts on things that are not files?
Yes. Name API contracts (api:/v1/users), database columns (db:users.email), environment variables, packages, ports, migrations, containers, deploys and issues (task:PROJ-142). You can also name one function in a file, so you do not collide with someone editing another.
Which agents can use it?
Claude Code on a PC is primary: MCP and hooks both run, so warnings arrive before the edit. Codex CLI works. The Claude mobile app, claude.ai and ChatGPT connect over remote MCP and get news appended when they call a relay tool, but relay cannot interrupt them. Gemini is not supported.