Expert in managing Obsidian vaults using obsidian-cli workflows for reading, writing, searching, moving, and organizing notes while preserving wiki-link integrity and vault structure...
Before performing vault operations:
Verify obsidian CLI is installed:
obsidian --version
The CLI is the native obsidian binary that ships with the Obsidian desktop app — not a separate npm package.
List available vaults:
obsidian vaults
Get vault path:
obsidian vault "<name>" info=path
Use obsidian for vault operations that touch links or structure. For iCloud-synced vaults (path contains Mobile Documents — check with obsidian vault "<name>" info=path), the Write tool is not reliable: iCloud paths are TCC-protected, so direct filesystem writes can be blocked even with the sandbox disabled — only the Obsidian app (via the CLI) is guaranteed to land. For creating a note with substantial content (multi-line, frontmatter, code blocks), use scripts/write-markdown-to-vault.js in this skill — it chunks large payloads under the CLI's ~10KB IPC ceiling, filters banner noise, retries transient errors, and verifies the write by reading the note back. Run it unsandboxed (the CLI hangs under the command sandbox). For vaults on ordinary filesystem paths (not iCloud), the Write tool works directly and is simpler for one-off notes.
| Task | Command | Notes |
|---|---|---|
| List vaults | obsidian vaults |
Always run first |
| Vault info | obsidian vault "<name>" |
Name, path, file count |
| Vault path | obsidian vault "<name>" info=path |
Path only, good for scripting |
| List folders | obsidian "vault=<name>" folders |
Quote vault name if it has spaces |
| Read note | obsidian "vault=<name>" read "<note name>" |
Reads by name (fuzzy) |
| Create note (large/iCloud) | node scripts/write-markdown-to-vault.js --vault <name> --path <path> --input <file> |
Chunked, retried, verified — run unsandboxed |
| Create note (small, non-iCloud) | obsidian "vault=<name>" create path="folder/name.md" content="$CONTENT" |
Use printf to build $CONTENT for multi-line |
| Overwrite note | obsidian "vault=<name>" create path="..." content="$CONTENT" overwrite |
|
| Append to note | obsidian "vault=<name>" append path="<path>" content="<text>" |
|
| Move note | obsidian "vault=<name>" move path="old.md" newpath="new.md" |
Auto-updates all links |
| Search content | obsidian "vault=<name>" search query="<term>" [path=<folder>] [format=json] |
|
| Daily note | obsidian "vault=<name>" daily |
Create/open today's note |
| Active/default vault | obsidian vault |
No name → the vault currently open |
| Append to daily note | obsidian "vault=<name>" daily:append content="<text>" |
Active vault; needs Daily Notes plugin |
See also:
# List vaults to confirm the name
obsidian vaults
# Get full info (name, path, file count)
obsidian vault "<name>"
# Get just the path (useful for scripting)
VAULT_PATH=$(obsidian vault "<name>" info=path)
# List folders
obsidian "vault=<name>" folders
# Search for existing notes
obsidian "vault=<name>" search query="<topic>" path=<folder> format=json
Use printf to build the content variable — this correctly handles newlines and multi-line content including frontmatter:
CONTENT=$(printf '---\ntags:\n - til\nindex: "[[Today I learned]]"\n---\n## Heading\n\nContent here.')
obsidian "vault=<name>" create path="til/2026-04-27 My Note.md" content="$CONTENT"
Look at an existing note first to match local formatting conventions (tag names, frontmatter fields, index backlinks, etc.):
obsidian "vault=<name>" read "<existing note name>"
# ✅ CORRECT: Auto-updates all links
obsidian "vault=<name>" move path="Random Notes/Design.md" newpath="Projects/Design.md"
# ❌ WRONG: Breaks all links to this note
mv "vault/Random Notes/Design.md" "vault/Projects/Design.md"
| Mistake | Why Wrong | Fix |
|---|---|---|
Using obsidian-cli |
That's a different npm package — the tool is obsidian |
Use obsidian |
Using --flags syntax |
The CLI uses key=value positional args, not --flags |
Use key=value format |
create with \n in double-quoted string |
Escapes get stripped, content truncated | Use printf to build a $CONTENT variable |
Using Write on an iCloud vault path |
TCC can silently block the write even with the sandbox disabled | Use scripts/write-markdown-to-vault.js instead |
Content over ~10KB in one create/append call |
Silent broken pipe (exit 0, nothing written) or a NativeImage error |
Use scripts/write-markdown-to-vault.js — it chunks automatically |
Using mv to move notes |
Breaks all [[wiki-links]] to that note |
Use obsidian move |
| Not checking existing note format | Each vault has different tagging/frontmatter conventions | Read an existing note first |
| Using absolute paths in wiki-links | Breaks when vault moves | Use vault-relative paths |
Edit after reading with obsidian readGrep directly on the vault path (use obsidian vault "<name>" info=path to get it)Always preserve:
---)[[Note]]#tag-nameVault operations succeed when:
[[wiki-links]] remain valid after moves