Skip to main content
Glama
ThatHunky
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).