Changelog#
All notable changes to conda-workspaces will be documented here.
The format follows Keep a Changelog.
Unreleased#
Added#
Documented and enforced a consistent
--jsoncontract across everyconda workspaceandconda tasksubcommand (see the--json contractsection inAGENTS.md). Commands with structured output (info,envs,list,export,import,add,remove,install,lock,quickstart, and theconda taskquery commands) keep emitting a single JSON payload on stdout. Side-effect-only commands (init,activate,run,shell) used to crash withunrecognized arguments: --jsonwhen CI wrappers passed the flag globally; they now accept it silently — the flag is registered withargparse.SUPPRESSso it does not show up in--help— produce no human-readable output, and rely on the exit code for status.conda workspace quickstart --jsonnow owns the JSON surface end-to-end: sub-handlers (init/add/install) are routed through a silent Rich console so no status banners leak before the structured payload.conda workspace initsimilarly suppresses itsCreated conda.toml workspacestatus line underconda_context.json.conda workspace exportgained three new manifest-format exporter plugins:conda-toml,pixi-toml, andpyproject-toml. They register via the sameconda_environment_exportershook asenvironment-yamlandconda-workspaces-lock-v1, so existing CLI behaviour (per-platform projection,--fileinference fromconda.toml/pixi.toml/pyproject.tomlbasenames,--outputstreaming) lights up for free. Each serializer is theexportmethod on the matchingManifestParsersubclass: declared specs shared across all requested platforms land under the top-level[dependencies]/[pypi-dependencies]tables, per-platform deltas under[target.<platform>.*]. Thepyproject-tomlexporter wraps the same content under[tool.conda]so the output drops straight into an existing PEP 621pyproject.toml— when the target file already exists, the exporter splices its[tool.conda]subtree into the existing document so peer[project],[build-system],[tool.ruff], and[tool.pixi]tables survive untouched (any stale[tool.conda]is replaced).conda.tomlandpixi.tomlkeep the default overwrite semantics of every other conda exporter. Together with the existingconda workspace importdirection,conda workspaceis now a bidirectional translator across every manifest dialect it understands.conda workspace lockgained--output <path>and--merge <glob>for CI-split locking pipelines.--outputwrites the solved lockfile to an arbitrary path (e.g.conda.lock.linux-64) instead of the default<workspace>/conda.lock, so matrix runners can each emit a per-platform fragment.--merge(repeatable, supports globs) stitches fragments back into a singleconda.lockwithout running the solver. The merger validates schema version agreement, per-environment channel-list equality, and rejects overlapping(environment, platform)pairs; violations raise the newLockfileMergeErrorand nothing is written. The merged output is byte-stable with a single-runconda workspace lockover the same inputs.--mergeis mutually exclusive with--environment,--platform,--skip-unsolvable, and--output.New
conda workspace quickstartcommand that bootstraps a workspace in one step. It composes the existinginit,add,install, andshellhandlers: run it in an empty directory to scaffold a manifest, immediately add any specs passed on the command line (e.g.conda workspace quickstart python=3.14 numpy), install the selected environment, and drop into an activated shell.--copy(alias--clone) copies an existing workspace’s manifest from a directory or file path instead of runninginit;--formatis then ignored with a warning since the copied manifest dictates the format. Flags frominit(--name,-c/--channel,--platform,--format) andinstall(-e/--environment,--force-reinstall,--locked,--frozen) are forwarded verbatim, alongside conda’s shared output/prompt options (--dry-run,--json,--yes,-v/-q,--debug,--trace,--console).--no-shellskips the finalshellstep (for CI),--jsonimplies--no-shelland prints a single structured{workspace, environment, manifest, specs_added, shell_spawned}payload, and--dry-runreports the pipeline without touching the filesystem.conda workspace locknow writes a singleconda.lockthat covers every platform declared by each environment, not just the host platform. Target-platform solves run withcontext._subdiroverridden for the duration of the solve so conda’s virtual package plugins (__linux,__osx,__win) and the solver’ssubdirsresolution both target the correct subdir.CONDA_OVERRIDE_*and the manifest[system-requirements]table continue to work as before, so downstream constraints like__glibc,__cuda, or__osxcan be pinned explicitly when solving for platforms the host machine would not otherwise advertise.conda workspace lock --platform <subdir>restricts the lock run to a subset of declared platforms. The flag is repeatable (--platform linux-64 --platform osx-arm64). Unknown platforms raisePlatformErrorbefore any solve runs.SolveErrornow names the target platform when it is known, so per-platform failures are easy to spot in CI logs.conda workspace lock --skip-unsolvablekeeps locking the remaining(environment, platform)pairs when an individual solve fails, emitting a yellowSkipping ...line for each skipped pair. The command still raisesAllTargetsUnsolvableErrorwith an aggregated summary if every pair fails, so CI never writes an empty lockfile. Non-solver errors (missing channel, invalid manifest, etc.) continue to abort regardless of the flag.conda_workspaces.resolver.known_platforms(config, resolved_envs)centralises the “platforms this workspace could legitimately be solved for” computation (workspace platforms unioned with the platforms surfaced by each resolved environment).conda workspace locknow uses it to validate--platform, andconda workspace infosurfaces the reachable set as aknown_platformsJSON key (and an extraKnown Platformsrow in the text output whenever a feature broadens the workspace-level set).New
demos/multi-platform.{tape,gif,mp4}demo showcasing cross-platform locking, the reachable-platform row inconda workspace info, and the--platformsubset flag. The existingdemos/lockfilerecording was refreshed to show the multi-platform default output.
Changed#
Internal refactor of the
conda.lockwrite path:generate_lockfilenow buildsconda.models.environment.Environmentobjects and delegates YAML serialisation to the samemultiplatform_exporthook used byconda export --format=conda-workspaces-lock-v1, removing the previously duplicated_build_lockfile_dicthelper.conda workspace lockandconda exportnow produce byte-identical output.Internal refactor of the
conda.lockread path:conda_workspaces.lockfilenow owns both the write path and theCondaEnvironmentSpecifierplugin (CondaLockLoader), and delegates YAML ->Environmentconversion toconda_lockfiles.rattler_lock.v6instead of re-implementing it.conda.lockis now documented as a derivative of rattler-lock v6 (pixi.lock), same schema family, distinct filename and on-disk version byte.conda_workspaces.parsersrenamed toconda_workspaces.manifests(the directory is named after its subject, not the verb; class namesCondaTomlParseretc. are unchanged). Public re-exports are preserved via relative imports within the package.conda_workspaces.env_specshrunk to theconda.tomlenv-spec plugin only (CondaWorkspaceSpec).CondaLockSpechas been replaced byconda_workspaces.lockfile.CondaLockLoader.Plugin metadata is now exposed as module-level
FORMAT/ALIASES/DEFAULT_FILENAMESconstants per plugin module. The canonical lockfileFORMATchanged fromconda-workspaces-locktoconda-workspaces-lock-v1; the old name is registered as an alias alongsideworkspace-lock, so existingconda export --format=conda-workspaces-lockinvocations keep working. Seedocs/reference/format-aliases.mdfor the naming policy.conda workspace addandconda workspace removenow install into the affected environment(s) and refreshconda.lockby default, matchingpixi add/pixi remove. Use--no-installto update the manifest and lockfile without touching the prefix,--no-lockfile-updateto keep the old manifest-only behaviour,--force-reinstallto recreate affected environments from scratch, or--dry-runto solve without writing anything to disk.conda workspace installnow shares a single solve/install/lock pipeline withaddandremove(conda_workspaces/cli/workspace/sync.py).
Added#
Inside a
conda workspace shellsession,add/remove/installprint a hint to re-spawn the shell when a newly installed package drops activation scripts into$PREFIX/etc/conda/activate.d/.
0.3.0 — 2026-03-31#
Added#
conda workspace importcommand to convertenvironment.yml,anaconda-project.yml,conda-project.yml,pixi.toml, andpyproject.tomlmanifests toconda.tomlProgress output during import (reading, format detection, write status)
Syntax-highlighted TOML preview in
--dry-runmodeconda task addandconda task removesupport forpixi.tomlandpyproject.tomlmanifestsCodecov integration and coverage badge
CI, docs, PyPI, and conda-forge badges to README
Documentation for
CONDA_PKGS_DIRShardlink optimization in CI/DockerDiataxis-organized documentation sidebar
Changed#
Import format detection uses human-readable labels instead of class names
Importers use
packaging.Requirementfor robust pip dependency parsingSimplified importer registry to a single
find_importerfunctionUnified installation docs (conda install and pixi global install)
Fixed#
--dry-runoutput no longer strips TOML section headers in non-terminal environmentsTrailing dot suppressed in import status when output is in the current directory
0.2.0 — 2026-03-30#
Added#
conda tasksubcommand withrun,list,add,remove, andexportconda workspace runcommand for one-shot execution in environmentsTask dependencies with topological ordering (
depends-on)Jinja2 template support in task commands (
{{ conda.platform }}, conditionals)Task output caching with input/output file declarations
Per-platform task overrides via
[target.<platform>.tasks]Task arguments with default values
Rich terminal output for all CLI commands (tables, status, errors)
Structured error rendering with actionable hints
Integration tests for CLI workflows
Demo recordings for terminal screencasts
Changed#
Verb-based status messages (Installing, Installed, etc.) replace symbol-based markers
All CLI output routed through Rich console for consistent formatting
Documentation standardized to use
conda workspace/conda taskas primary CLI forms (cw/ctnoted as aliases)Aligned parsers with pixi workspace semantics for broader manifest compatibility
Exception hierarchy expanded with type annotations and actionable hints
Fixed#
JSON output in
conda task list --jsonno longer includes ANSI escapesActivation script handling on Windows uses correct path validation
Solver output noise suppressed during lockfile generation
Stdout flushed after conda solver and transaction API calls
0.1.1 — 2026-03-05#
Changed#
Transferred repository to conda-incubator organization
Added PyPI release workflow with trusted publishing
Moved changelog to repository root
0.1.0 — 2026-03-05#
Added#
Initial implementation of conda-workspaces plugin
conda workspacesubcommand withinit,install,list,info,add,remove,clean,run, andactivatesubcommandsconda workspacestandalone CLI (also available ascw)Parser support for
pixi.toml,conda.toml, andpyproject.tomlmanifestsMulti-environment workspace model with composable features
Solve-group support for version coordination across environments
Per-platform dependency overrides via
[target.<platform>]PyPI dependency parsing (requires conda-pypi for installation)
Project-local environments under
.conda/envs/Sphinx documentation with conda-sphinx-theme
PyPI release workflow with trusted publishing