Driving the vault from the CLI
The official Obsidian CLI is the primary
interface to this vault. It ships with the desktop app and is on PATH at
/Applications/Obsidian.app/Contents/MacOS/obsidian.
Run obsidian help for the full command list, or obsidian help <command> for
one command. Do not guess flags — check first.
Three rules that prevent damage
- Obsidian must be running. If it is not, the first command starts it.
- Always target this vault. The CLI defaults to the most recently focused
vault, and several are registered on this machine — including a work vault.
Either run from inside
digital-garden/, or passvault="digital-garden"as the first parameter. A command aimed at the wrong vault is the most likely way to do real damage here. - Sync is live. The vault syncs through Obsidian Sync, so writes propagate
to other devices, and the author may be editing the same file right now.
Prefer
obsidian property:setover rewriting a whole file, and do not batch-rewrite many notes without asking.
Two output quirks
Every call prints Your Obsidian installer is out of date when the app
runtime has self-updated past the installer version. Filter that line out of
anything shown to the user. Installing the current installer from
https://obsidian.md/download removes it.
A command sometimes returns nothing, then works on the next call. Observed on
search, help, commands and version when the app is cold or busy.
Empty output is not a result. Re-run before concluding the vault has no match. A wrong “nothing found” is how a duplicate note gets created.
obsidian read on a missing file prints Error: File "..." not found. and
still exits 0. Never trust the exit code — check the output text, or test
with test -f first.
Commands that matter here
obsidian read path="Notes/Boolean blindness.md"
obsidian search:context query="Hamming" path="Notes"
obsidian create path="Inbox/My idea.md" template="Seedling 🌱"
obsidian append path="Inbox/My idea.md" content="line one\nline two"
obsidian property:set name="growth" value="Budding" path="Notes/X.md"
obsidian backlinks file="Boolean blindness"
obsidian unresolved counts
obsidian tags counts sort=countcreate ... template= resolves {{title}}, {{date}} and {{time}}
correctly and uses the filename as {{title}}. Prefer it over hand-writing
frontmatter — see the created_at rule in conventions.md.
Use \n for newlines inside a content= value, and quote any value with spaces.
property:set ... type=checkbox writes a real unquoted YAML boolean, which is
the only form that hides a note. Verified 2026-08-18.
Periodic notes: never write the file
The author creates daily and weekly notes by clicking a date in the Calendar plugin, which delegates to periodic-notes. That path applies the right template and the right filename. Reproduce it through the plugin:
obsidian command id="periodic-notes:open-daily-note"
obsidian command id="periodic-notes:open-weekly-note"
obsidian command id="periodic-notes:open-monthly-note"These create the note from its template when it does not exist. Then edit the
file on disk. Never use obsidian create or a file write for a periodic
note — that loses the template, the aliases, and the filename conformance.
The daily-notes trap, and its fix
The CLI’s daily:* commands read the core daily-notes plugin, not
periodic-notes. Core daily-notes had never been configured here, so it fell back
to the default new-file location:
obsidian daily:path → Inbox/2026-08-18.md ← wrong
Every daily command would have written into Inbox/. Fixed on 2026-08-18 by
writing .obsidian/daily-notes.json to match periodic-notes exactly:
{ "folder": "Journal", "format": "YYYY/MM/YYYY-MM-DD", "template": "Templates/Daily" }obsidian daily:path → Journal/2026/08/2026-08-18.md
Both plugins now agree, so daily, daily:path, daily:read, daily:append
and tasks daily all resolve correctly. Do not change that file.
There is no core equivalent for weekly notes. Compute the weekly path with the
ISO week-year — %G/%V, never %Y/%U, which break in early January:
WEEK="Journal/$(date +%G)/$(date +%G)-week-$(date +%V).md"Escape hatch
obsidian eval code="..." runs JavaScript in the app context — useful for
things the CLI does not expose, such as reading a plugin’s live settings:
obsidian eval code="JSON.stringify(app.plugins.plugins['periodic-notes'].settings.weekly)"It can also mutate the vault, so it is deliberately not in the project permission allowlist and will prompt.