rianprei

snapedit

Community rianprei
Updated

Snapshot-based editing for AI agents: send only the NEW content via stdio MCP. Immutable sha256 snapshots, 3-way merge, conflict detection, ambiguity-safe zero-write applies, cross-process locks.

snapedit

Snapshot-based file editing for AI agents — send only the NEW content, never the old block.

Node.jsLicense: MITMCPTests

snapedit lets an editing agent (Claude Code, OpenCode, or any MCP client)edit files by sending only the new content — never the old text. Files arecaptured as immutable, content-addressed snapshots; edits reference thesnapshot's 1-based line numbers, so lines shifted by prior edits elsewherenever silently misapply.

Agent                            snapedit                     Filesystem
  │  read_snapshot(path)            │
  ├────────────────────────────────►│  sha256(bytes) → blob_id
  │◄── blob_id + numbered page ────┤
  │                                 │   …(agent thinks)…
  │  apply_snapshot_patch(blob,     │
  │    from, to, NEW_CONTENT) ──────►│  base=snapshot · ours=live
  │                                 │  3-way merge OR splice
  │◄── ok:true / conflict / err ────┤
  │                                 │  atomic write + lock

Why

Direct rewrite tools force the agent to transmit the old text to locate achange; when a file changes between reads, misalignment silently corruptsfiles. snapedit replaces that with:

  • Immutable snapshotsblob_id = sha256(bytes). The agent carries onlythe id; content is never re-sent.
  • 3-way merge on apply — base = snapshot, ours = live file. Earlier edits(even insertions above the hunk) are preserved; the patch lands exactlywhere the snapshot said it should.
  • Explicit conflicts — if the live file changed inside the hunk withdifferent content, no write happens; a structured conflict is returned withpreviews of both sides.
  • Safety over guesswork — ambiguous patches (hunk text duplicated in thelive file) are refused with zero writes, never silently applied to thewrong occurrence.
  • No shell transport — all bodies travel over stdio MCP (JSON-RPC lines).Large files are paged, never truncated by a shell.

Features

Feature Details
Content-addressed store ~/.snapedit/blobs, sha256 verified on read, recency index
Cross-process safety advisory locks, EEXIST-tolerant writes, stale-lock recovery
Concurrency parallel edits: disjoint ranges both land; same range → clean conflict
Ambiguity safety duplicated hunk text ⇒ refused, file proven byte-identical
Store GC snapedit store prune [--days N] [--dry-run] (blobs never garbage-collected automatically)
Zero dependencies plain Node.js ≥ 18, ESM

Install

git clone https://github.com/rianprei/snapedit.git
cd snapedit
npm test          # 55 tests, no deps required
npm link          # optional: expose `snapedit` on PATH

Quick start (CLI)

# snapshot + numbered page (default page 0, 300 lines)
snapedit read path/to/file.txt

# apply NEW content to snapshot lines 2..4 (1-based, inclusive)
snapedit apply path/to/file.txt <blob_id> 2 4 --content $'wrote new lines\n'

# where does the hunk map in the live file today?
snapedit locate path/to/file.txt <blob_id> 2 4

# run the MCP server over stdio
snapedit mcp

Claude Code configuration

Add an MCP server entry (Claude Code ~/.claude.json, or OpenCode's "type": "local" MCP):

{
  "mcpServers": {
    "snapedit": {
      "command": "/abs/path/to/snapedit/bin/snapedit",
      "args": ["mcp"]
    }
  }
}

Agent edit protocol (keep this short)

  1. read_snapshot (page containing region) — remember blob_id.
  2. apply_snapshot_patch(path, blob_id, from, to, new_content).
    • ok:true → done.
    • mode:"conflict" → re-read_snapshot, retry on the new snapshot.
    • kind:"snapshot_missing" → re-read_snapshot.
  3. Never send the old text; never concatenate whole-file bodies yourself.

new_content is the exact replacement for snapshot lines [from..to](1-based, inclusive). Multi-line edits work as a single new_content; themerge replays the hunk in snapshot coordinates, so earlier shifts don't breakit.

Documentation

  • Protocol — full JSON-RPC tool contracts, results, errors
  • Architecture — modules, data flow, concurrency model
  • Safety & invariants — ambiguity gate, conflict rules,corruption defenses, GC, locking
  • Changelog
  • Contributing

Security

See docs/SAFETY.md for the full property list. Highlights:

  • Refuses ambiguous applies deterministically (match_count != 1 → write == false, proven byte-identical by sha256 in tests).
  • Path-like blob_ids rejected (no filesystem traversal via the store).
  • MCP input validation: malformed JSON-RPC → -32600, invalid tool args → bad_arg, never a crash of the server.
  • Atomic write: temp file in same dir + rename → readers never observe partial content.

License

MIT — see LICENSE.

MCP Server · Populars

MCP Server · New

    getArbor-dev

    Arbor

    Graph-native code intelligence that replaces embedding-based RAG with deterministic program understanding.

    Community getArbor-dev
    Q00

    ouroboros

    Agent OS: Stop prompting. Start specifying.

    Community Q00
    velane-sh

    velane

    Velane is agentic cloud for deploying your basic workflows, agents and sub-agents. 800+ OAuth integrations, sandboxed Bun and Python execution, and a full deployment pipeline managed via MCP

    Community velane-sh
    MCPBlender

    BlenderMCP

    🎨 Control Blender 3D with Claude AI — prompt-driven 3D modeling, materials & scene generation via MCP

    Community MCPBlender
    MCPBlender

    AbletonMCP

    🎵 Control Ableton Live with Claude AI — create tracks, arrange clips & compose music via MCP

    Community MCPBlender