Reference · Tooling
Pixi Cheat Sheet
Every Pixi command and pixi.toml setting this course uses, in one place: installing,
adding packages, running code, tasks, environments, lockfiles, global tools, CI, and fixes for common problems.
If you know pip, venv, or conda, the translation tables at the end map your habits to Pixi.
- Install Pixi and create a workspace
- Add conda-forge and PyPI dependencies, per feature and per platform
- Define tasks with dependencies, arguments, environment variables, and caching
- Compose environments from features and test across Python versions
- Keep the lockfile healthy locally and in CI
The mental model
A workspace is a folder with a pixi.toml manifest (what you want) and a
pixi.lock lockfile (exactly what was resolved, for every platform). Environments live in
.pixi/envs/<name> and are created from the lockfile. You never activate anything by hand:
pixi run puts the right environment on PATH for one command.
flowchart LR M["pixi.toml
(what you ask for)"] -- "pixi lock / pixi install" --> L["pixi.lock
(exact versions, all platforms)"] L -- "pixi install" --> E[".pixi/envs/default
(installed packages)"] E -- "pixi run / pixi shell" --> C["your command"] F["features"] --> M
Install and update Pixi
curl -fsSL https://pixi.sh/install.sh | sh
# or
brew install pixipowershell -ExecutionPolicy ByPass -c "irm -useb https://pixi.sh/install.ps1 | iex"
# or
winget install prefix-dev.pixipixi --version # check it is on PATH (restart the shell first)
pixi self-update # upgrade pixi itself (not for brew/winget installs)
pixi completion --shell zsh # shell completion; also bash, fish, powershellCreate a workspace
| Command | What it does |
|---|---|
pixi init my-app | New folder with pixi.toml, .gitignore, .gitattributes |
pixi init | Initialize the current folder |
pixi init --format pyproject | Put the Pixi config inside pyproject.toml under [tool.pixi] (this course keeps a separate pixi.toml) |
pixi init -c conda-forge -p linux-64 -p osx-arm64 | Choose channels and platforms up front |
pixi import environment.yml | Bring an existing conda environment file into the workspace |
pixi init hello && cd hello
pixi add "python=3.14.*"
pixi add numpy pytest
echo 'print("hi")' > app.py
pixi run python app.py
Add and remove dependencies
Pixi installs conda packages (from conda-forge by default) and PyPI packages
in the same environment. Prefer conda-forge: its packages ship compiled libraries and work across languages. Use
--pypi only for packages that are not on conda-forge.
| Command | Effect |
|---|---|
pixi add numpy | Add from conda-forge with a semver range, e.g. numpy = ">=2.3.4,<3" |
pixi add "numpy>=2.1,<3" "python=3.14.*" | Add with explicit version specs (quote them for the shell) |
pixi add --pypi requests-cache | Add a PyPI package ([pypi-dependencies]) |
pixi add --pypi --editable --path . my-package | Install your own src/ package in editable mode |
pixi add --pypi --git https://github.com/org/repo.git pkg --branch main | PyPI package from git (also --tag, --rev) |
pixi add --feature test pytest pytest-cov | Add to a feature instead of the default set |
pixi add --platform win-64 pywin32 | Platform-specific dependency ([target.win-64.dependencies]) |
pixi add --no-install pandas | Update manifest and lockfile only |
pixi remove numpy | Remove (add --pypi / --feature to match how it was added) |
pixi search pandas | Find a conda package and its latest version |
pixi list / pixi tree / pixi tree -i openssl | Installed packages / dependency tree / who depends on openssl |
[dependencies] # conda-forge packages, every environment
python = "3.14.*"
numpy = ">=2.3,<3"
[pypi-dependencies] # PyPI packages (only when not on conda-forge)
my-app = { path = ".", editable = true }
[target.linux-64.dependencies] # platform-specific
libstdcxx-ng = "*"
Run code: run, shell, exec
| Command | Use it when |
|---|---|
pixi run python app.py | Run any command inside the default environment |
pixi run test | Run a task defined in [tasks] |
pixi run -e py315 python -V | Run in a named environment |
pixi run --clean-env python app.py | Hide your shell's environment variables (catches hidden assumptions) |
pixi run python -m pytest -x | Run a module with flags |
pixi shell / pixi shell -e py315 | Interactive shell with the environment active; exit to leave |
pixi shell-hook | Print activation script (for direnv, Docker entrypoints) |
pixi exec --spec "python=3.15" python | One-off command in a temporary cached environment; no workspace needed |
pixi exec ruff check . | Try a tool without installing it (pixi x is the short alias) |
Tasks
Tasks are named commands in pixi.toml. They run cross-platform (Pixi uses its own shell, so
&&, pipes, and $VAR work on Windows too).
[tasks]
fmt = "ruff format ."
lint = "ruff check ."
test = { cmd = "pytest tests/unit", description = "Fast unit tests" }
# run other tasks first
ci = { depends-on = ["fmt", "lint", "test"] }
# arguments with defaults: pixi run greet | pixi run greet Ada
greet = { cmd = "echo hello {{ name }}", args = [{ arg = "name", default = "world" }] }
# environment variables and working directory
serve = { cmd = "python -m http.server 8000", cwd = "docs", env = { PYTHONUNBUFFERED = "1" } }
# caching: skipped when inputs and outputs are unchanged
build = { cmd = "python -m build", inputs = ["src/**/*.py", "pyproject.toml"], outputs = ["dist/*"] }
# run a dependency in another environment
test-315 = { depends-on = [{ task = "test", environment = "py315" }] }
[feature.docs.tasks] # tasks that only exist in environments with this feature
docs = "mkdocs serve"
| Key | Meaning |
|---|---|
cmd | Command string (or list of arguments) |
depends-on | Tasks to run first (names, or tables with task, args, environment) |
args | Named arguments, used as {{ name }} in cmd; optional default |
env | Environment variables for this task |
cwd | Working directory, relative to the workspace root |
inputs / outputs | Glob patterns; when both are unchanged, the task is a cache hit and is skipped |
description | Shown by pixi task list |
clean-env | Run with a minimal environment |
default-environment | Environment used when you don't pass -e |
pixi task list # what can I run?
pixi task add test "pytest tests" --description "All tests"
pixi task alias ci lint test # a task that only runs others
pixi task add --feature docs docs "mkdocs serve"
pixi task remove ci
pixi run greet Ada # pass a task argument
Features, environments, and solve groups
A feature is a named bundle of dependencies, tasks, and settings. An environment is a
list of features (plus the default feature, which is everything at the top level). A solve group makes
several environments share one resolution, so prod and test get identical versions of
shared packages.
[dependencies] # the default feature: in every environment
numpy = ">=2.3,<3"
[feature.test.dependencies]
pytest = "*"
[feature.lint.dependencies]
ruff = "*"
mypy = "*"
[feature.py314.dependencies]
python = "3.14.*"
[feature.py315.dependencies]
python = "3.15.*"
[environments]
default = { features = ["py314", "test", "lint"], solve-group = "main" }
prod = { features = ["py314"], solve-group = "main" } # same numpy as default
py315 = ["py315", "test"] # preview Python
lint = { features = ["lint"], no-default-feature = true } # tiny: no numpy
pixi install -e py315 # install one environment
pixi install --all # install all of them
pixi run -e py315 pytest # run in one
pixi workspace environment add docs --feature docs
pixi workspace environment list
pixi info # environments, features, platforms, cache paths
Platforms and system requirements
The lockfile is solved for every platform in platforms, even ones you are not on, so a Mac user's
lockfile works on a Linux CI runner.
[workspace]
name = "my-app"
channels = ["conda-forge"]
platforms = ["osx-arm64", "osx-64", "linux-64", "win-64"]
[system-requirements] # minimum system versions the packages may assume
macos = "13.0"
cuda = "12"
[target.win-64.tasks] # per-platform tasks (and dependencies, activation)
open-docs = "start docs/index.html"
pixi workspace platform add linux-aarch64
pixi workspace platform remove osx-64
pixi workspace channel add bioconda
Lockfile, update, and upgrade
| Command | Changes manifest? | Changes lockfile? | Use |
|---|---|---|---|
pixi install | No | Only if the manifest changed | Create/refresh environments |
pixi install --locked | No | No; fails if out of date | CI: prove the lockfile matches the manifest |
pixi install --frozen | No | No; installs the lockfile as is | Reproduce exactly, even if the manifest drifted |
pixi lock | No | Yes | Re-solve without installing |
pixi update / pixi update numpy | No | Yes: newest versions within current specs | Routine refresh |
pixi update --dry-run | No | No | Preview what would change |
pixi upgrade / pixi upgrade numpy | Yes: widens specs to the latest | Yes | Cross a major version |
pixi reinstall | No | Only if needed | Rebuild a broken environment |
Global tools
pixi global installs command-line tools each into its own isolated environment and puts their
executables on your PATH (in ~/.pixi/bin). Use it for tools you want everywhere
(gh, git, ripgrep), never for a project's own dependencies.
pixi global install gh ripgrep
pixi global install --environment py python=3.14 ipython # several packages in one env
pixi global list
pixi global update # update all global environments
pixi global remove --environment py ipython
pixi global uninstall gh
pixi global edit # open ~/.pixi/manifests/pixi-global.toml
pixi global sync # make installed tools match that manifest
CI with GitHub Actions
The official prefix-dev/setup-pixi action installs Pixi, installs your environments from the
lockfile, and caches them.
name: CI
on:
push: { branches: ["main"] }
pull_request: { branches: ["main"] }
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v4
- uses: prefix-dev/setup-pixi@v0.8.1
with:
pixi-version: latest
cache: true # cache .pixi keyed on pixi.lock
environments: default py315 # which environments to install
- run: pixi run ci
- run: pixi run -e py315 test
Interactive pixi.toml explorer
pixi.toml is plain TOML, so the standard library can read it. Edit the manifest below (add a task,
a feature, or an environment) and run the cell to see how Pixi would see it: tasks with their dependencies in
execution order, and each environment's resolved feature list.
Configuration and activation
[activation.env] # set whenever the environment is active
APP_ENV = "dev"
PYTHONWARNINGS = "default"
[pypi-options]
index-url = "https://pypi.org/simple"
no-build-isolation = ["my-legacy-package"]
pixi config list
pixi config set --local tls-root-certs system # use the OS certificate store (corporate proxies)
pixi config set default-channels '["conda-forge"]'
pixi auth login prefix.dev --token $TOKEN # private channels
Workspace-local settings live in .pixi/config.toml; user-wide ones in
~/.pixi/config.toml.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
pixi: command not found | Shell not restarted after install | Open a new terminal, or add ~/.pixi/bin to PATH |
ModuleNotFoundError when running python app.py | You ran the system Python, not the workspace's | pixi run python app.py; check with pixi run which python |
| "Cannot solve the request because of ..." | Conflicting specs (often two Python pins), or a package missing for one platform | Read the first lines of the message; loosen a spec; move pins into features; check pixi search |
lock-file not up-to-date with the workspace in CI | Manifest changed without committing a new pixi.lock | Run pixi lock locally and commit it |
| TLS / certificate errors behind a corporate proxy | Custom root certificate | pixi config set tls-root-certs system |
| Environment acts strange after an OS or Pixi update | Stale install | pixi clean then pixi install (or pixi reinstall) |
| Disk filling up | Package cache | pixi clean cache |
| Task works in your shell, fails in CI | Relies on a variable from your shell profile | Reproduce with pixi run --clean-env <task>; put the variable in env or [activation.env] |
| Need more detail | - | Add -v, -vv, or -vvv to any command |
pip, venv, and conda → Pixi
| You used to type | With Pixi |
|---|---|
python -m venv .venv | pixi init (environments are created automatically) |
source .venv/bin/activate | pixi shell, or just prefix commands with pixi run |
pip install numpy | pixi add numpy |
pip install obscure-pkg (not on conda-forge) | pixi add --pypi obscure-pkg |
pip install -e . | pixi add --pypi --editable --path . my-package |
pip install -r requirements.txt | pixi install (dependencies live in pixi.toml) |
pip freeze > requirements.txt | Automatic: pixi.lock |
pip uninstall numpy | pixi remove numpy |
pip list | pixi list |
pip install --upgrade numpy | pixi update numpy (or pixi upgrade numpy to raise the spec) |
python script.py | pixi run python script.py |
pipx install ruff | pixi global install ruff |
pipx run cowsay | pixi exec cowsay |
| You used to type | With Pixi |
|---|---|
conda create -n proj python=3.14 | pixi init proj && pixi add "python=3.14.*" |
conda activate proj | pixi shell (per folder, not a global name) |
conda install -c conda-forge pandas | pixi add pandas |
conda env export > environment.yml | pixi.toml + pixi.lock are always up to date |
conda env create -f environment.yml | pixi import environment.yml, then pixi install |
conda env list | pixi info (environments of this workspace) |
conda update --all | pixi update |
conda run -n proj pytest | pixi run pytest or pixi run -e test pytest |
conda clean --all | pixi clean cache |
conda install into base for a tool | pixi global install <tool> |
| You used to have | With Pixi |
|---|---|
make test | pixi run test with test = "pytest" in [tasks] |
ci: lint test target dependencies | ci = { depends-on = ["lint", "test"] } |
| Make's timestamp-based skipping | inputs / outputs on a task |
export FOO=1 && ... | env = { FOO = "1" } |
A .ps1 and a .sh version of each script | One task; Pixi's shell is cross-platform |