| name | obsidian-cli |
| description | Interact with Obsidian vaults using the Obsidian CLI to read, create, search, and manage notes, tasks, properties, and more. Also supports plugin and theme development with commands to reload plugins, run JavaScript, capture errors, take screenshots, and inspect the DOM. Use when the user asks to interact with their Obsidian vault, manage notes, search vault content, perform vault operations from the command line, or develop and debug Obsidian plugins and themes. |
Obsidian CLI
Use the obsidian CLI to interact with a running Obsidian instance. Requires Obsidian to be open.
Prerequisites (IMPORTANT)
-
Obsidian app must be running. The CLI binary (obsidian) communicates with a running Obsidian instance via IPC. If no instance is running, the CLI launches the Electron app server instead of executing CLI commands — you'll see Loaded main app package ...obsidian.asar output and the command hangs indefinitely. If this happens, ask the user to open Obsidian first.
-
All Bash calls MUST use dangerouslyDisableSandbox=true. The CLI needs IPC access to the running Obsidian process, which the sandbox blocks. Without this flag, commands will either time out or fail with permission errors.
Correct usage:
Bash(command='obsidian vaults', dangerouslyDisableSandbox=true)
Wrong — will hang or fail:
Bash(command='obsidian vaults') # missing sandbox bypass, IPC blocked
Command reference
Run obsidian help to see all available commands. This is always up to date. Full docs: https://help.obsidian.md/cli
Syntax
Parameters take a value with =. Quote values with spaces:
obsidian create name="My Note" content="Hello world"
Flags are boolean switches with no value:
obsidian create name="My Note" silent overwrite
For multiline content use \n for newline and \t for tab.
File targeting
Many commands accept file or path to target a file. Without either, the active file is used.
file=<name> — resolves like a wikilink (name only, no path or extension needed)
path=<path> — exact path from vault root, e.g. folder/note.md
Vault targeting
Commands target the most recently focused vault by default. Use vault=<name> as the first parameter to target a specific vault:
obsidian vault="My Vault" search query="test"
Creating notes
File placement
create name="My Note" places files at the vault root. To create notes in a specific folder, always use path=:
obsidian create path="pages/My Note.md" template="tech-note-template" silent
Before creating, discover the vault's folder structure with obsidian folders to find the correct notes directory.
Templates and content
When template= is provided, the CLI triggers Obsidian's template insertion (including Templater plugin variables like <% tp.file.title %>). Key behaviors:
template= fully resolves Templater <% tp.* %> syntax — dates, titles, etc. are expanded
template:read resolve only resolves core template variables ({{title}}, {{date}}), not Templater plugin syntax
- When both
template= and content= are provided, template wins and content is ignored
Correct workflow to create a note from template then add content:
obsidian create path="pages/My Note.md" template="tech-note-template" silent
obsidian create path="pages/My Note.md" content="..." overwrite silent
To discover available templates: obsidian templates
Writing content with special characters (IMPORTANT)
Problem: When passing content="..." directly, shell interprets special characters before the CLI sees them. Characters like |, →, ─, ┌, └, │, ▶, # get treated as shell operators, causing:
- ASCII art tables to be replaced with command output
- Table cells to be truncated
- Content to be partially executed as commands
Symptom: You see command output like ssh: connect to host... or Cloning into... mixed into your note content.
Solution: Write content to a temp file, then pass via $(cat file):
Write(file_path="/tmp/note-content.md", content="...\n---...\n")
CONTENT=$(cat /tmp/note-content.md)
obsidian vault="<vault>" create path="pages/My Note.md" overwrite content="$CONTENT" silent
rm /tmp/note-content.md
Why this works: The $(cat file) substitution happens inside double quotes after the shell has already parsed the command structure, preserving the raw content.
Properties (YAML frontmatter)
Note frontmatter is YAML. property:set must use the correct type= to produce valid YAML for each property. Omitting type= defaults to plain text, which breaks structured fields.
Supported types: text, list, number, checkbox, date, datetime
obsidian property:set name="tags" type="list" value="git, hooks" file="My Note"
obsidian property:set name="aliases" type="list" value="alias1, alias2" file="My Note"
obsidian property:set name="status" value="draft" file="My Note"
obsidian property:set name="priority" type="number" value="1" file="My Note"
obsidian property:set name="published" type="checkbox" value="true" file="My Note"
obsidian property:set name="due" type="date" value="2026-03-11" file="My Note"
obsidian property:set name="created" type="datetime" value="2026-03-11T10:00" file="My Note"
Common mistake: omitting type="list" for tags/aliases writes a comma-separated string instead of a YAML list, which Obsidian marks as invalid frontmatter.
Common patterns
obsidian read file="My Note"
obsidian create path="folder/New Note.md" template="Template" silent
obsidian append file="My Note" content="New line"
obsidian search query="search term" limit=10
obsidian daily:read
obsidian daily:append content="- [ ] New task"
obsidian property:set name="status" value="done" file="My Note"
obsidian property:set name="tags" type="list" value="tag1, tag2" file="My Note"
obsidian tasks daily todo
obsidian tags sort=count counts
obsidian backlinks file="My Note"
obsidian folders
obsidian templates
Use --copy on any command to copy output to clipboard. Use silent to prevent files from opening. Use total on list commands to get a count.
Agent workflows
Workflow 1: Add a knowledge note to a vault
Use when the user or agent wants to capture a learning, solution, or discovery as a structured note.
Steps:
-
Discover vault structure — find the notes folder and available templates:
obsidian vault="<vault>" folders
obsidian vault="<vault>" templates
-
Create note with template — use path= to place in the correct folder; silent to avoid opening:
obsidian vault="<vault>" create path="<notes-folder>/<Note Title>.md" template="<template-name>" silent
-
Set frontmatter properties — use correct type= for each property:
obsidian vault="<vault>" property:set name="tags" type="list" value="tag1, tag2" file="<Note Title>"
-
Verify template resolution — read back to confirm Templater variables expanded:
obsidian vault="<vault>" read file="<Note Title>"
-
Write body content — overwrite with full content (frontmatter + body) since template sections are now resolved:
obsidian vault="<vault>" create path="<notes-folder>/<Note Title>.md" overwrite content="<full note content with frontmatter>" silent
-
Final verification:
obsidian vault="<vault>" read file="<Note Title>"
Example — recording a dev solution:
obsidian vault="development" folders
obsidian vault="development" templates
obsidian vault="development" create path="pages/Git - Hook chaining.md" template="tech-note-template" silent
obsidian vault="development" property:set name="tags" type="list" value="git, hooks" file="Git - Hook chaining"
obsidian vault="development" read file="Git - Hook chaining"
obsidian vault="development" create path="pages/Git - Hook chaining.md" overwrite content="---\ncreation date: 2026-03-11\ntags:\n - git\n - hooks\n---\n\n# Git - Hook chaining\n\n## What is it?\n\n..." silent
obsidian vault="development" read file="Git - Hook chaining"
Workflow 2: Append to an existing note
Use when adding new content to an existing note (e.g. appending a log entry, adding a section).
obsidian vault="<vault>" append file="<Note Title>" content="\n## New Section\n\nContent here."
obsidian vault="<vault>" daily:append content="- [ ] Review PR #42"
Workflow 3: Search and read from a vault
Use when the agent needs to look up existing knowledge before creating new notes (avoid duplicates).
obsidian vault="<vault>" search query="hook chaining" limit=5
obsidian vault="<vault>" read file="<matched note>"
Workflow 4: Update properties on existing notes
Use when bulk-updating metadata (e.g. adding tags, changing status).
obsidian vault="<vault>" properties file="<Note Title>"
obsidian vault="<vault>" property:set name="status" value="published" file="<Note Title>"
obsidian vault="<vault>" property:set name="tags" type="list" value="git, hooks, new-tag" file="<Note Title>"
Important: property:set for list types replaces the entire list. To add a tag, read current tags first, then set the full list including the new one.
Plugin development
Develop/test cycle
After making code changes to a plugin or theme, follow this workflow:
- Reload the plugin to pick up changes:
obsidian plugin:reload id=my-plugin
- Check for errors — if errors appear, fix and repeat from step 1:
obsidian dev:errors
- Verify visually with a screenshot or DOM inspection:
obsidian dev:screenshot path=screenshot.png
obsidian dev:dom selector=".workspace-leaf" text
- Check console output for warnings or unexpected logs:
obsidian dev:console level=error
Additional developer commands
Run JavaScript in the app context:
obsidian eval code="app.vault.getFiles().length"
Inspect CSS values:
obsidian dev:css selector=".workspace-leaf" prop=background-color
Toggle mobile emulation:
obsidian dev:mobile on
Run obsidian help to see additional developer commands including CDP and debugger controls.