agent-coord
by ThatHunky
README.md
# agent-coord
A tiny, **zero-dependency** coordination layer that lets multiple coding agents
β **Claude Code**, **Codex**, or anything that speaks MCP β work on the same
repository at the same time without clobbering each other.
It solves a specific, real problem: when two agents run in parallel (e.g. each in
its own git worktree), they edit the same files, claim the same task, and
generally trip over each other. `agent-coord` gives them a shared **board** to
coordinate through:
- π **File locks** β reserve repo-relative globs before editing; others see them.
- π§© **Task claims** β claim a plan/task id so the other agent picks something else.
- π£ **Status messages** β a lightweight broadcast channel between agents.
- π‘οΈ **Hard enforcement on Claude Code** β a `PreToolUse` hook *blocks* edits to a
file another agent has locked, and *auto-claims* files Claude touches.
No SDK, no `npm install`, no database. The board is a single JSON file
(`~/.agent-coord/board.json`) guarded by an atomic, multi-process-safe mutex.
---
## How it works
```
Claude Code βββ βββ Codex
(MCP client) β stdio MCP ββββββββββββββ β (MCP client)
βββββββββββββββββΆβ server.mjs ββββββ€
PreToolUse β βββββββ¬βββββββ β (cooperative:
hook (guard) β β β calls the tools)
blocks edits ββ βββββββΌβββββββ β
to locked files β board.json ββββββ
β (shared) β
ββββββββββββββ
```
- Every agent points at the **same board file**, which lives *outside* any
worktree β so locks made in worktree A are visible in worktree B.
- Locks are keyed on the **repo-relative path** (+ a project id derived from the
git top-level dir), so `src/cart.ts` is the same lock in every worktree of the
repo, and unrelated repos never collide.
- **Claude Code** gets *enforcement* (the hook can deny an edit). **Codex** has no
pre-tool hook, so it cooperates *voluntarily* by calling the MCP tools β which
is why the agent instructions (below) matter for it.
> Best paired with **separate git worktrees per agent**. With one worktree per
> agent, git itself handles file merges; `agent-coord` stops the two agents from
> duplicating work or racing the same file before it's committed.
---
## Install
```bash
git clone https://github.com/ThatHunky/agent-coord
cd agent-coord
node test/smoke.mjs # optional: verify (no deps required)
```
Requires Node β₯ 18. There is nothing to build.
### Wire up Claude Code
Register the MCP server (user scope, identity = `claude`):
```bash
claude mcp add agent-coord -s user \
-e AGENT_COORD_AGENT=claude \
-- node /ABSOLUTE/PATH/TO/agent-coord/src/server.mjs
```
Add the enforcement hook to `~/.claude/settings.json` (see
[`examples/claude-settings.json`](examples/claude-settings.json)):
```json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write|MultiEdit|NotebookEdit",
"hooks": [
{
"type": "command",
"command": "AGENT_COORD_AGENT=claude node /ABSOLUTE/PATH/TO/agent-coord/src/guard.mjs"
}
]
}
]
}
}
```
### Wire up Codex
Add to `~/.codex/config.toml` (see [`examples/codex-config.toml`](examples/codex-config.toml)):
```toml
[mcp_servers.agent_coord]
command = "node"
args = ["/ABSOLUTE/PATH/TO/agent-coord/src/server.mjs"]
env = { AGENT_COORD_AGENT = "codex" }
```
### Tell both agents to use it
Paste [`docs/AGENTS-snippet.md`](docs/AGENTS-snippet.md) into your project's
`CLAUDE.md` and `AGENTS.md` so each agent knows the protocol.
---
## MCP tools
| Tool | What it does |
|------|--------------|
| `coord_status` | Show the board: active locks, task claims, recent messages. **Call first.** |
| `coord_claim_paths` | Reserve repo-relative path globs; returns cross-agent conflicts. |
| `coord_release_paths` | Release a lock (`lockId`) or all of yours (`all: true`). |
| `coord_claim_task` | Claim a task/plan id; fails if another agent holds it. |
| `coord_complete_task` | Mark a claimed task done. |
| `coord_post` | Broadcast a status message. |
| `coord_whoami` | Show this agent's identity, project, and board path. |
## CLI (for humans)
Watch what both agents are doing, live:
```bash
agent-coord watch # live board for the current repo
agent-coord status [project] # one-shot
agent-coord post "message" # broadcast (set AGENT_COORD_AGENT first)
agent-coord locks # every lock across all projects
agent-coord clear # drop all of your agent's locks
```
(Run via `node src/cli.mjs β¦`, or `npm link` to get the `agent-coord` binary.)
---
## Configuration
All optional, via environment variables:
| Variable | Default | Meaning |
|----------|---------|---------|
| `AGENT_COORD_AGENT` | `unknown` | This agent's identity (`claude`, `codex`, β¦). **Set this.** |
| `AGENT_COORD_DIR` | `~/.agent-coord` | Where the shared board lives. |
| `AGENT_COORD_PROJECT` | git top-level basename | Project id for scoping locks. |
| `AGENT_COORD_LOCK_TTL_MINUTES` | `120` | Default lock expiry. |
| `AGENT_COORD_AUTOCLAIM` | `1` | Claude hook auto-claims edited files (`0` to disable). |
| `AGENT_COORD_AUTOCLAIM_MINUTES` | `20` | TTL for auto-claimed locks. |
| `AGENT_COORD_MAX_MESSAGES` | `50` | Message ring-buffer size. |
---
## Design notes & limits
- **Fail-open.** The Claude hook never blocks your work on a bug β any unexpected
error allows the edit. The only thing that denies is a genuine, unexpired lock
held by a *different* agent.
- **Locks expire.** They're a coordination hint with a TTL, not a permanent
reservation, so a crashed agent can't wedge the repo.
- **Codex is cooperative, not enforced.** Without a pre-tool hook, Codex respects
the board only by calling the tools. The agent instructions make that reliable.
- **One machine.** The board is a local file; this is for agents sharing a
filesystem, not across machines.
## License
MIT β see [LICENSE](LICENSE).
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues