Skip to content

Quickstart

This walkthrough goes from an empty directory to a signed, verified box on disk. It uses the example recipe init scaffolds — an environment containing nothing but Python — so it runs in about a minute and produces a ~48 MB archive you can inspect by hand.

Prerequisites: the CLI and toolchain from Installation.

1. Create a project

A box records the commit it was built from, so a Scrollcase project must be a git checkout — building outside one fails rather than inventing a revision.

sh
mkdir my-boxes && cd my-boxes
git init

2. init — scaffold the project

sh
scrollcase init

init writes three things and never overwrites anything that already exists:

  • scrollcase.config.json — the workspace declaration: where recipes live and where builds, artefacts and keys go.
  • recipes/example-box-<platform>-<arch>-<accelerator>/ — an example recipe (recipe.json) and its pixi manifest (pixi.toml), targeting this machine by default.
  • .gitignore rules for .scrollcase/, the regenerated build state that must never be committed.

Then, if pixi or conda-pack is missing, init asks whether to install it:

text
This project needs pixi and conda-pack to build a box.
Install them into /work/my-boxes/.scrollcase/toolchain? [y/N]

Answer yes and both land inside the project, with the pixi download checksum-verified, conda-pack pinned to 0.9.2, and the installed pixi version pinned into the recipe for you. Answer no and nothing is downloaded — install them yourself as described in Installation, and set pixiVersion in the recipe by hand. Either way init never downloads anything you did not agree to, which is what makes it safe to re-run.

Use --install-toolchain or --no-install-toolchain to answer up front in a script.

3. doctor — check the machine

sh
scrollcase doctor --recipe example-box-macos-aarch64-metal

Every failing check comes with a remedy. Fix what it names and re-run; doctor never modifies anything, so it is always safe.

Recipe names

The recipe name on the command line is the name of its directory under recipes/ — here example-box-macos-aarch64-metal, assuming an Apple Silicon Mac. Substitute the name init printed on your machine throughout.

4. lock — resolve dependencies, once

sh
scrollcase lock example-box-macos-aarch64-metal

lock runs the pinned pixi against the recipe's pixi.toml and writes pixi.lock next to it. This is the only step that resolves anything: build later installs exactly what the lock pins, and never resolves. Commit the lock — it is what makes a build reproducible and what the licence audit reads.

sh
git add . && git commit -m "Example box recipe and lock"

Committing now also matters for the next steps: build refuses a dirty tree without --allow-dirty, because an artefact built from uncommitted changes is reproducible by nobody.

5. keygen — create a signing key

sh
scrollcase keygen

This writes a private ed25519 key (.scrollcase/keys/signing-private.pem, owner-only permissions) and the matching public key file (signing-public.json). Every document the build emits is signed; verify checks signatures against the public key file. For production custody — a KMS, an HSM — see Signing & Key Custody.

6. build — install, self-test, archive, sign

sh
scrollcase build example-box-macos-aarch64-metal

The pipeline, in order: install the locked environment, pack and relocate it with conda-pack, stage declared assets, prune, self-test with the interpreter inside the box, normalise timestamps, zip deterministically, and sign. The result lands in .scrollcase/dist/:

text
.scrollcase/dist/
├── example-box-1.0.0-macos-aarch64-metal.zip            # the box archive
├── example-box-1.0.0-macos-aarch64-metal.release.json   # signed release document
├── example-box-beta-macos-aarch64-metal.channel.json    # signed channel pointer
└── objects/boxes/example-box/1.0.0/macos-aarch64-metal/ # content-addressed staging tree

Rebuilding the same commit produces a byte-identical archive — see Architecture for what makes that true.

7. verify — prove what you built

sh
scrollcase verify .scrollcase/dist/example-box-1.0.0-macos-aarch64-metal.release.json --self-test

verify mirrors what an installing client does: signature against the trusted key, archive size and SHA-256, safe entry names, box.json inside the archive agreeing with the signed release, the declared interpreter present. With --self-test it goes further: it extracts the archive to a temporary directory and imports the recipe's declared modules with the box's own Python — the check that proves the environment runs somewhere other than where it was built.

Where to go next

The repository also ships a proven example, examples/hello-box-macos-arm64-metal, with a committed lock — the same walkthrough with nothing left to fill in.