Patchloom
OfficialPatchloom
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.

# 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"
EOFWhy Patchloom? | Install | Quick start | Commands | Comparison | When to use what | Architecture | Status
Why Patchloom?
The problem
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 |
|
Round-trip tax |
|
Platform fragmentation | Single static binary with zero dependencies. Same commands, same flags, same behavior on Linux, macOS, and Windows. |
What changes with patchloom
Without patchloom (6 tool calls)
Agent: edit file 1 ─── tool call ───▶ 15s
Agent: edit file 2 ─── tool call ───▶ 15s
Agent: edit file 3 ─── tool call ───▶ 15s
Agent: edit file 4 ─── tool call ───▶ 15s
Agent: edit file 5 ─── tool call ───▶ 15s
Agent: edit file 6 ─── tool call ───▶ 15s
Total: ~90sWith patchloom batch (1 tool call)
Agent: batch with
all 6 edits ─── tool call ───▶ 25s
5 round-trips saved
Total: ~25sKey capabilities
Capability | What it does | Example |
Parser-backed edits | Edit JSON/YAML/TOML by selector, preserving comments and formatting |
|
Batch N files in 1 call |
|
|
Comment preservation | YAML/TOML comments survive all edits, including array resizing |
|
Heading-aware markdown | Edit sections, tables, and bullets by heading, not line number |
|
AST-aware code ops | List, rename, replace, and analyze symbols across 20 languages |
|
Atomic rollback |
|
|
MCP server | Expose all operations as structured MCP tool calls |
|
Optional CLI sandbox | Reject |
|
Cross-platform | Identical behavior on Linux, macOS, Windows. No | Same binary everywhere |
When to use patchloom vs native tools
Patchloom is not a replacement for all file operations. Its instructions tell agents exactly when to use it and when native tools are faster:
Task | Use patchloom? | Why |
Edit a JSON/YAML/TOML value by selector | Yes | Parser guarantees valid output, preserves comments |
Edit 3+ files in one task | Yes |
|
Append a row to a markdown table | Yes | Heading-aware, no line number guessing |
Read a single file | No | Native |
Simple text search | No | Native |
Single-file text replacement | No | Native |
Correctness over speed
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.
Task PL-CLI MCP Native
────────────────────── ────── ────── ──────
search 18.5s 12.7s 13.9s ◀ ~same
replace 36.1s 26.6s 26.1s ◀ ~same
doc_set 30.9s 16.9s 13.7s ◀ native fastest
md_table 15.5s 13.5s 15.3s ◀ MCP fastest
tx_multi_file 41.4s 28.5s 22.9s ◀ native fastest
batch_6_files 50.6s 46.6s 30.3s ◀ native fastest
batch_mixed_ops 24.7s 13.6s 20.9s ◀ MCP fastest
yaml_comment_preserve 18.1s 11.6s 16.1s ◀ MCP fastest
md_insert 15.0s 11.7s 15.7s ◀ MCP fastest
file_ops 26.0s 16.6s 17.2s ◀ ~same
tidy 45.0s 30.3s 41.7s ◀ MCP fastest
────────────────────── ────── ────── ──────
TOTAL 321.9s 228.5s 233.8sMCP 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.
Related MCP server: mcp-json-yaml-toml
Install
# Homebrew (macOS/Linux)
brew install patchloom/tap/patchloom
# crates.io (requires Rust 1.95+, includes MCP server)
cargo install patchloom# Scoop (Windows)
scoop bucket add patchloom https://github.com/patchloom/scoop-bucket
scoop install patchloom/patchloom
# winget (Windows; PackageIdentifier Patchloom.Patchloom)
winget install Patchloom.Patchloom
# Chocolatey (Windows; community feed; newer versions may lag moderation)
choco install patchloom# npm / npx (downloads the platform binary from GitHub Releases)
npx patchloom --version
# or: npm install -g patchloomPre-built binaries for Linux, macOS, and Windows are on the Releases page. See Installation for shell installer scripts, source builds, and shell completion setup.
MCP Registry name:
mcp-name: io.github.patchloom/patchloom
Editor extension
Install the companion extension for VS Code, Cursor, Windsurf, or VSCodium:
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
patchloom initThis 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:
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 syntaxIf .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
# Parser-backed: changes the value, preserves comments and formatting
patchloom doc set config.yaml database.port 5432 --apply3. Batch multiple edits into one call
patchloom batch --apply <<'EOF'
doc.set config.json version '"2.0.0"'
md.upsert_bullet AGENTS.md "Rules" "- Always test"
replace src/main.rs "v1" "v2"
EOFValues are JSON-first: unquoted 2.0 becomes a number. Force a string with nested
quotes as above (Unix shells).
Or use a JSON plan with format and validate lifecycle:
{
"version": 1,
"operations": [
{ "op": "doc.set", "path": "config.json", "selector": "version", "value": "2.0.0" },
{ "op": "md.upsert_bullet", "path": "AGENTS.md", "heading": "Rules", "bullet": "- Always test" },
{ "op": "replace", "path": "src/main.rs", "old": "v1", "new": "v2" }
],
"format": [{ "cmd": "cargo fmt --all" }],
"validate": [{ "cmd": "cargo test", "required": true }]
}patchloom tx plan.json --applytx 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)
After installing with MCP support, start the server:
patchloom mcp-serverMCP-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.
Coding agents: set PATCHLOOM_MCP_SURFACE=core for an 11-tool pack (list_files, search/read/replace, doc/md, execute_plan, server_info) so schemas stay small. Product default remains full inventory when the env is unset. Prefer Patchloom MCP alone for list+edit (no second filesystem MCP). See the MCP setup guide for Cursor / Claude / Codex paste configs 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
Host teams embedding Patchloom instead of a private edit stack: see the
embedder host case study
(for_agent, peels, fuzzy refuse, apply_fragment, path-only ops).
Add patchloom as a dependency (omit CLI/MCP/AST with default-features = false):
[dependencies]
patchloom = { version = "0.22", default-features = false }use patchloom::api::{self, ApplyMode, ReplaceOptions, edit_error_kind, EditErrorKind};
use std::path::Path;
// Replace text (preview only, no disk write)
let result = 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)
let opts = ReplaceOptions::for_agent();
// Fail closed: zero matches become EditErrorKind::NoMatch
match 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)),
}
// for_agent auto-refuses over-wide fuzzy; custom options use api::fuzzy_span_suspicious
// Buffer multi-op + host write: api::refuse_batch_if_suspicious_fuzzy after apply_content_edits
// 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 → InvalidEncoding
let _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() on primary and fallback replace paths (auto span refuse); custom options still call api::fuzzy_span_suspicious / FuzzySpanPolicy after fuzzy Apply; buffer multi-op hosts call api::refuse_batch_if_suspicious_fuzzy after apply_content_edits (#2064). Library-only AST mutators: ast_rename / ast_replace_in_symbol / ast_rename_batch (feature ast + files), and FunctionSigEdit::parse_rust. Ordered host onboarding: Embedder host checklist (#2009). Full surface: docs.rs/patchloom.
Getting started
Resource | What you'll learn |
Install options and shell completions | |
Write modes, transaction plans, exit codes | |
Configure patchloom as an MCP server for your agent | |
VS Code, Cursor, Windsurf, and VSCodium integration | |
5-minute walkthrough | |
Every command, operation, and mode | |
Transaction plan templates |
Commands
Agent-optimized (these are faster or safer than native tools)
Command | What it does | When to use |
| Line-oriented multi-file edits in 1 call | Editing 3+ files with simple syntax |
| JSON plan with format/validate lifecycle | Complex multi-file edits with rollback |
| Parser-backed JSON/YAML/TOML edits | Changing config values without breaking syntax |
| Heading-aware markdown edits | Updating tables, sections, bullets in docs |
| AST-aware symbol operations (20 languages) | Renaming identifiers, listing symbols, impact analysis |
| Apply unified diffs with stale detection | Replaying patches safely |
| Text-file whitespace and newline normalization | CI checks for text tidiness |
| MCP protocol server | MCP-capable agents (no shell syntax) |
General-purpose (also useful in scripts and CI)
Command | Description |
| Fast literal or regex search across text files (supports --glob/--exclude/--ignore-file for layered custom ignore files, --max-results, -C context, etc.) |
| Mechanical string replacement across text files with diff preview |
| Freeform fragment with required anchors (MorphLLM-style markers stripped; no cloud merge) |
| Append content to an existing file |
| Prepend content to an existing file |
| Create a new file with content |
| Delete a file |
| Move (rename) a file |
| Read file contents with optional line range |
| Show which files have uncommitted changes |
| Summarize a tx plan in plain English |
| Restore files from a backup created by |
| Generate shell completions (bash, zsh, fish, elvish) |
| Set up patchloom in a project (agent rules, completions, MCP) |
| Export operation schemas with tier filtering and system prompts |
| Generate agent instructions for your project |
How patchloom compares
Tool | Strength | Where patchloom differs |
jq | JSON query/transform | patchloom also handles YAML, TOML, markdown; batches across files; preserves comments |
yq | YAML/JSON query/transform | patchloom preserves YAML comments via CST editing; adds markdown, batching, atomic transactions |
dasel | Multi-format get/set | patchloom adds batching (N edits in 1 call), atomic rollback, format/validate lifecycle |
sd | Regex find/replace | 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
database:
# Production settings
host: db.prod.internal
port: 5432 # PostgreSQL default
pool_size: 10The 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
patchloom doc set config.yaml \
database.port 5433 --applyThe 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 |
|
No rollback |
|
Platform-dependent | Same binary and syntax on Linux, macOS, Windows |
Stale context risk |
|
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.
When to use what
Need | Prefer | Prefer something else |
JSON/YAML/TOML by path | Patchloom | Generic filesystem MCP / blind text replace |
Multi-doc YAML stream | Patchloom selectors ( | Bare key on stream root |
Structural code pattern search | Text-only grep for shapes | |
Identifier rename in code | Patchloom | Fuzzy text replace for symbols |
Multi-file atomic apply + undo | Patchloom | N sequential shell edits |
Freeform snippet with known anchor (after/before/old) | Patchloom | Whole-file rewrite or guessing placement |
Freeform snippet without anchors (cloud model merge) | Morph Fast Apply or similar | Patchloom (anchor-less Morph merge is a non-goal) |
Full agent product | Claude Code / Codex / Cursor | Patchloom alone |
Longer write-ups: Comparisons · Embedder host checklist · MCP setup
Library hosts: Embedder host checklist: dual-path ReplaceOptions::for_agent() (primary + fallback, includes refuse_suspicious_fuzzy), peels via edit_error_kind / is_* / is_fuzzy_span_suspicious with #[non_exhaustive] _ arm, multi-op ContentEditsResult.op_honesty + refuse_batch_if_suspicious_fuzzy after buffer multi-op (#2064), plan/tx widest matched_text, optional apply_content_edits_to_file_with_span_policy. Custom options still use api::fuzzy_span_suspicious / FuzzySpanPolicy 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"]
endStatus
4000+ tests across 24 commands. Tested with Grok 4.3, GPT-5.4, and Claude Opus 4.6.
Component | Status |
CLI | Published on crates.io, Homebrew, Scoop, Chocolatey ( |
MCP server | Official MCP Registry name |
Editor extension | Published on VS Code Marketplace and Open VSX |
Full command reference
Every command, flag, transaction operation, and exit code is documented in the Command Reference (also available at docs/reference/README.md).
License
Licensed under either of:
MIT license (LICENSE)
Apache License, Version 2.0 (LICENSE-APACHE)
at your option.
Contributing
See CONTRIBUTING.md.
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.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseBqualityDmaintenanceAdvanced code search and transformation MCP server for AI assistants. Combines ugrep's speed with intelligent replace capabilities, dry-run previews, and language-aware refactoring across 11 tools.Last updated19MIT
- AlicenseAqualityCmaintenanceA token-efficient, schema-aware MCP server that enables AI assistants to safely read, modify, query, and validate JSON, YAML, and TOML files with automatic schema detection and format conversion capabilities.Last updated89MIT
- AlicenseAqualityAmaintenanceA robust, language-agnostic Model Context Protocol (MCP) server that provides AI coding agents with the ability to edit files surgically via Abstract Syntax Trees (AST) instead of relying on token-heavy, brittle search-and-replace or diff operations.Last updated287MIT
- AlicenseAqualityBmaintenanceAdmission-control MCP server for AI coding agents — rejects bad file edits without coaching the LLM.Last updated31MIT
Related MCP Connectors
OCR, transcription, file extraction, and image generation for AI agents via MCP.
MCP-native collaborative markdown editor with real-time AI document editing
65+ AI tools as MCP: research, write, code, scrape, translate, RAG, agent memory, workflows
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/patchloom/patchloom'
If you have feedback or need assistance with the MCP directory API, please join our Discord server