Insert at Anchor
vault_insert_at_anchorInsert whole lines before or after a line matching a short anchor substring in an Obsidian note. Add table rows, list items, or callouts at a precise location without needing heading structure.
Instructions
Insert content as whole lines before or after a specific line identified by a short anchor substring. Case-sensitive matching; an anchor matching more than one line is an error unless first_match is set. Same anchor resolution as vault_delete_span. Properties are preserved; YAML formatting may be normalized to block style on first edit. Operates on the body only.
Example: vault_insert_at_anchor({ path: "Tracker.md", anchor: "| 2024-03-02 | Acme", position: "after", content: "| 2024-03-03 | Beta Corp | New entry |" }) — inserts a new table row after the matched row. Example: vault_insert_at_anchor({ path: "Notes/Plan.md", anchor: "## Phase 2", position: "before", content: "> [!note] Phase 1 must close before this starts.\n" }) — inserts a callout and a blank line above the Phase 2 heading.
When to use: Adding content at a precise location identified by a nearby line's text, without needing to know the heading structure. Good for inserting rows into tables, adding items into lists at a specific position, or placing content relative to a known landmark line. Prefer vault_patch_note for heading-targeted inserts (append/prepend to a section). Prefer vault_replace_span when replacing a block rather than inserting next to it.
Parameters:
anchor locates a full line — the content is inserted as whole lines before or after it (never splits a line).
position: "before" inserts above the anchor line; "after" inserts below it.
content is inserted verbatim — blank lines inside it are kept, and a trailing newline adds a blank line after the inserted block.
first_match: when the anchor matches multiple lines, takes the first instead of erroring.
Errors:
"note not found" — verify path with vault_list_notes
"anchor not found" — fragment not on any line; verify with vault_read_note
"ambiguous anchor …" — the anchor matches multiple lines; use a longer fragment or set first_match: true
"hidden path blocked" — the path targets a hidden (dot-prefixed) file or folder like ".obsidian/"; hidden paths are not editable, matching Obsidian
"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
Obsidian syntax: content is Obsidian Flavored Markdown (no escaping applied). Watch for: #word = tag, [[ = wikilink, %% = comment block.
Returns: Confirmation message "Inserted lines <before|after> anchor in " — N counts the lines content supplied.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Vault-relative path to the note, including the ".md" extension (e.g. "Notes/Plan.md", "Tracker.md") | |
| anchor | Yes | Short, unique substring on the line to insert next to (case-sensitive). Pick a brief fragment — do not paste the whole line. | |
| content | Yes | Content to insert (one or more lines), inserted verbatim as whole lines — blank lines are kept, and a trailing newline adds a blank line after the block. | |
| position | Yes | "before" places the content on the lines above the anchor line; "after" places it on the lines below. The anchor line itself is never changed. | |
| first_match | No | If the anchor matches more than one line, use the first match instead of erroring (default: false — ambiguity is an error). |