The Runtime API

Some of you may have notice the recent addition of the Runtime API in the Edge builds and I wanted to give you some context on the direction that I'm thinking.

The Opportunity

Not wanting to sound too managementese here, but I'll use the word opportunity rather than problem anyway.

Once upon a time, SilverBullet was a rather simple note apps. Text files on a disk. Nothing fancy. Then the indexing story started, turning SilverBullet in a personal database. Then LIQ (Language Integrated Query) developed (and keeps getting fancier with aggregations, joins etc.) turning this even into a system with even more potential as a personal database.

This is great, but this database is only available from within the SilverBullet client (the part of SB that runs in the browser), because that is its architecture: the server is "dumb": it just serves and stores files, all the "smarts" are in the client, because I think it's important that it can operate just as well (and more responsively, and also when the server cannot be reached) if all that logic and data lives as close to you as possible (= the browser itself).

This architectural choice, which I've waffled over over the years, I think is still sensible but comes with two major drawbacks:

  1. The clients become heavier and have to maintain their own index. This means that "cold starts" of clients can be quite expensive for large spaces, and they need to happen over and over again on every client. This consumes a lot of CPU cycles.
  2. It "locks" all this power in the client, not making it available outside. Wouldn't it be nice to have a SilverBullet CLI to query your notes? Nope, can't do. Have other tools (e.g. LLMs) query your SilverBullet data? Only possible at the "plain text" level. A missed opportunity.

A new direction

For those who were around for SilverBullet v1, will remember it had two modes: a regular "server-style" mode, where actually all the indexing would happen on the server, and a "sync mode" which is basically what we have today. There were a lot of complicated mechanics to attempt to make this work, and it only worked partially. It worked by trying to offer a lot of browser-side APIs to the server, so it could do fancy things, but there were always limitations and lots of gotchas, and from an architectural complexity standpoint it wasn't great. Therefore with v2 I dropped the server mode entirely, rewrote the backend in Go (it was running on Deno before) giving us the model we have today.

However, a while ago I came up with a path forward that could offer the best of both worlds that is a bit of a "hack", but in practice seems to work remarkably well:

The server can run a "ghost" headless Chrom(e/ium) client, and expose essentially everything through API that way.

In a way, this is pretty insane: just running a full blown Chrome on your server. It's a bit of a brute force approach. But with a bit of tuning and tweaking I can reduce the running cost in terms of memory to about 200-300MB, and I'm switching a few SilverBullet client features off, most notably Sync, so it doesn't create another copy of your space in this headless client.

Then that's just wired up through some /.remote endpoints, and voila, you can now run random space lua queries via a server API and get results that are 100% compatible and can do everything a regular client can do (except of course, anything visual you won't actually see unless you explicltly run this in "visible Chrome" mode, which is also an option, in that case you'll just see a window pop up on wherever you run your server).

What this unlocks

At its core: this is an API level abstraction. I still have to see what APIs should be exposed and how, this is very much experimental.

Putting this behind an API abstraction also allows me to swap out the implementation later on. Right now it's using a headless Chromium instance. In the future there may be better solutions. However, I can change that without the API changing.

On top of the API you can now build different things. The first thing that the next release will offer is a silverbullet-cli tool, thait allows you to run e.g. Lua expressions on the server and the get the results back. There's also a basic REPL, which I hope to expand soon.

With either the HTTP API or the CLI, it's now also trivial to hook this into your AI agent (Claude Code, anything else) or create some sort of MCP server if that's your fancy.

You could also build custom UIs on your data: a task list manager that uses SilverBullet as a backend.

The opportunities are endless. And if there is one thing that keeps surprising me about the SilverBullet community is that it’s super creative and pushes every feature to the limit.

What this will hopefully also unlock in the future is a way to distribute an index snapshot to fresh clients. Which is why I mentioned that issue in the beginning. That way, fresh clients don't need to start from scratch, but can start with a snapshot coming from the headless chrome client (through some API). Not 100% this will work completely, but thinkining about it.

Status

All of this is currently already landed in the edge builds. I'll probably create a release soon. This is the point you can start experimenting but again, this is experimental so things may change drastically still. Don't be upset when this happens, I warned you :wink:

9 Likes

Excellent work! I’ve had some similar thoughts and was toying with the idea of a FUSE virtual filesystem with a rendered and unrendered version for each page, both for text editor and agent easier access, but the API is nice and cleaner. I like it!

1 Like

What you say seems like good news to me.
I preferred server mode precisely because of the "opportunities" that you now indicate.
I don't know how what you indicate can affect Firefox users.
Hopefully the current reindexing situation will improve little by little.
Thank you very much.

Very exciting indeed! What do you have in mind for the REPL mode, ie. how does the REPL experience differ from directly passing some (space-) Lua to the CLI?

Another quick question / suggestion: let's make virtual pages available to the CLI. We design virtual pages to help us navigate (via tag-pages, for example), and the CLI deserves this convenience too. A use case is: I tell my opencode to learn from a page. If it can "click the tags" on that page and navigate to the virtual tag-page, and then click the links in there, the context provided by this single page will be far more than just the wiki-links. It can learn from parent tags, pages under parent tags, etc.

This is incredibly exciting. I had actually just started using a cronjob to mirror the relational data to a database somewhere else to query relationally but when this gets firmed up I could easily see switching back to this. Really excited to see where this goes :saluting_face:

So this is now released. Let me know what you need and js still missing.

1 Like