Configuration#

Note

All paths below use ~/ as shorthand for your home directory: /home/<user>/ or /Users/<user>/ on macOS/Linux, %USERPROFILE% (typically C:\Users\<user>\) on Windows.

conda-workspaces searches for manifests in the current directory and its parents. The first matching file is used.

For the normative description of every field accepted in conda.toml and the [tool.conda.*] embedded form, see the conda.toml specification. This page is the how-to companion: it shows full examples and table summaries grouped by task.

Workspace search order#

  1. conda.toml — conda-native workspace manifest

  2. pixi.toml — pixi-native format (workspace/task compatibility)

  3. pyproject.toml — embedded under [tool.conda.*] or [tool.pixi.*]

Task search order#

  1. conda.toml — conda-native task manifest

  2. pixi.toml — pixi-native format (reads [tasks] directly)

  3. pyproject.toml — reads [tool.conda.tasks] or [tool.pixi.tasks]

conda task add and conda task remove edit whichever of these files is selected by that search order, using the same tables as above (for pyproject.toml, under [tool.conda.tasks] or [tool.pixi.tasks] according to the same precedence rules as reading).

When both [tool.conda] and [tool.pixi] exist in the same pyproject.toml, the entire [tool.conda] table takes precedence. This means that if [tool.conda] has any content (e.g. workspace settings) but no [tool.conda.tasks], tasks from [tool.pixi.tasks] will not be loaded. To use pixi tasks, either remove [tool.conda] entirely or define your tasks under [tool.conda.tasks].

When a file defines both workspace and task sections, both are used.

User-level tasks#

Tasks can also be defined in a user-level file that applies across all projects. This is useful for personal utility tasks (formatting, linting, cleanup) that you want available everywhere without repeating them in every project manifest.

User task file search order#

  1. $XDG_CONFIG_HOME/conda/tasks.toml (if XDG_CONFIG_HOME is set)

  2. ~/.config/conda/tasks.toml (XDG default)

  3. ~/.conda/tasks.toml (legacy fallback)

First file found wins. If none exist, user-level tasks are not loaded.

The format is the same [tasks] table as in conda.toml:

[tasks]
fmt = { cmd = "ruff format .", description = "Format Python files" }
clean = { cmd = "git clean -fdx -e .conda", description = "Remove untracked files" }
check = { cmd = "ruff check --fix .", description = "Lint and auto-fix" }

Merge semantics#

User tasks act as a base layer beneath project tasks:

  • Project tasks override user tasks on name collision (project always wins)

  • User-only tasks (not defined in the project) are included as-is

  • depends-on can reference tasks from either layer

  • conda task list shows user tasks with a (user) annotation

No project manifest required#

User tasks work even without a project conda.toml in the current directory. Running conda task run fmt in any directory executes the user-defined task. If neither a project manifest nor a user task file exists, conda task run falls back to ad-hoc command execution.

Lockfile format#

conda workspace lock and conda workspace install produce and consume conda.lock, conda-workspaces’ own lockfile. It is a derivative of rattler-lock v6 (pixi.lock): the YAML schema is the same, the converters in conda-lockfiles are reused, and only the on-disk version byte differs (conda.lock uses version: 1, pixi.lock uses version: 6). A tool can translate between the two lockfile names by changing that version field. A plain rename is not a valid conversion.

See Plugin format names and aliases for the canonical and alias strings accepted by conda env create --file conda.lock and conda export --format=....

File formats#

conda.toml#

The conda-native format. Its core workspace, feature, environment, dependency, and task tables follow the same shape as pixi.toml, but it uses [workspace] exclusively (no [project] fallback) and can include conda-workspaces-specific extensions. Supports both workspace and task definitions in a single file.

[workspace]
name = "my-project"
channels = ["conda-forge"]
platforms = ["linux-64", "osx-arm64", "win-64"]

[dependencies]
python = ">=3.10"
numpy = ">=1.24"

[pypi-dependencies]
my-pkg = { path = ".", editable = true }

[feature.test.dependencies]
pytest = ">=8.0"
pytest-cov = ">=4.0"

[feature.docs.dependencies]
sphinx = ">=7.0"
myst-parser = ">=3.0"

[environments]
default = []
test = { features = ["test"] }
docs = { features = ["docs"] }

[target.linux-64.dependencies]
linux-headers = ">=5.10"

[activation]
scripts = ["scripts/setup.sh"]
env = { PROJECT_ROOT = "." }

[tasks]
build = "python -m build"
test = { cmd = "pytest tests/ -v", depends-on = ["build"] }
lint = { cmd = "ruff check .", description = "Lint the code" }

[tasks.check]
depends-on = ["test", "lint"]

[target.win-64.tasks]
build = "python -m build --wheel"

pixi.toml#

The pixi-native format. conda-workspaces reads the workspace and task fields documented here, including pixi-style rich platform entries:

[workspace]
name = "my-project"
channels = ["conda-forge"]
platforms = ["linux-64", "osx-arm64", "win-64"]

[dependencies]
python = ">=3.10"
numpy = ">=1.24"

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

[environments]
default = []
test = { features = ["test"] }

[tasks]
build = "python -m build"
test = { cmd = "pytest", depends-on = ["build"] }

The legacy [project] table is also accepted (pre-workspace pixi manifests).

pyproject.toml#

Workspace and task configuration is embedded under [tool.conda.*] (preferred) or [tool.pixi.*]:

[tool.conda.workspace]
name = "my-project"
channels = ["conda-forge"]
platforms = ["linux-64", "osx-arm64", "win-64"]

[tool.conda.dependencies]
python = ">=3.10"
numpy = ">=1.24"

[tool.conda.feature.test.dependencies]
pytest = ">=8.0"

[tool.conda.environments]
default = []
test = { features = ["test"] }

[tool.conda.tasks]
build = "python -m build"

[tool.conda.tasks.test]
cmd = "pytest"
depends-on = ["build"]
[tool.pixi.workspace]
name = "my-project"
channels = ["conda-forge"]
platforms = ["linux-64", "osx-arm64", "win-64"]

[tool.pixi.dependencies]
python = ">=3.10"

[tool.pixi.feature.test.dependencies]
pytest = ">=8.0"

[tool.pixi.environments]
default = []
test = { features = ["test"] }

[tool.pixi.tasks]
build = "python -m build"
test = { cmd = "pytest", depends-on = ["build"] }

Workspace table#

The [workspace] (or [project]) table defines workspace metadata:

Field

Type

Description

name

string

Workspace name (optional, defaults to directory name)

version

string

Workspace version (optional)

description

string

Short description (optional)

channels

list of strings

Conda channels, in priority order

platforms

list of strings or rich platform tables

Supported platforms (e.g. linux-64, osx-arm64, { platform = "linux-64", cuda = "12.0" })

channel-priority

string

Channel priority mode: strict, flexible, or disabled

Dependencies#

Dependencies use conda match-spec syntax:

[dependencies]
python = ">=3.10"
numpy = ">=1.24,<2"
scipy = "*"          # any version
cuda-toolkit = { version = ">=12", build = "*cuda*" }

Shared conda specs can live under [workspace.dependencies]. Any conda dependency table can opt into a shared spec with { workspace = true }. The consuming entry may add non-version fields such as build or channel. This matches the workspace dependency inheritance syntax that pixi added in 0.70.0.

[workspace.dependencies]
numpy = "1.*"
cmake = { version = ">=3.28", channel = "conda-forge" }

[dependencies]
python = ">=3.12"
numpy = { workspace = true }

[feature.build.dependencies]
cmake = { workspace = true, build = "h*" }

Feature table#

Each [feature.<name>] table can contain:

Field

Type

Description

dependencies

table

Conda dependencies for this feature

pypi-dependencies

table

PyPI dependencies for this feature

channels

list

Additional channels for this feature

platforms

list

Platform restrictions for this feature

system-requirements

table

System-level requirements

activation.scripts

list

Activation scripts

activation.env

table

Environment variables set on activation

target

table

Per-platform dependency overrides for this feature

tasks

table

Tasks contributed by this feature

Environments table#

Each entry in [environments] defines a named environment:

Field

Type

Description

features

list of strings

Features to include (in addition to default)

solve-group

string

Accepted for pixi compatibility. Currently ignored by conda-workspaces

no-default-feature

bool

Exclude the default feature (default: false)

Shorthand forms are supported:

[environments]
# Full form
test = { features = ["test"] }

# Features only
lint = ["lint"]

# Default environment shorthand
default = []

Task fields#

Field

Type

Description

cmd

string or list[string]

Command to execute. Omit for aliases.

args

list

Named arguments with optional defaults.

depends-on

list

Tasks to run before this one.

cwd

string

Working directory for the task.

env

dict

Environment variables to set.

description

string

Human-readable description.

inputs

list[string]

Glob patterns for cache inputs.

outputs

list[string]

Glob patterns for cache outputs.

clean-env

bool

Run with minimal environment variables.

default-environment

string

Conda environment to activate by default.

target

dict

Per-platform overrides (keys are platform strings).

Task argument definitions#

[tasks.test]
cmd = "pytest {{ path }} {{ flags }}"
args = [
  { arg = "path", default = "tests/" },
  { arg = "flags", default = "-v" },
]

Task dependency definitions#

Simple list:

[tasks.check]
depends-on = ["compile", "lint"]

With arguments:

[tasks.check]
depends-on = [
  { task = "test", args = ["tests/unit/"] },
]

With environment:

[tasks.check]
depends-on = [
  { task = "test", environment = "py311" },
]

Archive configuration#

The [workspace.archive] table controls which files are included and excluded when creating archives with conda workspace archive, as well as the compression format.

[workspace.archive]
include = ["src/**", "conda.toml", "conda.lock"]
exclude = ["*.log", "data/raw/**"]
compression = "zst"
compression-level = 19

Field

Type

Description

include

list of strings

Glob patterns for files to include in archives. When set, only matching files are archived.

exclude

list of strings

Glob patterns for files to exclude from archives

compression

string

Compression algorithm: "zst" (default), "gz", or "bz2"

compression-level

integer

Compression level (algorithm-dependent, omit for library default)

When both include and exclude are set, include patterns narrow the file set first, then exclude patterns remove from that set. When include is empty (the default), all files are candidates.

Patterns use fnmatch matching against paths relative to the workspace root. Both directory globs (docs/**) and file globs (*.log) are supported.

Built-in exclusions always apply regardless of this setting:

  • .git

  • .conda/envs

  • .pixi

  • __pycache__

  • common credential material such as .env, .ssh, .aws, .azure, .config/gcloud, .docker, .gnupg, .kube, .terraform, .npmrc, .pypirc, .netrc, private keys, certificate/key bundles, and Terraform state files

Dotenv templates such as .env.example, .env.sample, .env.template, and .env.dist remain eligible for archives unless excluded explicitly.

CLI --exclude flags are combined with manifest exclusions. In git repos, only tracked files are considered regardless of exclusion patterns.

Receipt-compatible archive filters#

conda workspace archive --receipt requires the workspace manifest and conda.lock to be included in the archive because the receipt binds and later verifies both files. If you set include, make sure those files are part of the allowlist:

[workspace.archive]
include = ["conda.toml", "conda.lock", "src/**"]

Do not exclude the manifest or lockfile when writing receipts:

[workspace.archive]
exclude = ["docs/**", "*.log", "data/raw/**"]

If manifest settings or CLI --exclude patterns would remove either file, receipt creation fails before writing the archive or receipt. Run without --receipt only when you intentionally want an archive that is not receipt-verifiable.