packslip 1.8.0

A vendor-neutral signed release manifest: what shipped, and how to verify it
Documentation

packslip is a signed release manifest for software distributed as archives, installers, or executables. A release publishes one file, packslip.sigstore.json, beside its artifacts. A consumer, such as an installer, package manager, or mirror, verifies that file against the project's signer and reads three things from it: which artifact suits the host, where the executables are inside that artifact, and the digest the download must match. The consumer does not have to guess from file names or trust a checksum file served next to the binary.

This repository holds the specification, the packslip CLI that publishes, verifies, and installs releases, the Rust crate for building consumers, and two GitHub Actions: jdx/packslip publishes a packslip from a release job, and jdx/packslip/releases builds a signed release list. The format is stable at version 1; Stability says what that fixes and what a revision may add.

Start here

  • Install a tool: Install a tool with packslip discovers and verifies a signed release, installs its complete archive, and links the declared commands. It works for any supported tool that publishes a packslip, including mise.
  • Try it locally: Getting started creates and verifies a sample release with a local key. It needs no CI account.
  • Publish releases: Publish with GitHub Actions adds signing to a release job. Artifact configuration maps your files to platforms and executables. Resources covers completions, man pages, skills, and SBOMs, and Host requirements covers what the host must provide. Release recipes gives complete configurations for Rust, Go, monorepo, and desktop releases.
  • Withdraw, recommend, or self-host releases: Manage release lists and Host releases on your own domain.
  • Verify or install releases: Verify a release checks a downloaded release with the CLI against a repository, signer fingerprint, or public key you trust. Build an installer or mirror walks through finding, verifying, and selecting a release in your own tool, and shows the Rust crate that implements the verification and selection steps. packslip and mise covers installing mise with packslip and using mise to manage tools with packslip releases, including their completions, man pages, and skills.

How packslip fits a release shows how the pieces connect, and the documentation index lists every guide. For exact fields and rules, read the specification, CLI reference, or JSON schemas.

Install the CLI

With mise installed and activated:

mise use -g packslip
packslip version

For a standalone install on Linux or macOS, run curl -fsSL https://packslip.sh | sh. On Windows, run irm https://packslip.sh/install.ps1 | iex in PowerShell. Installation methods also cover distribution packages, pinned scripts, the container image, direct downloads, and source builds. Release executables cover Linux and Windows on x64 and ARM64, and macOS on ARM64; Intel Macs need a source build.

With packslip 1.5.1 or newer, install mise's latest stable release:

packslip install github.com/jdx/mise --pin ps1_nlhmwtfeufglxv5myvwvronk7a

The pin identifies mise's signing repository. packslip verifies the release and download before installing; it runs no downloaded code. It reports the command path and any PATH setup needed. See packslip and mise for pinned-bootstrapper and Docker examples, and the CLI overview for other tasks.

Add it to a GitHub release

In a tag-triggered release job, after your workflow builds the artifacts and uploads them to the GitHub release, add:

permissions:
  contents: write     # Upload the bundle to the release.
  id-token: write     # Sign with the workflow's identity.
  attestations: write # Attest the matched files.

steps:
  # Build the archives and upload them to the release before this step.
  - uses: jdx/packslip@v1
    with:
      artifacts: dist/*.tar.xz dist/*.zip
      bin: mytool

The action attests the matched files, signs a release manifest of their digests, platforms, and executable paths with the workflow's identity, verifies it, and uploads packslip.sigstore.json to the release. It does not upload the artifacts. No long-lived signing key is needed.

This one-job form gives the action contents: write. To keep it away from release write access, run it in a separate read-only job. Publish with GitHub Actions covers every input, how @v1 and packslip-version select the CLI, and how to build the CLI on the runner when packslip publishes no release for it, such as x64 macOS. A project hosted on its own domain also publishes a signed release list with jdx/packslip/releases; see Host releases on your own domain.

Verify a release

packslip signs its own releases. To check one with the packslip CLI, download a release's bundle and one of its archives. packslip verify checks the bundle against the workflow that signs packslip releases, and the archive against the digest in the bundle. This example checks the Linux x64 archive of 1.5.1; packslip show packslip.sigstore.json lists the others:

curl -fLO https://packslip.dev/v1.5.1/packslip.sigstore.json
curl -fLO https://packslip.dev/v1.5.1/packslip-v1.5.1-linux-x64.tar.xz
packslip verify packslip.sigstore.json \
  --identity-prefix https://github.com/jdx/packslip/.github/workflows/release.yml@ \
  --issuer https://token.actions.githubusercontent.com \
  --pin ps1_mcx64bcghek2t4vljgb3lho3ti \
  --artifact packslip-v1.5.1-linux-x64.tar.xz

The bundle's project is packslip.dev, a domain rather than a GitHub repository name, so verify cannot work out the expected signer from it, and the identity flags are required. --identity-prefix names the repository that signs packslip releases by its current name. --pin adds a check on top of the identity flags: its value is that repository's signer fingerprint, derived from the repository's ID, so a release signed from a different repository that later takes the name jdx/packslip is refused. The fingerprint stays the same if the repository is renamed or moves to another owner, but --identity-prefix would then need the new URL. See Pin a signer with its fingerprint.

Agent skill

The packslip skill helps a coding agent configure a release, declare resources, and diagnose verification failures. packslip releases after 1.4.0 declare the skill for their own version, so mise can link the copy that matches your installed CLI into your agent's skills directory:

mise use packslip
mise skills sync --dir .agents/skills

mise use packslip resolves through the mise registry, which supplies the signer pin for packslip's own releases, published as project packslip.dev. The synced links point into your mise installs, so keep them out of version control. Run the same mise skills sync --dir .agents/skills command again after changing the packslip version. To have mise do that after every mise install and mise use, set skills.dir to .agents/skills and turn on skills.auto_sync. Without skills.dir, mise links into .claude/skills.

Work on packslip

See CONTRIBUTING.md for setup, checks, and documentation sources, and RELEASING.md for the maintainer release process. Bug reports and format feedback belong in issues.

Developed by Jeff Dickey (@jdx), author of mise, and Shunsuke Suzuki (@suzuki-shunsuke), author of aqua. MIT licensed; see LICENSE.