Version control for many hands moving at once.
Git is the filesystem; Loom is air traffic control.
Without Loom. You point two Claude Code sessions at your repo. Agent A
spends 40 minutes and ~200k tokens rewriting src/auth/
around a new session model. Agent B, told to "clean up the login flow", touches the same files with the opposite assumption. Neither knows the other exists β git has nowhere to put that knowledge. B finishes last, so B's edits win; A's work is silently gone from the tree. The test suite goes red at commit time, and you spend the evening (and another few hundred thousand tokens) having a third session diagnose a breakage that is really two AIs' half-rewrites interleaved. The most expensive thing agents do is semantically reconcile two overlapping rewrites after the fact β and this workflow makes it routine.
With Loom. A leases src/auth/**
with the goal "move auth to the new session model". When B's session asks Loom what's being worked on β one MCP call β it sees that lease, goal attached, and self-partitions: it either takes the suggested disjoint scope or waits. The collision is reported at the start, when handling it costs one tool call, not at the end, after both budgets are spent. If both proceed anyway, each works in its own worktree, nothing is overwritten, and the second landing is told exactly which files moved and rebases once β the expensive reconciliation becomes rare instead of fast.
That is the entire bet: git reports collisions after the tokens are spent; Loom reports them before.
You run several coding agents on one repo. They overwrite each other's files, land red on top of red, and die mid-task leaving dirty worktrees nobody owns. You can't see who is doing what, so every collision is discovered at the end β at merge or in CI β when the only fix is expensive re-work. Git has no concept of intent: a branch name is a string, so agents can't ask "who is already working on this?" and route around each other.
Isolationβ every task gets its own git worktree; two threadsphysically cannotclobber each other's edits.Coordinationβ before editing, a thread declares an** intent lease**(machine-readable goal + file globs); overlaps warn at declaration time, which lets agents self-partition work over MCP with no human traffic cop. Leases warn, they never block β an agent is never stopped; the only gate is at landing.Integrationβ the mainline (** fabric**) advances only through a green verify run plus a human/consent gate, with an honest file-level merge: a file changed in both the fabric and the thread refuses to land ("fabric moved under you β rebase") instead of overwriting either side. Never-red main means no fleet-wide token burn diagnosing a stranger's breakage.Recoveryβ a dead agent's thread becomes an** orphan**: goal, acceptance criteria, and a seconds-old checkpoint attached, claimable by anyone. That is schedulable work, not a mystery dangling branch.
An honest concession: two careful humans working slowly don't need this. The value scales with writer count and edit frequency β it exists for fleets of agents (and humans who work like them).
N agents racing the SAME task. Loom coordinatesdifferenttasks on one repo. For redundant attempts at one task, use a judge/tournament harness β then lease the winner's landing.Replacing git. Loom sits on top; git stays your history, remotes, and review tooling. The optional bridge projects each landed weave into local git history β one commit per weave by default, checkpoint-level if you ask (seebridge_mode
below) β and never pushes.Humans doing normal PRs. Slow, coordinated-out-of-band work is what git+GitHub already does well.
The disaster being prevented, on your own machine. One repo, two terminals ("agents" A and B):
cargo install --path . # one binary: loom
cd your-repo
loom init --verify "cargo check" # or any command that exits 0 on green
A:
loom lease "greet in french" 'greeting.txt'
B, at the same time:
loom lease "greet louder" 'greeting.txt'
Both edit the same file β in their own worktrees, so nothing clobbers. A finishes first:
loom stitch # checkpoint (content-addressed; deletions tracked)
loom propose # verify runs in a scratch copy; on green it asks y/N
B proposes next, and gets the truth instead of a silent overwrite:
loom stitch && loom propose
loom rebase
loom stitch && loom propose
Kill a session mid-task (or let its lease TTL lapse) and loom status
shows
the thread as an orphan β loom adopt <thread-id>
hands the next agent its goal, criteria, and worktree, checkpoint intact.
claude mcp add loom -- loom mcp
The tool flow an agent follows:
loom_status
β who's working on what (threads, live leases, orphans).loom_lease
β declare goal + scope. The response'sworking_dir
is the thread's worktree:cd there and make all edits in it. Toe-step warnings come back in the same response β the moment to renegotiate scope.- work β
loom_stitch
every few edits (checkpoints + heartbeats the lease). loom_propose
β runs the verify in a scratch copy and reports green/red. The apply is always refused over MCP: landing takes a human at a terminal (loom propose
) or a host with an approvals queue. Proposing verifies; it never lands.- On "fabric moved":
loom_rebase
, reconcile any conflicts in the worktree, stitch, re-propose.loom_adopt
picks up orphans (local or a synced peer's).
Two people, one private GitHub repo. Loom syncs through it over hidden
refs/loom/*
refs β no server, no daemon, nothing new to host.
loom init --verify "npm test" # whatever green means for the project
loom sync --remote origin # remembers the remote for this repo
Then work exactly as in the quickstart β lease, edit in your worktree,
stitch, propose β and run loom sync
whenever you want to exchange state
(or opt in to loom sync --auto
to sync after every stitch/propose):
you> loom lease "dark mode styles" 'style.css' # + edit, stitch
friend> loom lease "compact header" 'style.css' # + edit, stitch
you> loom propose && loom sync # lands, publishes
friend> loom sync # pulls your weave into their tree
friend> loom propose # green β but landing says: fabric moved under you
friend> loom rebase # your change fast-forwards in; real conflicts kept
friend> loom stitch && loom propose && loom sync # merged result lands
you> loom sync # both trees now identical, both changes present
Zero merge fear in two sentences: neither of you can overwrite the other, because edits live in per-thread worktrees and the shared line only advances through a compare-and-swap ref push that refuses when it moved under you. The worst case is not a broken tree β it is being told, by name of file, what to look at before your work lands.
What sync shares, plainly: your loom metadata (goals, scopes, holders) and
the file content of your stitched scope go to that remote β the same
exposure as pushing a branch there. --auto
is opt-in per repo. Dead machines' threads show up as adoptable orphans; claims are first-push-wins on a git ref, and the loser is told who won.
One concrete breakage. Agents A and B both edit config.rs
on branches. Merge time: git sees the same lines touched, declares a conflict, and hands it to whoever merges last β a fresh agent session with no memory of either intent, reconciling two rewrites token-by-token. Or worse: they touched different lines, git auto-merges silently, and main is red with a breakage neither author can reproduce alone. Every agent then pulls red main and burns tokens on a failure that was manufactured by the workflow.
Loom's answer, point by point:
- The overlap was knowable at lease time; git had nowhere to record it. Loom reports it before either agent spends anything.
- Reconciliation, when it must happen, goes to the surviving author(who has the context), scoped to named files, against a green tree β not to a stranger at merge time against a red one. - Rebases are made rare, not fast: self-partitioning at lease time means most collisions never happen.
Landing is consent-gated. A green verify is evidence, not an action. The terminal asks y/N; MCP always refuses the apply; embedding hosts park an approval. Nothing reaches the repo tree without a yes.Deletions are first-class. A file you delete in your worktree is recorded as a tombstone, lands as a deletion, and delete-vs-edit collisions refuse like any other conflict.Big files are skipped, loudly. Files over 8 MiB are not snapshotted; each one is named in the stitch result. Raise the cap withLOOM_MAX_FILE_MB
if you must; prefer a.loomignore
at the repo root (gitignore-lite: literal dirs and simple globs, one per line) β it extends the built-in.git
/target
/node_modules
excludes and cannot un-ignore them.removes worktrees of woven threads β and refuses if the worktree holds anything not captured in a stitch.loom clean
Verify is whole-repo, in a scratch copy, with a hard timeout. Red never lands; a gate that can't even stage its check reports red, not silence.
The philosophy: one lease = one goal = one commit. Scope leases small and
the bridge's default gives you a semantic git log where every commit is a
goal that verified green. bridge_mode
exists for teams who want
checkpoint-level history in git itself β set it at loom init --bridge-mode <mode>
or later with loom config --bridge-mode <mode>
:
| mode | what lands in git | one-line guidance |
|---|---|---|
squash (default) |
||
| one commit per weave: goal + criteria + verify | scope leases small; keep the log semantic | |
stitches |
||
every checkpoint as a commit on a loom/<thread>-<goal> branch, then a merge commit carrying the weave message |
||
you want checkpoint-level git bisect /review without losing the semantic landing |
||
both |
||
| the squash commit + the per-thread branch preserved, unmerged | clean mainline log, archaeology on the side |
Checkpoint replay is pure git plumbing (a temporary index; read-tree
β
hash-object
β update-index
β write-tree
β commit-tree
) β it never touches your working tree, real index, or current branch; empty-diff checkpoints are skipped. Nothing is ever pushed, in any mode.
loom export [--thread <id>]
writes an unlanded thread's checkpoints to
the same per-thread branch β review an agent's in-flight work with plain
git log -p loom/<thread>-<goal>
; nothing lands, nothing moves.
| rung | status |
|---|---|
| Several agents, one machine | shipped β worktree isolation, leases, green gate, orphans, configurable git bridge + draft-branch export (45 tests) |
| A few people/machines, one shared git remote | shipped β loom sync : state over refs/loom/* , CAS fabric ref, cross-machine adoption claims; metadata is unsigned (machine ids are identity, not authentication) |
| Team knobs (consent dials, envelopes) | exists in the Aether integration, which embeds this crate; the generic mailbox namespace here is the hook it rides on |
| Many peers, no blessed remote (gossip) | design only β see |
| git worktrees alone | Jujutsu | CI-gated trunk | Loom | |
|---|---|---|---|---|
| Per-task isolation | yes | yes (working-copy commits) | no | yes (worktree per thread) |
| Machine-readable intent, collision warning at start | no | no | no | yes (leases + toe-steps) |
| Mainline can't go red | no | no | yes (post-hoc, in CI) | yes (verify before land, local) |
| Refuses to overwrite concurrent work | manual merge | manual resolve | last merge wins | yes (three-way refusal + rebase) |
| Crashed work is claimable with its goal attached | no | no | no | yes (orphans + adoption) |
| Agent-native interface (MCP) | no | no | no | yes |
| Multi-machine without new infra | via remotes, manual | via git remotes, manual | server | any shared git remote (loom sync ) |
| Is your git history | yes | yes | yes | yes (bridge: squash, per-checkpoint, or both β never pushed) |
MIT β see LICENSE.