SKILL.md

  1---
  2name: using-silverbullet
  3description: Manages notes in SilverBullet/SB via the CLI and Space Lua. Use when the user mentions notes, SilverBullet, pages, journal, tasks in their space, or asks to search/read/write/edit notes.
  4license: GPL-3.0-or-later
  5metadata:
  6  author: Amolith <amolith@secluded.site>
  7---
  8
  9SilverBullet is a self-hosted Markdown note-taking app with a Lua scripting layer. Do not write top-level `# Titles`; SilverBullet puts the page title at the top of the page and `Title\n\n# Title` is redundant.
 10
 11# CLI
 12
 13`silverbullet-cli` executes Lua _on_ the remote SilverBullet instance in one of two modes:
 14
 15- `lua '<expr>'` — single expression, prints its return value
 16- `lua-script` — multi-statement script from file or stdin; use `return` for output (`print` is swallowed)
 17
 18```bash
 19# expression
 20silverbullet-cli lua 'space.readPage("index")'
 21
 22# multi-statement via stdin
 23echo '
 24local text = space.readPage("index")
 25text = string.gsub(text, "old", "new")
 26space.writePage("index", text)
 27return "done"
 28' | silverbullet-cli lua-script
 29```
 30
 31# Editing pages with plainReplace
 32
 33`string.gsub` treats the search string as a **Lua pattern**, not plain text. Characters like `-`, `.`, `%`, and so on are magic and silently break replacements. **Always use the `plainReplace` helper** instead of raw `string.gsub` for find/replace on page content:
 34
 35```lua
 36function plainReplace(str, old, new, n)
 37  old = old:gsub("[%^%$%(%)%%%.%[%]%*%+%-%?]", "%%%0")
 38  new = new:gsub("%%", "%%%%")
 39  if n == nil then
 40    return str:gsub(old, new)
 41  else
 42    return str:gsub(old, new, n)
 43  end
 44end
 45```
 46
 47Usage: `plainReplace(text, "arm64-v8a", "x86_64", 1)`
 48
 49# Operations
 50
 51```bash
 52# search (full-text, returns JSON with excerpts/scores/offsets)
 53silverbullet-cli lua 'silversearch.search("query", {silent=true})'
 54
 55# read
 56silverbullet-cli lua 'space.readPage("PageName")'
 57silverbullet-cli lua 'space.getPageMeta("PageName")'
 58
 59# query the object index (Lua Integrated Query)
 60silverbullet-cli lua 'query[[from p = index.tag "page" order by p.lastModified desc limit 10 select p.name]]'
 61
 62# find pages that link to a specific page
 63silverbullet-cli lua 'query[[from l = index.tag "link" where l.toPage == "TargetPage" select l.fromPage]]'
 64
 65# write / create
 66silverbullet-cli lua 'space.writePage("PageName", "# Title\nContent")'
 67
 68# delete
 69silverbullet-cli lua 'space.deletePage("PageName")'
 70
 71# edit one-liner
 72silverbullet-cli lua 'space.writePage("Page", plainReplace(space.readPage("Page"), "typo", "fixed"))'
 73
 74# multiple replacements
 75echo '
 76local function plainReplace(str, old, new, n)
 77  old = old:gsub("[%^%$%(%)%%%.%[%]%*%+%-%?]", "%%%0")
 78  new = new:gsub("%%", "%%%%")
 79  if n == nil then
 80    return str:gsub(old, new)
 81  else
 82    return str:gsub(old, new, n)
 83  end
 84end
 85local text = space.readPage("Title")
 86text = plainReplace(text, "mistake one", "correction one", 1) -- specify the replacement limit; you usually want 1
 87text = plainReplace(text, "mistake two", "correction two", 1)
 88space.writePage("Title", text)
 89return "done"
 90' | silverbullet-cli lua-script
 91
 92# writing multi-line markdown with lua-script
 93# Use long-string delimiters [==[...]==] instead of [[...]] when the
 94# markdown itself contains [[ or ]], which would prematurely close a
 95# plain Lua long string and cause syntax errors.
 96echo '
 97local text = [==[
 98Some content with [[wiki links]] and ${template directives}.
 99]==]
100space.writePage("PageName", text)
101return "done"
102' | silverbullet-cli lua-script
103```
104
105# Fetching SilverBullet docs
106
107The official SilverBullet instance at `silverbullet.md` serves raw Markdown pages. When you need details on any Space Lua feature, API, or concept, fetch the docs directly:
108
109```bash
110# Fetch a specific docs page (URL-encode spaces and slashes)
111silverbullet-cli lua 'net.readURI("https://silverbullet.md/.fs/Space%20Lua.md")'
112
113# List all docs pages to find what you need
114silverbullet-cli lua-script <<'EOF'
115local result = http.request("https://silverbullet.md/.fs", {
116  headers = { ["X-Sync-Mode"] = "true" }
117})
118local names = {}
119for _, p in ipairs(result.body) do
120  table.insert(names, p.name)
121end
122return table.concat(names, "\n")
123EOF
124```
125
126URL-encode page names (`%20` for spaces, `%2F` for `/`). The page listing is always current, so no hardcoded index is needed.
127
128---
129
130If `silverbullet-cli` is unavailable when you run it, read [references/installation.md] (folder is next to this file) and ask the user to install it.