How file locking works
Switchman prevents file conflicts using a three-layer model: tasks, leases, and claims. On newer governed workflows, those claims also feed the write gateway and landing checks.
The problem it solves
When two AI agents edit the same file simultaneously, you get a merge conflict. In the best case it's annoying to resolve. In the worst case — when both agents have made significant changes to the same file — one agent's work gets thrown away entirely.
Traditional tools detect conflicts at merge time. Switchman prevents them at claim time — before a single conflicting line is written.
Three layers of coordination
Tasks
A task is a unit of work. Tasks live in a shared queue and have a title, priority, and status. Agents pick tasks up one at a time via switchman_task_next. The dequeue operation is atomic — no two agents can get the same task simultaneously.
switchman task add "Add auth middleware" --priority 9
switchman task add "Write auth tests" --priority 7
switchman task list
Leases
When an agent picks up a task, it gets a lease — a time-bounded ownership token. The lease has a heartbeat that the agent must refresh every 60 seconds. If the heartbeat stops, the lease expires, the task is released, and another agent can pick it up.
This prevents work from getting stuck forever if an agent crashes or the user closes their editor mid-task.
switchman lease heartbeat <lease-id> periodically.Claims
Within a lease, an agent registers claims on the specific files it will edit. A claim says "I own this file for the duration of my lease." Any other agent that tries to claim the same file gets blocked immediately.
The claim lifecycle
- Agent calls
switchman_task_next→ receives task + lease ID - Agent calls
switchman_task_claimwith file paths → claims are registered - Agent edits the claimed files
- Agent calls
switchman_task_done→ lease closes, claims released - Files are now available for other agents to claim
What happens when a claim is blocked
If agent2 tries to claim src/auth.js while agent1 owns it, the claim is rejected. The agent receives a clear error:
{
"ok": false,
"reason": "file_already_claimed",
"claimed_by": "agent1",
"task_id": "task-auth-001"
}
The agent should then either:
- Pick different files to edit that don't conflict
- Call
switchman_task_nextto get a different task entirely - Wait for agent1 to finish and the claim to be released
Stale lease recovery
If an agent crashes or stops sending heartbeats, its lease is marked stale after the timeout (default: 15 minutes). Switchman then:
- Expires the lease
- Releases all file claims held by that lease
- Requeues the task so another agent can pick it up
This happens automatically. You can trigger it manually:
switchman lease reap # reap all stale leases
switchman status # shows any stale work detected
The enforcement gateway
For the strongest conflict prevention, agents should write files through the Switchman gateway instead of directly:
# MCP tool — validates claim before writing
switchman_write_file
# CLI equivalent
switchman write <path> <content>
Related MCP tools include switchman_append_file, switchman_make_directory, switchman_move_path, and switchman_remove_path. The gateway checks that the agent has an active claim on the file before allowing the write. Direct file system writes are not blocked, but they are detected by the background monitor:
switchman monitor status # check for rogue edits
Concurrency model
Switchman uses SQLite with WAL mode and BEGIN IMMEDIATE transactions. The file claims table has a partial unique index on (file_path, status='active'). This means:
- Two agents claiming the same file simultaneously → exactly one wins, one gets rejected
- Claim operations complete in under 5ms
- No deadlocks — SQLite's busy timeout handles contention gracefully