create skill: silverbullet-query — SLIQ query/filter widgets for SilverBullet notes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
a26678119b
commit
d7dfb6c0e2
2 changed files with 184 additions and 0 deletions
170
silverbullet-query/SKILL.md
Normal file
170
silverbullet-query/SKILL.md
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
---
|
||||
name: silverbullet-query
|
||||
description: 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
|
||||
|
||||
1. Ask what objects they want (pages, tasks, items, tags, etc.)
|
||||
2. Ask what filter applies (folder prefix, tag, current page, a condition)
|
||||
3. Ask how to sort (newest first is `lastModified desc`, alphabetical is `p.name`)
|
||||
4. Ask if they want a limit
|
||||
5. Pick the right `templates.*` for the object type
|
||||
6. 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:
|
||||
|
||||
```space-lua
|
||||
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()}`
|
||||
Loading…
Add table
Add a link
Reference in a new issue