Address a heading, block, or frontmatter field โ then read it back, or append, replace, and move content. No line numbers, no regex, no sed.
Everything above is a canned example. This is the actual npm package, bundled for the browser and running on this page โ paste your own Markdown, write your own instruction, and watch the engine work. Nothing is uploaded; there is no server.
projectMap / print-map give you. Click one to target it.The playground bundle isn't built in this checkout โ npm run build:site produces it, and the Pages workflow builds it on every deploy.
Errors are the engine's own โ InvalidInstructionError, TargetNotFoundError, PreconditionFailedError โ thrown by the same code an npm install gets you. Click the version token to send it as ifMatch, then edit the document out from under the instruction to watch a stale write fail.
The obvious ways to edit Markdown programmatically all break on contact with real documents. Each one is handled by the engine, not by your code.
The engine supplies every separator, so "X", "X\n", and "\nX\n" all produce the same document. One missing newline can never merge two paragraphs again.
A # Section in your content lands as a direct child of wherever it's written โ the engine rebases levels, so pasted subtrees always fit their new depth.
Pass ifMatch with the document's version token. If the file changed under you, the patch throws instead of landing in the wrong place.
Two identical ### Fixed headings? The document map hands each occurrence a distinct address โ a regex matches both, a path names exactly one.
Append rows as string[][] โ cells are content, not source. Pipes are escaped for you and column counts are checked.
readTarget takes the same address as patch. Read at a scope, replace at that scope with the value unchanged: a guaranteed no-op.
Every address you can patch, you can also query. The bundled mdpatch CLI and the TypeScript API drive the same engine: two commands write, two retrieve.
| command | what it does | |
|---|---|---|
| mdpatch patch | write | quick flag-based form for common single edits |
| mdpatch apply | write | full instruction JSON โ moves, table rows, ifMatch pipelines |
| mdpatch query | read | print a target's content: a section, a block, a frontmatter value |
| mdpatch print-map | read | show everything addressable โ headings, blocks, fields, version token |
In the library, readTarget is the mirror image of patch โ the same (targetType, target) address, read instead of written. Pull one section out of a note without parsing anything yourself. Full signatures for every function and type live in the API reference.
An LLM agent shouldn't re-emit a 4,000-token file to add one paragraph โ and with markdown-patch it can't mangle the 3,900 tokens it had no business touching. This is the engine behind Obsidian Local REST API's PATCH endpoints and MCP tools, where exactly that kind of client is the norm.
Illustrative counts for a typical meeting note. Retrieval is cheap too: the agent reads the compact document map, not the whole file.
print-map hands the model a few dozen tokens describing everything addressable โ including distinct addresses for duplicate headings โ plus a version token.
The model picks an address straight off the map and, if it needs context, query-reads just that section โ no full-file round trips.
One small instruction lands the edit. Sent with ifMatch, a stale write throws instead of landing in the wrong place โ and retrying from a fresh map is the agent's native gesture.