4.9 KiB
| name | description |
|---|---|
| silverbullet-query | Write Space Lua queries (SLIQ) for SilverBullet notes. Use this skill whenever the user wants to build a query, filter, or live view in their SilverBullet space — including filtering pages by folder or tag, listing tasks, showing recently modified notes, building dashboards, or embedding any kind of dynamic query widget in a note. Triggers on phrases like "make a query," "show all pages tagged," "build a filter," "list tasks in," "show recent notes," "create a silverbullet view," or "make a live widget." |
SilverBullet Query Skill
SilverBullet uses SLIQ (Space Lua Integrated Query) — an SQL-inspired query language embedded in Lua. Queries live inside ${...} expressions that render as live widgets in any note.
Quick reference
Embedding a query in a note
Queries render inline using the ${...} expression syntax:
${template.each(query[[
from p = index.tag "page"
where p.name:startsWith("proj/")
order by p.lastModified desc
]], templates.pageItem)}
Use template.each(collection, template) to render a list. Use query[[...]] alone when you just need the raw data or a single computed value.
Data sources
| What you want | from clause |
|---|---|
| All pages | from p = index.tag "page" |
| All tasks | from t = index.tag "task" |
| All bullet items | from i = index.tag "item" |
| All paragraphs | from p = index.tag "paragraph" |
| All tags | from t = index.tag "tag" |
| A Lua list | from n = {1, 2, 3} |
Always use the explicit variable binding form (p =) — it's more reliable and future-proof.
Filtering (where)
-- Pages in a folder
where p.name:startsWith("proj/")
-- Pages with a specific tag
where table.includes(p.tags, "account")
-- Pages matching name
where p.name:startsWith("Person")
-- Tasks on the current page only
where t.page == _CTX.currentPage.name
-- Combine conditions
where p.name:startsWith("proj/") and table.includes(p.tags, "active")
Sorting (order by)
order by p.lastModified desc -- newest first
order by p.lastModified asc -- oldest first
order by p.name -- alphabetical
order by p.lastModified desc, p.name -- multi-key
Nulls default to last (asc) or first (desc). Override with nulls first / nulls last.
Limits and offsets
limit 10
limit 10, 2 -- limit 10, skip first 2 (inline offset)
offset 5
Selecting / transforming results
select p.name -- just the name
select { name = p.name, mod = p.lastModified } -- custom object
select p -- full object (default)
Render templates
| Template | Renders as |
|---|---|
templates.pageItem |
* [[page name]] |
templates.fullPageItem |
* [[page name|page name]] |
templates.taskItem |
* [state] [[ref]] task text |
templates.itemItem |
* [[ref]] item text |
templates.paragraphItem |
* [[ref]] paragraph text |
templates.tagItem |
* [[tag:name|#name]] |
Common patterns
Pages in a folder, newest first
${template.each(query[[
from p = index.tag "page"
where p.name:startsWith("FOLDER/")
order by p.lastModified desc
]], templates.pageItem)}
Pages with a given tag
${template.each(query[[
from p = index.tag "page"
where table.includes(p.tags, "TAGNAME")
order by p.lastModified desc
]], templates.pageItem)}
Open tasks on the current page
${template.each(query[[
from t = index.tag "task"
where t.page == _CTX.currentPage.name and t.state == " "
]], templates.taskItem)}
5 most recently modified pages
${template.each(query[[
from p = index.tag "page"
order by p.lastModified desc
limit 5
]], templates.pageItem)}
Inline count (no template)
${#query[[from p = index.tag "page" where p.name:startsWith("proj/")]]} projects
How to write a query for the user
- Ask what objects they want (pages, tasks, items, tags, etc.)
- Ask what filter applies (folder prefix, tag, current page, a condition)
- Ask how to sort (newest first is
lastModified desc, alphabetical isp.name) - Ask if they want a limit
- Pick the right
templates.*for the object type - Wrap in
${template.each(...)}and drop it into the note
If the user already described the intent (e.g., "show all proj pages newest first"), skip the questions and just write it.
Placing the query
Queries go directly in the note as Markdown text — no fenced code block needed. The ${...} syntax renders on Alt-click (or view mode). Drop the expression on its own line for clean rendering.
If the user wants the query to live in a space-lua block as a reusable function rather than an inline expression, wrap it:
function myView()
return template.each(query[[
from p = index.tag "page"
where p.name:startsWith("proj/")
order by p.lastModified desc
]], templates.pageItem)
end
Then call it anywhere: ${myView()}