name: obsidian-mechanics
description: >
Personal Obsidian CLI mechanics and patterns not covered by the base
obsidian-cli skill. Load when driving the Obsidian CLI for content creation,
file operations, vault hygiene, or version history. Triggers on: "search my
vault", "find notes about", "show orphan notes", "find broken links", "rename
this note", "move this note", "show note history", "restore version", "list
backlinks", "show outline", "heredoc obsidian", "obsidian fallback", "vault
hygiene".
Obsidian Mechanics
Personal patterns for driving the Obsidian CLI. Fills gaps in the base
obsidian-cli skill (heredoc content creation, file operations, version
history, vault hygiene, direct-file fallback).
MANDATORY: Load obsidian-cli for the base CLI reference (syntax, file
targeting, common patterns).
Vault context
Personal vault is a second-brain / Zettelkasten in Obsidian Flavored Markdown.
- OneDrive sync, NO git. Recovering from bad edits is hard. Be careful with edits and deletions. Track your changes so you can restore manually.
- No build, no tests, no package manager.
- Strict line breaks enabled.
- New files created in the current folder by default.
- Attachments live in
999-system/Attachments/. - Community plugins listed in
.obsidian/community-plugins.json.
Folder layout
001-Quick-Notes/ Fleeting notes, inbox
010-Daily/ Daily notes (Obsidian daily notes plugin)
011-personal/ Personal documentation and non-work long-term notes
020-work/ Work notes and project notes
project-notes/<name>/ - per-project, date-prefixed files
100-wiki/ LLM-maintained personal wiki - see second-brain skill
<category>/<topic>/ - dynamic folders, kebab-case
999-system/ Obsidian internals, archive, attachments, templates
Run tree -d -L 3 over the vault path for the live layout.
Prerequisites
Obsidian GUI must be open for the CLI to work. Assume it's running, and only try to open it if any of the commands fail:
open -a Obsidian
Only verify connectivity if commands fail: obsidian vault should return vault
info. If it fails, wait a few seconds after opening and retry.
Finding Existing Content
# Returns matching file paths only (like grep -l)
obsidian search query="auth middleware"
# Returns file:line: content for each match (like grep -n)
obsidian search:context query="auth middleware"
# Limit to a folder
obsidian search query="e2e tests" path="<folder>"
# List files in a folder
obsidian files folder="<folder>"
# Read a file
obsidian read path="<folder>/<note>.md"
Resolving the vault path
Default: obsidian vault info=path returns the active vault's absolute path.
Cache the result per session - don't re-shell every time.
VAULT=$(obsidian vault info=path)
Fallback: $SECOND_BRAIN_PATH env var. Use when CLI calls fail (Obsidian GUI
not running, subagent context, etc.).
Creating new files
Default: Write tool, not obsidian create.
Write <vault>/<folder>/<slug>.md
Why default to Write:
- Native diff in chat. Reviewable.
- No shell escaping, no heredoc, no
\t/\n/\rbug. - One tool call, not a 100-line bash invocation.
- Works whether Obsidian GUI is running or not.
Tradeoff: Obsidian indexes the file on its next vault scan (seconds). Wikilinks resolve fine - they're filename-based, not index-based.
When to use obsidian create instead
- You explicitly need its
template=<name>flag. - You want the file opened in the GUI immediately (
open,newtab). - Otherwise: prefer
Write.
If you do use it, pass content= via heredoc (<<'EOF') and remember:
- Without
overwrite, an existing path creates a duplicate (file 1.md). - The CLI interprets
\t/\n/\ras escape sequences incontent=. A literalpath\to\filebecomespath<tab>o\file. Fall back toWritewhen this hits.
Appending to Existing Files
obsidian append \
path="<folder>/<note>.md" \
content="\n## New Section\n\nAdditional findings here"
Editing and reading existing files
Default to direct file tools (Read, Edit, Write) for any file already on
disk. They give better diffs, user review, no shell escaping, and work whether
Obsidian GUI is running or not.
Reserve the obsidian CLI for what it uniquely offers: wikilink-aware
rename/move, vault-wide search, property edits, backlinks, history, and hygiene
commands.
Absolute path: prepend the vault path (see
Resolving the vault path) to any vault-relative
path returned by the CLI (e.g. Created: <folder>/note.md).
# Read
Read <vault>/<folder>/<note>.md
# Edit a section
Edit <vault>/<folder>/<note>.md
# Full rewrite
Write <vault>/<folder>/<note>.md
When to use obsidian append instead
Only when you need fire-and-forget append without reading context first:
obsidian append \
path="<folder>/<note>.md" \
content="\n## New Section\n\nContent here"
For anything structural (inserting mid-file, replacing a section, reordering),
use Read then Edit.
Links
Obsidian resolves wikilinks by filename only - not by title, aliases, or
headings. Aliases only help with autocomplete suggestions.
Internal links (wikilinks)
[[filename-without-ext]] [[filename-without-ext|Display Text]]
[[filename-without-ext#Heading]] [[#Heading in same note]]
Rules
- Always use pipe syntax for
relatedfrontmatter -"[[filename|Display Title]]"so the link resolves correctly and the display text stays human-readable. - Use
[[wikilinks]]for internal vault links - Obsidian tracks renames automatically. - Use
[text](url)only for external URLs. - No colons in wikilink display text - Obsidian creates files from these;
macOS/Windows forbid
:in filenames.
Example
related:
- '[[2026-03-17-my-note|My Note Title]]'
- '[anthropics/claude-code#100](https://github.com/anthropics/claude-code/issues/100)'
- '[RFC discussion](https://github.com/org/repo/discussions/42)'
See [[2026-03-17-my-note|My Note Title]] for details. Related:
[anthropics/claude-code#100](https://github.com/anthropics/claude-code/issues/100)
File operations
Move and rename
rename is preferred over move when only changing the name - Obsidian
auto-updates all wikilinks pointing to the file.
# Rename (updates all wikilinks automatically)
obsidian rename path="<folder>/old-name.md" \
name="new-name.md"
# Move to a different folder
obsidian move path="<folder>/<note>.md" \
to="<other-folder>/"
# Move and rename (to= is full destination path)
obsidian move path="<folder>/<note>.md" \
to="<other-folder>/new-name.md"
Delete
# Soft delete (moves to Obsidian trash)
obsidian delete path="<folder>/<note>.md"
# Permanent delete (skips trash)
obsidian delete path="<folder>/<note>.md" permanent
Property management
Set, read, or remove individual frontmatter properties without editing the whole
file. Useful for updating status, tags, etc.
# Read a property
obsidian property:read name="status" \
path="<folder>/<note>.md"
# Set a property
obsidian property:set name="status" value="completed" \
path="<folder>/<note>.md"
# Set with explicit type
obsidian property:set name="tags" value="neovim,lsp" \
type=list path="<folder>/<note>.md"
# Remove a property
obsidian property:remove name="aliases" \
path="<folder>/<note>.md"
Supported types: text, list, number, checkbox, date, datetime.
Navigation and linking
Backlinks and outgoing links
# List what links TO a note
obsidian backlinks path="<folder>/<note>.md"
# With link counts
obsidian backlinks path="<folder>/<note>.md" counts
# List outgoing links FROM a note
obsidian links path="<folder>/<note>.md"
Outline
Show heading structure of a note - useful before appending to find the right section.
obsidian outline path="<folder>/<note>.md"
# format: tree (default), md, json
obsidian outline path="<folder>/<note>.md" format=md
Tags
# List all tags in vault with counts
obsidian tags counts sort=count
# Get files for a specific tag
obsidian tag name="neovim" verbose
# List tags for a specific file
obsidian tags path="<folder>/<note>.md"
Vault hygiene
Find broken links, orphaned notes, and dead-end files.
# Files with no incoming links (orphans)
obsidian orphans
# Files with no outgoing links (dead ends)
obsidian deadends
# Broken/unresolved wikilinks
obsidian unresolved
# With source file info
obsidian unresolved verbose
Graph queries
The vault is a graph: notes are nodes, edges are wikilinks, tags, and frontmatter properties. The CLI exposes one-hop traversal natively. Multi-hop is composed via shell loops or via Bases.
Edges
- Wikilinks:
obsidian backlinks(incoming),obsidian links(outgoing). - Tags:
obsidian tag name="<tag>" verboselists all files carrying that tag (tag = many-to-many edge). - Properties:
obsidian properties name="<name>" countsfor frequency,obsidian property:readto read one cell.
Wikilinks resolve by filename only. aliases and title are autocomplete
sugar, not edges.
Multi-hop traversal
Compose shell loops. Output formats are tsv (default), csv, json.
# 2-hop: notes that link to anything `<note>` links to
for f in $(obsidian links file="<note>" | tail -n +2); do
obsidian backlinks file="$f" | tail -n +2
done | sort -u
# Notes sharing at least one tag with `<note>`
for t in $(obsidian tags file="<note>" | cut -f1); do
obsidian tag name="${t#\#}" verbose | tail -n +2
done | sort -u
Bases (saved queries)
.base files are Obsidian's database-views feature. They filter and group on
properties, tags, and link relations. Closest the CLI gets to a real query
layer.
# List all base files
obsidian bases
# Run a saved view, get JSON
obsidian base:query file="<base>" view="<view>" format=json
Use a Base when a query is reused often (e.g. "all type: comparison notes
tagged agent-memory"). For one-offs, shell loops are lighter.
See obsidian-bases for authoring .base files.
Limits
- No native path / shortest-path / weighted edges.
- No transitive closure built in - compose with loops.
- Edges are edited by editing markdown, not by a graph API.
Version history
Safety net for accidental overwrites. Obsidian tracks local file versions automatically.
# List files that have history
obsidian history:list
# List versions for a file
obsidian history path="<folder>/<note>.md"
# Read a specific version (1 = most recent)
obsidian history:read path="<folder>/<note>.md" \
version=1
# Diff between versions
obsidian diff path="<folder>/<note>.md" \
from=1 to=2
# Restore a version
obsidian history:restore path="<folder>/<note>.md" \
version=1
Working without the Obsidian CLI
Direct file tools are a superset of what the CLI can do for single-file operations. Use them:
- As the default for creating, reading, and editing files (see Creating new files and Editing and reading existing files)
- When Obsidian GUI is not running (CLI errors)
- In subagents or CI contexts where launching Obsidian is undesirable
- For bulk operations where
Glob/Grepis faster than vault search
What you lose by skipping the CLI:
rename/movewikilink auto-update (manual find-replace needed)- Property-level edits via
property:set - Version history tracking
- Vault-aware search (backlinks, orphans, unresolved)
# Resolve vault path once (see Resolving the vault path section)
VAULT=$(obsidian vault info=path) # primary
VAULT=${VAULT:-$SECOND_BRAIN_PATH} # env var fallback
# Create
Write $VAULT/<folder>/<slug>.md
# Edit
Edit $VAULT/<folder>/<note>.md
# Read
Read $VAULT/<folder>/<note>.md
# Search
Glob $VAULT/**/*.md
Grep "auth middleware" $VAULT/
Vault writing conventions
Apply to every note written into this vault (wiki, project memory, quick notes, daily, personal docs, etc.). Per-skill rules layer on top.
- Obsidian callouts (
> [!type]) for highlighted info. - 80-char line width. Unordered lists use
-(dash). - Code fences use short language identifiers (
md,ts,tsx,py,bash). - No em-dashes (
—) or en-dashes (–) - use-. - British English. No Oxford comma.
- For OFM syntax (wikilinks, embeds, callouts, properties), see
obsidian-markdownskill. - For general markdown formatting, see the
Markdownsection in your main agent instructions or from your context.
Sources convention
Applies to any note that cites sources (wiki pages, project-notes notes, any
long-form note). Goal: investigations stay reproducible. The note itself is the
comparison point if a source changes - retrieved dates anchor when the claims
were true.
Rules:
## Sourcessection at end of note, just above## Changelogif one exists.- Both
## Sourcesand any following## Changelogheading must be preceded by---on its own line. - Never put sources in frontmatter.
- External links (
[Title](https://...)) and internal wikilinks ([[clipped-article|Title]]) both valid. - Empty section is fine - keep the heading.
For new entries (any source cited while writing or updating today):
- Append
- retrieved YYYY-MM-DDto the parent bullet, today's date. - Add a nested bullet with a one-line note on what the source covers. No
Extracted:prefix.
If a pre-existing entry lacks the retrieved suffix or the nested note, add
them next time the source is re-consulted.
Example:
...
---
## Sources
- [Article Title](https://example.com/article) - retrieved 2026-04-21
- core tradeoff between X and Y
- [[clipped-article|Local Clipping]] - retrieved 2026-04-21
- full article preserved in vault
- [Legacy page](https://example.com/old)
- summary of what was used
---
## Changelog