For the complete documentation index, see llms.txt. This page is also available as Markdown.

Tooling

The sbuild CLI

sbuild is the tool for the soarpkgs tree. One binary, six commands, no state of its own. It turns a recipe into a version file, and the whole tree into the index Soar reads.

Install

Statically linked, no dependencies:

curl -fsSL "https://github.com/pkgforge/sbuilder/releases/download/nightly/sbuild-$(uname -m)-linux" -o sbuild
chmod +x sbuild

Built for x86_64, aarch64 and riscv64, each with a .b3sum beside it. Or cargo install --git https://github.com/pkgforge/sbuilder.

Commands

Every command takes the tree root as its first argument, defaulting to ..

new

Scaffold a recipe, so a new package starts from something that parses.

sbuild new ripgrep BurntSushi/ripgrep --type static

resolve

Ask each upstream what its current version is, and write the version file that pins it: the URL per host, plus whatever digest the forge already reports.

sbuild resolve                      # every package
sbuild resolve . ripgrep fzf        # only these

This is one API call per package, so it needs GITHUB_TOKEN for anything beyond a handful. Re-resolving an unchanged package rewrites nothing.

hashfill

Most forges report a sha256 for an asset. None report blake3, which is what Soar verifies against. This downloads whatever is pinned without a hash beside it, streaming the body so memory stays flat regardless of artifact size.

Run it after resolve and before committing. A pinned URL with no hash is the one state validate refuses.

validate

Check the tree. Every pinned URL has a hash, every install target stays inside the package directory, every recipe parses and says what it must.

This is the gate in CI, and the only thing that has to pass before a merge.

audit

Download each archive and check that every path the recipe installs actually resolves inside it. validate cannot see this: it reads the tree, and whether bin/foo exists in a tarball is a fact about the tarball.

Slow and network bound by design, so it runs on its own rather than on every merge.

meta

Generate the index for one host, out of the tree and nothing else. No network, no build state. The same tree in gives the same index out, which is why it needs no runner of the architecture it generates for.

Soar reads this after soar json2db turns it into SQLite. See metadata for what the published index looks like.

Working on a package locally

A blobless clone is worth it here. The tree is mostly small text files but has a long history.

Last updated