Scrollcase Overview
Scrollcase is a tool for packaging and distributing complete Python environments, especially when a project needs to include:
- a specific Python version;
- exact libraries and dependencies;
- application code;
- model weights or other assets;
- support for a specific platform or hardware accelerator;
- integrity checks and signed releases.
Its purpose is to avoid forcing each end user to install Python, native libraries, model dependencies, and model files manually.
The developer describes what the runtime box should contain, runs a small number of commands, and Scrollcase produces a package that can be published and later installed by another application.
Who Uses Scrollcase
There are two main roles:
This is the person or team that builds and publishes the box.
The developer must:
- defines the Python environment;
- specifies the dependencies;
- provides model files or downloadable assets;
- chooses the target platform;
- builds the box;
- publishes the generated files.
What Scrollcase Automates
Scrollcase automatically handles:
- creating the Python environment;
- installing dependencies;
- using the locked dependency versions;
- downloading declared assets;
- verifying asset sizes and hashes;
- making the environment relocatable;
- copying local code and files;
- running configured tests;
- creating the runtime box;
- generating the ZIP archive;
- generating release manifests;
- calculating hashes;
- signing the release;
- preparing files for publication.
These operations happen during the build. The developer does not run them one by one.
Initial Setup
The initial setup is usually performed once per project.
1. Install Scrollcase
Install Scrollcase in the repository using the method supported by the project.
2. Initialise the Workspace
Run:
scrollcase initThis creates the initial project structure.
3. Generate a Signing Key
Run:
scrollcase keygenThis creates the key pair used to sign releases.
The private key must be stored securely and must not be committed to the repository.
The public key must be distributed to the consuming application so that it can verify releases.
Writing a Recipe
A recipe is the configuration that describes the box to build.
The developer specifies information such as:
- box name and version;
- target operating system;
- target architecture;
- hardware accelerator;
- Python version;
- local files to include;
- remote assets or model weights;
- expected file hashes;
- Python modules to import during tests;
- optional custom checks.
Conceptually, the recipe says:
Box: model-x
Version: 1.0.0
Operating system: macOS
Architecture: Apple Silicon
Accelerator: Metal
Python: 3.11
Dependencies: PyTorch, NumPy, model-x library
Weights: URL, file size, SHA-256
Tests: import torch, import model_xThe recipe describes the desired result. It does not require the developer to implement the internal packaging process.
Defining Dependencies
Dependencies are declared in the dependency file used by the recipe, normally through Pixi.
Conceptual example:
# pixi.toml
[dependencies]
python = "3.11.*"
pytorch = "2.*"
numpy = "2.*"This file defines acceptable dependency versions.
It does not necessarily select the exact build of every package yet.
Locking Dependency Versions
After defining the dependencies, run:
scrollcase lock recipe-nameThis generates a lock file containing the exact resolved dependency versions.
This should normally be committed to the Git repository.
When to Run lock
Run it:
- the first time the recipe is created;
- when a dependency changes;
- when upgrading a library;
- when changing the environment configuration.
It does not need to be rerun for every build if the dependencies have not changed.
Checking the Configuration
Before building, the developer can run:
scrollcase doctor --recipe recipe-nameThis checks things such as:
- workspace configuration;
- recipe availability;
- Git repository state;
- required tools;
- whether the current machine can build the selected target;
- whether required files exist.
doctor helps detect configuration problems before starting a full build.
First Build Workflow
The practical workflow for the first box is:
1. Initialise the Project
scrollcase init2. Write the Recipe
Define:
- box identity;
- target platform;
- Python version;
- dependencies;
- assets;
- tests.
3. Lock Dependencies
scrollcase lock recipe-name4. Commit the Configuration
Commit the recipe and lock file to Git.
5. Generate or Configure the Signing Key
scrollcase keygen6. Build the Box
scrollcase build recipe-name7. Review the Output
The build typically produces:
- the box ZIP archive;
- the release document;
- the channel document;
- a publication-ready object structure.
8. Distribute the files (if needed)
Upload the generated files to the chosen distribution system, such as:
- object storage;
- static hosting;
- a release repository;
- a private server.
Scrollcase prepares the files, but does not upload them anywhere.
What Happens During build
From the developer's perspective, the build is a single command:
scrollcase build recipe-nameScrollcase then performs the internal packaging steps automatically.
The developer does not need to:
- install Python manually inside the box;
- copy libraries one by one;
- download every asset manually;
- repair environment paths manually;
- create the ZIP archive;
- calculate hashes;
- write release manifests;
- sign every file manually.
The internal complexity remains inside the tool.
Publishing and distribution
Scrollcase is not a hosting/distribution service.
After the build, the developer can publish the generated files on its own.
This can be done:
- manually;
- with a script;
- through CI/CD;
- with GitHub Actions;
- through an object-storage deployment pipeline.
A typical flow could be:
Scrollcase builds the files
↓
the deployment system uploads them
↓
the consuming application downloads themUpdate Workflow
After the initial setup, publishing a new version requires fewer steps.
Case 1: Only Code or Included Files Change
- update the code;
- increase the version;
- run the build;
- publish the new files.
scrollcase build recipe-nameCase 2: Dependencies Change
- update the dependency configuration;
- regenerate the lock file;
- review the result;
- run the build;
- publish the new files.
scrollcase lock recipe-name
scrollcase build recipe-nameCase 3: Model Weights Change
- update the asset URL, file size, and hash in the recipe;
- increase the version;
- run the build;
- publish the new release.
Supporting Multiple Platforms
A box is specific to one target.
Examples include:
- macOS Apple Silicon with Metal;
- macOS Apple Silicon with CPU only;
- Linux x86_64 with CPU;
- Linux x86_64 with CUDA;
- Windows x86_64 with CPU;
- Windows x86_64 with CUDA.
Supporting several targets requires several builds and usually separate target-specific recipes or configurations.
The workflow becomes:
macOS recipe
↓
macOS build
Linux CPU recipe
↓
Linux CPU build
Linux CUDA recipe
↓
Linux CUDA build
Windows recipe
↓
Windows buildEach build must run on a machine compatible with the target.
This is one of the main sources of complexity when supporting a large platform matrix.
What the Consuming Application Must Implement
Scrollcase creates the box, but it does not implement installation inside the final application.
The consuming application must handle:
- detecting the operating system and architecture;
- detecting the available accelerator when relevant;
- choosing the correct channel and release;
- downloading the manifests;
- verifying the signatures;
- checking runtime requirements;
- downloading the ZIP archive;
- verifying its size and hash;
- extracting the box;
- downloading optional on-demand assets;
- starting the correct Python runtime or script;
- handling updates, errors, and uninstallation.
What the End User Does
An ideal could be:
the user access the application that uses Scrollcase
↓
the user selects a feature or model
↓
the application selects the correct box
↓
the user press install (or a similar call to action)
↓
the application downloads it, verifies it and extracts it
↓
the application starts it when requestedIs Scrollcase Complicated?
Conceptually
The mental model is simple:
describe the environment
↓
lock the versions
↓
build the box
↓
publish the filesFor a single box with common dependencies, the workflow can be fairly straightforward.
In Practice
The complexity increases when the project includes:
- difficult native libraries;
- strict version requirements;
- old scientific packages;
- dependencies unavailable through supported channels;
- several operating systems;
- several CUDA versions;
- very large model files;
- complex scientific validation;
- advanced signing and release pipelines.
In most cases, the complexity comes more from the Python environment and the model than from Scrollcase itself.
What Scrollcase Actually Simplifies
Scrollcase removes much of the repetitive work required to turn a Python environment into a distributable product.
Without a tool like this, the developer would have to manage:
- environment creation;
- exact dependency versions;
- relocatability;
- native dependencies;
- verified downloads;
- manifests;
- signatures;
- hashes;
- release structure;
- tests;
- distribution conventions.
With Scrollcase, these concerns are collected into a recipe and a small number of commands.
TL;DR
For a quick summary, check out the Scrollcase tl;dr page here.