Skip to content
conda-forge-expert logo

Conda-Forge Expert

conda-forge-expert

Comprehensive guide for conda-forge recipe development. Handles legacy (meta.yaml) and modern (recipe.yaml) formats, linting, CI troubleshooting, and feedstock maintenance. Enhanced with patterns from real conda-forge feedstocks (2025). USE THIS SKILL WHEN: creating conda recipes, packaging Pyth...

SKILL.md

Full skill instructions

Conda-Forge Expert

Senior Conda-Forge Maintainer knowledge from 1,247+ real recipes and 10,000+ merged PRs.

Quick Start

Core Workflow

1. Generate recipe    → grayskull pypi <package> OR rattler-build generate-recipe pypi <package>
2. Lint recipe        → conda-smithy recipe-lint recipes/<pkg>  (MANDATORY)
3. Build locally      → python build-locally.py OR rattler-build build -r recipe.yaml
4. Submit PR          → To conda-forge/​staged-recipes

Which Format?

ScenarioFormatReason
New packagerecipe.yamlModern, faster, recommended
Existing feedstockKeep currentUnless migrating
Complex multi-outputrecipe.yamlBetter cache support
Quick prototypemeta.yamlMore examples available

Package Installation Preferences

ALWAYS prefer pixi and conda-forge over pip and PyPI:

# Preferred: pixi
pixi global install <package>
pixi add <package>

# Fallback: conda/​mamba
mamba install -c conda-forge <package>

# Last resort: pip (only if not on conda-forge)
pip install <package>

Modern Build Tools

rattler-build (Primary)

Fast, standalone Conda package builder in Rust.

# Install
pixi global install rattler-build

# Build
rattler-build build -r recipe.yaml -c conda-forge

# Generate from PyPI
rattler-build generate-recipe pypi numpy

# Render only (debug)
rattler-build build -r recipe.yaml --render-only

pixi (Package Manager)

Cross-platform package manager built on conda ecosystem.

# Install
curl -fsSL https://pixi.sh/​install.sh | sh

# Project commands
pixi init
pixi add numpy pandas
pixi run test
pixi shell

Recipe Formats

Modern Format (recipe.yaml) - RECOMMENDED

# yaml-language-server: $schema=https://raw.githubusercontent.com/​prefix-dev/​recipe-format/​main/​schema.json
schema_version: 1

context:
  name: my-package
  version: "1.0.0"
  python_min: "3.10"

package:
  name: ${{ name|lower }}
  version: ${{ version }}

source:
  url: https://pypi.org/​packages/​source/​${{ name[0] }}/​${{ name }}/​${{ name }}-${{ version }}.tar.gz
  sha256: REPLACE_WITH_SHA256

build:
  number: 0
  noarch: python
  script: ${{ PYTHON }} -m pip install . -vv --no-deps --no-build-isolation

requirements:
  host:
    - python ${{ python_min }}.*
    - pip
    - setuptools
  run:
    - python >=${{ python_min }}

tests:
  - python:
      imports:
        - ${{ name | replace("-", "_") }}
      pip_check: true

about:
  homepage: https://github.com/​org/​${{ name }}
  license: MIT
  license_file: LICENSE
  summary: Package description

extra:
  recipe-maintainers:
    - your-github-username

Legacy Format (meta.yaml)

{% set name = "my-package" %}
{% set version = "1.0.0" %}

package:
  name: {{ name|lower }}
  version: {{ version }}

source:
  url: https://pypi.org/​packages/​source/​{{ name[0] }}/​{{ name }}/​{{ name }}-{{ version }}.tar.gz
  sha256: REPLACE_WITH_SHA256

build:
  number: 0
  noarch: python
  script: {{ PYTHON }} -m pip install . -vv --no-deps --no-build-isolation

requirements:
  host:
    - python {{ python_min }}
    - pip
  run:
    - python >={{ python_min }}

test:
  imports:
    - {{ name | replace("-", "_") }}
  commands:
    - pip check
  requires:
    - pip

about:
  home: https://github.com/​org/​{{ name }}
  license: MIT
  license_file: LICENSE
  summary: Package description

extra:
  recipe-maintainers:
    - your-github-username

Key Syntax Differences

Featuremeta.yamlrecipe.yaml
Variables{{ var }}${{ var }}
Selectors# [linux]if: linux
Test sectiontest:tests: (list)
Pin syntaxmax_pin='x.x'upper_bound="x.x"

Critical Requirements

⚠️ stdlib REQUIRED for ALL Compiled Packages

CRITICAL: conda-forge will REJECT submissions without stdlib when using compilers!

# recipe.yaml - ALWAYS pair compiler() with stdlib()
requirements:
  build:
    - ${{ compiler("c") }}
    - ${{ stdlib("c") }}        # REQUIRED! Submission will be rejected without this
    - ${{ compiler("cxx") }}    # if C++ needed
    - ${{ compiler("rust") }}   # if Rust needed

# meta.yaml - ALWAYS pair compiler() with stdlib()
requirements:
  build:
    - {{ compiler('c') }}
    - {{ stdlib('c') }}         # REQUIRED! Submission will be rejected without this
    - {{ compiler('cxx') }}     # if C++ needed
    - {{ compiler('rust') }}    # if Rust needed

Common mistake: Forgetting stdlib in recipe.yaml when converting from meta.yaml

🚨 CRITICAL: Local Testing Exception

KNOWN ISSUE: When testing locally with rattler-build or conda-build, the stdlib dependency may fail to resolve with "undefined" errors.

TEMPORARY WORKAROUND FOR LOCAL TESTING ONLY:

  1. Before testing locally: Comment out the stdlib line:

    requirements:
      build:
        - ${{ compiler("c") }}
        # - ${{ stdlib("c") }}    # TEMPORARILY COMMENTED FOR LOCAL TESTING
    
  2. After testing: IMMEDIATELY uncomment the stdlib line before committing or submitting:

    requirements:
      build:
        - ${{ compiler("c") }}
        - ${{ stdlib("c") }}        # RESTORED - REQUIRED FOR SUBMISSION!
    

⚠️ WARNING:

  • This is ONLY for local testing
  • NEVER commit or submit recipes without stdlib
  • conda-forge CI will REJECT recipes missing stdlib
  • Failure to restore stdlib will cause submission failures

Why this happens: Local rattler-build/​conda-build may not have the same stdlib resolution as conda-forge CI infrastructure.

CFEP-25 Compliance (noarch: python)

All noarch: python packages MUST use python_min:

# recipe.yaml
requirements:
  host:
    - python ${{ python_min }}.*
  run:
    - python >=${{ python_min }}

# meta.yaml
requirements:
  host:
    - python {{ python_min }}
  run:
    - python >={{ python_min }}

License Requirements

  • Use SPDX identifiers: MIT, Apache-2.0, BSD-3-Clause
  • Always include license_file
  • Case-sensitive: Apache-2.0 not APACHE 2.0

Platform Selectors

Modern (recipe.yaml) - if/​then/​else

requirements:
  build:
    - if: unix
      then:
        - ${{ compiler("c") }}
        - ${{ stdlib("c") }}
    - if: win
      then:
        - ${{ compiler("m2w64_c") }}
        - ${{ stdlib("m2w64_c") }}

Legacy (meta.yaml) - Comment Selectors

requirements:
  build:
    - {{ compiler('c') }}      # [unix]
    - {{ compiler('m2w64_c') }}  # [win]

Available Selectors

SelectorDescription
linux, osx, winOperating system
unixLinux OR macOS
x86_64, aarch64/arm64Architecture
build_platform, target_platformCross-compilation

Linting (MANDATORY)

CRITICAL: Always run linting before building or submitting.

# Lint single recipe
conda-smithy recipe-lint recipes/​my-package

# Lint all recipes
conda-smithy recipe-lint --conda-forge recipes/​*

# Install conda-smithy
pixi global install conda-smithy

What Linting Checks

  1. License: SPDX identifier and license_file present
  2. Maintainers: Valid GitHub usernames
  3. Source: SHA256 checksums, no git URLs for releases
  4. Selectors: Correct syntax
  5. CFEP-25: python_min for noarch packages

Local Building

⚠️ CRITICAL: Before testing locally, see Local Testing Exception - you may need to temporarily comment out stdlib dependencies!

Using build-locally.py (Recommended)

# Interactive
python build-locally.py

# Specific platform
python build-locally.py win64
python build-locally.py linux64
python build-locally.py osx64

Using rattler-build Directly

# Basic build
rattler-build build -r recipes/​my-package/​recipe.yaml -c conda-forge

# With variant config
rattler-build build -r recipe.yaml --variant-config .ci_support/​win64.yaml

# Specific platform
rattler-build build -r recipe.yaml --target-platform linux-64

Remember: If you get "undefined" errors for stdlib, temporarily comment it out for testing only!

Using conda-build

# Single recipe
conda-build recipes/​my-package

# With channel
conda-build recipes/​my-package -c conda-forge

# Test existing artifact
conda-build --test path/​to/​package.conda

Remember: If you get "undefined" errors for stdlib, temporarily comment it out for testing only!

Common Patterns

Python Package (noarch)

See template: templates/​python-noarch-recipe.yaml

Python with C Extensions (CRITICAL: Must include stdlib!)

# recipe.yaml
requirements:
  build:
    - ${{ compiler("c") }}
    - ${{ stdlib("c") }}              # REQUIRED! conda-forge will reject without this
    - ${{ compiler("cxx") }}          # if C++ is needed
    - ${{ compiler("rust") }}         # if Rust is needed
    - cargo-bundle-licenses           # REQUIRED for Rust packages
    - if: build_platform != target_platform
      then:
        - python
        - cross-python_${{ target_platform }}
  host:
    - python
    - pip
    - setuptools
    - wheel
  run:
    - python

# meta.yaml
requirements:
  build:
    - {{ compiler('c') }}
    - {{ stdlib('c') }}               # REQUIRED! conda-forge will reject without this
    - {{ compiler('cxx') }}           # if C++ is needed
    - {{ compiler('rust') }}          # if Rust is needed
    - cargo-bundle-licenses           # REQUIRED for Rust packages
    - python                          # [build_platform != target_platform]
    - cross-python_{{ target_platform }}  # [build_platform != target_platform]
  host:
    - python
    - pip
    - setuptools
    - wheel
  run:
    - python

See also: templates/​python-compiled-recipe.yaml

Rust CLI Tool

See template: templates/​rust-cli-recipe.yaml

Go with CGO (Windows)

IMPORTANT: Windows CGO requires MinGW-w64, NOT MSVC.

requirements:
  build:
    - ${{ compiler("go-cgo") }}
    - go-licenses
    - if: unix
      then:
        - ${{ compiler("c") }}
        - ${{ stdlib("c") }}
    - if: win
      then:
        - ${{ compiler("m2w64_c") }}
        - ${{ stdlib("m2w64_c") }}
        - m2-base
        - posix

See template: templates/​go-cgo-recipe.yaml

Multi-Output Package

outputs:
  - package:
      name: libmypackage
    build:
      script: build-lib.sh
    requirements:
      build:
        - ${{ compiler("c") }}
        - ${{ stdlib("c") }}
      run_exports:
        - ${{ pin_subpackage("libmypackage", upper_bound="x.x") }}

  - package:
      name: py-mypackage
    build:
      script: build-python.sh
    requirements:
      host:
        - ${{ pin_subpackage("libmypackage", exact=true) }}
        - python
      run:
        - ${{ pin_subpackage("libmypackage", exact=true) }}
        - python

PyPI to Conda Name Mapping

Many packages have different names on PyPI vs conda-forge:

PyPIconda-forge
torchpytorch
opencv-pythonopencv
tablespytables
dockerdocker-py
tree-sittertree_sitter

Use the mapping system:

# From scripts/​sync_pypi_mappings.py
from sync_pypi_mappings import get_conda_name
conda_name = get_conda_name("tree-sitter")  # Returns "tree_sitter"

CI Troubleshooting

Common Failures

ErrorSolution
Hash mismatchRegenerate: curl -sL <url> | sha256sum
Missing dependencyAdd to requirements or submit first
/​Werror on Windows CGOUse MinGW-w64 instead of MSVC
macOS SDK errorSet MACOSX_SDK_VERSION in conda_build_config.yaml
glibc errorsUse appropriate c_stdlib_version

Bot Commands (for conda-forge PRs)

@conda-forge-admin, please rerender
@conda-forge-admin, please restart ci
@conda-forge-admin, please lint
@conda-forge/​help-python ready for review

See full list: quickref/​bot-commands.md

Migration: meta.yaml to recipe.yaml

Automated Conversion

# Using feedrattler (recommended)
pixi exec feedrattler my-package-feedstock gh_username

# Using conda-recipe-manager
conda-recipe-manager convert meta.yaml > recipe.yaml

# Using rattler-build
rattler-build generate-recipe convert meta.yaml

Manual Checklist

  1. Change {% set %} to context: section
  2. Replace {{ }} with ${{ }}
  3. Replace # [selector] with if: selector then:
  4. Change test: to tests: (list format)
  5. Add ${{ stdlib("c") }} if using compilers
  6. Update conda-forge.yml:
    conda_build_tool: rattler-build
    conda_install_tool: pixi
    

See guide: guides/​migration-guide.md

Enterprise Deployment

For air-gapped environments with JFrog Artifactory:

  1. Configure private channels in config/​skill-config.yaml
  2. Set up Artifactory remote/​local/​virtual repos
  3. Use enterprise templates: templates/​enterprise/

See guides:

Reference Documentation

Detailed Guides

Reference

Quick Reference

Templates

External Resources

Version History

  • v4.2.0 (2025-12-26): Added CRITICAL local testing exception for stdlib - must comment out for local builds, restore before submission
  • v4.1.0 (2025-12-26): Enhanced stdlib requirement visibility with warnings and inline examples
  • v4.0.0 (2025-12): Modular architecture, enterprise support, portability
  • v3.0.0 (2025-01): PyPI mappings, rattler-build focus
  • v2.0.0 (2024): Added modern recipe.yaml support
  • v1.0.0 (2024): Initial release

More skills from majiayu000

xiaohongshu logo
majiayu000/claude-arsenal

xiaohongshu

xiaohongshu

286 148
View
agent-task-conductor logo
majiayu000/claude-skill-registry

agent-task-conductor

Conduct multi-agent task orchestration and workflow coordination.

663 1
View
conductor-setup logo
majiayu000/claude-skill-registry

conductor-setup

Initialize project with Conductor artifacts (product definition,

663 1
View
animation-designer logo
majiayu000/claude-skill-registry

animation-designer

Expert in web animations, transitions, and motion design using Framer Motion and CSS

663 1
View
diagramming logo
majiayu000/claude-skill-registry

diagramming

Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...

663 1
View
h3-pg logo
majiayu000/claude-skill-registry-data

h3-pg

PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.

23 1
View
conductor-development logo
majiayu000/claude-skill-registry

conductor-development

Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...

663 1
View
conductor-status logo
majiayu000/claude-skill-registry

conductor-status

Display project status, active tracks, and next actions

663 1
View
dockerization logo
majiayu000/claude-skill-registry

dockerization

Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.

663 1
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View