Query your vault with bases
A base is a small, line-oriented query over your vault's notes —
"every note under Tasks/ with status is active, sorted by last
modified" — saved as a .base file so the view stays live. The grammar is
implemented once and shared by the desktop Bases
surface, the base_query MCP tool, and inline where: filters in search —
so a query you write here behaves identically everywhere it runs.
The grammar
from notes
where <field> <op> <value> [or <field> <op> <value> ...]
sort <field> [asc|desc]
columns a, b, c
group by <field>
view table|list|cards|kanban|graph
limit N
- Keywords are case-insensitive;
#starts a comment line. - Multiple
wherelines AND together;orjoins predicates within one line (a quoted value containing the literal text " or " is never split). columnstakes at most 6 fields (a parse error above that).sortdefaults toascif you omit the direction.
Fields
Any frontmatter key, plus four meta fields:
| Field | Meaning |
|---|---|
__title |
The note's title. |
__path |
Its vault-relative path. |
__modified |
Last-modified timestamp. |
__folder (alias folder) |
The note's containing directory (dirname of its path). |
The __ prefix matters: a bare title in your frontmatter is a different
field from the meta __title.
Values
Double-quoted strings ("active"), a single bare word (active — quotes
optional only when there's no whitespace), numbers, or true/false. A
value containing spaces must be quoted, or it's a parse error.
Operators
| Op | Meaning |
|---|---|
is / is not |
Case-insensitive equality (or negation). Against an array field, matches if any element equals the value. |
contains / not contains |
Case-insensitive substring match over the stringified value. |
exists / missing |
No value needed. "Missing" covers absent, null, an empty array, or a blank string. |
gt / gte / lt / lte |
Numeric comparison. Numeric strings parse leniently on the note side; against __modified the value may also be an ISO-8601 date ("2024-06-01") or an epoch-ms number. |
under |
Folder-hierarchy prefix: the field equals the value, or sits nested below it. Most useful on folder/__path — where folder under "Projects" matches Projects/Atlas.md and Projects/Sub/Deep.md, but is not a plain substring match (under "Proj" matches nothing — it must land on a folder-segment boundary). |
A worked example: an inbox triage view
from notes
where folder under "Tasks"
where status is "active" or status missing
sort __modified desc
columns title, status, __modified
view table
limit 50
This is a live table of everything under Tasks/ that's either explicitly
active or hasn't been given a status yet, newest-first, capped at 50 rows
— exactly the kind of view you'd want sitting at the top of an inbox-triage
workflow (pair it with [[Triage your inbox with an agent]] to work the list
down).
Another common one — a folder-grouped kanban of everything with a status:
from notes
where status exists
group by folder
view kanban
Saving and running it
- In the desktop app's Bases surface, write the query and use
Save to vault — it normalizes your filename into a canonical
Bases/<name>.basepath (a bare name defaults intoBases/; a trailing.baseyou type is stripped and re-added)..basefiles are the same format Obsidian uses, so a vault's bases are interoperable both ways. - An agent or an MCP client can run the identical grammar without a saved
file via the
base_querytool — pass{ "dsl": "<the query text>" }and get back{ view, columns, group_by, sort, limit, rows, error }. A parse or eval failure comes back as a structurederror: { message, line }in the result, never a thrown tool error, so a widget or agent can render the problem instead of crashing. - The same
wheregrammar also works inline inside the regular vaultsearchtool'swhereparameter, ANDed onto whatever text/regex query you're already running.
See also
- Solomon's
Bases/folder in your own vault, once you've saved a query, to see the canonical.basefile shape. - [[Triage your inbox with an agent]] — pair a live base view with an agent pass over the same notes.
- [[Bases and widgets]] — the concept page behind the grammar, plus how a widget can wire itself to a base query.
- [[MCP tool surface]] — the
base_querytool an agent or MCP client calls to run the identical grammar.