Patch Note
vault_patch_noteSurgical edits to a markdown note — append, prepend, replace, or insert content by heading. Frontmatter values are preserved; YAML formatting may be normalized to block style on first edit.
Instructions
Surgical edits to a markdown note — append, prepend, replace, or insert content by heading. Frontmatter values are preserved; YAML formatting may be normalized to block style on first edit.
Example: vault_patch_note({ path: "Projects/plan.md", operation: "append", heading: "Open questions", content: "- Which region hosts the backup?" }) Example: vault_patch_note({ path: "Notes/Plan.md", operation: "replace", heading: "Status", content: "On track for launch.\n" }) Example: vault_patch_note({ path: "Notes/Plan.md", operation: "insert_before", heading: "Phase 2", content: "## Phase 1\nDone.\n" }) Example: vault_patch_note({ path: "Notes/Plan.md", operation: "prepend", content: "> [!info] Draft\n> Not reviewed yet.\n" })
When to use: Modifying part of an existing note without overwriting the entire body. Prefer vault_write_note for creating new notes, or full rewrites (with overwrite: true). Prefer vault_replace_in_note for in-place text changes (typos, renaming) that stay in the same location. Prefer vault_insert_at_anchor for inserting next to a specific line inside a section. Prefer vault_replace_span for replacing a run of lines inside a section. Prefer vault_delete_span for removing lines. Prefer vault_update_properties for changing frontmatter properties. Prefer vault_create_task for adding a task. Prefer vault_update_task for completing or moving a task in one write.
Operations:
append: add content at end of section (or end of file if no heading)
prepend: add content after heading line (or at the top of the body, below frontmatter, if no heading — how you add a leading callout). To start a new section above the note's current first heading, use insert_before on that heading, not a no-heading prepend.
replace: replace section body (requires heading)
insert_before: insert content above the heading line (requires heading)
Heading-targeted ops keep the matched heading and write content verbatim. No separator is added around the content — end it with a newline to leave a blank line after the inserted block.
Limitation: A no-heading prepend inserts at body line 0. If the note has content above its first heading and your content starts with a heading, the pre-existing content becomes the new section's body. The write still succeeds.
Section boundaries: a section spans from its heading to the next heading of the same or higher level (or EOF), so it includes its child headings. Empty headings ("##" with no text) act as boundaries but cannot be targeted — edit their content via vault_replace_in_note instead.
Editing a leading callout: read it via vault_read_note(outline: true), then vault_replace_in_note the old block for the new one (a no-heading prepend would stack a second callout above it).
Errors:
"note not found" — path does not exist; check vault_list_notes for valid paths
"path must end in …" — add the .md extension
"heading not found" — no heading matches the text; error lists available headings
"ambiguous heading" — multiple headings match; use heading_level to disambiguate, or use vault_replace_in_note to target by text content when headings share the same level
"operation … requires a heading target" — pass heading, or use append or prepend to edit the file body
"heading cannot be empty" — heading is whitespace only; pass the heading's text
"content begins with the heading … which would duplicate it" — content's first line repeats the target heading; omit it
"section … has N child headings …" — the target section contains child headings that replace would destroy; pass include_children: true to confirm, or target the child heading directly
"absolute path blocked" / "path traversal blocked" / "hidden path blocked" — use a vault-relative path with no hidden (dot-prefixed) file or folder in it
"concurrent write in progress" — another write to this note is in flight; re-read the note and retry
"content contains a control character" — content includes a non-printable control byte; remove it before writing
"properties block …" — the note's properties block can't be read, or a rewrite would lose it; the error says how to repair it
"the note would open with a properties block …" — the edit would leave --- lines at the top of a note with no properties, around text that can't be kept as properties; the error says how to avoid it
Obsidian syntax: Content is Obsidian Flavored Markdown (no escaping applied). Watch for: #word = tag, [[ = wikilink, %% = comment block. Inserting heading-level content (## New Section) changes the note's structure — future heading-targeted ops may resolve differently. Table rows: send only the data row ("| cell1 | cell2 |"), not the header or separator — duplicating them splits the table.
Returns: Confirmation message — "Applied to → ", where target is the matched heading (e.g. "## Active") or "file body" for a no-heading append/prepend. A no-heading prepend that nested existing content under an inserted heading adds a sentence naming the content's size and the call that would have avoided it.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Vault-relative path to the note, including the ".md" extension (e.g. "TASKS.md", "Projects/plan.md"). Use the exact letter case. | |
| content | Yes | Markdown content to insert. | |
| heading | No | Target heading text (case-sensitive exact match). Omit for a file-level append or prepend. | |
| operation | Yes | append | prepend | replace | insert_before. | |
| heading_level | No | Heading level (1-6) for disambiguation when multiple headings share the same text | |
| include_children | No | When true, allows replace to overwrite a section that contains child headings. |