Graft v0.2.0 · open results

Source control for agent swarms

Graft moves commits, rebases and merges to the server. An agent reads, writes and lands a change in one call: no clone, no pull, no push. With 48 agents on one branch, the median change landed in 5 ms. Through Git it took 15.5 s.

replay · 16 agents · same app t = 0.0 s
graft0 / 48 landed
git0 / 48 landed

Recorded run, played in real time. Each row is an agent. Gray is thinking; color is time spent in source control: ■ commit/land ■ push ■ pull --rebase ■ conflict recovery.

5 ms
median time to land a change, Graft, 48 agents
55×
faster to finish the whole app than Git (4.86 s vs 4.5 min)
4.3×
fewer source-control commands for real Claude agents
0
lost updates across 14 finished apps, all checked
How it works

One request instead of a retry loop

Git assumes every client keeps a full copy and works offline. Agents are always online and land small changes, many at once. Graft keeps history on the server and does the merge work where the data already is.

01 · READ

Read at an exact revision

Agents list, search and read files over MCP. Every answer names the changeset it came from. Nothing is cloned.

graft_read_file path="app.js"
@ 3f9c1e0a2b77 app.js
02 · SEND

Send the change and its base

One call carries the revision the agent read and its edits: whole files, exact string replacements, moves or deletes.

graft_commit base="3f9c1e0a2b77"
  edits: "// routes" → "…"
03 · LAND

The server lands it

If main moved, the server rebases the change in memory with a three-way merge and swaps the branch pointer. Only a real textual conflict comes back.

Landed on main: 8be21c… 
(auto-rebased from 51aa9e…)
git agent every step is a git process; every lost race goes around again pull --rebase edit add + commit push landed accepted rejected: another agent landed first → rebase locally, maybe resolve a conflict, push again graft agent one request; the retry loop runs inside the server read @ C edit graft_commit server, in memory rebase + merge swap ref (CAS) landed
Where the retry loop runs is the whole difference. A lost race costs a Git agent another pull, rebase and push. It costs Graft one in-memory rebase.
What's in the box

Everything an agent team needs

One container for the server. One file for the MCP plugin. A CLI for agents that need real files to run tests.

MCP plugin

13 tools for Claude Code and any MCP client: read, search, find, commit-and-land, diff, log, blame, branches. Plus a skill that teaches the loop.

Lock-free landing

Branches move only by compare-and-swap on one row. No merge queue, no global lock. Lost races are retried on the server.

Small changesets

A commit stores only the paths it changed. Trees, blame and path history are derived from parents and cached, with checkpoints every 64 generations.

Sparse workspaces

graft clone --sparse src/ fetches only what you ask for. Every workspace on a machine shares one content-addressed cache.

Secure by default

Loopback-only until you set a token. CSRF and DNS-rebinding defenses, strict CSP, hash-verified blobs, sandboxed client paths.

Web viewer

Live history, changeset diffs, a file browser with blame, and code search for the people watching the agents.

Results

Measured, not promised

The same workload ran through three backends at 8, 16, 32 and 48 agents, then 16 real Claude agents built the same pages in two teams. Every finished app was checked for lost work.

Median time from "ready to commit" to "on main"

graft (MCP / API)graft CLIgit
1 ms10 ms100 ms1 s10 s100 s8163248agents5 ms4.25 s15.5 s

Log scale: each gridline is ten times the one below. One Mac, no network, which favors Git.

Real Claude agents, 8 per team

Same model, same 8 pages, same instructions. Only the source-control loop differed.

gitgraft Commands run37688 Time in source control9.64 s6.15 s Mean time per agent1.2 min55.4 s Pushes rejected410 Lost work in final appnonenone
Security

Audited before this release

Every network-facing module was reviewed before v0.2.0 shipped. Each finding is fixed and pinned by a regression test: 30 tests in all.

11 security findings fixed

4 high3 medium4 low

Plus 16 correctness bugs from a repository-wide scan, and a clean npm audit.

  • S1
    Cross-site request forgery

    JSON bodies require content-type: application/json, blob uploads require application/octet-stream; requests a browser marks cross-site (Origin, Sec-Fetch-Site) are refused.

  • S2
    Open by default + DNS rebinding

    Default bind is 127.0.0.1; listening elsewhere without GRAFT_TOKEN exits with an error (opt-out: GRAFT_ALLOW_OPEN=1); tokens must be ≥ 16 chars; without a token only loopback host names are served (GRAFT_ALLOWED_HOSTS to extend).

  • S3
    Path traversal from the server

    Paths must be canonical and resolve inside the workspace after following symlinks; .git segments are rejected by both server and client.

  • S6
    zod < 4.6.6

    Upgraded to zod 4.6.7; npm audit reports 0 vulnerabilities.

Get started

Running in three commands

Node 22.5+ or Docker. The deployment guide covers TLS, backups, upgrades and releases.

SERVER

Start Graft

export GRAFT_TOKEN=$(openssl rand -hex 32)
docker compose up -d --build
curl -s localhost:7070/api/version
AGENTS

Connect Claude Code

claude plugin marketplace add ./graft
claude plugin install graft@graft
export GRAFT_URL=https://graft.example.com
FILES

Workspaces for tests

graft clone app work --sparse src
# edit, run tests…
graft commit -m "Fix the router"