Jadpo is experimental and not ready for production. These docs follow the compiler's main branch as of 30 Oct 2026. What's built · Install 0.1.0
jadpo
Reference: Tooling

Tooling

Which jadpo runs

On this page

A project is written for one release line of Jadpo, such as 0.1, and while Jadpo is at 0.x a minor release may break an app. So the jadpo that runs a command is the one the project names, whatever you have installed. You don't do anything for that.

The jadpo you install (Homebrew, the npm package @jadpo/jadpo, or the shell or PowerShell installer) is a whole jadpo that can also start another release, as the go command does. Before a command runs, it finds the project: the folder you run it from, walked up to app.jadpo, or else the first argument that names a file or folder in a project. It reads the line from application { jadpo: "0.1" } (The root).

When the project is on the installed jadpo's own line, or names no line, the installed jadpo runs the command. Otherwise it runs the release the project needs, in the same folder and with the same arguments, and exits as that release does. It picks:

  1. the release jadpo.lock pins, if there is one (see "Pin a release" below);
  2. else the newest release of the line it already keeps;
  3. else the newest release of the line published on GitHub, which it fetches once.

A project on the installed jadpo's own line runs with that jadpo, so a newer patch of the line is used once you install it, or pin it.

Outside a project there is no line to read, so jadpo new, jadpo --version, jadpo help and every other command run with the installed version. The VS Code extension runs jadpo lsp from the project's folder, so it gets the project's release with no setting.

Fetching a release

A release comes from github.com/jadpo-dev/jadpo's releases, and is kept in jadpo/releases/<version>/ in your cache folder: $XDG_CACHE_HOME, else ~/.cache, else %LOCALAPPDATA% on Windows. Nothing is written anywhere else, and two commands that need the same release at once fetch it once.

Nothing in a download runs until it passes two checks. Its SHA-256 has to be the one the release publishes beside it. Its GitHub artifact attestation has to verify too: that is a signed record, kept by GitHub and Sigstore's public log, saying this repository's release.yml built that archive at the release's tag. jadpo checks it with Sigstore's own verifier against the trusted root it carries. A download that fails either check is refused, and nothing is kept.

While it fetches, stderr shows a live line, Fetching Jadpo 0.2.3 for aarch64-apple-darwin, with a bar once the archive's size is known, or that line once where stderr doesn't animate. Then it says what it got, and the command's own output follows:

text
✓ Fetched Jadpo 0.2.3 (24.1 MB) and checked its SHA-256 and attestation in 2.3 s

Under --json, nothing is written but the command's own document.

The releases kept

Command Does
jadpo toolchain (or list) Lists the releases kept, newest first, with each one's size
jadpo toolchain remove <version> Deletes a kept release

Both take --json, and both always run with the jadpo you installed, since they look after its cache. A release you remove is fetched again the next time a project needs it.

Pin a release

Pin the exact release a project runs with when its builds must be reproducible:

Command Does
jadpo toolchain pin Writes the release the project runs with into jadpo.lock
jadpo toolchain unpin Takes the pin out again

The pin is the lock's first line, jadpo version 0.1.2 (What is committed). pin runs as the project's release, so that is the release it writes. Commit the lock with the code. A pin on another line than jadpo: names is out of date, record.out_of_date, until jadpo toolchain pin writes it again.

Run your own build on every project

People working on the compiler set JADPO_TOOLCHAIN=local, so the jadpo they start runs every command itself, whatever line the project names. A project on another line is then refused by jadpo check, with the errors below.

When the release can't be run

When jadpo can't run the release a project needs, because it is offline with nothing kept, the line has no release yet, or a download fails its checks, it stops. It never compiles the project itself. The error names the release to install, says why it couldn't be fetched, and gives the next step for that cause. It is toolchain.version_newer when the project needs a later release than this one, and toolchain.version_older when it needs an earlier one.

What a release must keep, for older launchers

Every jadpo ever installed goes on running the releases later projects name, so it fetches them by what it was built knowing. These are a contract with every installed jadpo, and changing any of them is a breaking change to all of them. A test pins each (crates/jadpo-cli/src/launcher.rs, contract), so a change fails the gate pointing here.

  • The line. application { jadpo: "X.Y" } in app.jadpo, the jadpo: member of the application singleton with its value a string of two numbers, read on its own without the rest of the project (jadpo_check::jadpo_version::declared). Any app.jadpo a later release accepts must still put the line there in that form.
  • The pin. A jadpo version X.Y.Z line in jadpo.lock, a release with no pre-release, read without the rest of the lock.
  • Where releases are. GitHub Releases of jadpo-dev/jadpo, tagged vX.Y.Z, each archive at https://github.com/jadpo-dev/jadpo/releases/download/vX.Y.Z/jadpo-cli-<target>.tar.gz, .zip for x86_64-pc-windows-msvc, for each target dist-workspace.toml names; a target dropped from it can never run a later release.
  • The SHA-256 and the archive. <archive>.sha256 beside it, its first word the archive's SHA-256 in hex (sha256sum's form); inside the archive, jadpo (jadpo.exe on Windows) at its top or in its one folder, jadpo-cli-<target>/. Nothing else in the archive is used.
  • The attestation. A GitHub artifact attestation of the archive's digest on Sigstore's public-good instance, whose certificate GitHub Actions issued to https://github.com/jadpo-dev/jadpo/.github/workflows/release.yml@refs/tags/vX.Y.Z: the repository, the workflow's path and its run at the tag (release-please starts it with --ref "$TAG"). Renaming the repository or the workflow, or running it on a branch, makes every installed jadpo refuse the release.
  • Finding a line's newest release. GitHub's API without signing in, https://api.github.com/repos/jadpo-dev/jadpo/releases?per_page=100, pages of 100 up to ten, reading each release's tag_name, draft and prerelease; and /attestations/sha256:<digest> for the attestation, its attestations[].bundle. GitHub allows 60 such requests an hour from one address. A fetch takes two or three, and a kept release none, so the limit is met only on a shared address such as CI's. When it is met, the error says GitHub's API refused it for that limit and to run the command again in an hour; nothing is fetched or kept.
  • The handshake. A release a jadpo starts gets JADPO_TOOLCHAIN_LAUNCHED set to its own version and runs the command itself when that is its version, so it never hands the command on again; JADPO_TOOLCHAIN=local runs everything with the jadpo started. The command line reaches the release whole, before any of it is read, so a command or flag a later release adds works through any launcher.
  • The cache. jadpo/releases/<X.Y.Z>/jadpo in the user's cache folder, written whole by a rename under .<X.Y.Z>.lock; a folder there is a release that was checked.
  • The trusted root. Each jadpo checks attestations against the Sigstore trusted root it was built with, without refreshing it. After Sigstore rotates a key that signs GitHub's attestations, older launchers refuse releases signed with the new key: the error says Jadpo X couldn't be fetched to run it because its archive's attestation doesn't verify, and to run again, then to install the newest jadpo, whose trusted root may be newer, if it fails the same way. Installing a jadpo built after the rotation is the fix, and its release notes say so.

Markdown for agents: /docs/which-jadpo-runs.md.Built from Jadpo main at a707efb.