Skip to content

V3 packages (beta)#

Beta — not for production use

V3 is an opt-in preview of the next conda repodata revision and is still under active development. The on-disk repodata format, the index.json layout, recipe fields (build.flags, requirements.extras, …) and the MatchSpec bracket syntax described on this page can and will change in backwards-incompatible ways before V3 is finalized. Concretely, this means:

  • Packages built with today's --v3 may stop being parseable by a future rattler-build / rattler / pixi without a rebuild.
  • The repodata_revision: 3 shape is not stable; the field name, value, and surrounding schema may all change.
  • Recipes using V3-only features may need edits when the syntax stabilizes.

Do not publish V3 packages to channels that other users or CI systems depend on. Use V3 only for experimentation, prototyping, and feedback — and expect to rebuild from source when the format stabilizes. Track the discussion in the relevant CEPs and the rattler-build issue tracker before depending on it.

V3 is a new revision of the conda repodata format. It extends the existing package record with two new fields and adds a richer MatchSpec bracket syntax that lets you express conditional, optional and variant-tagged dependencies. Rattler-Build can produce V3 packages and parse V3 recipes, but only when the feature is explicitly enabled.

Opting in#

V3 is gated behind a single flag. There are two ways to turn it on:

  • Pass --v3 on the command line:

    rattler-build build --v3 --recipe recipe.yaml
    
  • Or use the equivalent option from the Python bindings / library API (CommonData::new(..., v3: true, ...), RenderConfig::new().with_v3(true), ParseConfig { v3: true }).

When the flag is off (the default), Rattler-Build behaves exactly like before:

  • Recipes that use V3-only fields (build.flags, requirements.extras) fail to evaluate with an error pointing at --v3.
  • MatchSpec strings that use V3-only bracket keys (flags=[…], extras=[…], when="…") fail to parse with the same error.
  • Built packages get the legacy index.json shape — there is no repodata_revision field and no flags array.

When the flag is on:

  • The new recipe fields are accepted and round-tripped through Stage 0/Stage 1 evaluation.
  • V3 MatchSpec syntax is parsed everywhere a dependency string is allowed (requirements.{build,host,run,run_constraints,extras}, run_exports).
  • Built packages are tagged with repodata_revision: 3 in index.json and carry their declared variant flags in a top-level flags array. Optional dependency groups are written into the extra_depends mapping.

What V3 adds#

build.flags — package variant flags#

Flags are short lowercase tags that describe a variant of a package — the canonical examples are cuda, blas:openblas, mpi:mpich. They are stored on the package record and can be matched by downstream specs (see below).

build:
  flags:
    - cuda
    - blas:openblas

A flag must match ^[a-z0-9_]+(:[a-z0-9_]+)?$ — i.e. lowercase ASCII, digits and underscores, optionally with a single :-separated suffix. Flags are conditional and templated like other recipe lists, so this is valid:

build:
  flags:
    - if: cuda_compiler_version != "None"
      then: cuda
    - blas:${{ blas_impl }}

Flags that depend on a Jinja variable participate in variant hashing, so each flag combination produces its own build hash.

requirements.extras — optional dependency groups#

extras is a mapping from a group name to a list of dependencies. The group is not installed by default — consumers opt in via the extras=[…] MatchSpec bracket key. This mirrors the "optional dependencies" idea from pyproject.toml.

requirements:
  run:
    - python >=3.10
  extras:
    plot:
      - matplotlib >=3.8
    full:
      - matplotlib >=3.8
      - pandas >=2

A consumer that wants the plot group writes:

requirements:
  run:
    - mypkg[extras=[plot]]

In the built package, optional groups land in index.json::extra_depends.

Richer MatchSpec syntax#

V3 extends the bracket form of MatchSpec with three new keys. They can be combined with the existing keys (version=…, build=…, channel=…, …).

flags=[…] — match by variant flag#

Selects builds whose flags array contains the listed entries. A * suffix is a glob over the second segment.

requirements:
  run:
    - pytorch[flags=[cuda]]
    - numpy[flags=[blas:*]]          # any BLAS flavour
    - mamba[flags=[cuda, blas:openblas]]

when="…" — conditional dependencies#

A spec with when="…" is only included when the embedded predicate is satisfied by the rest of the resolved environment. This replaces the old ; if syntax (which is now deprecated).

requirements:
  run:
    - python
    - scipy[when="python >=3.10"]
    - numpy >=2.0[when="python >=3.10 and __linux"]

The predicate is itself a small spec language and supports and, or, not, parentheses, virtual packages (__linux, __glibc, …) and nested MatchSpecs.

extras=[…] — pull in optional groups#

Already shown above — uses the group names declared by the producing package's requirements.extras.

requirements:
  run:
    - mypkg[extras=[plot, full]]

What ends up in index.json#

A V3 build writes (in addition to the existing fields):

{
  "repodata_revision": 3,
  "flags": ["cuda", "blas:openblas"],
  "extra_depends": {
    "plot": ["matplotlib >=3.8"]
  }
}

flags and extra_depends are omitted when empty. The repodata_revision field is the signal that downstream tools should use the V3 parser; it is only written when the build was run with --v3.

Compatibility notes#

  • V3 packages are still valid .conda archives — they only differ in metadata. Older clients that ignore unknown fields will still install the base package, but will silently miss conditional dependencies, flag-based selection and optional groups.
  • Consuming a V3 package correctly requires a resolver that understands V3 (recent rattler / pixi / conda versions). Check your toolchain before publishing.
  • Mixing V3 syntax in a recipe without passing --v3 is always an error — it never silently downgrades.