Obsidian Skill
Comprehensive skill for working with Obsidian vaults. Covers four domains:
| Domain | When to use | Key references |
|---|---|---|
| Markdown | Creating/editing .md notes with wikilinks, callouts, embeds, properties, tags | callouts, embeds, properties |
| Bases | Creating/editing .base files with views, filters, formulas | functions |
| CLI | Interacting with vaults via obsidian command, plugin dev |
(inline below) |
| Web Clipper | Creating importable JSON templates for the Obsidian Web Clipper | variables, filters, json-schema, logic, analysis, bases-workflow |
Official docs: For edge cases or details beyond this skill, consult the Official Documentation Index — curated from help.obsidian.md covering Bases, Editing, Web Clipper, CLI, and Linking.
Obsidian Flavored Markdown
Create and edit valid Obsidian Flavored Markdown. Obsidian extends CommonMark and GFM with wikilinks, embeds, callouts, properties, comments, and other syntax. Standard Markdown (headings, bold, italic, lists, quotes, code blocks, tables) is assumed knowledge.
Workflow: Creating an Obsidian Note
- Add frontmatter with properties (title, tags, aliases) at the top of the file. See references/markdown-properties.md for all property types.
- Write content using standard Markdown for structure, plus Obsidian-specific syntax below.
- Link related notes using wikilinks (
[[Note]]) for internal vault connections, or standard Markdown links for external URLs. - Embed content from other notes, images, or PDFs using the
![[embed]]syntax. See references/markdown-embeds.md for all embed types. - Add callouts for highlighted information using
> [!type]syntax. See references/markdown-callouts.md for all callout types. - Verify the note renders correctly in Obsidian's reading view.
When choosing between wikilinks and Markdown links: use
[[wikilinks]]for notes within the vault (Obsidian tracks renames automatically) and[text](url)for external URLs only.
Internal Links (Wikilinks)
[[Note Name]] Link to note
[[Note Name|Display Text]] Custom display text
[[Note Name#Heading]] Link to heading
[[Note Name#^block-id]] Link to block
[[#Heading in same note]] Same-note heading link
Define a block ID by appending ^block-id to any paragraph. For lists and quotes, place the block ID on a separate line after the block.
Embeds
Prefix any wikilink with ! to embed its content inline:
![[Note Name]] Embed full note
![[Note Name#Heading]] Embed section
![[image.png]] Embed image
![[image.png|300]] Embed image with width
![[document.pdf#page=3]] Embed PDF page
See references/markdown-embeds.md for audio, video, search embeds, and external images.
Callouts
> [!note]
> Basic callout.
> [!warning] Custom Title
> Callout with a custom title.
> [!faq]- Collapsed by default
> Foldable callout (- collapsed, + expanded).
Common types: note, tip, warning, info, example, quote, bug, danger, success, failure, question, abstract, todo.
See references/markdown-callouts.md for the full list with aliases, nesting, and custom CSS callouts.
Properties (Frontmatter)
---
title: My Note
date: 2024-01-15
tags:
- project
- active
aliases:
- Alternative Name
cssclasses:
- custom-class
---
Default properties: tags (searchable labels), aliases (alternative note names for link suggestions), cssclasses (CSS classes for styling).
See references/markdown-properties.md for all property types, tag syntax rules, and advanced usage.
Tags
#tag Inline tag
#nested/tag Nested tag with hierarchy
Tags can contain letters, numbers (not first character), underscores, hyphens, and forward slashes. Tags can also be defined in frontmatter under the tags property.
Other Obsidian Syntax
- Comments:
%%hidden text%%(inline) or%%\nblock\n%%(block, hidden in reading view) - Highlighting:
==highlighted text== - Math (LaTeX): Inline
$e^{i\pi} + 1 = 0$, block$$\frac{a}{b} = c$$ - Mermaid diagrams: Use
```mermaidcode blocks. Link nodes to notes withclass NodeName internal-link; - Footnotes:
Text[^1]with[^1]: Content.or inline^[This is inline.]
Complete Example
---
title: Project Alpha
date: 2024-01-15
tags: [project, active]
status: in-progress
---
# Project Alpha
This project aims to [[improve workflow]] using modern techniques.
> [!important] Key Deadline
> The first milestone is due on ==January 30th==.
- [x] Initial planning
- [ ] Development phase
The algorithm uses $O(n \log n)$ sorting. See [[Algorithm Notes#Sorting]] for details.
![[Architecture Diagram.png|600]]
Official docs: Obsidian Flavored Markdown, Links, Embeds, Callouts, Properties
Obsidian Bases
Workflow
- Create the file: Create a
.basefile in the vault with valid YAML content - Define scope: Add
filtersto select which notes appear (by tag, folder, property, or date) - Add formulas (optional): Define computed properties in the
formulassection - Configure views: Add one or more views (
table,cards,list, ormap) withorderspecifying which properties to display - Validate: Verify the file is valid YAML with no syntax errors. Check that all referenced properties and formulas exist. Common issues: unquoted strings containing special YAML characters, mismatched quotes in formula expressions, referencing
formula.Xwithout definingXinformulas - Test in Obsidian: Open the
.basefile in Obsidian to confirm the view renders correctly. If it shows a YAML error, check quoting rules below
Schema
Base files use the .base extension and contain valid YAML.
# Global filters apply to ALL views in the base
filters:
and: []
or: []
not: []
# Define formula properties that can be used across all views
formulas:
formula_name: 'expression'
# Configure display names and settings for properties
properties:
property_name:
displayName: "Display Name"
formula.formula_name:
displayName: "Formula Display Name"
file.ext:
displayName: "Extension"
# Define custom summary formulas
summaries:
custom_summary_name: 'values.mean().round(3)'
# Define one or more views
views:
- type: table | cards | list | map
name: "View Name"
limit: 10 # Optional: limit results
groupBy: # Optional: group results
property: property_name
direction: ASC | DESC
filters: # View-specific filters
and: []
order: # Properties to display in order
- file.name
- property_name
- formula.formula_name
summaries: # Map properties to summary formulas
property_name: Average
Filter Syntax
Filters narrow down results. They can be applied globally or per-view.
# Single filter
filters: 'status == "done"'
# AND - all conditions must be true
filters:
and:
- 'status == "done"'
- 'priority > 3'
# OR - any condition can be true
filters:
or:
- 'file.hasTag("book")'
- 'file.hasTag("article")'
# NOT - exclude matching items
filters:
not:
- 'file.hasTag("archived")'
# Nested: combine and/or/not
filters:
or:
- file.hasTag("tag")
- and:
- file.hasTag("book")
- file.hasLink("Textbook")
Filter Operators: == (equals), != (not equal), >, <, >=, <=, && (logical and), || (logical or), ! (logical not)
Properties
Three types:
- Note properties - From frontmatter:
note.authoror justauthor - File properties - File metadata:
file.name,file.mtime, etc. - Formula properties - Computed values:
formula.my_formula
File Properties Reference:
| Property | Type | Description |
|---|---|---|
file.name |
String | File name |
file.basename |
String | File name without extension |
file.path |
String | Full path to file |
file.folder |
String | Parent folder path |
file.ext |
String | File extension |
file.size |
Number | File size in bytes |
file.ctime |
Date | Created time |
file.mtime |
Date | Modified time |
file.tags |
List | All tags in file |
file.links |
List | Internal links in file |
file.backlinks |
List | Files linking to this file |
file.embeds |
List | Embeds in the note |
file.properties |
Object | All frontmatter properties |
The this Keyword: In main content area refers to the base file itself. When embedded, refers to the embedding file. In sidebar, refers to the active file.
Formula Syntax
Formulas compute values from properties. Defined in the formulas section.
formulas:
total: "price * quantity"
status_icon: 'if(done, "✅", "⏳")'
formatted_price: 'if(price, price.toFixed(2) + " dollars")'
created: 'file.ctime.format("YYYY-MM-DD")'
days_old: '(now() - file.ctime).days'
days_until_due: 'if(due_date, (date(due_date) - today()).days, "")'
Key Functions
Most commonly used functions. For the complete reference of all types (Date, String, Number, List, File, Link, Object, RegExp), see references/bases-functions.md.
| Function | Signature | Description |
|---|---|---|
date() |
date(string): date |
Parse string to date (YYYY-MM-DD HH:mm:ss) |
now() |
now(): date |
Current date and time |
today() |
today(): date |
Current date (time = 00:00:00) |
if() |
if(condition, trueResult, falseResult?) |
Conditional |
duration() |
duration(string): duration |
Parse duration string |
file() |
file(path): file |
Get file object |
link() |
link(path, display?): Link |
Create a link |
Duration Type: When subtracting two dates, the result is a Duration type (not a number). Fields: .days, .hours, .minutes, .seconds, .milliseconds. Duration does NOT support .round(), .floor(), .ceil() directly — access a numeric field first, then apply number functions.
# CORRECT
"(date(due_date) - today()).days" # Returns number of days
"(now() - file.ctime).days.round(0)" # Rounded days
# WRONG - will cause error:
# "((date(due) - today()) / 86400000).round(0)" # Duration doesn't support division
Date Arithmetic: Duration units: y/year/years, M/month/months, d/day/days, w/week/weeks, h/hour/hours, m/minute/minutes, s/second/seconds.
View Types
Table is the most common view type:
views:
- type: table
name: "My Table"
order:
- file.name
- status
- due_date
summaries:
price: Sum
count: Average
Other view types: Cards (gallery/card layout), List (simple list), Map (requires lat/lng properties and Maps community plugin). All use the same order, filters, groupBy, and summaries options.
Default Summary Formulas
| Name | Input Type | Description |
|---|---|---|
Average |
Number | Mathematical mean |
Min / Max / Sum / Range / Median / Stddev |
Number | Standard aggregations |
Earliest / Latest |
Date | Date range |
Checked / Unchecked |
Boolean | Count of true/false values |
Empty / Filled / Unique |
Any | Count of empty, non-empty, or unique values |
For complete examples (Task Tracker, Reading List, Daily Notes Index), see references/bases-examples.md.
Embedding Bases
![[MyBase.base]]
![[MyBase.base#View Name]]
YAML Quoting Rules
- Use single quotes for formulas containing double quotes:
'if(done, "Yes", "No")' - Use double quotes for simple strings:
"My View Name" - Escape nested quotes properly in complex expressions
Troubleshooting
- Unquoted special chars: Strings with
:,{,},[,], etc. must be quoted. E.g.displayName: "Status: Active" - Mismatched quotes: Formulas with double quotes must be wrapped in single quotes
- Duration math: Subtracting dates returns Duration, not a number — always access
.days,.hours, etc. first - Missing null checks: Use
if()to guard:'if(due_date, (date(due_date) - today()).days, "")' - Undefined formulas: Every
formula.Xinorder/propertiesneeds a matchingformulasentry
Official docs: Bases Syntax, Functions, Views. Full function reference: references/bases-functions.md.
Obsidian CLI
Use the obsidian CLI to interact with a running Obsidian instance. Requires Obsidian to be open.
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 use =: obsidian create name="My Note" content="Hello world". Quote values with spaces.
Flags are boolean switches: obsidian create name="My Note" silent overwrite. Use \n for newlines, \t for tabs.
Targeting
- File:
file=<name>(resolves like wikilink) orpath=<path>(exact vault-root path). Without either, targets the active file. - Vault:
vault=<name>as first parameter targets a specific vault (defaults to most recently focused).
Common patterns
obsidian read file="My Note"
obsidian create name="New Note" content="# Hello" 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 tasks daily todo
obsidian tags sort=count counts
obsidian backlinks file="My Note"
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.
Plugin development
After making code changes to a plugin or theme:
obsidian plugin:reload id=my-plugin # 1. Reload plugin
obsidian dev:errors # 2. Check for errors
obsidian dev:screenshot path=screenshot.png # 3. Verify visually
obsidian dev:dom selector=".workspace-leaf" text
obsidian dev:console level=error # 4. Check console output
Additional developer commands:
obsidian eval code="app.vault.getFiles().length" # Run JavaScript
obsidian dev:css selector=".workspace-leaf" prop=background-color # Inspect CSS
obsidian dev:mobile on # Toggle mobile emulation
Run obsidian help for additional developer commands including CDP and debugger controls.
Web Clipper Templates
This section helps you create importable JSON templates for the Obsidian Web Clipper.
Workflow
- Identify User Intent: specific site (YouTube), specific type (Recipe), or general clipping?
- Check Existing Bases: Read
Bases/*.baseto find a matching category and use its properties to structure the template. See references/clipper-bases-workflow.md. - Fetch & Analyze Reference URL: (REQUIRED) Use WebFetch to retrieve page content. Analyze HTML for Schema.org JSON-LD, Meta tags, and CSS selectors. Verify each selector against the fetched content — never guess selectors. See references/clipper-analysis-workflow.md.
- Draft the JSON: Create a valid JSON object per references/clipper-json-schema.md.
- Consider template logic: Conditionals, loops, variable assignment, and fallbacks. Keep simple templates simple. See references/clipper-logic.md.
- Verify Variables: Ensure chosen variables (Preset, Schema, Selector) exist in your analysis. If a selector cannot be verified, state that explicitly and ask for another URL. See references/clipper-variables.md.
Selector Verification Rules
- Always verify selectors against live page content before responding.
- Never guess selectors. If the DOM cannot be accessed or the element is missing, ask for another URL or a screenshot.
- Prefer stable selectors (data attributes, semantic roles, unique IDs) over fragile class chains.
- Document the target element in your reasoning (e.g., "About sidebar paragraph") to reduce mismatch.
Output Format
ALWAYS output the final result as a JSON code block that the user can copy and import.
The Clipper template editor validates template syntax. If you use template logic (conditionals, loops, variable assignment), ensure it follows the syntax in references/clipper-logic.md and the official Logic docs so the template passes validation.
{
"schemaVersion": "0.1.0",
"name": "My Template",
...
}
Clipper Resources
References: variables, filters, json-schema, logic, bases-workflow, analysis-workflow. Example templates: assets/.