Coming from conda#
If you manage environments with conda create, conda activate, and
environment.yml files, this guide shows how conda-workspaces brings
project-scoped environments, lockfiles, and tasks to the workflow you
already know.
What stays the same#
conda-workspaces is a conda plugin — it uses conda’s solver, channels,
and package infrastructure under the hood. Your .condarc settings,
channel configuration, and package cache all carry over. Environments
are real conda prefixes you can inspect with conda list.
What changes#
Traditional conda |
conda-workspaces |
|---|---|
Environments live in a global location |
Environments live in |
One environment per |
Multiple environments from a single manifest |
No lockfile (or separate conda-lock) |
|
No built-in task runner |
|
|
|
Share |
Share |
Command mapping#
conda |
conda-workspaces |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Migrating an environment.yml#
The fastest way to migrate is the built-in import command:
conda workspace import environment.yml
This reads your environment.yml and writes a conda.toml with the
equivalent workspace configuration. Use --dry-run to preview the
output without writing a file, or -o custom.toml to choose a
different output path.
For reference, given an existing environment.yml:
name: my-project
channels:
- conda-forge
dependencies:
- python>=3.10
- numpy>=1.24
- pandas>=2.0
- pip:
- requests>=2.31
The equivalent conda.toml is:
[workspace]
name = "my-project"
channels = ["conda-forge"]
platforms = ["linux-64", "osx-arm64"]
[dependencies]
python = ">=3.10"
numpy = ">=1.24"
pandas = ">=2.0"
[pypi-dependencies]
requests = ">=2.31"
Then install:
conda workspace install
Lockfiles: reproducibility built in#
Traditional conda has no built-in lockfile. You might use conda env export to capture a snapshot, but the output is platform-specific and
re-solving from it can produce different results over time.
conda-workspaces generates a conda.lock file automatically when you
run conda workspace install or conda workspace lock. The lockfile
records exact package URLs and checksums for every environment and
platform in your workspace:
conda workspace lock # solve only, write conda.lock
conda workspace install # solve, lock, and install
conda workspace install --locked # install from lockfile (validates freshness)
conda workspace install --frozen # install from lockfile (skip freshness check)
--locked ensures the lockfile matches your manifest — if you’ve
changed dependencies since the lockfile was generated, the install
fails and tells you to re-lock. --frozen skips that check and
installs exactly what’s in the lockfile, which is useful in CI where
you want zero solver overhead.
Commit conda.lock to version control and every contributor, CI
runner, and deployment target gets identical environments.
Works with conda env create#
conda-workspaces registers environment spec plugins so that standard conda commands understand workspace manifests and lockfiles directly:
conda env create --file conda.toml -n myenv # solve and create from manifest
conda env create --file conda.lock -n myenv # install exact lockfile contents
This means you can share a conda.toml or conda.lock with someone
who has conda-workspaces installed and they can create an environment
with the familiar conda env create command — no new workflow to
learn.
The companion conda-lockfiles
plugin (installed as a dependency) adds the same conda env create
support for pixi.lock and conda-lock.yml files. Together the two
plugins cover all common lockfile formats:
Plugin |
Files |
Format |
|---|---|---|
conda-workspaces |
|
workspace manifest |
conda-workspaces |
|
rattler-lock v6 |
conda-lockfiles |
|
rattler-lock v6 |
conda-lockfiles |
|
conda-lock v1 |
Multiple environments from one manifest#
With traditional conda you create separate environments and manage them individually. conda-workspaces lets you define composable features in a single file:
[workspace]
name = "my-project"
channels = ["conda-forge"]
platforms = ["linux-64", "osx-arm64"]
[dependencies]
python = ">=3.10"
numpy = ">=1.24"
[feature.test.dependencies]
pytest = ">=8.0"
[feature.docs.dependencies]
sphinx = ">=7.0"
[environments]
default = []
test = { features = ["test"] }
docs = { features = ["docs"] }
One conda workspace install creates all three environments, each
with the right subset of dependencies. Features compose — the test
environment includes everything in default plus pytest.
Adding tasks#
Traditional conda has no task runner, so most projects use Makefiles, shell scripts, or tox. conda-workspaces has tasks built in:
[tasks]
test = { cmd = "pytest tests/ -v", depends-on = ["lint"] }
lint = "ruff check src/"
[tasks.check]
depends-on = ["test", "lint"]
description = "Run all checks"
conda task run -e test check # resolves dependency order automatically
conda task list # shows all available tasks
Tasks support dependency graphs, input/output caching, Jinja2 templates, and per-platform overrides — see features for details.
Project-local environments#
Traditional conda stores environments globally (typically under
~/miniconda3/envs/). conda-workspaces stores them inside your
project:
my-project/
├── conda.toml
├── conda.lock
└── .conda/envs/
├── default/
├── test/
└── docs/
This keeps your project self-contained. Different projects can have different versions of the same packages without conflicting.
Next steps#
Your first project — full walkthrough with environments and tasks
Configuration — all manifest fields and file formats
CI pipeline — using conda-workspaces in GitHub Actions