# \[space-lua\] Command to update silverbullet-libraries

**URL:** <https://community.silverbullet.md/t/space-lua-command-to-update-silverbullet-libraries/3421>\
**Category:** General\
**Created:** [October 19, 2025, 7:42pm UTC](https://community.silverbullet.md/t/space-lua-command-to-update-silverbullet-libraries/3421 "2025-10-19T19:42:46Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Mr.Red](https://community.silverbullet.md/user_avatar/community.silverbullet.md/mr.red/32/821_2.png) [@Mr.Red](https://community.silverbullet.md/u/Mr.Red)\
**Post date:** [October 19, 2025, 7:42pm UTC](https://community.silverbullet.md/t/space-lua-command-to-update-silverbullet-libraries/3421/1 "2025-10-19T19:42:47Z")

</div>

Here is my first attempt to make an Update Library command for your imported libraries, for the **currently opened page**.

Like I mentioned in the General chat: this is my first attempt, and the error check is not that complex. it only does some basic safety checks.  
How it currently works:

- Gets the current page and reads its `githubUrl` from frontmatter.
- Converts the GitHub link to a raw URL.
- Fetches the latest file content from GitHub.
- Replaces the page content (adding the URL back to the frontmatter).
- Saves and reloads the updated page.

```lua
command.define {
  name = "Import: Update library for current page from GitHub",
  key = "Ctrl-Alt-u",
  mac = "Cmd-Alt-u",
  run = function()
    local page = editor.getCurrentPage()
    if not page then
      editor.flashNotification("No page open to update", "error")
      return
    end

 -- get current text and original frontmatter block (raw)
    local original_text = editor.getText() or ""

    local parsed = index.extractFrontmatter(original_text)
    local fm = parsed.frontmatter or {}
    local url = fm.githubUrl
    local frontmatter = '---\ngithubUrl: "'.. url ..'"\n---'
    
    if not url or url == "" then
      editor.flashNotification("⚠️ No 'githubUrl' found in frontmatter", "error")
      return
    end

    -- Convert GitHub URL to raw URL
    local rawUrl = url
    rawUrl = rawUrl:gsub("^https://github%.com/", "https://raw.githubusercontent.com/")
    rawUrl = rawUrl:gsub("/blob/", "/")
    rawUrl = rawUrl:gsub("/tree/", "/")

    editor.flashNotification("Fetching latest version from GitHub…")

    local req = http.request(rawUrl)
    if not req.ok then
      js.log("Failed to fetch " .. rawUrl)
      editor.flashNotification("⚠️ Update failed: could not fetch remote file", "error")
      return
    end

    local newContent = req.body or ""
    if newContent == "" then
      editor.flashNotification("⚠️ Fetched content is empty.", "error")
      return
    end

    local final = nil
    if fm and fm ~= "" then
      final = frontmatter .. "\n\n" .. newContent
    else
      final = newContent
    end

    -- write back and navigate
    space.writePage(page, final)
    editor.flashNotification("✅ Page updated from GitHub")
    editor.navigate({ kind = "page", page = page })
  end
}

```

It will do following safety checks:

- Checks if a page is open (duh).
- Verifies that githubUrl exists in the frontmatter.
- Confirms the HTTP request succeeds.
- Ensures the fetched content is not empty.

The script is still in development so use it at your own risk.  
When I will have a foolproof version, will add it to my library, until then feel free to improve or give feedback.

---

<div class="post-metadata">

**Author:** ![Mr.Red](https://community.silverbullet.md/user_avatar/community.silverbullet.md/mr.red/32/821_2.png) [@Mr.Red](https://community.silverbullet.md/u/Mr.Red)\
**Post date:** [October 19, 2025, 9:21pm UTC](https://community.silverbullet.md/t/space-lua-command-to-update-silverbullet-libraries/3421/2 "2025-10-19T21:21:32Z")

</div>

And here it is in action:

I deleted a bunch of code and text from one of my libraries. Then after I ran the command, everything automagically reappeared:

![screencast](https://community.silverbullet.md/uploads/default/original/2X/4/4aff6d7143aa9114ab3b7f9fa59da47f021aee2e.gif)

---

<div class="post-metadata">

**Author:** ![malys](https://community.silverbullet.md/user_avatar/community.silverbullet.md/malys/32/840_2.png) [@malys](https://community.silverbullet.md/u/malys)\
**Post date:** [October 20, 2025, 3:41pm UTC](https://community.silverbullet.md/t/space-lua-command-to-update-silverbullet-libraries/3421/3 "2025-10-20T15:41:20Z")

</div>

Thanks for your reactivity. Could you include It to your libraries ?

---

<div class="post-metadata">

**Author:** ![Mr.Red](https://community.silverbullet.md/user_avatar/community.silverbullet.md/mr.red/32/821_2.png) [@Mr.Red](https://community.silverbullet.md/u/Mr.Red)\
**Post date:** [October 20, 2025, 3:51pm UTC](https://community.silverbullet.md/t/space-lua-command-to-update-silverbullet-libraries/3421/4 "2025-10-20T15:51:26Z")

</div>

I will do, but currently it’s a little raw…

I would like to add some interactivity to it with the options to chose between:

Update current page only …  
Update all custom libraries …  
List Custom/Imported Libraries …  
|-\> Open the selected Page  
|-\> Update selected Page

that’s the plan at least. but i dunno if i can do all this alone 😛  
but good that i have ChatGPT on my side 😉

---

<div class="post-metadata">

**Author:** ![Mr.Red](https://community.silverbullet.md/user_avatar/community.silverbullet.md/mr.red/32/821_2.png) [@Mr.Red](https://community.silverbullet.md/u/Mr.Red)\
**Post date:** [October 29, 2025, 10:44pm UTC](https://community.silverbullet.md/t/space-lua-command-to-update-silverbullet-libraries/3421/6 "2025-10-29T22:44:48Z")

</div>

This is a complete Solution for importing and Managing your Silvernbullet-Libraries  
The “old” “[UpdateSilverbulletLibraries.md](http://UpdateSilverbulletLibraries.md)” is deprecated and therefor it will be not further updated.

Here is the new Version

> <https://github.com/Mr-xRed/silverbullet-libraries/blob/main/Manage_Silverbullet_Libraries.md>

And here some screenshots:

 ![image](https://community.silverbullet.md/uploads/default/original/2X/d/d0fd9558ec6f9064582fdc1f980788d1907fb35f.png)

 ![image](https://community.silverbullet.md/uploads/default/original/2X/4/4ed9f26d435b078e33e277a66486e2255fd7272d.jpeg)

---

<div class="post-metadata">

**Author:** ![zef](https://community.silverbullet.md/user_avatar/community.silverbullet.md/zef/32/7_2.png) [@zef](https://community.silverbullet.md/u/zef)\
**Post date:** [October 30, 2025, 1:28pm UTC](https://community.silverbullet.md/t/space-lua-command-to-update-silverbullet-libraries/3421/7 "2025-10-30T13:28:56Z")

</div>

Have it running! It’s failing when you use an invalid Github token I found, but seeing how SilverBullet can give a better error when that happens (I had to debug this by adding a bunch of print statements…).

---

<div class="post-metadata">

**Author:** ![Mr.Red](https://community.silverbullet.md/user_avatar/community.silverbullet.md/mr.red/32/821_2.png) [@Mr.Red](https://community.silverbullet.md/u/Mr.Red)\
**Post date:** [October 30, 2025, 1:59pm UTC](https://community.silverbullet.md/t/space-lua-command-to-update-silverbullet-libraries/3421/8 "2025-10-30T13:59:02Z")

</div>

Currently it’s either NO TOKEN at all OR you need to supply a Correct Personal Access Token (it’s enough a read only token, with no permission whatsoever if someone is paranoid), i will provide link and instructions on how to get such a token.

 ![image](https://community.silverbullet.md/uploads/default/original/2X/6/662c3615ebbcebf453e452be28d8dc5feafb5f5b.png)

Also I can add later some sanity checks and fallback to NO-Autherntication if incorrect TOKEN is used, or user warning to add/correct Github API Token, or simply tell the user to wait 1 hour & try again if the 60 requests are used up.

Fixed it, but now I need get home, and will push it ASAP.

 ![image](https://community.silverbullet.md/uploads/default/original/2X/7/7b6a804289ace3659a4d728538ec2d26a6b524e9.png)

---

<div class="post-metadata">

**Author:** ![zef](https://community.silverbullet.md/user_avatar/community.silverbullet.md/zef/32/7_2.png) [@zef](https://community.silverbullet.md/u/zef)\
**Post date:** [October 30, 2025, 2:37pm UTC](https://community.silverbullet.md/t/space-lua-command-to-update-silverbullet-libraries/3421/9 "2025-10-30T14:37:08Z")

</div>

Nice. In the mean time I just pushed a fix that will actually jump to the source location of a Lua error when it occurs (in many cases). Try this (once the new build goes live):

```lua
command.define {
  name = "Explode",
  run = function()
    editor.flashNotification "Hello world!"
    error("BOOM")
  end
}

```

---

<div class="post-metadata">

**Author:** ![Mr.Red](https://community.silverbullet.md/user_avatar/community.silverbullet.md/mr.red/32/821_2.png) [@Mr.Red](https://community.silverbullet.md/u/Mr.Red)\
**Post date:** [October 30, 2025, 2:50pm UTC](https://community.silverbullet.md/t/space-lua-command-to-update-silverbullet-libraries/3421/10 "2025-10-30T14:50:11Z")

</div>

My Windows Defender doesn’t like the new edge build (flagged as Trojan again)…need to wait to get home to try it on my linux machine.

---

<div class="post-metadata">

**Author:** ![zef](https://community.silverbullet.md/user_avatar/community.silverbullet.md/zef/32/7_2.png) [@zef](https://community.silverbullet.md/u/zef)\
**Post date:** [October 30, 2025, 2:51pm UTC](https://community.silverbullet.md/t/space-lua-command-to-update-silverbullet-libraries/3421/11 "2025-10-30T14:51:37Z")

</div>

No comment

---

<div class="post-metadata">

**Author:** ![Mr.Red](https://community.silverbullet.md/user_avatar/community.silverbullet.md/mr.red/32/821_2.png) [@Mr.Red](https://community.silverbullet.md/u/Mr.Red)\
**Post date:** [October 30, 2025, 7:43pm UTC](https://community.silverbullet.md/t/space-lua-command-to-update-silverbullet-libraries/3421/12 "2025-10-30T19:43:11Z")

</div>

Pushed the bugfix!

Hit the green [Update]-button in the Library Manager to update itself 😉

⚠ The config variable has changed from apiKey to apiToken, matching GitHub’s terminology.

---

<div class="post-metadata">

**Author:** ![zef](https://community.silverbullet.md/user_avatar/community.silverbullet.md/zef/32/7_2.png) [@zef](https://community.silverbullet.md/u/zef)\
**Post date:** [October 30, 2025, 7:52pm UTC](https://community.silverbullet.md/t/space-lua-command-to-update-silverbullet-libraries/3421/13 "2025-10-30T19:52:50Z")

</div>

Really liking this. Wonder how to build these things generally. It’s kind of messy to have the UI and its implementation mixed in one page… On the other side, the whole thing is optimized to share single page “apps” 🤔

---

<div class="post-metadata">

**Author:** ![Mr.Red](https://community.silverbullet.md/user_avatar/community.silverbullet.md/mr.red/32/821_2.png) [@Mr.Red](https://community.silverbullet.md/u/Mr.Red)\
**Post date:** [October 30, 2025, 8:04pm UTC](https://community.silverbullet.md/t/space-lua-command-to-update-silverbullet-libraries/3421/14 "2025-10-30T20:04:28Z")

</div>

> [@\[space-lua\] Command to update silverbullet-libraries](https://community.silverbullet.md/t/space-lua-command-to-update-silverbullet-libraries/3421/13):
>
> Really liking this. Wonder how to build these things generally. It’s kind of messy to have the UI and its implementation mixed in one page… On the other side, the whole thing is optimized to share single page “apps” thinking

Thank you 🙏!

You can always copy/paste the table and the buttons on any new page, so you’ve separated the “UI” from the code:

 ![image](https://community.silverbullet.md/uploads/default/original/2X/4/4002bbda16bd7adc1e6a602bda271a336a8a03e4.png)

 ![image](https://community.silverbullet.md/uploads/default/original/2X/d/d3160478e884c6c1c31ec7599700cadcc5417965.png)

The only downside is you need to manually Copy/Paste it again if some major breaking changes happen.

---

<div class="post-metadata">

**Author:** ![Mr.Red](https://community.silverbullet.md/user_avatar/community.silverbullet.md/mr.red/32/821_2.png) [@Mr.Red](https://community.silverbullet.md/u/Mr.Red)\
**Post date:** [October 30, 2025, 8:08pm UTC](https://community.silverbullet.md/t/space-lua-command-to-update-silverbullet-libraries/3421/15 "2025-10-30T20:08:53Z")

</div>

BTW I tried it and it workzzz

 ![image](https://community.silverbullet.md/uploads/default/original/2X/0/02a01f49d2ec28ea72f581357a797ba4a0cb336d.png)

it jumped straight to the `error("BOOM")` line even if I were on a complete other page! Love this one!

---

<div class="post-metadata">

**Author:** ![Mr.Red](https://community.silverbullet.md/user_avatar/community.silverbullet.md/mr.red/32/821_2.png) [@Mr.Red](https://community.silverbullet.md/u/Mr.Red)\
**Post date:** [October 30, 2025, 8:24pm UTC](https://community.silverbullet.md/t/space-lua-command-to-update-silverbullet-libraries/3421/16 "2025-10-30T20:24:28Z")

</div>

Alternatively you could create a command to **Install UI** , which will inject the UI Page contents into a new file with the push of a button, and the UI is “installed” in a separate page:

 ![image](https://community.silverbullet.md/uploads/default/original/2X/6/6dfe0cfc8a36a9bd6d91f2f28202dbd89ed50633.png)

So the user has minimal maintenance to do.

Here the code to copy/paste.

```lua
local initUI = [[

${widgets.commandButton("Import: URL")} | ${widgets.commandButton("Import: Browse GitHub Repositories")} | ${widgets.commandButton("Update All Github Libraries","Import: Check & Update All GitHub Libraries")} | ${widgets.commandButton("Update All Markdown Libraries","Import: Update All Raw-Markdown Libraries")} | ${widgets.commandButton("Import: Check All Github Update Statuses")}

# 📥 Imported Silverbullet-Libraries

${buildTable(query[[from index.tag "page" where githubUrl != nil or source == "markdown-import" 
select {
  ref = ref,
  maintainer = (githubUrl and githubUrl:match("github%.com/([^/]+)/")) or "",
  githubUrl = githubUrl,
  sourceUrl = sourceUrl,
  status = (
      (not updateDate or updateDate == "" or updateDate == nil  
      or not lastCommitDate or lastCommitDate == "" or lastCommitDate == nil ) and "⚪ Unknown"
      or updateDate < lastCommitDate and "🔴 Outdated" or "🟢 Up to date"),
   last_updated = (updateDate and parse_datetime(updateDate)) 
    and os.date("%y.%m.%d %H:%M", parse_datetime(updateDate)) or "",
   last_commit = (lastCommitDate and parse_datetime(lastCommitDate)) 
    and os.date("%y.%m.%d %H:%M", parse_datetime(lastCommitDate)) or ""
  }
order by updateDate]] .. "]])}" 

command.define {
  name = "Install ManageLibraries UI",
  hide = true,
  run = function()
          local UIFile = space.writeDocument("Library/ManageLibraries.md", initUI)
          editor.flashNotification("UI-Page was saved with size: " .. UIFile.size .. " bytes")
          editor.navigate("Library/ManageLibraries")
    end
}

```

I already did this to inject the .js from a markdown/space-lua into a new file in my [Treeview\_Extension\_DragAndResize](https://github.com/Mr-xRed/silverbullet-libraries/blob/main/Treeview_Extension_DragAndResize.md) library.

---

<div class="post-metadata">

**Author:** ![zef](https://community.silverbullet.md/user_avatar/community.silverbullet.md/zef/32/7_2.png) [@zef](https://community.silverbullet.md/u/zef)\
**Post date:** [October 30, 2025, 9:16pm UTC](https://community.silverbullet.md/t/space-lua-command-to-update-silverbullet-libraries/3421/17 "2025-10-30T21:16:38Z")

</div>

I think maybe this can be exposed as a virtualPage under e.g. `library:manager` or something. Makes sense to make it read only anyway. 🤔

---

<div class="post-metadata">

**Author:** ![Mr.Red](https://community.silverbullet.md/user_avatar/community.silverbullet.md/mr.red/32/821_2.png) [@Mr.Red](https://community.silverbullet.md/u/Mr.Red)\
**Post date:** [October 30, 2025, 9:24pm UTC](https://community.silverbullet.md/t/space-lua-command-to-update-silverbullet-libraries/3421/18 "2025-10-30T21:24:33Z")

</div>

I didn’t dive so deep into virtual pages yet. but I guess it can and it definitely should be Read Only.

---

<div class="post-metadata">

**Author:** ![zef](https://community.silverbullet.md/user_avatar/community.silverbullet.md/zef/32/7_2.png) [@zef](https://community.silverbullet.md/u/zef)\
**Post date:** [October 31, 2025, 7:01am UTC](https://community.silverbullet.md/t/space-lua-command-to-update-silverbullet-libraries/3421/19 "2025-10-31T07:01:39Z")

</div>

Ok, just a head’s up I got a very exciting idea regarding repository management and unifying libraries and plugs this way. I’ll be spending my Friday on this, I’ll post an update later. Thanks a lot for your work and ideas here @Mr.Red this is helping a lot in solving this problem finally.

---

<div class="post-metadata">

**Author:** ![Mr.Red](https://community.silverbullet.md/user_avatar/community.silverbullet.md/mr.red/32/821_2.png) [@Mr.Red](https://community.silverbullet.md/u/Mr.Red)\
**Post date:** [October 31, 2025, 9:07am UTC](https://community.silverbullet.md/t/space-lua-command-to-update-silverbullet-libraries/3421/20 "2025-10-31T09:07:31Z")

</div>

Sounds promising!  
Have fun & a productive day.

---

<div class="post-metadata">

**Author:** ![zef](https://community.silverbullet.md/user_avatar/community.silverbullet.md/zef/32/7_2.png) [@zef](https://community.silverbullet.md/u/zef)\
**Post date:** [October 31, 2025, 3:50pm UTC](https://community.silverbullet.md/t/space-lua-command-to-update-silverbullet-libraries/3421/21 "2025-10-31T15:50:27Z")

</div>

Update: made a lot of progress, but not there yet. High level what I’m working on:

I’m introducing concept of a repository, in effect nothing more than a regular silverbullet page with `#meta/library/remote` data items.

These can be space lua libraries (that need in turn need to be tagged with `#meta/library` to enable updating), but also “plug wrappers”:

````auto
```#meta/library/remote
# Example of a space lua library
name: Git
uri: github:zefhemel/silverbullet-libraries/Git.md
---
name: Ghost
uri: github:zefhemel/silverbullet-libraries/Ghost.md
---
# This is a plug "wrapper"
name: Mermaid
uri: github:silverbulletmd/silverbullet-mermaid/README.md
---
name: Silversearch
uri: ghr:zefhemel/silversearch@edge/README.md
---
# And would be the repo itself (this very page)
name: REPO
uri: github:zefhemel/silverbullet-libraries/REPO.md
```

````

A linked page can contain additional assets (defined in front matter), such as a plug’s JS file that will be downloaded and placed into your space during install/update, see [silverbullet-mermaid/README.md at main · silverbulletmd/silverbullet-mermaid · GitHub](https://github.com/silverbulletmd/silverbullet-mermaid/blob/main/README.md) for an example.

Then there are broadly speaking the following commands:

- `Library: Install` which will give you a filter-box style UI to pick the library/plug (encoded as `#meta/library/remote` objects) you’d like to install.
- `Library: Update` which will look at all the currently installed libraries (tagged with `#meta/library`), find their remote counter part, compare versions and if they’re different, upgrade
- `Library: Delete` to delete a library (and its assets)
- `Repo: Add` to add a repo (based on some URI), which in effect would simply import

Anyway, still ironing out the details. Next week, probably.

[Next page](https://community.silverbullet.md/t/space-lua-command-to-update-silverbullet-libraries/3421.md?page=2)
