grove

Wikilinks and backlinks

Wikilinks turn markdown into a graph. In Grove, the graph reaches notes, files, symbols, and headings — not just other notes.

Forms

Syntax Resolves to
[[Note]] A note with that filename stem, case-insensitive
[[folder/Note]] A note at that subpath
[[Note|Alias]] Same as [[Note]], but renders Alias as the visible label
[[Note#Heading]] Opens the note and scrolls to the matching heading
[[fn:Symbol]] Opens the file containing Symbol and jumps to the declaration

fn: links use tree-sitter's outline pass, so they work in any language Grove ships a grammar for — no LSP server required.

Heading resolution

[[Note#Heading]] finds the heading by exact case-insensitive match first, then starts-with, then contains. So [[plan#out of scope]] will land on ## What is explicitly out of scope (v1) in plan.md.

The scroll keeps re-firing for ~1.5s after the file opens so Mermaid renders and other async layout don't drift the heading out of view.

Autocomplete

Typing [[ opens a floating popup of vault notes, ranked exact > prefix > contains. Selecting a note inserts a real wiki_link schema node — not raw [[…]] text — so the WYSIWYG renders the alias from the start.

What the index covers

Wikilinks resolve across:

  • The workspace tree (honouring .gitignore).
  • Every task's notes under <workspace>/.grove/workspace/.
  • Every task's worktree contents.

So [[some-note]] works regardless of which task's checkout the note lives in. A noise filter (node_modules, target, dist, …) keeps the index out of build artefacts.

The index is cached per workspace and invalidated on filesystem changes.

Renaming or moving a note in the vault rewrites the wikilinks that point at it across the workspace, so the graph follows the note instead of silently rotting. The rewriting is resolution-faithful: a bare [[Note]] is only retargeted when the renamed note was genuinely what it resolved to (an ambiguous name is never guessed at), [[folder/Note]] links follow both renames and moves, and #heading / |alias suffixes survive verbatim. Renames done outside the vault UI (your shell, an external tool) don't rewrite.

The right rail can show a Backlinks panel listing every note that links to the current file (via wikilink or fn:), with the linking line's snippet. Click any entry to open at that line. The panel rebuilds off the same outgoing-links table the resolver uses.

The anchor layer: prose that points at code

Beyond [[wikilinks]], plain code references in your notes — paths, folders, filenames, symbols — become anchors: content-pinned edges from prose to repo targets, stored in a rebuildable index. Your markdown is never rewritten; the index projects onto it.

  • Anchors use the same relocation math as comments — a content hash plus a tree-sitter semantic path — so a link to a function still lands after the file is refactored. Anchors that can't relocate are flagged stale, never deleted.
  • A background scan on workspace open pre-resolves the references in every doc, so the graph exists even for prose nobody has clicked yet.
  • Ambiguous references open a picker on click; your choice is sticky per occurrence.

The payoff is delivery — the invisible graph made visible in three places:

  • The editor gutter: a glyph on every line of code that a vault doc is anchored to. Hover shows the docs with snippets; click jumps to them. Your past thinking resurfaces exactly where it's relevant.
  • Find-references: LSP results include a Knowledge section listing the notes anchored to that symbol.
  • Agents: the anchors_in_scope MCP tool gives agents the same knowledge — notes about the code they're editing, relocated to current line numbers. See MCP.

See also