# Pixi: Multi-Language Package and Workflow Manager


Pixi is a cross-platform package manager and workflow tool that manages both [conda-forge](https://pydevtools.com/handbook/reference/conda-forge.md) packages and PyPI packages from a single project manifest. It replaces [conda](https://pydevtools.com/handbook/reference/conda.md)'s global environment model with project-local environments and automatic lockfiles.

> [!NOTE]
> Pixi targets the same package ecosystem as conda but with a different workflow model. If you don't need conda-forge packages, [uv](https://pydevtools.com/handbook/reference/uv.md) is a simpler choice. See [When should I choose pixi over uv?](https://pydevtools.com/handbook/explanation/when-should-i-choose-pixi-over-uv.md) for a detailed comparison.

## When to use pixi

Use pixi when your project depends on native libraries that conda-forge packages more reliably than PyPI: CUDA toolkits, GDAL, HDF5, OpenCV, MKL, NetCDF. Some of these have PyPI packages, but conda-forge bundles the underlying C/C++/Fortran libraries so you don't need to install them separately. Pixi also works well for mixed-language projects (Python + R, Python + C++) and for teams that want reproducible cross-platform lockfiles covering both conda and PyPI dependencies.

For pure Python projects, [uv](https://pydevtools.com/handbook/reference/uv.md) provides a simpler workflow.

## Installation

```bash
curl -fsSL https://pixi.sh/install.sh | bash
```
```powershell
iwr -useb https://pixi.sh/install.ps1 | iex
```
This installs the `pixi` binary to `~/.pixi/bin` (macOS/Linux) or `%UserProfile%\.pixi\bin` (Windows). See the [official installation guide](https://pixi.sh/latest/getting_started/) for other methods.

## Project setup

Initialize a new project with `pixi init`:

```bash
pixi init my-project
cd my-project
```

This creates a `pixi.toml` manifest:

```toml
[workspace]
authors = ["Your Name <you@example.com>"]
channels = ["conda-forge"]
name = "my-project"
platforms = ["osx-arm64"]  # auto-detected from your system
version = "0.1.0"

[dependencies]

[tasks]
```

To use `pyproject.toml` instead (useful if you're building a Python package):

```bash
pixi init --format pyproject my-project
```

With `pyproject.toml`, pixi configuration lives under `[tool.pixi.*]` sections (e.g. `[tool.pixi.workspace]`, `[tool.pixi.dependencies]`), while standard `[project]` metadata remains portable to other Python tools.

## Managing dependencies

### Conda packages

```bash
pixi add python numpy pandas
```

### PyPI packages

```bash
pixi add --pypi requests
```

Pixi resolves conda dependencies first, then resolves PyPI packages against what conda already installed. It uses [uv](https://pydevtools.com/handbook/reference/uv.md) internally for PyPI resolution.

### Workspace dependencies

For workspaces with multiple packages, `pixi workspace dependencies add` adds shared dependencies at the workspace level:

```bash
pixi workspace dependencies add python numpy
```

Use package-level dependency tables when only one workspace member needs a package.

### Installing the environment

```bash
pixi install
```

This creates a `.pixi/` directory containing the project environment. The directory is local to the project and should be added to `.gitignore` (pixi does this automatically on `pixi init`).

## Running commands

```bash
# Run a command in the project environment
pixi run python main.py

# Start an interactive shell
pixi shell
```

## Running self-contained scripts

Pixi runs [PEP 723](https://pydevtools.com/handbook/explanation/what-is-pep-723.md) scripts directly, without a project directory or `pixi.toml`:

```python {filename="hello.py"}
# /// script
# requires-python = ">=3.11"
# dependencies = ["rich>=13.9.2"]
# ///
import rich

rich.print("Hi from [bold magenta]hello.py[/bold magenta]!")
```

```bash
pixi run --script hello.py
```

Pixi reads the metadata block, creates an isolated environment with the listed packages, and runs the script. `pixi init --script` writes an empty block into a script that has none (it refuses a script that already carries one), and `pixi add --script` fills the block in:

```bash
pixi init --script report.py
pixi add --script report.py --pypi rich
```

### Mixing conda dependencies

Pixi extends the standard PEP 723 block with a `[tool.pixi]` section for conda packages, something uv and other PEP 723 runners cannot do. Omit `--pypi` and `pixi add` treats the package as a conda dependency:

```bash
pixi init --script earthquakes.py --channel conda-forge
pixi add --script earthquakes.py gdal
pixi add --script earthquakes.py --pypi httpx
```

Those commands leave the script's own code alone and write the metadata above it:

```python {filename="earthquakes.py"}
# /// script
# requires-python = ">=3.11"
# dependencies = ["httpx"]
#
# [tool.pixi.workspace]
# channels = ["conda-forge"]
#
# [tool.pixi.dependencies]
# gdal = "*"
# ///
```

Another PEP 723 runner reads `dependencies` and ignores `tool.pixi`, so it installs `httpx` but not GDAL.

### Running remote scripts and locking versions

`pixi run --script` accepts URLs, GitHub Gist URLs, or stdin (`-`):

```bash
pixi run --script https://example.com/fetch.py
pixi run --script - < fetch.py
```

Remote and stdin scripts must already carry a metadata block; only local paths can be edited, inspected, or locked.

To lock a script's dependencies for reproducibility:

```bash
pixi lock --script hello.py
```

This writes a `hello.py.pixi.lock` sidecar next to the script.

### Conda scripts

Pixi's experimental `conda-script` format embeds conda dependencies and an entrypoint in a source file, including the channels used to resolve them. Unlike PEP 723, the format works with languages whose comment prefix contains no letters or digits (`#`, `//`, `--`, `%`), covering Python, R, Bash, C++, SQL, and MATLAB but not languages that use word-based comments like `REM`. Enable it once before running these scripts:

```bash
pixi config set experimental.conda-script true --global
```

For example, this R file declares its interpreter and stays valid R source code:

```r {filename="hello.R"}
# /// conda-script
# channels = ["conda-forge"]
# entrypoint = "Rscript ${SCRIPT}"
#
# [dependencies]
# r-base = "*"
# /// end-conda-script

cat("Hello from pixi!\n")
```

Run it without creating a workspace:

```console
$ pixi run --script hello.R
⚠️ Running hello.R through `experimental.conda-script`, a draft format that may still change
✨ Pixi script (hello.R): Rscript ${SCRIPT}
Hello from pixi!
```

Pixi resolves the environment, caches it, and runs the declared entrypoint. With the experimental setting enabled, `pixi init --script hello.R` generates the metadata block and starter code from the file extension.

## Tasks

Pixi includes a built-in task runner. Tasks are defined in `pixi.toml` and run within the project environment.

```bash
# Add tasks
pixi task add test "pytest -s"
pixi task add lint "ruff check ."

# Run a task
pixi run test
```

Tasks can also be defined directly in `pixi.toml` with dependencies on other tasks:

```toml
[tasks]
lint = "ruff check ."
test = { cmd = "pytest -s", depends-on = ["lint"] }
```

## Multi-environment support

Pixi can define multiple environments from composable "features." Each feature is a named set of dependencies; environments combine one or more features. Named environments include the default feature's dependencies unless you set `no-default-feature = true`.

```toml
[dependencies]
python = ">=3.12"
numpy = ">=2.0"

[feature.test.dependencies]
pytest = ">=8"

[feature.docs.dependencies]
sphinx = ">=7"

[environments]
test = ["test"]
docs = ["docs"]
```

Run commands in a specific environment:

```bash
pixi run --environment test pytest
pixi run --environment docs sphinx-build docs build
```

## Cross-platform lockfiles

Pixi resolves dependencies for all target platforms in a single `pixi.lock` file. Add platforms with:

```bash
pixi workspace platform add linux-64 win-64
```

The lockfile captures the full dependency graph for every platform and environment combination. Each platform is solved separately, so exact builds may differ across OSes, but every collaborator gets a reproducible install for their platform.

Pixi upgrades older lockfile formats automatically on the next `pixi lock` or `pixi update`, but older pixi builds may be unable to read a regenerated `pixi.lock`. Coordinate lockfile upgrades across collaborators and CI before committing one. Pixi lockfiles record build and host environments, avoid churn from comment-only manifest edits, and keep relative paths relative for Docker and cross-machine portability.

## Tool management

Like [pipx](https://pydevtools.com/handbook/reference/pipx.md) or `uvx`, pixi can install CLI tools globally or run them in temporary environments:

```bash
# Install a tool globally
pixi global install ruff

# Run a tool without installing it
pixi exec black --check .

# List globally installed tools
pixi global list
```

## Building packages from source (preview)

Pixi Build lets pixi build packages from source instead of only consuming prebuilt conda packages. The system uses language-specific build backends inspired by Python's [PEP 517](https://pydevtools.com/handbook/explanation/what-is-pep-517.md) [build backend](https://pydevtools.com/handbook/explanation/what-is-a-build-backend.md) protocol: `pixi-build-python` for Python projects (using hatchling and [uv](https://pydevtools.com/handbook/reference/uv.md) internally) and `pixi-build-rust` for Rust projects.

Enable the feature with a preview flag in `pixi.toml`:

```toml
[workspace]
preview = ["pixi-build"]
```

Configure a build backend in the package manifest:

```toml
[package.build.backend]
name = "pixi-build-python"

[host-dependencies]
hatchling = "*"

[run-dependencies]
python = ">=3.12"
```

Build dependencies stay isolated from the runtime environment. Pixi rebuilds packages in dependency order with caching, so a monorepo with path dependencies (`fibtable = { path = "." }`) rebuilds only what changed.

SciPy, Xarray, Dask, and CPython have adopted pixi-build in early preview. See the [pixi-build documentation](https://pixi.sh/latest/features/build/) for the full configuration reference.

## Other useful commands

```bash
# Search for a package on configured channels
pixi search opencv

# Show the dependency tree
pixi tree

# Show environment and system info
pixi info

# Update dependencies to latest compatible versions
pixi update
```

## Supply chain security

Pixi supports `exclude-newer`, which delays adoption of newly released packages by a configurable period. This gives malicious or broken packages time to be caught before they reach a project's resolved dependencies.

Set a workspace-wide cooldown in `pixi.toml`:

```toml
[workspace]
exclude-newer = "7d"
```

Per-channel or per-package overrides are supported for packages under internal control:

```toml
[workspace]
channels = [
  "conda-forge",
  { channel = "https://prefix.dev/my-channel", exclude-newer = "0d" },
]
exclude-newer = "14d"

[exclude-newer]
my-internal-package = "0d"
```

The value accepts a duration (`"7d"`, `"30d"`) or an ISO date (`"2026-01-01"`). The setting applies to both conda and PyPI packages.
