Claude-skill-registry conda-forge-expert
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/conda-forge-expert" ~/.claude/skills/majiayu000-claude-skill-registry-conda-forge-expert && rm -rf "$T"
skills/data/conda-forge-expert/SKILL.mdConda-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?
| Scenario | Format | Reason |
|---|---|---|
| New package | | Modern, faster, recommended |
| Existing feedstock | Keep current | Unless migrating |
| Complex multi-output | | Better cache support |
| Quick prototype | | More 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
| Feature | meta.yaml | recipe.yaml |
|---|---|---|
| Variables | | |
| Selectors | | |
| Test section | | (list) |
| Pin syntax | | |
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:
-
Before testing locally: Comment out the
line:stdlibrequirements: build: - ${{ compiler("c") }} # - ${{ stdlib("c") }} # TEMPORARILY COMMENTED FOR LOCAL TESTING -
After testing: IMMEDIATELY uncomment the
line before committing or submitting:stdlibrequirements: 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
will cause submission failuresstdlib
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.0BSD-3-Clause - Always include
license_file - Case-sensitive:
notApache-2.0APACHE 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
| Selector | Description |
|---|---|
, , | Operating system |
| Linux OR macOS |
, / | Architecture |
, | Cross-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
- License: SPDX identifier and license_file present
- Maintainers: Valid GitHub usernames
- Source: SHA256 checksums, no git URLs for releases
- Selectors: Correct syntax
- 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:
| PyPI | conda-forge |
|---|---|
| |
| |
| |
| |
| |
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
| Error | Solution |
|---|---|
| Hash mismatch | Regenerate: |
| Missing dependency | Add to requirements or submit first |
on Windows CGO | Use MinGW-w64 instead of MSVC |
| macOS SDK error | Set in conda_build_config.yaml |
| glibc errors | Use appropriate |
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
- Change
to{% set %}
sectioncontext: - Replace
with{{ }}${{ }} - Replace
with# [selector]if: selector then: - Change
totest:
(list format)tests: - Add
if using compilers${{ stdlib("c") }} - Update
:conda-forge.ymlconda_build_tool: rattler-build conda_install_tool: pixi
See guide: guides/migration-guide.md
Enterprise Deployment
For air-gapped environments with JFrog Artifactory:
- Configure private channels in
config/skill-config.yaml - Set up Artifactory remote/local/virtual repos
- Use enterprise templates: templates/enterprise/
See guides:
Reference Documentation
Detailed Guides
Reference
Quick Reference
Templates
External Resources
- conda-forge Documentation
- rattler-build Documentation
- pixi Documentation
- CFEP-25: python_min
- Recipe Format Schema
- conda-forge Staged Recipes
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