Install
$ agentstack add skill-lexbritvin-obsidian-skills-pack-obsidian-dataview ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Dataview
Reference for authoring queries and scripts against the Obsidian Dataview plugin. Dataview indexes vault metadata (frontmatter, inline fields, tasks, links) and exposes it through four codeblock surfaces.
This file is the index. For deep coverage, consult the reference files (loaded only when relevant).
What Dataview is
A read-only metadata index. It scans the vault, builds a typed in-memory database from frontmatter + inline fields + tasks + the Obsidian link graph, and renders results back into notes through codeblocks. It does not modify files (the one exception: clicking a checkbox in a rendered TASK block toggles the underlying source, but DataviewJS code itself cannot write).
The four codeblock surfaces
| Surface | Fence | Use it for | |---|---|---| | DQL query | `dataview | Static, declarative views. Safer, faster to render, no JS required. | | DataviewJS | `dataviewjs | Anything DQL can't express: control flow, multi-step computation, custom DOM, awaiting dv.io/dv.query, custom views via dv.view. | | Inline DQL | ` = expr (default prefix =) | Single-value expression rendered inline mid-paragraph. | | **Inline JS DQL** | $= expr (default prefix $=) | Same idea, full dv` API available. |
JS surfaces are gated by the plugin's "Enable JavaScript Queries" toggle. Treat third-party DataviewJS as untrusted code — it has full vault read access.
Decision tree — DQL vs DataviewJS
Pick DQL unless one of these is true:
- The output needs
await(dv.query,dv.io.csv,dv.io.load,dv.view). - You want loops, mutable state, conditionals over the rendered output (e.g. one header per group, then a per-group table).
- You want to render a custom DOM structure or multiple sub-views in one block.
- The transformation needs intermediate variables that DQL can't express.
- You need to import a
dv.view("Scripts/foo", input)helper.
Otherwise DQL wins on conciseness, performance, and reactivity.
DQL — minimum viable shape
FROM
...
- Query type is mandatory and first:
TABLE,LIST,TASK,CALENDAR(withWITHOUT IDvariants forTABLE/LIST). FROMis optional but, if present, must come right after the query type (max one).WHERE,SORT,GROUP BY,FLATTEN,LIMITare repeatable and execute in the order written — order matters (e.g.LIMITbeforeSORTtruncates an unsorted set).
TABLE rating, file.mtime AS Modified
FROM #book
WHERE rating >= 7
SORT rating DESC
LIMIT 10
Full grammar, every data command, multi-clause behavior, source syntax, expression operators, literals, and gotchas → references/dql.md.
DataviewJS — the canonical shape
const pages = dv.pages('"Books"').where(p => p.rating >= 7);
for (const g of pages.groupBy(p => p.genre)) {
dv.header(3, g.key);
dv.table(
["Title", "Rating"],
g.rows.sort(p => p.rating, "desc").map(p => [p.file.link, p.rating])
);
}
Three things are always in scope:
dv— the API object (also aliaseddataview).this— the post-processor context (rarely needed directly).- Top-level
await— yes, it's allowed insidedataviewjs.
Full dv.* catalog (rendering, page access, queries, I/O, views, links, dates, evaluation), the DataArray method list, sync vs async cheatsheet, and end-to-end examples → references/dataviewjs.md.
What Dataview indexes
Every page exposes:
- Implicit
file.*fields —file.name,file.path,file.folder,file.link,file.size,file.ctime/cday,file.mtime/mday,file.tags(subtag-expanded),file.etags(no subtag expansion),file.inlinks,file.outlinks,file.aliases,file.tasks,file.lists,file.frontmatter,file.day,file.starred. - YAML frontmatter — every key is a field, types coerced (number, boolean, date, list, object, link).
- Inline fields — three syntaxes:
Key:: value(line form, key visible in Reader mode)[Key:: value](bracketed, embedable mid-line, key visible)(Key:: value)(parenthesized, key hidden in Reader mode)- Keys are normalized to lowercase + dashes (
Last Reviewed::→last-reviewed). - Tasks and list items — every
- []line, with auto-extracted fields (status,completed,fullyCompleted,text,due,scheduled,start,completion,created,children,link,section,tags,outlinks, …) and Tasks-plugin emoji shorthands (📅 ✅ ➕ 🛫 ⏳).
Full field type system, every file.* field, every task field, frontmatter vs inline rules, normalization edge cases → references/metadata.md.
Functions
Dataview exposes a rich function library, available in DQL directly and in DataviewJS via dv.func.. Categories: numeric (round, min, sum, reduce, minby, …), string (lower, regexreplace, containsword, split, truncate, …), list/object (length, contains, filter, map, unique, flat, extract, …), date (date, dateformat, striptime, dur, durationformat), constructors (object, list, link, embed, elink), utility (default, choice, typeof, meta, localtime, currencyformat, hash).
Every function with signature and one-line example → references/functions.md.
Common patterns and integration
Cookbook (open tasks across the vault, daily-note metric aggregation, leaderboards, custom dv.view helpers, link/section/block links, recursive task expansion, group-by then per-group table), settings that affect rendering, plugin-developer integration (getAPI(app), dataview:index-ready, dataview:metadata-change, dataview:refresh-views), performance notes, and the full caveats list → references/patterns.md.
Order of operations cheatsheet — DQL
- Query type picks what gets rendered (TABLE/LIST/TASK/CALENDAR).
FROMpicks the initial page set (single position, source-level booleansand/or/!).- Each subsequent clause runs on the previous output:
WHERE pred— filter (predicate-level booleans&&/||/!).SORT key [ASC|DESC], key2 [ASC|DESC]— multi-key only via comma; a secondSORTclause overwrites, doesn't tie-break.GROUP BY key— collapses rows into groups; thereafter onlykeyandrowsare addressable.FLATTEN field— explodes a list-valued field; reverses GROUP BY.LIMIT n— truncate; put it afterSORTfor top-N.
Common pitfalls
- Folders need double-quoting in
dv.pagesandFROM:dv.pages('"Books"'),FROM "Books". Never bare. FROMboolean syntax usesand/or/!/-.WHEREboolean syntax uses&&/||/!. Don't mix the two positions.LIMITbeforeSORTtruncates an unsorted set —SORT … LIMIT nis the top-N idiom.- Two
SORTclauses do not chain. The second resorts the already-sorted list, breaking nothing. UseSORT a ASC, b DESCfor tie-breaking. - After
GROUP BY, original-row fields disappear. Reach them viarows.(a list) orrows[0].. - Reserved names need bracket access —
row["where"],row["limit"]if a field name collides with a keyword. completed≠checked.completedis true only for[x].checkedis true for any non-blank status (/,-,>, etc.).- Tasks-plugin recurrence/priority/dependency emojis are NOT auto-promoted to fields. Only the date emojis (📅 ✅ ➕ 🛫 ⏳) are. To filter on
🔁/ priority /⛔use plain[recurrence:: weekly]-style annotations. - Frontmatter links must be quoted:
class: "[[Math]]", not bare[[Math]]. - Header chars
( ) / # [ ]in[[file#Heading]]break parsing — keep headings to plain text + dash separators. - Inline field keys are normalized:
**Bold Field**::→bold-field. Query the normalized form. dv.viewcannot read dot-prefixed folders (.scripts/). Throws "custom view not found".- Paths in
dv.ioanddv.vieware vault-rooted; passoriginFileto switch resolution. dv.queryreturnsResult— branch on.successfuland.value.type("list"/"table"/"task"/"calendar").dv.tryQuerythrows instead.- DataviewJS re-runs the whole script on every refresh. Hot expensive work belongs in
dv.viewfiles or external plugins, not inline.
Custom helper plugins
If the vault has a companion Obsidian plugin owning shared DataviewJS helpers (a common pattern — sometimes called a "vault toolkit"), prefer the toolkit accessor over duplicating logic across notes:
const tk = app.plugins.plugins["vault-toolkit"].api.dataview;
const rows = tk.data.loadByStatus(dv, '"Some/Folder"', { status: "active" });
tk.ui.progressBars(this.container, { bars: [...] });
The vault's own CLAUDE.md should document its toolkit conventions. The typical shape: inside a dataviewjs block keep three hardcoded values — the toolkit accessor, the source string (folder/tag), and any domain constants — and route everything else through the toolkit.
For one-off views inside a single note, plain dataviewjs is fine — keep blocks under ~70 lines or Obsidian's lazy-render leaves a gap until you scroll the block into view.
How to use this skill
- Identify the surface: DQL block, DataviewJS, inline DQL, inline JS, or external-plugin integration.
- For DQL: pick query type, build the source, append clauses in the right order. Consult
references/dql.mdfor syntax,references/functions.mdfor the function vocabulary,references/metadata.mdfor available fields. - For DataviewJS: lean on
references/dataviewjs.mdfor the API + DataArray methods. If the user wants a recurring helper, propose adv.viewfile or — if the vault has a custom toolkit plugin — a module on that. - When something doesn't render or returns empty, walk the "Common pitfalls" list above before spelunking — most issues are one of those.
- Keep blocks focused. If a single block grows past ~70 lines, suggest extracting helpers.
Source of truth for everything in this skill: .
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: lexbritvin
- Source: lexbritvin/obsidian-skills-pack
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.