Standard Library
Want ships a standard library of Spore packages.
Planning files can import these packages.
An import names a package (a directory of .sp files) or a single
file.
Standard-library packages are namespaced: the want standard library is want: and the spore standard library is core:.
An import with no colon resolves in the same source as the importing file — a module-relative path in your module, or a sibling package within a standard library:
ns = (#import "core:ns")
build = (#import "want:build")
linux = (#import "want:linux")
paths = (#import "want:build/paths")
Callers are responsible for spawning and awaiting Jobs through their job port; the standard library functions take that port (build.JobCtx) as their first argument, by convention.
A tool package may set up a package-specific context
instead and take it first: the zig and go commands take a zig.Ctx or
go.Ctx (built with new from the job port, limits, platform, and version).
build
The core of the build library (stdlib/build).
Types
FS: a wantfs tree. This is the value adoproc returns and the type almost everything operates on.Ctx: the build context handed to adoproc:Ctx = (#Struct { .jobs = JobCtx .input = FS .secrets = (#List (#Port Unit Unit)) })secretsis empty unless the build publishes; seeSinkCtxbelow.SinkCtx: the context handed to a unit file's.sinkproc bywant build --publish:(#Struct { .jobs = JobCtx .input = FS .internet = (#Port Unit Unit) .secrets = (#List (#Port Unit Unit)) }).inputis the target'sdoresult;secretsis the file's granted secret ports, in the order the WANT's.secretsnames them (supplied with--secret NAME:PATHor--secrets NAME:PATH). Sinks run only for targets the build query names directly, and a publish build fails if a directly queried target (or its running sink) is granted a name that was not supplied.JobCtx: the jobs port used to spawn and await child Jobs.Task,JobID,JobState,JobResult: the job system's wire types.Limits: the resource ceiling a spawn requests for its child ((#Struct { .memory = B64 .cpu = B64 .max_duration = B64 })).memoryis bytes,cpuis microseconds per second, andmax_durationis seconds (0 means no ceiling); a child running longer thanmax_durationis cancelled.
Jobs
spawn jc limits op input -> JobID: start a child job for a Task underlimits.limits jc -> Limits: the current job's spawn-time ceiling. Passing it tospawnpropagates the ceiling down the tree unchanged.await jc id -> AnyValue: wait for a child; a failed child faults the parent.inspect jc id -> JobState: check a child without blocking.awaitAny jc ids -> JobID: wait for any of several children.
Filesystem
pick jc root path -> FS: re-root the tree atpath; picking a file yields a flat single-file FS.pickRoot jc root path -> FS: the same operation, named for re-rooting a directory.fileAt jc root path -> FS: pick a single file (a synonym forpick).place jc ents -> FS: mount named single-file FSes at their names:(build.place jc [ (build.ent "bin/hello" exe) ])ls jc root path -> (#List String): the immediate children of a directory.filterPaths jc root set -> FS: keep only the entries ofrootwhose path the PathSetsetcontains; entry paths are unchanged, so the filtered tree is not re-rooted.emptyDir jc -> FS: a tree with no entries.
Downloads
downloadFile jc task -> FS: fetch a file from one oftask.urls, verified againsttask.hash; a non-nonetask.compressiondecompresses the verified payload into the returned file.downloadTree jc task -> FS: fetch an archive (tar, zip, or deb) and expand it into a tree.task.compressionnames the archive payload's compression (gzip, xz, zstd, or none); decompression is explicit, never sniffed.
OCI
downloadOciImage jc task -> FS: pull an OCI/Docker image into an OCI layout.pushOciImage jc task -> PushedOCIImage: push an OCI layout to a registry repository and attach the task's tags. The push is idempotent: blobs, manifests, and tags the registry already holds are skipped. The registry credentials come fromtask.secrets, a--secretsmap whose exports include.OCI_USERNAMEand.OCI_PASSWORD.OCIImageTask(url,repo,algo,hash),PushOCIImageTask(url,repo,tags,image,secrets), andPushedOCIImage(digest,tags): the OCI wire types.
Importing build also gives you its download, job, and oci modules'
exported functions, since a package is compiled from every immediate child
.sp file.
build/paths
The PathSet constructors used in .input and .output:
Set: the PathSet tagged union itself ((#TaggedUnion {.unit = String .prefix = String .suffix = String})), the parameter type ofbuild.filterPaths.unit p -> Set: the single pathp.prefix p -> Set: every path beginning withp.suffix s -> Set: every path ending ins.
linux
The Linux container executor (stdlib/linux).
run jc cspec -> CSpawnResult: run a container described bycspec, and return its exit code plus the tree captured from its output mount.CSpec: the container description:init,args,env,wd,mounts,network,stdin,stderr,stdout.initMemfd fs: run an executable from a flat single-file FS (copied into an anonymous memfd).initPath p: run the executable already at pathpinside the container.- Mount sources:
snapshot fs(read-only),output,emptyDir,tmpfs n,drive n,overlay rlayer wlayer(lower may be asnapshot/drive; upper must be a writabledrive/tmpfs),devNull,procfs,sysfs,cgroup2fs,devpts. mount dst src -> Mount: pin a source at a container path.net name backend,loopback,private,internet cap: network interfaces.- stdio:
stdinNull,stdin ctx,stdout ctx,stderr ctx,outputLog,outputClosed,stdinClosed. fileAtPath jc root path -> FS: pull a file out of a container tree.
linux/dist/alpine
A pinned Alpine minirootfs: a small musl userland with the busybox shell.
rootfs jc -> FS: expand the pinned minirootfs tarball into a tree.fileAt jc path -> FS: pull a single file out of it.version,arch: the pinned release.
linux/dist/debian
A pinned rblaine95/debian base image (a GHCR mirror of Docker Hub's
official image). Like Alpine, but a full glibc userland.
image jc -> FS: pull the pinned image as an OCI layout.rootfs jc -> FS: unpack the image's root filesystem.fileAt jc path -> FS: pull a single file out of it.
linux/dist/arch
Arch Linux packaging on top of a pinned official Arch container image (with
the bash, pacman, and bsdtar makepkg itself uses). package takes
already-built artifacts as a build.FS tree and produces the
.pkg.tar.zst pacman installs; nothing is compiled.
rootfs jc -> FS: the pinned image's root filesystem.fileAt jc path -> FS: pull a single file out of it.version: the pinned image build.Spec: the required metadata (.name,.version,.arch,.desc,.builddate,.files).versionis the full pkgver including the pkgrel (and optional epoch), andbuilddateis a decimal Unix timestamp that fixes every file's mtime, so equal inputs produce equal packages.Meta: the full metadata record;meta spec -> Metafills the optional fields with defaults.withUrl,withPackager,withLicense,withDepends,withOptdepends,withProvides,withConflicts,withReplaces,withGroups,withBackup,withInstall: rebind one optional field.filename meta -> String: the output file's name,name-version-arch.pkg.tar.zst.pkginfo meta -> String: the rendered.PKGINFO.package jc meta -> FS: assemble the package and return the tree captured from the output mount (one file,filename meta); usebuild.fileAtfor the package as a flat single-file tree. The target faults if the packager fails.checkExit code -> Unit: fault unless a container exited zero.
The payload is a tree rooted at /, built with build.place or picked from
a build output:
files = (build.place jc [
(build.ent "usr/bin/hello" exe),
])
m = (arch.meta {.name = "hello" .version = "1.0-1" .arch = "x86_64"
.desc = "..." .builddate = "1700000000" .files = files})
m = (arch.withLicense m ["MIT"])
pkg = (arch.package jc m)
docker
pull jc task -> FS: pull an OCI image.umoci jc -> FS: the pinned umoci binary.rootfs jc img -> FS: unpack a pulled image's root filesystem.
git
A pinned static git build (darkvertex/static-git), used to give a container a
git binary with no package manager or network.
tool jc -> FS: the expanded static git tree (gitat its root). Mount it onPATH(e.g. at/git) and setGIT_TEMPLATE_DIRto an existing directory.
github
Upload release assets to an existing GitHub release (stdlib/github).
Credentials come from a --secrets map whose only required export is
.GITHUB_TOKEN, a token with write access to the repository's releases
(contents: write). The preferred setup is a spore file:
.GITHUB_TOKEN = "..."
want build --publish --secrets github:~/.config/want/github.sp
Ctx: the GitHub context ((#Struct {.jobs = JobCtx .secrets = (#Port Unit Unit)})); build it once withnew.new jc secrets -> Ctx: bind the job port and the secrets port granted by the WANT's.secrets.UploadOpts:(#Struct {.owner = String .repo = String .tag = String}), naming the existing release to attach assets to.Asset: one uploaded asset (.id,.name,.size,.content_type,.browser_download_url).ReleaseUpload: the op's result: the release and the assets it now carries.uploadRelease ctx opts assets -> ReleaseUpload: upload every top-level file inassetsas an asset of the named release; an existing asset with the same name is replaced.
go
The pinned Go toolchain (stdlib/go).
Ctx: the go environment ((#Struct {.jc = JobCtx .limits = Limits .platform = Platform .version = Version .modcache = FS .env = (#List String)})). Every command takes it as its first argument.new jc limits platform version -> Ctx: set up the environment once, then hand it to every command.platform/versionselect the toolchain distribution to fetch;jcandlimitsare the job resources commands run under. The module cache starts empty.withModcache ctx modcache -> Ctx: rebind the module cache to the tree returned bypkg.withEnv ctx env -> Ctx: rebind the command-wide environment. Entries are prepended to the fixed environment and the first entry for a variable wins, so they override it (for exampleGOFLAGS,GOPROXY,CGO_ENABLED).withTarget ctx platform -> Ctx: prependGOOS/GOARCHforplatform, cross-compiling pure-Go builds with the host toolchain.LATEST,v1_27_1: the pinnedVersionvalues;linux_amd64is the pinnedPlatform;GOOS_*/GOARCH_*name every target.dist ctx -> FS: download the pinned distribution and re-root it as a container root.pkg ctx src hash -> FS: rungo mod downloadfor the module treesrc(under the context's environment) in a network-enabled container and return the resulting module cache, audited againsthash.cmd ctx cwd args -> CSpawnResult: run the pinned go tool over the module treecwd(mounted at /src) in a container with no network.argsis the full argv, e.g.["go", "build", "-o", "/out/app", "./cmd/foo"].build ctx modfs entrypoint -> FS: compile the main package atentrypointinto a static executable.test ctx modfs -> CSpawnResult: rungo test ./...; its stdout and stderr are captured as/stdoutand/stderrin the output tree.testBinaries ctx modfs -> CSpawnResult: compile every package's test binaries into the output tree without running them.checkExit code -> Unit: fault the build unlesscodeis zero.
go/dist
The Go release pins and the mirror URLs used to fetch them (stdlib/go/dist.sp,
part of the go package): Version, LATEST, v1_27_1, Platform,
linux_amd64, tarballName, topDir, dist, and mkurls.
python
The pinned Python toolchains: CPython (the interpreter, from
python-build-standalone) and uv (the package manager), each fetched from its
own release artifacts (stdlib/python).
Ctx: the python environment ((#Struct {.jc = JobCtx .limits = Limits .platform = Platform .uv = UvVersion .python = PythonVersion .venv = FS .env = (#List String)})). Every command takes it as its first argument.new jc limits platform uv python -> Ctx: set up the environment once, then hand it to every command.platformselects both distributions;uvandpythonpin the versions to fetch (see below).jcandlimitsare the job resources commands run under. The project environment starts empty.withVenv ctx venv -> Ctx: rebind the project environment to the tree returned bypkg; commands mount it at /venv and prefer itsbin/on PATH.withEnv ctx env -> Ctx: rebind the command-wide environment. Entries are prepended to the fixed environment and the first entry for a variable wins, so they override it (for exampleUV_NO_DEV).UV_LATEST,PYTHON_LATEST,PYTHON_3_13: the pinnedUvVersionandPythonVersionvalues;x86_64_linuxis the pinnedPlatform.uvDist ctx -> FS: the pinned uv distribution (uvanduvx), to mount at /uv.pythonDist ctx -> FS: the pinned CPython distribution, to mount at /python.pkg ctx src hash -> FS: runuv sync --frozenfor the project treesrc(which must contain pyproject.toml and uv.lock) in a network-enabled container with the pinned toolchains, and return the resulting venv, audited againsthash. Mount the result on the context with withVenv before running commands.cmd ctx cwd argv -> CSpawnResult: run any command over the treecwdin the hermetic command container;argvis resolved on PATH through the venv, the pinned interpreter, and uv, and each element is passed verbatim.python ctx cwd args,uv ctx cwd args,sh ctx cwd script:cmdwith the pinned interpreter, uv, or the Debian shell (for pipelines and redirects) as the program.checkExit code -> Unit: fault the build unlesscodeis zero.
python/dist
The uv and CPython release pins and the asset URLs used to fetch them
(stdlib/python/dist.sp, part of the python package): UvVersion,
PythonVersion, UV_LATEST, PYTHON_LATEST, PYTHON_3_13, Platform,
x86_64_linux, uvUrl, pythonUrl, uvDist, and pythonDist.
zig
The pinned Zig toolchain.
Ctx: the zig environment ((#Struct {.jc = JobCtx .limits = Limits .platform = Platform .version = Version .pkgfs = FS .env = (#List String)})). Commands take it as their first argument.new jc limits platform version -> Ctx: set up the environment once, then hand it to every command.platform/versionselect the toolchain;jcandlimitsare the job resources commands run under. The package directory starts empty.withPkgfs ctx pkgfs -> Ctx: rebind the package directory to the tree returned bypkg; commands mount it at /src/zig-pkg.withEnv ctx env -> Ctx: rebind the command-wide environment. Entries are prepended to the fixed environment and the first entry for a variable wins, so they override it.LATEST,STABLE,v0_16_0: the pinnedVersionvalues;x86_64_linuxis the pinnedPlatform.dist ctx -> FS: download the pinned distribution and re-root it as a container root.pkg ctx src hash -> FS: fetch thebuild.zig.zondependencies ofsrcthroughzig build --fetch, audited againsthash(thezig-pkgfingerprint).cmd ctx cwd args -> CSpawnResult: run the pinned zig tool over the source treecwd(mounted at /src);argsis the full argv, e.g.["/zig/zig", "build", "test"].buildArgs ctx src args -> CSpawnResult:cmdplus the fixed--build-file,--prefix, and--cache-dirflags, for arbitraryzig buildsteps; returns the exit code plus the captured output tree.build ctx src target -> FS: run thebinariesstep for the Zig target tripletargetand return its output tree.checkExit code -> Unit: fault the build unlesscodeis zero.run ctx args -> AnyValue: run the compiler with stdio wired to the host.watch ctx stdin stdout stderr -> B8: runzig build --watchon the build context's working directory, with stdio wired to the given ports; returns the container's exit code.
zig/dist
The Zig release pins and the mirror URLs used to fetch them (stdlib/zig/dist.sp,
part of the zig package): Version, LATEST, STABLE, v0_16_0, Platform,
x86_64_linux, tarballName, topDir, dist, and mkurls.
mdbook
Renders a markdown book to static HTML, using the pinned static-musl mdbook release inside an Alpine container. The environment (Alpine rootfs and mdbook) is mounted from constant snapshots, so only the book source changes between builds.
tool jc -> FS: the pinned mdbook distribution, re-rooted.build jc src book_toml summary -> FS: render the markdown insrc, withbook_tomlas itsbook.tomlandsummaryassrc/SUMMARY.md, and return the generated site. The build faults if mdbook fails or produces noindex.html.
sys
Types for the surrounding system context used by entrypoints (not by build
planning files): Ctx, ctxPort, and the NetBackend choices.
ns
Helpers for building namespaces (NS, get, mkEntry), used when a Spore
entrypoint is handed its context as a namespace.
bits
Bit-width aliases (B8…B256) and the bitwise primitives: AND, OR, and
XOR on Bit, plus b32AND and b32OR on B32.
strings
Byte-level string helpers mirroring a subset of Go's strings (a String is
a List of bytes):
len s -> B32.hasPrefix s p -> Bit,hasSuffix s p -> Bit,contains s p -> Bit.index s p -> (Maybe B32): the first index ofpins, or Nothing.count s p -> B32: non-overlapping instances ofp; an emptypcountslen(s) + 1insertion points.split s sep -> (#List String): an emptysepsplits into single bytes.join parts sep -> String,repeat s count -> String.trimPrefix s p -> String,trimSuffix s p -> String,trimSpace s -> String(ASCII whitespace).