diff --git a/skills/using-silverbullet/SKILL.md b/skills/using-silverbullet/SKILL.md new file mode 100644 index 0000000000000000000000000000000000000000..8c63f5c35c0443e2c1e2850ce6bc1737af59cce1 --- /dev/null +++ b/skills/using-silverbullet/SKILL.md @@ -0,0 +1,126 @@ +--- +name: using-silverbullet +description: 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. +license: GPL-3.0-or-later +metadata: + author: Amolith +--- + +SilverBullet 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. + +# CLI + +`silverbullet-cli` executes Lua _on_ the remote SilverBullet instance in one of two modes: + +- `lua ''` — single expression, prints its return value +- `lua-script` — multi-statement script from file or stdin; use `return` for output (`print` is swallowed) + +```bash +# expression +silverbullet-cli lua 'space.readPage("index")' + +# multi-statement via stdin +echo ' +local text = space.readPage("index") +text = string.gsub(text, "old", "new") +space.writePage("index", text) +return "done" +' | silverbullet-cli lua-script +``` + +# Editing pages with plainReplace + +`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: + +```lua +function plainReplace(str, old, new, n) + old = old:gsub("[%^%$%(%)%%%.%[%]%*%+%-%?]", "%%%0") + new = new:gsub("%%", "%%%%") + if n == nil then + return str:gsub(old, new) + else + return str:gsub(old, new, n) + end +end +``` + +Usage: `plainReplace(text, "arm64-v8a", "x86_64", 1)` + +# Operations + +```bash +# search (full-text, returns JSON with excerpts/scores/offsets) +silverbullet-cli lua 'silversearch.search("query", {silent=true})' + +# read +silverbullet-cli lua 'space.readPage("PageName")' +silverbullet-cli lua 'space.getPageMeta("PageName")' + +# query the object index (Lua Integrated Query) +silverbullet-cli lua 'query[[from p = index.tag "page" order by p.lastModified desc limit 10 select p.name]]' + +# find pages that link to a specific page +silverbullet-cli lua 'query[[from l = index.tag "link" where l.toPage == "TargetPage" select l.fromPage]]' + +# write / create +silverbullet-cli lua 'space.writePage("PageName", "# Title\nContent")' + +# delete +silverbullet-cli lua 'space.deletePage("PageName")' + +# edit one-liner +silverbullet-cli lua 'space.writePage("Page", plainReplace(space.readPage("Page"), "typo", "fixed"))' + +# multiple replacements +echo ' +local function plainReplace(str, old, new, n) + old = old:gsub("[%^%$%(%)%%%.%[%]%*%+%-%?]", "%%%0") + new = new:gsub("%%", "%%%%") + if n == nil then + return str:gsub(old, new) + else + return str:gsub(old, new, n) + end +end +local text = space.readPage("Title") +text = plainReplace(text, "mistake one", "correction one", 1) -- specify the replacement limit; you usually want 1 +text = plainReplace(text, "mistake two", "correction two", 1) +space.writePage("Title", text) +return "done" +' | silverbullet-cli lua-script + +# writing multi-line markdown with lua-script +# Use long-string delimiters [==[...]==] instead of [[...]] when the +# markdown itself contains [[ or ]], which would prematurely close a +# plain Lua long string and cause syntax errors. +echo ' +local text = [==[ +Some content with [[wiki links]] and ${template directives}. +]==] +space.writePage("PageName", text) +return "done" +' | silverbullet-cli lua-script +``` + +# Fetching SilverBullet docs + +The 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: + +```bash +# Fetch a specific docs page (URL-encode spaces and slashes) +silverbullet-cli lua 'net.readURI("https://silverbullet.md/.fs/Space%20Lua.md")' + +# List all docs pages to find what you need +silverbullet-cli lua-script <<'EOF' +local result = http.request("https://silverbullet.md/.fs", { + headers = { ["X-Sync-Mode"] = "true" } +}) +local names = {} +for _, p in ipairs(result.body) do + table.insert(names, p.name) +end +return table.concat(names, "\n") +EOF +``` + +URL-encode page names (`%20` for spaces, `%2F` for `/`). The page listing is always current, so no hardcoded index is needed.