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

And much, much more.

Learn more

Space Lua is documented in depth on silverbullet.md: