Nothing unverified is ever executable
Three of the packages are one upstream release each: shellcheck, the shell linter; age, the file encryption tool, whose release holds two binaries; and zellij, a terminal multiplexer. None of them is installed on the machine the usual way. Each is a launcher, shellcheck.sh and its kind, with a pin beside it, versions.conf. A consumer types the launcher's path where it used to type the tool's name.
The first run installs the tool, and the order of the steps is the point:
- The launcher looks up this machine's platform in the pin. With no line for it, the launcher exits with code 3 and downloads nothing. Code 3 is kept apart from failure on purpose, so a caller can choose to skip the tool.
- It downloads the release to a file, never into a pipe, because a pipe hides a 404.
- It extracts the one binary it needs into a staging folder and hashes it. The pinned hash is of that binary, not of the archive.
- Only when the hash matches does it make the file executable, move it into
.runtime/beside the launcher and write a stamp. A mismatch deletes what was downloaded and installs nothing. - Every later run compares the stamp with the pin, then hands over to the tool. Bump the version in
versions.conf, and every vendored copy that has synced replaces its binary on its next run.
--status hashes the binary again on demand. If the file no longer matches, it withdraws the stamp and fails. The install itself writes nothing to standard output, so a program that reads the tool's output gets only the tool's output.
shellcheck_version=0.11.0 url.linux-x86_64=https://github.com/koalaman/shellcheck/releases/download/v0.11.0/shellcheck-v0.11.0.linux.x86_64.tar.gz sha256.linux-x86_64=4da528ddb3a4d1b7b24a59d4e16eb2f5fd960f4bd9a3708a15baddbdf1d5a55b url.linux-aarch64=https://github.com/koalaman/shellcheck/releases/download/v0.11.0/shellcheck-v0.11.0.linux.aarch64.tar.gz sha256.linux-aarch64=127f13925eadd52c341bca0ebaf9ab0dbd78c6468f30a8f262a528bf8de47546
Six packages, one shape
- shellcheck 0.11.0, for six platforms.
- age 1.3.1, for five. Its archive holds two binaries, and both are hashed before either one moves. One more platform has a download and no pin: nothing is pinned on a guess.
- zellij 0.45.1, for five. It is about 18 MB to fetch and 52 MB on disk, so a consumer that should ask first runs the install only after a yes.
- uvpython: uv 0.12.3 and CPython 3.12, a toolchain for scripts that declare their own dependencies. It never uses the machine's own uv or Python. Its pin is checked another way: the installer comes from a URL that names its version, and the installed uv has to report exactly the pinned version.
- pywebview 6.2.1, with the Qt bindings at 6.11.0, for the desktop windows of the pane host. It has no runtime folder of its own and installs through uvpython. On Linux it uses Qt from the Python package index, about 200 MB, because only that renderer comes as ready-built packages all the way down; Windows and macOS use the system's own web view.
- fetchkit, a small module on the standard library alone, from Python 3.9 up. It downloads a release asset to a file and lifts one member out of a zip or a tar, and an ambiguous member name is an error, not a guess. It pins nothing: the pin and the check stay with whoever calls it.
Windows too
The three binary launchers each have a .cmd twin that follows the shell version line for line, with the curl, tar and certutil that ship with Windows, and their shell versions also run under Git Bash. uvpython and pywebview have Windows launchers of their own.
Why a package, and why one runtime is shared
The library once had a bin/ folder, with a manifest of tools. Decision 0022 retired it: a pinned tool is a package with its pin beside its launcher, and that is the one way the library ships a binary. A pin that lives beside the launcher is updated with it, by the same sync as everything else.
uvpython keeps its toolchain inside its own package folder. On a machine that has the library, consumers link that one runtime rather than vendor their own, and that choice was measured, not guessed: two copies of the toolchain running the same script kept invalidating each other's cache, and a run took about 180 ms instead of 75 ms.
Tested without the network
The suites never download anything. A stand-in for curl serves a fake archive, and the test pin carries that fake binary's real hash, so the whole install runs offline. There are 74 Python tests, and ten shell suites: five for the POSIX shell and five for cmd.exe.