Space Lua
Space Lua is the scripting language built into SilverBullet. It’s a custom dialect of Lua — the same language that powers Neovim, Redis, World of Warcraft addons, and a long list of other tools. In SilverBullet, it’s the magic sauce that turns a (seemingly) minimalist markdown editor into a programmable, queryable power house.
You don’t need to know Lua to use SilverBullet. You can write notes, link them, tag them, and be happy. But the moment you want more — a custom dashboard, a dynamic query, a command that automates a workflow — Space Lua is right there, waiting. Expecting.
How it works
Space Lua adds two things to SilverBullet’s markdown dialect:
space-lua code blocks
Fenced code blocks tagged space-lua are loaded and executed automatically across your entire space. Functions and variables you define are available everywhere. Want a custom command to greet you? Add a space-lua block on any page, reload and it will become available from anywhere.
```space-lua
command.define {
name = "Hello world!",
key = "Ctrl-Shift-h",
run = function()
editor.flashNotification "Hello world!"
end
}
```
Lua ${expression} live preview
Inline Lua expressions are evaluated and rendered in place as you’re editing. This is how SilverBullet’s queries (see below) work — you drop a ${query[[ ... ]]} into any page, and results are rendered inline.
Language Integrated Query
The most powerful Space Lua language extension is Space Lua Integrated Query (SLIQ) — a SQL-like query language that lets you query any type of collection of objects, including pages, tasks, links and many other things.
The basics
All the pages in your space are accessible via the tags.page collection and can be filtered now and sorted from there:
${query[[
from p = tags.page
order by p.lastModified desc
select p.name
limit 3
]]}
Filtering with where
Narrow results with conditions, just like SQL:
${query[[
from p = tags.page
where p.name:startsWith("Meeting")
]]}
Transforming with select
Shape the output as you like with select, tabular data will render as tables, use templates to do fancier things.
For instance to show all page names and their file sizes in a table:
${query[[
from p = tags.page
select { name = p.name, size = p.size }
limit 5
]]}
Grouping and aggregation
Group results and compute aggregates — count, sum, min, max, avg:
${query[[
from p = tags.tag
group by p.name
select { tag = name, count = #group }
order by count desc
limit 5
]]}
You can filter aggregates with having, use per-aggregate filter(where ...), and even control ordering within aggregates:
${query[[
from p = tags.page
group by p.tags[1]
having count(p.name) > 2
select {
tag = key,
total = count(p.name),
biggest = max(p.size)
}
order by total desc
]]}
Rendering with templates
Combine queries with templates for rich output:
${query[[
from t = tags.task
where not t.done
order by t.pageLastModified
desc limit 10
select templates.taskItem(t)
]]}
Queries update live as your data changes. Write once, stay current forever.
What you can build
- Queries as described above
- Custom commands: create custom editor commands accessible via the command palette or via custom keyboard shortcuts
- Widgets: inline rendered components
- Event listeners: react to things happening in the editor
- Tag definitions: define custom tags with schemas and other fanciness
And much, much more.
Learn more
Space Lua is documented in depth on silverbullet.md: