🔒
mutex_
flock(1) for agents that live on different machines.
Named locks and counting semaphores over plain HTTP.
# the whole integration:
curl -X POST 'https://mutex.legible.sh/migrate-prod-db?ttl=60'
200 {"lease":"9f2c…","fence":12,"expires":"…"} # yours for 60s
409 {"code":"BUSY","holders":["worker-1"]} # it isn't
Two of your agents just decided to migrate the same database — from
different machines, different sandboxes. flock(1) stops at the
network boundary; ZooKeeper costs a cluster. mutex is a named lock you
acquire, renew, and release with nothing but HTTP. No signup, no SDK:
the first request creates the topic.
This is a lease, not a lock.
No network lock service can promise true mutual exclusion — a stalled holder
can outlive its TTL. So every grant carries a fencing token:
a per-topic number that only goes up. Stamp it on the resource you protect
and reject lower fences. The zombie's write bounces. That's the fix etcd and
ZooKeeper use, in every mutex grant by default.
The whole API
| request | meaning |
|---|---|
| POST /{topic}?ttl=60 | acquire — 200 {lease, fence, expires} or 409 {holders, waiting} |
| POST /{topic}?ttl=60&wait=300 | block like flock: long-poll, FIFO, 408 on timeout |
| POST /{topic}?capacity=3 | semaphore: at most 3 holders — "3 agents against staging, max" |
| POST /{topic}/{lease}/renew?ttl=60 | heartbeat — 404 means you lost it: stop working |
| DELETE /{topic}/{lease} | release |
| GET /{topic} | status: {capacity, holders, waiting} — lease tokens never shown |
| GET /{topic}/sse | live events: grant · renew · release · expire |
Topics are created by first use — an unguessable name is your access control. Errors are JSON with honest status codes. Open a topic in a browser for a live status page.
Or wrap a command
mutex run deploy --ttl 60 -- ./deploy.sh production
# acquire → heartbeat at ttl/3 → run (MUTEX_FENCE in env) → release
# lease lost mid-run? the command is killed. exit 75.
Self-host in one line
npx mutex-sh serve # same API on 127.0.0.1:4185
# --data-dir to survive restarts · --token to require a bearer
Source on GitHub — MIT, Node ≥ 20, zero dependencies. Tests, docs, and a 12-line block that teaches your agent the whole tool.