Restore on the airlock
This page is written for the person (or agent) standing in front of the disconnected machine. Nothing here needs network access — if any step tries to reach out, stop and report it.
1. Get the branch
Section titled “1. Get the branch”# on the connected host, include both refs in the transferred Git bundlegit bundle create project-airlock.bundle main sandbox/dev-linux-64The sandbox branch carries its static tooling under .pixi-sandbox/tools/<platform>/; its root
contains Markdown only. The normal project branch carries the minimal launchers generated by
pixi-sandbox init.
git clone project-airlock.bundle projectcd project./restore.sh # Linux/macOS# .\\restore.ps1 # WindowsThe launcher resolves its branch from the config selected by init (pixi-sandbox.toml is
preferred and .pixi-sandbox.toml is the compatibility fallback), derives
<branch_prefix>/<bundle>-<platform> for the host, calls git archive, extracts into
project-local scratch, and invokes the verified nested binary. When a connected clone lacks the
sandbox ref, it fetches that one branch into origin/<branch>; set PIXI_SANDBOX_FETCH=skip to
require local Git objects only. Set PIXI_SANDBOX_BRANCH to pin an exact branch, or
PIXI_SANDBOX_BUNDLE to choose between bundles that cover the same platform.
2. Look before you leap
Section titled “2. Look before you leap”/tmp/sb/.pixi-sandbox/tools/linux-64/pixi-sandbox doctor \ --branch-location /tmp/sb --verifyThis checks every sha256 in manifest.json and reports the payload breakdown. It writes
nothing. Treat any failure as a hard stop.
Keep evidence when the primary log is unreachable
Section titled “Keep evidence when the primary log is unreachable”If an Actions or operator log cannot cross the airlock boundary, ask the connected side to rerun
pack, doctor, or publish with a fresh --log-file <PATH>. The file is flushed after every
phase and includes the complete causal error chain on failure; -v mirrors phase names to stderr
and -vv adds reviewed non-secret context. Transfer that bounded text file beside the incident
report, not inside the transport branch. Never reuse its path: pixi-sandbox refuses to
overwrite an existing diagnostic log so the first failure is not silently destroyed. Remote
credentials and common token/password query values are not recorded.
For a local airlock check, the same binary can write evidence without changing doctor’s normal report:
/tmp/sb/.pixi-sandbox/tools/linux-64/pixi-sandbox doctor \ --branch-location /tmp/sb --verify \ --log-file /path/to/new/doctor-attempt.log3. Restore
Section titled “3. Restore”cd /path/to/project/tmp/sb/.pixi-sandbox/tools/linux-64/pixi-sandbox restore \ --branch-location /tmp/sb \ --output-path . --forceWhat it does, in order: verifies the tools, stages a copy of each pack under a work dir on
the project’s filesystem, unpacks with the bundled pixi-unpack, moves each environment to
.pixi/envs/<env>, writes pixi’s conda-meta markers, materialises the vendored crates, writes
Cargo source replacement to sandbox-owned .pixi-sandbox/cargo-home/config.toml, adds
per-environment Pixi/Conda activation hooks that set CARGO_HOME, removes any legacy
.pixi/sandbox-env.sh, verifies the restored tree against the manifest’s per-file digests, and
— only after that verification — registers the user tools (below).
There is one supported command entrypoint after restore: pixi. A verified restore puts small
managed launchers for pixi and pixi-sandbox into ~/.local/bin (Windows:
%USERPROFILE%\.pixi-sandbox\bin) and adds that directory to your shell profile’s PATH
(Windows: the user PATH in the registry — no administrator rights). In a new shell,
pixi and pixi sandbox then work directly; pixi discovers pixi sandbox by finding
pixi-sandbox on PATH, which is why both are registered. The launchers exec the
manifest-verified copies under <project>/.pixi/tools/<platform>/ and carry a
managed by pixi-sandbox marker; restoring another project retargets them, so the most
recently registered restore is the user-level tool source. An already-running shell cannot be
mutated — open a new one, or run the export PATH=... line the restore prints.
No project-level activation script is generated or supported. Do not source
.pixi/sandbox-env.sh and do not run bare cargo, rustc, or bun from a restored prefix;
use pixi run ... so pixi selects the environment, loads the restore-owned Cargo activation
hook, and keeps the lockfile/offline contract visible.
Registration refuses to overwrite a pixi or pixi-sandbox you already have in the user bin
directory unless you pass --force. For CI runners, shared accounts, or locked-down airlocks,
set PIXI_SANDBOX_USER_TOOLS=skip before running the generated launcher (or append
--user-tools skip when you call pixi-sandbox restore yourself and know the binary
understands it): restore then touches nothing outside the project, and verification and
project output are identical either way. The generated launchers pass the policy as an
environment variable rather than a flag on purpose — the binary a launcher executes comes
from the packed branch, which may predate the flag, and an unknown variable is ignored where
an unknown flag is a hard error. --user-bin <dir> relocates the launchers for sites with
their own bin-directory policy.
Two things follow from that staging. Before each environment is moved into place, every text file
in it has the staging path rewritten to the final one, so nothing in .pixi/envs/<env> points
into scratch — a .pc file, a CMake config or an activation script keeps working at the airlock
path. And on success the work dir is removed: a completed restore leaves no scratch behind. A
failed restore keeps it, because that is where the partial materialisation is worth looking at.
4. Prove it is offline-clean
Section titled “4. Prove it is offline-clean”pixi install --frozen --offline # must be a no-op, must not touch the networkpixi run --frozen -- cargo build --offline # uses the vendored crates onlyIn a new shell, plain pixi and pixi sandbox resolve through the registered user tools. If
registration was skipped, call the manifest-owned binary explicitly:
./.pixi/tools/<platform>/pixi run --frozen <task>.
If pixi install --frozen --offline starts doing real work, the environment on disk does
not match pixi.lock — do not let it continue; re-run the restore instead. If your project
already tracks .cargo/config.toml for aliases, rustflags, target runners, or [env], the
default restore leaves it byte-for-byte intact; Cargo’s vendor replacement lives in
.pixi-sandbox/cargo-home/config.toml and is selected by Pixi’s environment activation.
What the bundle does not contain
Section titled “What the bundle does not contain”Post-link scripts
Section titled “Post-link scripts”Unpacking runs package post-link scripts, i.e. code from the bundle executes on your
machine. That is inherent to conda environments — the bundle is signed/verified content and
the branch should be protected accordingly. Ask for --verify-only runs and signed
manifests if your site requires it.