Documentation

Architecture, merge algorithm, CRDT state, MCP tools, and CLI reference.

Getting Started How It Works Architecture CRDT State MCP Server CLI Commands Languages

Getting started

Get weave running in your repo in 30 seconds.

~/my-project
# Install
$ cargo install --git https://github.com/Ataraxy-Labs/weave weave-cli
$ cargo install --git https://github.com/Ataraxy-Labs/weave weave-driver

# Configure your repo
$ cd my-project
$ weave setup
✓ Configured git merge driver
✓ Updated .gitattributes

# Preview a merge before doing it
$ weave preview feature-branch
  src/auth.ts — auto-resolved
    2 entities matched, 2 modified, 0 conflicts
  src/config.json — auto-resolved
    1 entity matched, 1 modified, 0 conflicts

✓ Merge would be clean (2 file(s) auto-resolved by weave)

# Now git merge uses weave automatically
$ git merge feature-branch
Merge made by the 'ort' strategy.

For AI agents (MCP)

Claude Code (CLI)
# Install the MCP server binary
$ cargo install --git https://github.com/Ataraxy-Labs/weave weave-mcp

# Add to Claude Code (available in all projects)
$ claude mcp add --scope user weave -- weave-mcp

# Restart Claude Code, then verify with /mcp
Claude Desktop
# Add to Claude Desktop config (~/.config/claude/claude_desktop_config.json)
{
  "mcpServers": {
    "weave": { "command": "weave-mcp" }
  }
}

How the merge driver works

When git encounters a merge, it calls weave-driver with three versions of the file: base, ours, theirs. Here's what happens inside.

1
Parse all three versions
tree-sitter extracts entities (functions, classes, methods) from base, ours, and theirs. Each entity gets a stable ID based on its type, name, and parent.
2
Extract regions
The file is split into alternating Entity and Interstitial regions. Interstitials are the whitespace, imports, and syntax between entities.
3
Match entities across versions
For each entity in base: did ours change it? Did theirs? Both? Neither? This is where weave understands that two agents editing different functions is not a conflict.
4
Resolve per-entity
Only ours changed? Use ours. Only theirs? Use theirs. Both changed identically? Use either. Both changed differently? Try 3-way merge via diffy. If that fails on a container (class/impl/trait), try inner entity merge: decompose into method-level chunks, match by name, merge each independently. Renames are detected via structural_hash (AST-normalized). Conflicts are classified using the ConGra taxonomy (Text/Syntax/Functional).
5
Reconstruct the file
Reassemble the merged file preserving ours-side ordering, with theirs-only additions placed at the correct positions. Write to the ours path per git convention.

Architecture

Five crates in a Cargo workspace. Each can be used independently.

weave-core
The merge algorithm. Takes three strings (base, ours, theirs) + file path, returns merged content + conflict list. Uses sem-core for entity extraction and diffy for line-level fallback.
↓
weave-driver
Git merge driver binary. Git calls it with %O %A %B %L %P. Reads three temp files, calls entity_merge(), writes result to %A. Exit 0 = clean, 1 = conflicts.
↓
weave-crdt
Automerge-backed entity state. Advisory claims, agent tracking, conflict detection. Persisted at .weave/state.automerge. Not committed to git — local coordination state, auto-excluded via .git/info/exclude on first write.
↓
weave-mcp
MCP server with one tool per weave command. stdio transport for Claude Desktop/CLI integration. Wraps weave-crdt and weave-core into callable agent tools.
↓
weave-cli
Human-facing CLI. weave setup, weave preview, weave status, weave claim, weave release.

CRDT state

CRDT stands for Conflict-free Replicated Data Type — a data structure that multiple agents can edit simultaneously without conflicts. Think of it like a Google Doc that always merges correctly.

Why does weave need it?

The merge driver is reactive — it resolves conflicts after they happen. But if two agents are about to edit the same function, you want to know before they collide. The CRDT gives agents a shared "who's editing what" map. Agent A claims processData, Agent B sees the claim and picks a different function instead.

Advisory, not enforced

Claims are signals, not hard locks. If an agent ignores a claim and edits anyway, the merge still works — weave's merge driver handles it. This matches the optimistic concurrency model: trust agents to cooperate, handle it gracefully if they don't.

Document structure

The state is an Automerge document saved to .weave/state.automerge. It has three top-level maps:

{
  "entities": {                       // every code entity weave knows about
    "src/lib.ts::function::processData": {
      "name": "processData",
      "type": "function",
      "file_path": "src/lib.ts",
      "content_hash": "a1b2c3...",
      "claimed_by": "agent-1",          // advisory lock
      "claimed_at": 1706745600000,
      "last_modified_by": "agent-1",
      "version": 3
    }
  },
  "agents": {                         // registered agents
    "agent-1": {
      "name": "agent-1",
      "status": "active",
      "branch": "feature-auth",
      "last_seen": 1706745600000,
      "working_on": ["src/lib.ts::function::processData"]
    }
  },
  "operations": [...]               // audit log of claim/release/modify
}

Agent coordination flow

1
Agent registers
Calls weave_agent_register with its ID and branch. Gets added to the agents map.
2
Agent claims an entity
Calls weave_claim_entity. Gets back Claimed, AlreadyOwnedBySelf, or AlreadyClaimed { by }.
3
Agent edits the code
Periodically calls weave_agent_heartbeat with its working_on list. Other agents can check weave_who_is_editing before starting work.
4
Agent releases the claim
Calls weave_release_entity when done. If an agent crashes, cleanup_stale_agents releases its claims after a timeout.

Core operations

OperationWhat it does
claim_entitySet advisory lock on an entity for an agent
release_entityRemove the lock (only the owner can release)
record_modificationMark that an agent changed an entity, bump version
detect_potential_conflictsFind entities being worked on by multiple agents
register_agentAdd an agent to the state with name and branch
agent_heartbeatKeep-alive + update working_on list
cleanup_stale_agentsRelease claims from agents that stopped heartbeating
sync_from_filesExtract entities from working tree files into CRDT state

MCP server

MCP (Model Context Protocol) lets AI agents call tools. weave-mcp exposes five tools over stdio transport: weave_preview, weave_explain, weave_check, weave_land and weave_patch. Add it to Claude Code, Claude Desktop, or any MCP-compatible client.

Setup

install
$ cargo install --git https://github.com/Ataraxy-Labs/weave weave-mcp
Claude Code (CLI)
# Add to Claude Code (available in all projects)
$ claude mcp add --scope user weave -- weave-mcp

# Restart Claude Code, then verify with /mcp
Claude Desktop
# Add to ~/.config/claude/claude_desktop_config.json
{
  "mcpServers": {
    "weave": {
      "command": "weave-mcp",
      "args": []
    }
  }
}

Tools

weave_preview
Dry-run a merge of two branches. Per-file verdicts, a findings document, or the strategy used on each entity. Input: {base_branch, target_branch, file_path?, detail?}
weave_explain
Why a file conflicted: which guard refused, and the hunks both sides wrote in. Input: {file_path, markers?}
weave_check
Is the resolution right? Leftover markers, lost or duplicated lines, and cross-file breakage. Input: {base?, ours?, theirs?}
weave_land
Label every file of a stopped merge PROVEN, VERIFIED or REFUSED, and write the ones that pass. Input: {resolver?, dry_run?, base?, ours?, theirs?}
weave_patch
Extract typed entity ops, or apply them to a drifted file as a three-way merge. Input: {file_path, ops?, base_content?, write?}

For callers and blast radius use sem's MCP server. The live multi-agent CRDT tools (claim, release, status, ...) are listed only with WEAVE_EXPERIMENTAL=1, and older tool names still answer when called.

Example: agent workflow

agent calls via MCP
// Agent starts up
weave_agent_register({ agent_id: "claude-1", branch: "feature-auth" })

// Check what's in the file
weave_extract_entities({ file_path: "src/auth.ts" })
// → [{name: "validateToken", type: "function", ...},
//     {name: "authenticate", type: "function", ...}]

// Claim before editing
weave_claim_entity({ agent_id: "claude-1", file_path: "src/auth.ts", entity_name: "validateToken" })
// → "Claimed"

// ... agent edits the function ...

// Release when done
weave_release_entity({ agent_id: "claude-1", file_path: "src/auth.ts", entity_name: "validateToken" })
// → "Released successfully"

CLI commands

The weave CLI wraps all functionality for human use.

weave setup Configure current git repo to use weave as merge driver
--driver <path> Path to weave-driver binary (auto-detected if omitted)
--local Write merge attributes to .git/info/attributes instead of .gitattributes
weave preview <branch> Preview what a merge would look like without actually merging
--file <path> Preview a specific file only
weave status Show entity and agent state from CRDT
--file <path> Show entities for a specific file
--agent <id> Show status for a specific agent
weave claim <agent> <file> <entity> Claim an entity before editing
weave release <agent> <file> <entity> Release a previously claimed entity
weave bench Run merge benchmarks comparing weave vs git line-level merge

Environment variables

VariableDefaultDescription
WEAVE_TIMEOUT 5 Merge timeout in seconds. If entity-level merge takes longer, weave falls back to line-level merge. Increase for very large files.
WEAVE_MAX_DUPLICATES 10 Maximum same-name entities before skipping entity merge. Test files often have many similarly named functions. Increase to allow entity merge on such files.
WEAVE_REPO auto-detected Override git repo root for the MCP server. Useful when running weave-mcp from outside a repository.

Supported languages

Entity extraction powered by sem-core and tree-sitter. 23 programming languages + 5 data formats.

LanguageExtensionsEntities
TypeScript.ts .tsxfunctions, classes, interfaces, types, enums, exports
JavaScript.js .jsx .mjs .cjsfunctions, classes, variables, exports
Python.pyfunctions, classes, decorated definitions
Go.gofunctions, methods, types, vars, consts
Rust.rsfunctions, structs, enums, impls, traits, mods, consts
Java.javaclasses, methods, interfaces, enums, fields, constructors
Dart.dartclasses, functions, methods, enums, extensions, mixins
Scala.scala .sc .sbtclasses, objects, traits, functions, types
C.c .hfunctions, structs, enums, unions, typedefs
C++.cpp .cc .hppfunctions, classes, structs, enums, namespaces, templates
C#.csclasses, methods, interfaces, enums, structs, properties
Ruby.rbmethods, classes, modules
PHP.phpfunctions, classes, methods, interfaces, traits, enums
Swift.swiftfunctions, classes, protocols, structs, enums, properties
Elixir.ex .exsmodules, functions, macros, guards, protocols
Bash.shfunctions
HCL/Terraform.hcl .tf .tfvarsblocks, attributes (qualified names)
Kotlin.kt .ktsclasses, interfaces, objects, functions, properties
Fortran.f90 .f95 .ffunctions, subroutines, modules, programs
Vue.vuetemplate/script/style blocks + inner TS/JS entities
Svelte.svelte .svelte.js .svelte.tscomponent blocks, rune modules + inner JS/TS entities
XML.xml .plist .svg .csprojelements (nested, tag-name identity)
ERB.erbblocks, expressions, code tags

Data formats

FormatExtensionsEntities
JSON.jsonproperties, objects (RFC 6901 paths)
YAML.yml .yamlsections, properties (dot paths)
TOML.tomlsections, properties
CSV.csv .tsvrows (first column as ID)
Markdown.md .mdxheading-based sections