From 051effb8a708abed87b4ec03c64a5de737172c2c Mon Sep 17 00:00:00 2001 From: Amolith Date: Sun, 7 Jun 2026 15:12:06 -0600 Subject: [PATCH] Update SilverBullet skill CLI guidance Refresh the using-silverbullet skill to prefer current sb CLI patterns such as get, describe, and query. Keep Lua guidance for page bodies and edits where the CLI still needs Space Lua, and avoid documenting upgrade commands. --- SKILL.md | 188 ++++++++++++++++++++++++------------------------------- 1 file changed, 82 insertions(+), 106 deletions(-) diff --git a/SKILL.md b/SKILL.md index 99a1a1b1e974a2086d4008bed4e2ca7d19ae7511..61501c4543a5456b8766d9a729133ac1f22e9737 100644 --- a/SKILL.md +++ b/SKILL.md @@ -8,145 +8,121 @@ metadata: 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 +# Prefer the high-level CLI -`sb` executes Lua _on_ the remote SilverBullet instance. Use `sb --help` to explore available commands. +`sb` talks to a running SilverBullet instance through the Runtime API. Prefer `get`, `describe`, and `query` before dropping into Lua. Use `sb -h` for full flags and edge cases. -- `sb eval ''` — single expression, prints its return value -- `sb script` — multi-statement script from file (`-f`), inline argument, or stdin; use `return` for output (`print` is swallowed) -- `sb query ''` — runs Space Lua Integrated Query directly (wraps in `query[[...]]` for you) +Most useful commands: -```bash -# expression -sb eval '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" -' | sb script -``` - -# Editing pages with plainReplace +- `sb space ls`, `sb space add`, `sb space rm ` — manage saved space connections. Use `-s ` to select a space when more than one is configured. +- `sb get` — list indexed tag names in the space. +- `sb describe [tag]` — show query syntax and live schemas, e.g. `sb describe page` or `sb describe task`. +- `sb get [ref]` — list indexed objects or fetch one object by ref. For pages, the ref is the page name. +- `sb query ''` — run Space Lua Integrated Query; this wraps the argument in `query[[...]]`. +- `sb eval ''` — evaluate one Space Lua expression and print its return value. +- `sb script [code]`, `sb script -f file.lua`, or stdin — run multi-statement Space Lua. The positional argument is inline code, not a filename. +- `sb logs`, `sb logs -n 20`, `sb logs -f` — inspect or follow headless client logs. -`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 -``` +Use `--json` for parseable output, `-o jsonl` for line-oriented pipelines, and `--text` for human-readable output. `--text` is an output format, not “page text”. -Usage: `plainReplace(text, "arm64-v8a", "x86_64", 1)` +# Common operations -# Space Lua tripwires +```bash +# List recent page metadata +sb get page --sort-by lastModified:desc --limit 10 --select name,lastModified -- Space Lua APIs are camelCase: `space.readPage`, not `space.read_page`. -- Use `return`; `print()` output is swallowed. -- Don't chain `:gsub()` calls. `gsub` returns `(string, count)`, so reassign each step. -- Don't use `query` as a variable or parameter name; it can parse as LIQ syntax. -- The standard Lua `utf8` library is unavailable. -- In LIQ, use explicit binding: `from p = ...`. +# Find pages by name/prefix metadata +sb get page --where name:contains=meeting --select name,lastModified +sb get page --where name:startsWith=Journal/ --select name,lastModified -# Operations +# Fetch one page metadata object. This does NOT return the Markdown body. +sb get page "Journal/2026-06-07" --json -```bash -# search (full-text, returns JSON with excerpts/scores/offsets) -sb eval 'silversearch.search("query", {silent=true})' +# Read the Markdown body of a page +sb eval 'space.readPage("Journal/2026-06-07")' -# read -sb eval 'space.readPage("PageName")' -sb eval 'space.getPageMeta("PageName")' +# Full-text search; returns matches with excerpts, scores, and offsets +sb eval 'silversearch.search("search terms", {silent=true})' -# query the object index (Space Lua Integrated Query) -sb query 'from p = index.tag "page" order by p.lastModified desc limit 10 select p.name' +# Tasks: prefer get filters for routine list/filter/sort work +sb get task --where done=false --sort-by priority:desc --limit 20 +sb get task --where due:lte=2026-06-30 --where done=false -# find pages that link to a specific page +# Query when get cannot express the relationship sb query 'from l = index.tag "link" where l.toPage == "TargetPage" select l.fromPage' -# also available through eval, but the query wrapper is more convenient when sufficient -sb eval 'query[[from l = index.tag "link" where l.toPage == "TargetPage" select l.fromPage]]' +sb query 'from p = index.tag "page" order by p.lastModified desc limit 10 select p.name' -# write / create -sb eval 'space.writePage("PageName", "# Title\nContent")' +# Write/create only when asked to change the space +sb eval 'space.writePage("PageName", "Content without a duplicate top heading")' -# delete +# Delete only when explicitly asked sb eval 'space.deletePage("PageName")' +``` + +`sb get` supports `--where`, `-l/--selector`, `--sort-by`, `--limit`, `--offset`, and `--select`; run `sb get -h` rather than memorising every filter operator. + +# Editing pages safely -# edit one-liner -sb eval 'space.writePage("Page", plainReplace(space.readPage("Page"), "typo", "fixed"))' +`string.gsub` treats the search string as a Lua pattern, not plain text. Characters like `-`, `.`, and `%` are magic and can silently break replacements. Use a helper that returns only the replacement string: -# multiple replacements -echo ' +```lua local function plainReplace(str, old, new, n) old = old:gsub("[%^%$%(%)%%%.%[%]%*%+%-%?]", "%%%0") new = new:gsub("%%", "%%%%") + + local replaced if n == nil then - return str:gsub(old, new) + replaced = str:gsub(old, new) else - return str:gsub(old, new, n) + replaced = str:gsub(old, new, n) end + return replaced 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" -' | sb script - -# writing multi-line Markdown with sb script -# Use [==[...]==] instead of [[...]] when Markdown contains wiki links -# or templates. If the content contains ]==], use a regular quoted string -# with \n escapes or edit existing content with plainReplace instead. -echo ' -local text = [==[ -Some content with [[wiki links]] and ${template directives}. -]==] -space.writePage("PageName", text) -return "done" -' | sb script - -# If multi-line content ends with ]] immediately before the closing ]==], -# add a newline before the close and trim it off. -echo ' -local text = [==[ -Ends with [[Page]] -]==]:sub(1, -2) -space.writePage("PageName", text) -return "done" -' | sb 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: +Use `sb script` for multi-step edits: ```bash -# Fetch a specific docs page (URL-encode spaces and slashes) -sb eval 'net.readURI("https://silverbullet.md/.fs/Space%20Lua.md")' - -# List all docs pages to find what you need sb 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) +local function plainReplace(str, old, new, n) + old = old:gsub("[%^%$%(%)%%%.%[%]%*%+%-%?]", "%%%0") + new = new:gsub("%%", "%%%%") + + local replaced + if n == nil then + replaced = str:gsub(old, new) + else + replaced = str:gsub(old, new, n) + end + return replaced end -return table.concat(names, "\n") + +local text = space.readPage("PageName") +text = plainReplace(text, "old literal text", "new literal text", 1) +space.writePage("PageName", text) +return "done" EOF ``` -URL-encode page names (`%20` for spaces, `%2F` for `/`). The page listing is always current, so no hardcoded index is needed. +For multi-line Markdown literals, prefer `[==[...]==]` over `[[...]]` so wiki links and templates do not terminate the string accidentally. If the content itself contains `]==]`, use a normal quoted string with `\n` escapes or edit existing content with `plainReplace`. ---- +# Space Lua tripwires + +- Space Lua APIs are camelCase: `space.readPage`, not `space.read_page`. +- Use `return`; `print()` output is swallowed. +- Do not chain `:gsub()` calls. `gsub` returns `(string, count)`, so reassign each step. +- Do not use `query` as a variable or parameter name; it can parse as SLIQ syntax. +- The standard Lua `utf8` library is unavailable. +- In SLIQ, use explicit binding: `from p = ...`. +- Use current command names: `eval` and `script`. Old `lua`/`lua-script` aliases are hidden compatibility shims. + +# SilverBullet docs + +The official docs space serves raw Markdown pages. Fetch docs directly when you need detail on Space Lua, SLIQ, or the CLI: + +```bash +curl -fsSL 'https://silverbullet.md/.fs/CLI.md' +curl -fsSL 'https://silverbullet.md/.fs/Space%20Lua.md' +``` -If `sb` is unavailable when you run it, fetch the contents of https://silverbullet.md/.fs/CLI.md to read the installation instructions yourself and link the user to https://silverbullet.md/CLI so they can read it too. If they use mise.jdx.dev, the line to add to their global config is `"github:silverbulletmd/silverbullet" = "latest"` and the binary they want is `sb`. +URL-encode page names (`%20` for spaces, `%2F` for `/`). If `sb` is unavailable, read `https://silverbullet.md/.fs/CLI.md` yourself and link the user to `https://silverbullet.md/CLI`.