Agent-safe structured edits: JSON/YAML/TOML/md/AST, dry-run, batch/tx. Not a filesystem MCP.
io.github.patchloom/patchloom MCP Server
Patchloom is an MCP server for agent-safe, structured edits across JSON, YAML, TOML, Markdown, and AST data. It supports dry-run and batch/transaction-style operations, and is explicitly not a filesystem MCP. It targets code-analysis and tree-sitter-based workflows, with emphasis on reliable structured-editing.
๐ ๏ธ Key Features
Agent-safe structured edits
Formats: JSON, YAML, TOML, md, AST
Dry-run support
Batch/tx operations
Not a filesystem MCP
๐ Use Cases
Automated refactoring and transformations of structured documents
Agent-driven code edits with validation/dry-run
Integrating structured-editing into developer-tools pipelines
Code analysis workflows using tree-sitter and AST data
โก Developer Benefits
Structured-editing tooling for AI-agents and automation
Developer-focused utilities across json/yaml/toml and AST
One binary. Every platform. Structured file edits for AI agents.
Patchloom is a single-binary CLI that gives AI coding agents safe, structured file editing on any operating system. It edits JSON, YAML, and TOML by selector (not regex), preserves comments, understands code structure across 20 languages, batches multiple file edits into one tool call, and works identically on Linux, macOS, and Windows.
Not a generic filesystem MCP. Default MCP filesystem servers read/write files as text. Patchloom adds dry-run previews, parser-backed config and markdown edits, AST ops, multi-file batch/tx with undo, and stable error_kind peels for hosts. Full coding agents (Claude Code, Codex, Cursor) own the loop; Patchloom is the tool layer they (or a Rust embedder) call.
bash
# Edit a YAML value by selector without breaking comments or formatting
patchloom doc set config.yaml database.port 5432 --apply
# Batch 6 file edits into a single tool call
patchloom batch --apply <<'EOF'
doc.set package.json version "2.0.0"
doc.set config.yaml app.version "2.0.0"
doc.set config.toml project.version "2.0.0"
replace README.md "1.0.0""2.0.0"
replace CHANGELOG.md "1.0.0""2.0.0"
file.create VERSION "2.0.0"
EOF
AI agents edit files through tool calls. Each call is a round-trip back to the LLM. When a task touches config files, that process has three failure modes:
Syntax corruption. The agent uses text replacement on JSON, YAML, or TOML and produces invalid output (mismatched braces, broken indentation, lost comments).
Round-trip tax. Editing 6 files means 6 separate tool calls. Each one waits for the LLM to generate, execute, read the result, and plan the next call.
Platform fragmentation. On Linux the agent uses sed, jq, grep. On Windows, none of those exist. The agent falls back to verbose PowerShell or makes errors with unfamiliar syntax.
How patchloom solves each one
Problem
How patchloom solves it
Syntax corruption
doc commands parse the file, change the value by selector path, and write valid output. Comments and formatting are preserved. No regex needed.
Round-trip tax
batch and tx combine N operations into 1 tool call. Six file edits become one command with atomic rollback on failure.
Platform fragmentation
Single static binary with zero dependencies. Same commands, same flags, same behavior on Linux, macOS, and Windows.
Patchloom is not faster than native tools for simple, single-file edits. Use native tools for those. But native text replacement cannot safely edit structured files: a sed on YAML can corrupt indentation, strip comments, or produce invalid syntax. doc set parses the file, changes the value by selector, and writes valid output. That guarantee is the point.
Where patchloom is faster is multi-file batching. Six file edits via native tools means six round-trips to the LLM. One batch call does the same work in a single round-trip.
Benchmark details (Claude Opus 4 via Grok Build, 11 tasks)
MCP mode wins overall (228.5s vs 233.8s native) because structured tool calls skip shell syntax construction entirely. MCP wins 5/11 tasks; native wins 3/11; 3 are ties. CLI mode is always slowest due to shell construction overhead.
# Scoop (Windows)
scoop bucket add patchloom https://github.com/patchloom/scoop-bucket
scoop install patchloom/patchloom
# Chocolatey (Windows; community feed; newer versions may lag moderation)
choco install patchloom
bash
# npm / npx (downloads the platform binary from GitHub Releases)
npx patchloom --version
# or: npm install -g patchloom
Pre-built binaries for Linux, macOS, and Windows are on the
Releases page.
See Installation for shell
installer scripts, source builds, and shell completion setup.
The extension auto-discovers the CLI (or installs it for you), generates
AGENTS.md, configures MCP servers, and adds Quick Actions to the command
palette. See the Editor Extension guide for details.
Quick start
1. Set up your project
bash
patchloom init
This creates AGENTS.md in a new project or appends the rules to an existing agent instructions file, offers shell completions, and detects MCP configuration opportunities. Pass -y to skip confirmation prompts.
If you only want the rules text:
bash
patchloom agent-rules >> AGENTS.md
# Or tailor the output:
patchloom agent-rules --mode mcp >> AGENTS.md # MCP-only (no CLI examples)
patchloom agent-rules --platform windows >> AGENTS.md # Windows-only syntax
If .vscode/ or .cursor/ exists, init also prints ready-to-copy .vscode/mcp.json or .cursor/mcp.json snippets.
Your AI agent reads AGENTS.md and learns when to use patchloom vs native tools.
2. Edit a config file safely
bash
# Parser-backed: changes the value, preserves comments and formatting
patchloom doc set config.yaml database.port 5432 --apply
tx plans are trusted input. format and validate run their cmd fields through the host shell (sh -c on Unix, cmd /C on Windows), so only run plans you trust.
4. Or use MCP for structured tool calls (no shell syntax)
MCP-capable agents call patchloom tools directly as structured JSON, with no shell quoting or command construction. The agent sends {"path": "config.json", "selector": "version", "value": "2.0"} instead of building patchloom doc set config.json version '"2.0"' --apply.
See the MCP setup guide for per-agent configuration and the full security model.
Using VS Code, Cursor, or Windsurf? The Patchloom extension handles setup automatically: it installs the binary, runs init, and configures your editor's MCP settings.
As a Rust library
Add patchloom as a dependency (omit CLI/MCP/AST with default-features = false):
use patchloom::api::{self, ApplyMode, ReplaceOptions, edit_error_kind, EditErrorKind};
use std::path::Path;
// Replace text (preview only, no disk write)letresult = api::replace_text(
Path::new("src/config.rs"),
"old_value", "new_value",
&ReplaceOptions::default(),
ApplyMode::Preview,
None,
)?;
println!("{}", result.diff);
// Agent hosts: shared primary+fallback policy (unique, require_change, fuzzy @ 0.90)letopts = ReplaceOptions::for_agent();
// Fail closed: zero matches become EditErrorKind::NoMatchmatch api::replace_in_content("body", "missing", "x", &opts) {
Ok(r) => println!("changed={}", r.changed),
Err(e) => assert_eq!(edit_error_kind(&e), Some(EditErrorKind::NoMatch)),
}
// After fuzzy Apply: refuse over-wide spans before trust (api::fuzzy_span_suspicious)// Invalid options and bad regex peel InvalidInput (CLI/tx typed errors included)match api::replace_in_content("body", "", "x", &ReplaceOptions::default()) {
Err(e) => assert_eq!(edit_error_kind(&e), Some(EditErrorKind::InvalidInput)),
Ok(_) => panic!("empty pattern must error"),
}
// Set a value in a JSON file
api::doc_set(
Path::new("config.json"),
"version",
serde_json::json!("2.0"),
ApplyMode::Apply,
None,
)?;
// Multi-doc YAML: merge into document 0 (selector None = root only)
api::doc_merge(
Path::new("stream.yaml"),
serde_json::json!({"env": "prod"}),
ApplyMode::Apply,
None,
Some("0"),
)?;
// Sole-path text load: binary โ EditErrorKind::Binary; invalid UTF-8 โ InvalidEncodinglet_text = api::load_text(Path::new("notes.md"))?;
All API types are Send + Sync. Beyond the api module, utility modules are also public: containment (workspace path guarding), exec (shell command execution), files (file-walking, load_text_strict, binary detection), backup (restore_path_from_latest_backup for post-Apply validate/revert), and write (atomic file writes with policy transformations). Library users needing temp dirs (e.g. agents) can use PathGuard::builder(cwd).allow_temp_directory() (handles /tmp on macOS); see the containment and api module rustdocs. Multi-doc bare keys and wrong-root merges peel to EditErrorKind::TypeError via edit_error_kind. Create/rename dest-exists peels to EditErrorKind::AlreadyExists (or api::is_already_exists / api::error_kind_str for CLI-stable "already_exists" strings). Fine-grained kinds also have bool peels (is_not_found, is_conflicts, is_changes_detected, is_type_error, is_format_failed, is_guard_rejected, is_invalid_input, is_no_match, is_ambiguous) matching edit_error_kind.
Replace fail-closed / shell-token options: CLI replace --require-change and --command-position (also plan/MCP fields and ReplaceOptions on the library). Agent hosts: ReplaceOptions::for_agent() plus api::fuzzy_span_suspicious after fuzzy Apply. Library-only AST mutators: ast_rename / ast_replace_in_symbol / ast_rename_batch (feature ast + files), and FunctionSigEdit::parse_rust. Host checklist: Embedder host. Full surface: docs.rs/patchloom.
Fast literal or regex search across text files (supports --glob/--exclude/--ignore-file for layered custom ignore files, --max-results, -C context, etc.)
replace
Mechanical string replacement across text files with diff preview
patchloom adds parser-backed structured edits; batching; never produces invalid JSON/YAML
comby
Structural code patterns
patchloom targets config files and agent workflows, not source code pattern matching
The key difference: patchloom is designed for AI agent workflows. One batch or tx call replaces N sequential tool calls, cutting round-trips and eliminating partial-failure states.
vs agent-native editing tools
The table above compares patchloom to human CLI tools. But agents already have built-in editing: Claude Code's edit_file, Cursor's apply, Grok Build's search_replace, Aider's /code blocks. Why add patchloom on top?
Agent-native tools use text matching. They find a block of text and replace it. This works for source code but fails on structured config files:
Agent uses search_replace on YAML
yaml
database:# Production settingshost:db.prod.internalport:5432# PostgreSQL defaultpool_size:10
The agent replaces port: 5432 with port: 5433. Result depends on implementation. Many agents lose the inline comment, break indentation, or fail to match because of surrounding context changes.
Agent uses patchloom doc set
bash
patchloom doc set config.yaml \
database.port 5433 --apply
The YAML parser changes the value at the selector path. Comments, indentation, key ordering, and all other formatting are preserved. The output is always valid YAML.
Limitation of agent-native tools
How patchloom addresses it
Comment destruction
CST-level YAML/TOML editing preserves all comments
One file per tool call
batch/tx edit N files in 1 call (6.7x faster in benchmarks)
No rollback
tx with strict: true reverts all files if validation fails
Platform-dependent
Same binary and syntax on Linux, macOS, Windows
Stale context risk
patch apply uses fuzz matching to handle context drift
When to keep using native tools: Single-file reads, simple text search, single-file text replacement where comments don't matter. Patchloom's agent-rules tell agents exactly when to use each approach.
Library hosts:ReplaceOptions::for_agent() (includes refuse_suspicious_fuzzy), peels via edit_error_kind / is_* / is_fuzzy_span_suspicious, multi-op ContentEditsResult.op_honesty. Custom options still use api::fuzzy_span_suspicious after fuzzy Apply.
Context budget: line-range read, search --count / --files-with-matches, one batch/tx, --jsonl for large streams.
How it works with your AI agent
Two integration modes, same capabilities:
flowchart LR
subgraph CLI["CLI mode (any agent)"]
direction TB
A["patchloom agent-rules >> AGENTS.md"] --> B["Agent reads AGENTS.md"]
B --> C{"What kind of edit?"}
C -->|Simple edit| D["Native tool (faster)"]
C -->|Config edit| E["patchloom doc (safer)"]
C -->|Markdown edit| F["patchloom md (smarter)"]
C -->|Multi-file edit| G["patchloom batch (batched)"]
end
subgraph MCP["MCP mode (MCP-capable agents)"]
direction TB
H["patchloom mcp-server"] --> I["Agent discovers tools via MCP"]
I --> J["Structured JSON tool calls"]
J --> K["No shell syntax needed"]
end
Status
3900+ tests across 23 commands. Tested with Grok 4.3, GPT-5.4, and Claude Opus 4.6.
Component
Status
CLI
Published on crates.io, Homebrew, Scoop, Chocolatey (choco install patchloom), and npm (npx patchloom). winget package under community review.
MCP server
Official MCP Registry name io.github.patchloom/patchloom (stdio; crates.io / npm packages; see server.json). Local MCPB for Smithery / desktop hosts: make pack-mcpb (mcpb/). Glama directory prep: root glama.json + manual Add MCP Server (see MCP setup)
For local verification before opening a pull request, run make check. It matches the main Linux CI gate: formatting, clippy, unit tests (including feature-matrix jobs), integration tests, PTY tests, release-notes structure, test hygiene, and generated-doc freshness (check-patchloom-md, check-readme). While iterating locally, make check-fast is the same except it skips only check-patchloom-md (it still runs check-readme so a drifted test-count badge fails before CI).
All commits must be signed off with git commit -s.
Agent integration tests
make agent-test runs 19 pytest scenarios that verify AI agents correctly use patchloom when given instructions. make bench-agent runs 3-way benchmarks (CLI vs MCP vs native) across 11 tasks. Use MODEL=X to switch models and RUNS=N for variance reduction. Requires an LLM API key. Not part of make check. See tests/agent/README.md for details.
Security
For current security reporting guidance, see SECURITY.md.