Skip to main content

A lightweight, single-binary conda bootstrapper — powered by rattler

Project description

conda-express (cx)

CI Docs codecov License Crates.io PyPI

A lightweight, single-binary bootstrapper for conda, powered by rattler. The cx binary is short for conda express.

cx replaces the miniconda/constructor installation pattern with a ~17 MB static binary that bootstraps a fully functional conda environment in seconds.

Quick start

# Bootstrap a conda installation (first run only, ~3–5 s)
cx bootstrap

# Use conda normally — cx delegates transparently
cx install -n myenv numpy pandas
cx create -n science python=3.12 scipy

# Activate environments using conda-spawn (no shell init needed)
cx shell myenv

On first use, cx automatically installs conda and its plugins into ~/.cx from an embedded lockfile. Subsequent invocations hand off directly to the installed conda binary with no overhead.

What gets installed

cx installs a minimal conda stack from conda-forge:

Package Role
python >= 3.12 Runtime
conda >= 25.1 Package manager
conda-rattler-solver Rust-based solver (replaces libmamba)
conda-spawn Subprocess-based environment activation
conda-pypi PyPI interoperability
conda-self Base environment self-management

The conda-libmamba-solver and its 27 exclusive native dependencies (libsolv, libarchive, libcurl, spdlog, etc.) are excluded by default, reducing the install from 113 to 86 packages.

Installation

Homebrew (recommended)

The easiest way to install on macOS and Linux:

brew tap jezdez/conda-express https://github.com/jezdez/conda-express
brew install jezdez/conda-express/cx

Update later with brew upgrade cx.

Shell script

macOS / Linux:

curl -fsSL https://jezdez.github.io/conda-express/get-cx.sh | sh

Windows (PowerShell):

powershell -ExecutionPolicy ByPass -c "irm https://jezdez.github.io/conda-express/get-cx.ps1 | iex"

The script detects your platform, downloads the right binary, verifies the checksum, updates your shell profile / PATH, and runs cx bootstrap. Customize with environment variables:

  • CX_INSTALL_DIR — where to place the binary (default: ~/.local/bin or %USERPROFILE%\.local\bin)
  • CX_VERSION — specific version to install (default: latest)
  • CX_NO_PATH_UPDATE — set to skip shell profile / PATH modification
  • CX_NO_BOOTSTRAP — set to skip running cx bootstrap

From GitHub Releases

Download the binary for your platform from the latest release:

Platform File
Linux x86_64 cx-x86_64-unknown-linux-gnu
Linux ARM64 cx-aarch64-unknown-linux-gnu
macOS x86_64 (Intel) cx-x86_64-apple-darwin
macOS ARM64 (Apple Silicon) cx-aarch64-apple-darwin
Windows x86_64 cx-x86_64-pc-windows-msvc.exe

Each file has a matching .sha256 checksum.

Docker

A minimal, hardened multi-arch image (~37 MB) is published to GHCR on every release:

docker run --rm -v cx-data:/home/nonroot/.cx ghcr.io/jezdez/conda-express bootstrap

The image runs as non-root (uid 65532), works with --read-only, and includes provenance attestations and SBOMs. Docker Desktop on macOS and Windows automatically selects the right architecture (linux/amd64 or linux/arm64).

# Run conda commands through cx
docker run --rm -v cx-data:/home/nonroot/.cx ghcr.io/jezdez/conda-express create -n myenv python=3.12

Use as a container in CI (GitHub Actions):

jobs:
  test:
    container: ghcr.io/jezdez/conda-express:latest
    steps:
      - run: cx bootstrap && cx create -n test python numpy

Use as a base for multi-stage application builds:

FROM ghcr.io/jezdez/conda-express:latest AS conda-builder
RUN cx bootstrap && cx create -n app python numpy pandas
FROM gcr.io/distroless/cc-debian12:nonroot
COPY --from=conda-builder /home/nonroot/.cx/envs/app /opt/conda

From PyPI

pip install conda-express

From crates.io

cargo install conda-express

The package is published as conda-express on PyPI and crates.io.

Building from source

Requires pixi (recommended) or Rust (edition 2024).

With pixi (recommended)

pixi manages the Rust toolchain from conda-forge for reproducible builds:

git clone https://github.com/jezdez/conda-express.git
cd conda-express

pixi run build          # cargo build --release
pixi run test           # cargo test
pixi run lint           # fmt-check + clippy

With system Rust

git clone https://github.com/jezdez/conda-express.git
cd conda-express

# Build (first build solves packages at compile time — needs network)
cargo build --release

# Binary is at target/release/cx
./target/release/cx --help

The first build runs a compile-time solve via build.rs, generating a rattler-lock v6 lockfile that gets embedded into the binary. Subsequent builds reuse the cached lockfile unless pixi.toml changes.

Configuration

Package specs, channels, and exclusions live in the [tool.cx] section of pixi.toml:

[tool.cx]
channels = ["conda-forge"]
packages = [
    "python >=3.12",
    "conda >=25.1",
    "conda-rattler-solver",
    "conda-spawn",
    "conda-pypi",
    "conda-self",
]
exclude = ["conda-libmamba-solver"]

Edit this section to customize what cx installs, then rebuild. You can also override these values at build time using environment variables — see Building custom cx binaries below.

CLI reference

cx bootstrap [OPTIONS]           Bootstrap a fresh conda installation
  --force                        Re-bootstrap even if prefix exists
  --prefix DIR                   Target directory (default: ~/.cx)
  --channel CH                   Channels (default: conda-forge)
  --package PKG                  Additional packages to install
  --exclude PKG                  Packages to exclude (default: conda-libmamba-solver)
  --no-exclude                   Disable default exclusions
  --no-lock                      Ignore embedded lockfile, do a live solve
  --lockfile PATH                Use an external lockfile instead

cx status [--prefix DIR]         Show cx installation status
cx shell [ENV]                   Alias for conda spawn (activate via subshell)
cx uninstall [OPTIONS]           Remove cx, conda prefix, and all environments
  --prefix DIR                   Target directory (default: ~/.cx)
  -y, --yes                      Skip confirmation prompt

cx help                          Getting-started guide
cx <conda-args>                  Passed through to conda

Disabled commands

cx uses conda-spawn instead of traditional shell-based activation. The following commands are intentionally disabled:

Command Instead
conda activate / deactivate cx shell myenv
conda init Add condabin to your PATH (see below)

Frozen base prefix

The ~/.cx prefix is protected with a CEP 22 frozen marker after bootstrap. This prevents accidental modification of the base environment (e.g., conda install numpy into base). Users should create named environments for their work:

cx create -n myenv numpy pandas
cx shell myenv

Updating the base installation is handled by conda self update (via conda-self).

Building custom cx binaries

You can build a cx binary with your own set of packages using the composite GitHub Action or the reusable workflow.

Composite action (uses: jezdez/conda-express@main)

Use in a step within your own workflow. You control the platform matrix:

jobs:
  build:
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: jezdez/conda-express@main
        id: cx
        with:
          packages: "python >=3.12, conda >=25.1, conda-rattler-solver, conda-spawn, numpy, pandas"

      - uses: actions/upload-artifact@v4
        with:
          name: ${{ steps.cx.outputs.asset-name }}
          path: ${{ steps.cx.outputs.binary-path }}

Reusable workflow

Builds all 5 platforms in one call:

jobs:
  build-cx:
    uses: jezdez/conda-express/.github/workflows/build.yml@main
    with:
      packages: "python >=3.12, conda >=25.1, conda-rattler-solver, conda-spawn, numpy, pandas"

Build-time environment variables

When building from source, you can override the package configuration without editing pixi.toml:

Variable Overrides Format
CX_PACKAGES [tool.cx].packages Comma-separated match specs
CX_CHANNELS [tool.cx].channels Comma-separated channel names
CX_EXCLUDE [tool.cx].exclude Comma-separated package names
CX_PACKAGES="python >=3.12, conda >=25.1, numpy" pixi run build

Uninstalling

To completely remove cx, the conda prefix, all environments, and the cx binary:

cx uninstall

This will show what will be removed and ask for confirmation. Use --yes to skip the prompt. The command also cleans up PATH entries from shell profiles that were added by the installer.

How it works

  1. Compile time: build.rs reads [tool.cx] from pixi.toml, solves dependencies using rattler, filters excluded packages, and writes a rattler-lock v6 lockfile embedded into the binary.

  2. First run: cx parses the embedded lockfile, downloads packages from conda-forge, and installs them into the prefix. No repodata fetch or solve needed at runtime.

  3. Subsequent runs: cx detects the existing prefix and replaces its own process with the installed conda binary, passing all arguments through.

Activation model

cx ships with conda-spawn instead of traditional conda activate. There is no need to run conda init or modify shell profiles.

# Add cx to PATH (one-time setup)
export PATH="$HOME/.cx/condabin:$PATH"

# Activate an environment (spawns a subshell)
cx shell myenv

# Deactivate by exiting the subshell
exit

Lockfile format

The embedded lockfile uses the rattler-lock v6 format (same as pixi.lock). It can be:

  • Read by pixi
  • Imported by conda-lockfiles
  • Checked into version control for reproducibility auditing

License

BSD 3-Clause. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

conda_express-0.4.1.tar.gz (264.5 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

conda_express-0.4.1-py3-none-win_amd64.whl (8.0 MB view details)

Uploaded Python 3Windows x86-64

conda_express-0.4.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (7.9 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

conda_express-0.4.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (7.6 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

conda_express-0.4.1-py3-none-macosx_11_0_arm64.whl (7.4 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

conda_express-0.4.1-py3-none-macosx_10_12_x86_64.whl (7.7 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file conda_express-0.4.1.tar.gz.

File metadata

  • Download URL: conda_express-0.4.1.tar.gz
  • Upload date:
  • Size: 264.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for conda_express-0.4.1.tar.gz
Algorithm Hash digest
SHA256 27be1c85f9c7a296b1686556803856690f788f52810f5e08477daade9e65b22f
MD5 f5d63d17a044033ee84c7866d4122630
BLAKE2b-256 c95b38fa4eeff590572007096fb2804600b42c01fa9ee7726094d8fe84f4b2ab

See more details on using hashes here.

Provenance

The following attestation bundles were made for conda_express-0.4.1.tar.gz:

Publisher: release.yml on jezdez/conda-express

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file conda_express-0.4.1-py3-none-win_amd64.whl.

File metadata

File hashes

Hashes for conda_express-0.4.1-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 81ee8fa3cec8d105ba2a596e6c1745bc71f99b05c7994ec95ec9a4d670bd2f25
MD5 da53dc520915ccd26a0ef9c7b8b9cc6f
BLAKE2b-256 17a87b7e1f8ab00fa6236bd48be176d8548c78bf5f01afdfc7b77f82ccecc4eb

See more details on using hashes here.

Provenance

The following attestation bundles were made for conda_express-0.4.1-py3-none-win_amd64.whl:

Publisher: release.yml on jezdez/conda-express

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file conda_express-0.4.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for conda_express-0.4.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 280d2d801f5f7d8d0f7db5ddbf304a0bf7970f2a56b81f06e2885bb6304ea1a6
MD5 a3da67f7a1169c43afda8424f7105ab3
BLAKE2b-256 1b5a67dfe845dc6786bc0611f5e04f2a386db9d6479ab6fc4387a25f0c53a9e1

See more details on using hashes here.

Provenance

The following attestation bundles were made for conda_express-0.4.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on jezdez/conda-express

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file conda_express-0.4.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for conda_express-0.4.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 ba88d67403d69c8c910fcba256dac9c9b3cbbb21e87f4c5f6668a48384b02dd1
MD5 34ff52541efa2920bee5a6a0b77941dd
BLAKE2b-256 b522a9c5d6974621ffab421d3ee2c138b4630fcb04c30547a9322d9b9fbb5242

See more details on using hashes here.

Provenance

The following attestation bundles were made for conda_express-0.4.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on jezdez/conda-express

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file conda_express-0.4.1-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for conda_express-0.4.1-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 12df31640be6951ae6d6805ade6a0904fdda2c384ef4cec7cda00cf81f948518
MD5 616df5a28407f618334e50000286f6fb
BLAKE2b-256 bf4dba9e58aef0231fa5b2842a01b19c9a9bdbab86fcdb77d9cc9cb8e78b257b

See more details on using hashes here.

Provenance

The following attestation bundles were made for conda_express-0.4.1-py3-none-macosx_11_0_arm64.whl:

Publisher: release.yml on jezdez/conda-express

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file conda_express-0.4.1-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for conda_express-0.4.1-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 c579f11d8deb022e64c9ba6eee027ded651ed0d9740dddb4b886d388a049b109
MD5 30fdea0e50a1e6bc788ebb52a08124c0
BLAKE2b-256 39417087bcca9d37f723a6ac63beda9fd12d5ed585fb20ab88c3bbfee5591ecc

See more details on using hashes here.

Provenance

The following attestation bundles were made for conda_express-0.4.1-py3-none-macosx_10_12_x86_64.whl:

Publisher: release.yml on jezdez/conda-express

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page