agent-semaphore
Provides integration with Git through a pre-commit hook, enforcing claims and conflict detection before commits, with a landing queue that uses git operations like rebase and update-ref.
Uses a single SQLite file as the local-first rendezvous point for coordination state, claims, and radar snapshots across worktrees.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@agent-semaphore claim src/api for auth refactoring"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
agent-semaphore
A coordination layer for parallel coding agents. Worktrees do not remove merge conflicts — they postpone them to integration time. agent-semaphore closes the gap: intent-carrying claims on scopes, a warning at the moment of writing, conflict prediction before anything is committed, and a serialized landing queue with a mandatory test gate.
Local-first: no daemon, no cloud, no account. A single SQLite file in the git common dir
is the whole rendezvous point, so every worktree of the repo sees it by construction.
Cross-vendor by design — Claude Code hooks and MCP, Codex CLI over MCP, everyone else
over a git pre-commit hook.
The problem
Agent-written pull requests conflict at 27.7% — against 10–20% for human ones (AgenticFlict, 107K+ agent PRs). On co-active pairs the split is 19.8% intra-agent vs 41.7% cross-agent: agents have no horizontal awareness of each other, and every product that ships coordination coordinates only its own agents. A badly resolved conflict carries up to ~26x the bug density of ordinary code (EMSE 2020) — the expensive part is not the conflict, it is the quiet bad resolution.
Isolation is solved and commoditized (a worktree or a container per agent — everyone
ships it). Prediction and integration are not: nobody runs git merge-tree between live
worktrees, and standalone local merge queues effectively do not exist.
Related MCP server: MCP Agent Mail
What it does
Layer | Mechanism |
Claims | Leases, never locks: TTL, renewal by activity, monotonic fencing epochs, a mandatory intent ( |
Enforcement | A |
Radar | Snapshots of dirty worktrees taken through a temporary index (never mutating the working tree), compared pairwise with |
Queue | FIFO under |
Hard guarantees exist at exactly one place: the landing path. Hooks and pre-commit are
cooperative admission control and telemetry, not a security boundary — ASEM_HOOK_OFF=1
and ASEM_OVERRIDE=1 are documented, audited escape hatches. This is stated up front
because a coordination layer that pretends to be a sandbox is worse than none.
Quickstart
uv tool install git+https://github.com/alwh1te/agent-semaphore # asem on PATH
# or, from a clone: uv tool install -e .
cd <your repo>
curl -O https://raw.githubusercontent.com/alwh1te/agent-semaphore/main/.agent-semaphore.toml.example
mv .agent-semaphore.toml.example .agent-semaphore.toml # set the gate command, hot classes, target branch
asem init # state in .git/agent-semaphore/
asem install --git-hooks # Claude Code hooks + .mcp.json + git pre-commit
asem doctor # PASS checklistasem claim src/api/ -i "refactor auth parsing" --ttl 30m # exit 3 = held by someone else
asem check src/api/routes.py # who holds it, and what for
asem radar # conflicts between worktrees, before any commit
asem land feature-branch # rebase -> gate -> CAS into the staging branch
asem notices # messages addressed to you
asem status | asem queue status | asem doctorExit codes are part of the contract: 0 ok/free, 3 held/conflict/bounced, 2
usage, 1 internal error — a script can tell "coordination said no" from "the tool
broke".
Measured
Nobody in this space had measured whether claims actually reduce conflicts, so the repo ships two benchmarks of its own.
Scripted (docs/benchmark.md, 60 runs, deterministic agents,
compliance = 1 by construction): integration conflicts 60% → 0%, human interventions
9 → 0.
Live agents (docs/bench-llm.md, 40 runs of two concurrent
claude -p agents, $17.95):
mode | ICR | WME | did_work | caught-up | $/run | COR |
no coordination | 40% | 2 | 100% | 0% | $0.34 | 1.00x |
advisory claims | 20% | 1 | 100% | 40% | $0.50 | 1.72x |
claims + radar | 10% | 2 | 80% | 40% | $0.46 | 1.93x |
strict + queue | 0% | 0 | 100% | 40% | $0.50 | 1.98x |
Three findings the scripted harness structurally could not produce:
Conflicts are removed by the catch-up, not by the claim. 10 out of 10 runs where an agent rebased onto its peer's branch merged clean; every conflicted coordinated run is one where both agents claimed politely and neither rebased. A claim serializes writing — it does not hand you the other agent's result. That finding is what produced the "release wakes the waiters and names the branch" feature.
The hook never fired once in 40 runs. With the protocol in the prompt, agents claim before editing and never write into a held scope, so enforcement turned out to be insurance that was not needed — not the working layer.
Coordination can convert a conflict into work that never happened. In two runs the blocked agent quoted the holder, its intent and its branch, and abandoned its task. Without the
did_workcolumn next to ICR, those runs read as a clean success — which is why the column is there.
Semantic drift (textually clean, semantically broken) survives every advisory layer in both benchmarks and is caught only by the queue's mandatory gate.
How it plugs in
Claude Code —
asem installwrites project.claude/settings.json(PreToolUse + PostToolUse), addsBash(asem:*)andmcp__semaphore__*to the allow-list, and registers the MCP server in.mcp.json. Committed wiring is host-portable ($HOMEand a bareasem), so a repo shared across machines does not carry one host's paths.MCP (
asem mcp, server keysemaphore) —claim,release,check,status,extend,report_intent,radar,enqueue_land,land_status. Every response drains pending notices, so agents learn about steals, bounces and moved targets without polling.Codex CLI — same MCP server via
~/.codex/config.toml, plus a protocol snippet forAGENTS.md. Headless Codex silently cancels MCP calls unless the tools are pre-approved;docs/integration.mdhas the working config.Anything else —
asem install --git-hooksputs apre-commitgate in the shared hooks dir (it chain-loads whatever hook was there before).
Documentation
docs/00-research.md— the research dossier this design is built on: the measured problem, the tool landscape, the classic prior art worth stealing from, the 2024–26 papers, and the three confirmed gaps in the market.docs/adr/ADR-001-architecture.md— the architecture, plus a risk register and ten adversarial attacks from a blind review (eight of them changed the design).docs/adr/ADR-002-stack-and-state.md— stack, naming, and where state lives.docs/benchmark.md/docs/bench-llm.md— both benchmarks: method, results, and the limitations spelled out.docs/integration.md— installation and what is wired where.
Status
v1 is implemented and dogfooded: the repository coordinates its own agents through it. 150 tests, a p95 hook-latency gate in CI, both benchmarks reproducible from the repo.
Known limits, stated plainly: promotion from the staging branch to main is still manual
and ungated (asem promote is the next feature); the queue never pushes; there is no
symbol-level scoping, no semantic conflict detection beyond the test gate, no LLM
auto-resolution (the published ceiling is ~55–60% correctness, which is not good enough
to run unattended); and multi-host is a v2 design, though the schema already carries the
host column.
Development
uv run pytest -q # 150 tests
uv run ruff check . && uv run ruff format --check .
uv run python bench/hook_latency.py 200 # hook latency gate (p95 < 100 ms)
uv run python bench/runner.py --seeds 3 && uv run python bench/report.pyThe PreToolUse hook script is vendored outside the package and must stay stdlib-only —
it runs on every write of every agent, so it has a latency budget rather than
dependencies. See CONTRIBUTING.md.
License
MIT — see LICENSE.
Available Tools
9 toolscheckA
Read-only: who holds these paths/scopes right now (holders with intents, hot-class membership). Call before expanding your edit scope.
Inputs: paths (required).
claimB
Atomically claim path scopes (dir/ preferred, file, or basename glob) before editing them. Blocked responses name the holders, their intent, lease remaining, and advice (wait | narrow_scope | coordinate | steal_candidate).
Inputs: reason (required), scopes (required), mode, wait, +3 more.
enqueue_landA
Enqueue my branch for serialized, test-gated landing into the integration
target. My active claims become retained until the land completes. The queue is
processed by asem queue run (run it via Bash after enqueueing, or poll
land_status). Never merge into the target yourself.
Inputs: branch, gate_cmd.
extendC
Extend one of my leases (activity usually renews them automatically).
Inputs: claim_id (required), ttl_minutes.
land_statusB
Status of land-queue entries. Bounce/park results carry conflict files and exact instructions — a bounced entry means YOU rebase and fix in your worktree, then enqueue again.
Inputs: entry_id.
radarA
Cross-worktree conflict prediction: dry-run merges (git merge-tree) between every dirty worktree snapshot and the integration target. TEXTUAL/STRUCTURAL pairs mean your uncommitted direction already collides with someone — coordinate now, not at merge time. UNSTABLE means a snapshot tore mid-scan: rerun.
Inputs: no named parameters.
releaseB
Release my claims (all, or those matching the given scope patterns). retain=true keeps them alive until my branch lands (use when work is committed but not yet merged).
Inputs: retain, scopes.
report_intentB
Declare what you PLAN to touch (no blocking): records an intent claim and returns overlaps with other agents' claims and intents so overlapping tasks can be serialized before work starts.
Inputs: task_id (required), plan_summary (required), expected_scopes (required).
statusB
Live coordination picture: agents, claims with intents, integration queue, wait tickets, stale items.
Inputs: no named parameters.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 9 tools
Most tools have clearly distinct roles: claiming, releasing, extending, conflict prediction, enqueueing, and status inspection. The closest overlaps are check vs. status (scoped vs. global read-only views) and claim vs. report_intent (blocking vs. non-blocking declaration), but the descriptions make those distinctions reasonably clear.
The naming mixes bare verbs (claim, check, release, extend), verb_noun forms (report_intent, enqueue_land), and noun-style names (radar, status, land_status). It is still readable and none of the names are cryptic, but there is no predictable naming convention across the set.
Nine tools is well-scoped for an agent coordination server covering claims, intents, conflict detection, and landing. Each tool appears to earn its place without obvious redundancy in count.
The surface covers the main lifecycle: discovery, claiming, releasing, extending, intent reporting, conflict prediction, enqueueing, and status checking. Minor gaps remain, such as no explicit cancel/dequeue operation for a land-queue entry or intent revision, but core workflows are supported.
Maintenance
Related MCP Connectors
Coordination for AI coding agents: declare plans, catch design conflicts early, share team memory.
Source control for coding agents: declare an intent, settle overlaps before code, verify each push.
Coding agents from Claude Code, Cursor and Codex claim jobs and lock files on one shared board.
Coordination hub for AI coding agents: message teammates, ask humans, audit every event.
Related MCP Servers
- AlicenseBqualityAmaintenanceA coordination layer for coding agents that provides memorable identities, inbox/outbox messaging, searchable message history, and file lease management to prevent conflicts. Uses Git for human-auditable artifacts and SQLite for fast queries, enabling multiple agents to collaborate across projects without stepping on each other.412,232MIT
- AlicenseNot gradedqualityDmaintenanceA coordination layer for coding agents that provides identities, message threading, and searchable history. It features file reservation leases to prevent agents from overwriting each other's work in multi-agent environments.1MIT
- AlicenseBqualityDmaintenanceA coordination server that enables multiple AI coding agents to work together on the same project by providing shared memory, file locking, decision tracking, and architecture guidance, preventing conflicts and maintaining consistency across sessions.5218 PyPI1MIT
- AlicenseNot gradedqualityFmaintenanceA mail-like coordination layer for coding agents, providing identities, inbox/outbox, searchable threads, and advisory file reservations to prevent conflicts in multi-agent workflows.1MIT