Features#
Single-binary bootstrapper#
cx is a single ~17 MB static binary written in Rust. It requires no Python, no installer framework, and no shell modifications. Download it, run it, and you have a working conda installation.
Compile-time lockfile#
build.rs performs a full dependency solve at cargo build time using rattler
crates, producing a rattler-lock v6
lockfile that is embedded into the binary. At runtime, bootstrap skips repodata
fetching and solving entirely — it downloads and installs packages directly from
the locked URLs.
This gives cx deterministic, reproducible bootstraps with ~3–5 second install times.
Package exclusion#
conda on conda-forge hard-depends on conda-libmamba-solver, which pulls in
27 native dependencies (libsolv, libarchive, libcurl, spdlog, etc.). Since cx
uses conda-rattler-solver instead, these are unnecessary.
cx removes them via a post-solve transitive dependency pruning algorithm: after the solver produces a complete solution, cx identifies packages that are exclusively required by the excluded packages and removes them. This reduces the install from 113 to 86 packages.
conda-rattler-solver#
cx configures conda-rattler-solver
as the default solver via .condarc. This solver is based on
resolvo, the fastest SAT solver in the
conda ecosystem, and ships as a pure Python package with
py-rattler wheels.
conda-spawn activation#
cx ships with conda-spawn
and disables traditional conda activate/deactivate/init. Instead:
cx shell myenv # spawns a subshell with myenv activated
exit # leaves the environment
No .bashrc/.zshrc modifications required. Just add ~/.cx/condabin to
your PATH.
cx shell alias#
cx shell is a convenience alias for conda spawn. It works identically:
cx shell myenv # same as: conda spawn myenv
Frozen base prefix (CEP 22)#
After bootstrap, cx writes a conda-meta/frozen marker file per
CEP 22. This protects the base
prefix from accidental modification. Users should create named environments
for their work:
cx create -n myenv numpy pandas
cx shell myenv
Auto-bootstrap#
If the prefix doesn’t exist when you run a conda command, cx automatically bootstraps before executing:
# First time: bootstraps ~/.cx, then creates the environment
cx create -n myenv python=3.12
External lockfile support#
For custom deployments, you can override the embedded lockfile:
cx bootstrap --lockfile /path/to/custom.lock
Or skip the lockfile entirely for a live solve:
cx bootstrap --no-lock
Uninstall (cx uninstall)#
cx provides a clean uninstall command that reverses the bootstrap:
cx uninstall
This will:
List what will be removed (prefix, named environments, cx binary)
Ask for confirmation (
--yesto skip)Remove the conda prefix and all environments
Remove the cx binary
Clean up PATH entries from shell profiles
GitHub Action for custom builds#
cx ships a composite GitHub Action and a reusable workflow that let you build custom cx binaries with your own package set baked in. The build performs a full compile-time dependency solve, producing a self-contained binary with an embedded lockfile — just like the official cx releases.
This is powered by the same environment variable overrides that work locally, but wrapped in a ready-to-use Action.
See the GitHub Action reference for inputs, outputs, and behavior. For a step-by-step walkthrough, see the custom builds guide.
Multi-platform support#
cx builds and tests on 5 platforms via GitHub Actions:
Platform |
Runner |
|---|---|
linux-x64 |
|
linux-aarch64 |
|
macos-x64 |
|
macos-arm64 |
|
windows-x64 |
|
PyPI and crates.io distribution#
cx is published as conda-express on both
PyPI and
crates.io:
pip install conda-express # from PyPI
cargo install conda-express # from crates.io
Both use trusted publishing (OIDC) for secure, tokenless releases.