Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ For more background on why distributing agent skills through package managers ma
| [conda-forge](https://conda-forge.org) | `agent-skill-conda-forge` | conda-forge packaging operations |
| [Matplotlib Data Visualization](https://matplotlib.org) | `agent-skill-matplotlib-data-visualization` | Chart design and data storytelling guidelines |
| [Polars](https://pola.rs) | `agent-skill-polars` | DataFrame library for fast data manipulation |
| [py-rattler](https://github.com/conda/rattler/tree/main/py-rattler) | `agent-skill-py-rattler` | Python bindings for the rattler conda library |
| [rattler-build](https://rattler.build) | `agent-skill-rattler-build` | Build conda packages with rattler-build |
| [SQLAlchemy](https://www.sqlalchemy.org) | `agent-skill-sqlalchemy` | Python SQL toolkit and ORM |
| [Typst](https://typst.app) | `agent-skill-typst` | Modern markup-based typesetting system |
Expand Down
55 changes: 55 additions & 0 deletions recipes/py-rattler/PROMPT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# py-rattler Skill Update Instructions

py-rattler skill with API documentation from https://github.com/conda/rattler/tree/main/py-rattler

## Source of Truth

The Python source files live at `py-rattler/rattler/` in the rattler repository. The Rust FFI types are defined in `py-rattler/src/` but the Python wrappers in `py-rattler/rattler/` are the authoritative API surface.

When updating, clone or check out the rattler repo and read the Python sources directly. Do not rely on external documentation alone — the code is the source of truth.

## Structure

- `SKILL.md` - Hub file with navigation table, quick start, and import reference
- `references/solving-installing.md` - `solve()`, `solve_with_sparse_repodata()`, `install()`
- `references/match-spec.md` - `MatchSpec`, `NamelessMatchSpec`, `PackageNameMatcher`
- `references/version.md` - `Version`, `VersionSpec`
- `references/channels-platforms.md` - `Channel`, `ChannelConfig`, `ChannelPriority`, `Platform`
- `references/virtual-packages.md` - `VirtualPackage`, `GenericVirtualPackage`, `VirtualPackageOverrides`, `Override`
- `references/networking.md` - `Client`, all middleware classes, `fetch_repo_data()`
- `references/gateway-repodata.md` - `Gateway`, `SourceConfig`, `RepoDataSource`, `RepoData`, `SparseRepoData`
- `references/package-records.md` - `PackageRecord`, `RepoDataRecord`, `NoArchType`
- `references/package-metadata.md` - `PackageName`, `IndexJson`, `AboutJson`, `RunExportsJson`, `PathsJson`, related types
- `references/lock-files.md` - `LockFile`, `Environment`, `LockChannel`, locked package types, `PackageHashes`
- `references/shell-activation.md` - `activate()`, `Shell`, `ActivationVariables`, `ActivationResult`
- `references/package-streaming.md` - `extract`, `download_*` functions
- `references/indexing.md` - `index_fs()`, `index_s3()`, `S3Credentials`
- `references/prefix-records.md` - `PrefixRecord`, `PrefixPaths`, `PrefixPathsEntry`, link types
- `references/pty.md` - `PtyProcess`, `PtySession`, `PtyProcessOptions`
- `references/exceptions.md` - All exception classes

## Content Guidelines

- **Every public class, method, and property** should be documented. When new API is added upstream, add it to the appropriate reference file.
- **Include full function signatures** with all parameters, types, and defaults. Users of this skill are AI coding agents that need exact signatures.
- **Use tables** for parameter lists and property lists — they are compact and scannable.
- **Include code examples** for non-obvious usage patterns but keep them minimal. One example per concept is enough.
- **Keep SKILL.md as a hub** — it should have the navigation table, a quick start example, and the import reference. Detailed API docs go in reference files.

## What to Watch for When Updating

- New modules or classes added to `rattler/__init__.py` exports
- New parameters on `solve()`, `install()`, or `Gateway`
- New middleware classes in `rattler/networking/`
- Changes to the `RepoDataSource` protocol
- New lock file package types (e.g., new ecosystems beyond conda and PyPI)
- New `PackageFormatSelection` enum values
- Breaking changes to constructor signatures or property types
- Deprecated APIs

## What NOT to Include

- Internal/private APIs (methods prefixed with `_`)
- Implementation details of the Rust FFI layer
- The Rust source code or PyO3 bindings
- Detailed algorithmic explanations of the solver internals
114 changes: 114 additions & 0 deletions recipes/py-rattler/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
---
name: py-rattler
description: >-
Python bindings for the rattler conda library. Use when solving dependencies,
installing packages, managing conda environments, working with repodata, lock
files, or shell activation programmatically from Python.
license: BSD-3-Clause
---

# py-rattler

py-rattler provides async Python bindings for the [rattler](https://github.com/conda/rattler) Rust library for working with the conda ecosystem. It powers tools like [pixi](https://pixi.sh) and [rattler-build](https://rattler.build).

Install: `pip install py-rattler` or `pixi add py-rattler`.

## When to Use This Skill

Use this skill when writing Python code that programmatically interacts with the conda ecosystem: solving package dependencies, installing packages into environments, reading or creating lock files, activating environments, managing repodata, or working with conda package archives.

## API Reference

Determine which reference applies based on the task:

| Task | Reference |
|------|-----------|
| Solve package dependencies | [references/solving-installing.md](references/solving-installing.md) |
| Install packages into an environment | [references/solving-installing.md](references/solving-installing.md) |
| Parse or match package specs | [references/match-spec.md](references/match-spec.md) |
| Work with version strings | [references/version.md](references/version.md) |
| Configure channels and platforms | [references/channels-platforms.md](references/channels-platforms.md) |
| Detect or override virtual packages | [references/virtual-packages.md](references/virtual-packages.md) |
| Build HTTP clients with middleware | [references/networking.md](references/networking.md) |
| Query repodata with Gateway | [references/gateway-repodata.md](references/gateway-repodata.md) |
| Work with package records | [references/package-records.md](references/package-records.md) |
| Inspect package metadata (index.json, about.json, paths.json) | [references/package-metadata.md](references/package-metadata.md) |
| Read or write lock files | [references/lock-files.md](references/lock-files.md) |
| Generate shell activation scripts | [references/shell-activation.md](references/shell-activation.md) |
| Download and extract conda packages | [references/package-streaming.md](references/package-streaming.md) |
| Index conda channels (filesystem or S3) | [references/indexing.md](references/indexing.md) |
| Inspect installed packages in a prefix | [references/prefix-records.md](references/prefix-records.md) |
| Run interactive PTY sessions (Unix only) | [references/pty.md](references/pty.md) |
| Handle errors | [references/exceptions.md](references/exceptions.md) |

---

## Quick Start

All I/O operations are **async**. The standard pattern is: solve specs, then install records.

```python
import asyncio
from rattler import solve, install, VirtualPackage

async def main():
records = await solve(
sources=["conda-forge"],
specs=["python 3.12.*", "numpy >=1.26"],
virtual_packages=VirtualPackage.detect(),
)
await install(records, target_prefix="/path/to/env")

asyncio.run(main())
```

## Import Reference

```python
from rattler import (
# Solving & installing
solve, solve_with_sparse_repodata, install,
# Specifications
MatchSpec, NamelessMatchSpec, Version, VersionSpec,
# Channels & repodata
Channel, ChannelConfig, ChannelPriority,
Gateway, SourceConfig, RepoData, SparseRepoData,
# Package records
PackageRecord, RepoDataRecord, PatchInstructions,
# Platform & virtual packages
Platform, VirtualPackage, GenericVirtualPackage, VirtualPackageOverrides, Override,
# Networking
Client,
# Lock files
LockFile, Environment, LockChannel, PackageHashes,
LockedPackage, CondaLockedBinaryPackage, CondaLockedSourcePackage, PypiLockedPackage,
# Package metadata
PackageName, IndexJson, AboutJson, PathsJson, PathsEntry, RunExportsJson,
PathType, PrefixPlaceholder, FileMode, NoArchType,
# Prefix records
PrefixRecord, PrefixPaths, PrefixPathsEntry, PrefixPathType, Link, LinkType,
# Shell activation
activate, Shell, ActivationVariables, ActivationResult, PathModificationBehavior,
# Package streaming
extract, extract_tar_bz2,
# Indexing
index_fs, index_s3,
# PTY (Unix only)
PtySession, PtyProcess, PtyProcessOptions,
)
from rattler.networking import (
fetch_repo_data, FetchRepoDataOptions,
RetryMiddleware, AuthenticationMiddleware, MirrorMiddleware,
AddHeadersMiddleware, OciMiddleware, S3Middleware, GCSMiddleware,
)
from rattler.repo_data import RepoDataSource, PackageFormatSelection
from rattler.index import S3Credentials
```

## Key Design Principles

- **Async-first**: all I/O operations are `async` — use `asyncio.run()` or `await`
- **Thread-safe**: `Gateway` and `Client` can be shared across threads
- **Immutable**: most objects are logically immutable after construction
- **Rust-backed**: computation-heavy operations are delegated to Rust via PyO3
- **Singleton caching**: `Platform` instances are cached (same string returns same object)
3 changes: 3 additions & 0 deletions recipes/py-rattler/pixi.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[package.build.backend]
name = "pixi-build-rattler-build"
version = "*"
50 changes: 50 additions & 0 deletions recipes/py-rattler/recipe.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
context:
skill: py-rattler

package:
name: agent-skill-${{ skill }}
version: "0.0.1"

source:
url: https://raw.githubusercontent.com/conda/rattler/refs/heads/main/LICENSE
sha256: 679d42a76b82a6dc20ffd9048ab45fb2e5557a526113aaedc7419e12f3cfab38

build:
number: 0
noarch: generic
script:
- mkdir -p $PREFIX/share/agent-skills/${{ skill }}
- cp $RECIPE_DIR/SKILL.md $PREFIX/share/agent-skills/${{ skill }}/SKILL.md
- cp -R $RECIPE_DIR/references $PREFIX/share/agent-skills/${{ skill }}/

requirements:
run_constraints:
- py-rattler >=0.23.0,<0.24

tests:
- package_contents:
files:
- share/agent-skills/${{ skill }}/SKILL.md
- share/agent-skills/${{ skill }}/references/*.md
strict: true
- script:
- agentskills validate $CONDA_PREFIX/share/agent-skills/${{ skill }}
requirements:
run:
- skills-ref

about:
summary: Agent skill for programmatic conda operations with py-rattler
description: |
Python bindings for the rattler conda library:
- Solve package dependencies asynchronously
- Install packages into conda environments
- Manage repodata, channels, and networking with middleware
- Work with lock files, shell activation, and virtual packages
- Stream and extract conda packages
- Index conda channels (filesystem and S3)
homepage: https://github.com/conda/rattler/tree/main/py-rattler
repository: https://github.com/pavelzw/skill-forge
documentation: https://github.com/conda/rattler/tree/main/py-rattler
license: BSD-3-Clause
license_file: LICENSE
134 changes: 134 additions & 0 deletions recipes/py-rattler/references/channels-platforms.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# Channels and Platforms

## Channel

Represents a conda channel (a source of packages).

### Constructor

```python
Channel(name: str, channel_configuration: ChannelConfig | None = None)
```

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `name` | `str` | required | Channel name or URL (e.g., `"conda-forge"`, `"https://repo.prefix.dev/conda-forge"`) |
| `channel_configuration` | `ChannelConfig \| None` | `None` | Custom channel configuration |

### Properties

| Property | Type | Description |
|----------|------|-------------|
| `name` | `str \| None` | Channel name |
| `base_url` | `str` | Base URL of the channel |

### Methods

| Method | Signature | Description |
|--------|-----------|-------------|
| `to_lock_channel` | `to_lock_channel() -> LockChannel` | Convert to a `LockChannel` for lock files |

**Example:**

```python
from rattler import Channel, ChannelConfig

ch = Channel("conda-forge")
ch = Channel("https://repo.prefix.dev/conda-forge")
print(ch.name) # "conda-forge"
print(ch.base_url) # "https://conda.anaconda.org/conda-forge/"

# With custom alias
config = ChannelConfig(channel_alias="https://repo.prefix.dev/")
ch = Channel("my-channel", config)
```

---

## ChannelConfig

Configuration for channel URL resolution.

### Constructor

```python
ChannelConfig(
channel_alias: str = "https://conda.anaconda.org/",
root_dir: str = os.getcwd(),
)
```

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `channel_alias` | `str` | `"https://conda.anaconda.org/"` | Base URL for resolving channel names |
| `root_dir` | `str` | `os.getcwd()` | Root directory for resolving local channels |

---

## ChannelPriority

Enum controlling how multi-channel package searches work. Used in `solve()`.

| Value | Description |
|-------|-------------|
| `ChannelPriority.Strict` | Use the first channel where a package is found exclusively |
| `ChannelPriority.Disabled` | Search all channels, prefer highest version regardless of channel |

---

## Platform

Represents a target platform. Uses a singleton pattern: same platform string returns the same instance.

### Constructor

```python
Platform(value: PlatformLiteral | str)
```

### PlatformLiteral

```python
PlatformLiteral = Literal[
"noarch", "unknown",
"linux-32", "linux-64", "linux-aarch64", "linux-armv6l", "linux-armv7l",
"linux-loongarch64", "linux-ppc64le", "linux-ppc64", "linux-ppc",
"linux-s390x", "linux-riscv32", "linux-riscv64",
"freebsd-64",
"osx-64", "osx-arm64",
"win-32", "win-64", "win-arm64",
"emscripten-wasm32", "wasi-wasm32", "zos-z",
]
```

### Class Methods

| Method | Signature | Description |
|--------|-----------|-------------|
| `current` | `Platform.current() -> Platform` | Detect the current platform |
| `all` | `Platform.all() -> Iterator[Platform]` | Iterate over all 23 supported platforms |

### Properties

| Property | Type | Description |
|----------|------|-------------|
| `is_linux` | `bool` | `True` if platform is Linux |
| `is_osx` | `bool` | `True` if platform is macOS |
| `is_windows` | `bool` | `True` if platform is Windows |
| `is_unix` | `bool` | `True` if platform is Unix (Linux or macOS) |
| `arch` | `Arch \| None` | Architecture (e.g., `x86_64`, `aarch64`) |
| `only_platform` | `str \| None` | Platform name without architecture |

**Example:**

```python
from rattler import Platform

p = Platform.current()
print(p) # e.g., "osx-arm64"
print(p.is_osx) # True
print(p.arch) # Arch("aarch64")

for platform in Platform.all():
print(platform)
```
Loading
Loading