obsidian
Obsidian Skill
Routing Policy
Use the backend that best matches user intent:
-
MCP (default for vault data operations)
- Read/write/patch/move/search notes
- Frontmatter and tag updates
- Metadata and batch note operations
-
Obsidian CLI/App context (only when app context is needed)
- Open a note in Obsidian from URI
- Trigger app/plugin workflows that MCP cannot perform
-
CLI git (sync/backup workflows)
- Initialize repo, configure remote, commit, pull, push
- Periodic or manual vault backup/sync requests
When a request is ambiguous, pick MCP first unless the user explicitly asks for sync/backup/git/app behavior.
Gotchas
-
patch_note rejects multi-match by default. With
replaceAll: false, ifoldStringappears more than once the call fails and returnsmatchCount. SetreplaceAll: trueonly when you mean it, or add surrounding context to make the match unique. -
patch_note matches inside frontmatter. The replacement runs against the full file including the YAML block. A generic string like
title:will match frontmatter fields. Include enough context to target the right occurrence. -
patch_note forbids empty strings. Both
oldStringandnewStringmust be non-empty and non-whitespace. To delete text, usenewStringwith a single space or restructure the note withwrite_note. -
search_notes returns minified JSON. Fields are abbreviated:
p(path),t(title),ex(excerpt),mc(matchCount),ln(lineNumber),uri(obsidianUri). Hard cap of 20 results regardless oflimit. -
search_notes multi-word queries score terms individually AND as a phrase. Each term is OR-matched, so a document matching any term appears in results. The full phrase gets an additional scoring boost.
-
write_note auto-creates directories. Parent folders are created recursively. In
append/prependmode, if the note doesn't exist it's created. Frontmatter is merged (new keys override) in append/prepend; replaced entirely in overwrite. -
delete_note requires exact path confirmation.
confirmPathmust be character-identical topath. No normalization, no trailing-slash tolerance. Mismatch silently fails withsuccess: false. -
move_file needs double confirmation. Both
confirmOldPathandconfirmNewPathmust exactly match their counterparts. Usemove_notefor markdown renames (text-aware, no confirmation needed); usemove_fileonly for binary files or when you need binary-safe moves. -
manage_tags reads from two sources but writes to one.
listmerges frontmatter tags + inline#hashtags.add/removeonly modify the frontmattertagsarray. Inline tags are never touched. -
read_multiple_notes never rejects. Uses
allSettledinternally. Failed files appear in theerrarray; successful ones inok. Always check both. Hard limit of 10 paths per call.
Error Recovery
| Error | Next step |
|---|---|
| patch_note "Found N occurrences" | Add surrounding lines to oldString to make it unique, or set replaceAll: true |
| delete_note / move_file confirmation mismatch | Re-read the note path with read_note or list_directory, then retry with the exact string |
| search_notes returns 0 results | Try single keywords instead of phrases, toggle searchFrontmatter, or broaden with partial terms |
read_multiple_notes partial err |
Verify failed paths with list_directory, fix typos or missing extensions, retry only failed ones |
Git Sync Mode
When the user asks to "sync", "backup", or "store my vault with git", use CLI git with this behavior:
-
Run a preflight before changing anything:
gitavailable- current directory is a git repo (or prompt to initialize)
git config user.nameandgit config user.emailare set- at least one remote exists for push/pull sync
-
If preflight is incomplete, ask exactly one targeted question with a recommended default.
- Use askuserquestion for decisions that materially change behavior.
- Good examples:
- "No git repo found. Initialize one in this vault now? (Recommended: Yes)"
- "No remote configured. Set up GitHub remote now via gh if available, or provide remote URL? (Recommended: Set up via gh)"
- "Local and remote diverged. Try
git pull --rebasenow? (Recommended: Yes)"
-
Safe sync sequence (never force push by default):
git add -Agit commit -m "vault sync: YYYY-MM-DD HH:mm"(skip commit if no changes)git pull --rebasegit push
-
ghis optional:- Use
ghonly for remote bootstrapping (create repo / set origin) when requested. - Do not require
ghfor normal sync once remote is configured.
- Use
-
Stop on conflicts and report clear next steps.
- Do not auto-resolve merge conflicts silently.
- Explain what failed and what user should run next.
Resources
Load these only when needed, not on every invocation.
- Tool Patterns - read when you need a tool's response shape, mode details, or the move_note vs move_file decision
- Obsidian Conventions - read when creating/writing note content (link syntax, frontmatter fields, daily note format, template variables)
- Git Sync - read when user asks for backup/sync/store-vault workflows with git/gh