Using in your project
This guide is for project owners who want to ship their pixi environments to airlocked machines.
The two product commands
Section titled “The two product commands”Run the first command from the root of your Pixi project on the connected side:
Connected hosts need Pixi installed. Install the native package from the canonical channel, then initialise:
pixi global install --channel https://prefix.dev/archont561/archont561 --channel conda-forge pixi-sandboxpixi-sandbox initpixi-sandbox init creates the preferred pixi-sandbox.toml, the GitHub workflow, and exactly one launcher for
the connected host:
pixi-sandbox.toml.github/workflows/publish-sandbox.ymlrestore.sh # Linux/macOS# restore.ps1 # Windows insteadReview and commit those files. Existing projects that carry .pixi-sandbox.toml keep using it;
an explicit --config PATH wins over both conventional names. Pushing the project runs the generated workflow and publishes the
configured sandbox/<bundle>-<platform> branches. Transfer Git history containing the project and
sandbox branch into the disconnected network. On the airlock, the second product command is:
./restore.shThat script only uses local Git objects: it archives the platform’s sandbox branch, locates the
verified nested binary, and restores everything offline. It never contacts GitHub. Windows users
run .\\restore.ps1 instead.
The Git push, workflow completion, and transfer across the air gap are deployment operations, not additional pixi-sandbox commands. The airlock clone must contain the sandbox branch.
Use a mirror
Section titled “Use a mirror”Configure Pixi’s channel or mirror settings before running the canonical install command when your organisation proxies prefix.dev.
1. Prerequisites
Section titled “1. Prerequisites”- Your project has
pixi.toml+pixi.lock - Optional:
Cargo.toml+Cargo.lockif you want vendored crates - On the connected host: Pixi and Git
- On the airlock: Git and
tar; Pixi andpixi-sandboxdo not need to be installed
The connected host installs pixi-sandbox from the signed native package channel. Standalone release binaries and SHA256SUMS remain available for verified transport bootstrap.
2. Decide what to ship
Section titled “2. Decide what to ship”Not every env in pixi.toml should be an airlock branch. Declare explicitly in pixi-sandbox.toml:
schema = 1branch_prefix = "sandbox"cargo_vendor = true # false if you only need conda envs
[[bundle]]name = "developer"environments = ["dev", "docs"]platforms = ["linux-64", "osx-arm64", "win-64"]
[[bundle]]name = "minimal"environments = ["default"]platforms = ["linux-64"]cargo_vendor = falseValidate:
pixi-sandbox plan --config pixi-sandbox.tomlpixi-sandbox plan --config pixi-sandbox.toml --jsonThis emits a GitHub Actions matrix — one job per bundle × platform.
3. Local pack → doctor → publish
Section titled “3. Local pack → doctor → publish”# Build static self-binarycargo build -p pixi-sandbox --release
# Packpixi-sandbox pack \ --repo-root . \ --envs dev,docs \ --output-dir .sandbox-out \ --platform linux-64 \ --cargo-vendor \ --fetch-tools \ --self-bin target/release/pixi-sandbox
# Verify (writes nothing)pixi-sandbox doctor --branch-location .sandbox-out --verify
# Publishpixi-sandbox publish \ --input-dir .sandbox-out \ --branch-name sandbox/developer-linux-64 \ --remote origin# Download verified release# (use setup action in CI, or manual curl + sha256sum check)
pixi-sandbox pack \ --repo-root . \ --envs dev \ --output-dir .sandbox-out \ --platform linux-64 \ --fetch-tools \ --self-bin ./pixi-sandbox-x86_64-unknown-linux-muslNever pack
$(command -v pixi-sandbox). Installed withpixi global install, that path is a launcher trampoline, not the standalone binary: it looks fortrampoline_configuration/pixi-sandbox.jsonbeside the executable, which only exists in the global prefix — so the packed branch passes every hash check and then dies at restore withCouldn't open "…/trampoline_configuration/pixi-sandbox.json"(issue #81). Pack probes--self-binby executing it under an empty environment and refuses such files;doctor --verifyapplies the same check to a transport before anyone restores it. The only correct sources are the release asset (pixi-sandbox-<target>, verified against the release’sSHA256SUMS) or a binary you built yourself.
4. What gets published?
Section titled “4. What gets published?”sandbox/developer-linux-64 (orphan branch)├── .pixi-sandbox/│ ├── manifest.json # SHA-256 catalog, source commit, tool versions│ ├── envs/dev/pack/ # pixi-pack --directory-only output│ │ ├── channel/linux-64/*.conda│ │ ├── environment.yml│ │ └── pixi-pack.json│ ├── envs/docs/pack/ # second env, shared .conda files deduped by git│ ├── tools/linux-64/ # pixi, pixi-unpack, pixi-sandbox (static, verified)│ └── vendor/ # cargo vendor --versioned-dirs (if enabled)├── README.md # human restore instructions└── AGENTS.md # agent instructionsSizes (measured small project, 2 envs, 33 crates, linux-64):
| Part | Size |
|---|---|
| conda envs (.conda) | 133 MB |
| cargo vendor (loose) | 33 MB |
| tools (pixi, pixi-unpack, self) | 96 MB |
| transport dir | 262 MB |
| orphan branch after git dedup | ~110 MB |
Tools dominate small bundles — expected, git stores each tool blob once.
5. Restore on airlock
Section titled “5. Restore on airlock”After the project and its sandbox branch have crossed the air gap:
./restore.shThe generated script reads pixi-sandbox.toml and selects
<branch_prefix>/<bundle>-<platform> for the native platform — the same name
pixi-sandbox plan gives the publisher, so renaming a bundle or prefix needs no regenerated
launcher. It then uses git archive into .pixi/.restore-transport and delegates verification
and restoration to the branch’s .pixi-sandbox/tools/<platform>/pixi-sandbox. When the config
cannot decide — no bundle covers this platform, or several do — it falls back to the branch
baked in at init time. Override branch selection only when needed:
PIXI_SANDBOX_BRANCH=sandbox/developer-linux-64 ./restore.sh # exact branchPIXI_SANDBOX_BUNDLE=developer ./restore.sh # pick among several bundlesSee Airlock Restore for transfer options and the operator checklist.
6. Without cargo vendoring
Section titled “6. Without cargo vendoring”If you only need conda envs:
schema = 1cargo_vendor = false
[[bundle]]name = "python"environments = ["dev", "test"]platforms = ["linux-64", "win-64"]And pack without --cargo-vendor:
pixi-sandbox pack --repo-root . --envs dev --output-dir .sandbox-out --platform linux-64 --fetch-tools --self-bin target/release/pixi-sandbox7. Tips
Section titled “7. Tips”.pixi/.restore-work. Never use small tmpfs /tmp (pixi-unpack stages into TMPDIR).doctor –verify is the same code as restore’s preflight. CI must run it.Init does not modify your Pixi manifest
Section titled “Init does not modify your Pixi manifest”pixi-sandbox init writes only the files it owns — the publisher workflow, the relock
workflow, the offline launcher, and pixi-sandbox.toml when it does not exist yet. Your
pixi.toml is left byte-identical: the CLI is installed globally with an explicit channel
(pixi global install --channel https://prefix.dev/archont561/archont561 …), which never
reads the project’s channel list, and no generated file needs the project to know where the
CLI came from.
Upgrading from 0.4.3? That release appended
https://prefix.dev/archont561— the publisher’s namespace root, which is a web page, not a channel — to[workspace].channels, sopixi lockfailed with a 404 on any project with at least one dependency. Remove that entry from yourchannelsarray; nothing needs to replace it.