Use when python is needed. Develop Python projects with uv (PEP 723 inline metadata, venv management, script execution). Use when user mentions uv, creates Python scripts, or needs Python environment setup.
Modern Python development using uv for package management, PEP 723 for single-file scripts, and best-in-class tooling.
By default, create self-contained scripts using PEP 723 format:
#!/usr/bin/env uv run python3
# /// script
# dependencies = [
# "typer",
# "rich",
# ]
# ///
"""
Script description and usage examples.
Usage:
uv run python3 script.py --help
uv run python3 script.py --option value
"""
import sys
# ... rest of script
Run with: uv run python3 script.py
For larger projects requiring multiple files:
# Pin Python version
uv python pin 3.12
# Create virtual environment
uv venv --python 3.12
# Activate environment
source .venv/bin/activate
# Add dependencies
uv add package-name
# Run script
uv run python script.py
All tooling configuration is centralized in /tests/pyproject.toml.
Run from /tests directory:
cd tests
# Run tests
uv run pytest
uv run pytest -v # verbose
# Type checking
uv run pyright
uv run pyright --stats
# Linting & formatting
uv run ruff check ../.opencode/skill
uv run ruff check --fix ../.opencode/skill
uv run ruff format ../.opencode/skill
Tool choices:
For detailed usage, see:
references/ruff.md - Linting and formattingreferences/pyright.md - Static type checkingreferences/pytest.md - Testing framework--help flaguv run python3 script.py --help--dry-run - Show what would happen without executing--verbose - Detailed output for debugging#!/usr/bin/env uv run python3
# /// script
# dependencies = [
# "typer", # Modern CLI framework
# "rich", # Beautiful terminal output
# "httpx", # Modern HTTP client
# ]
# ///
Minimize dependencies - Try using stdlib first.
uv add <package> # Add package to pyproject.toml
uv remove <package> # Remove package
uv sync # Install/sync dependencies
uv lock # Create/update lock file
uv python install <version> # Install Python version
uv python list # List installed versions
uv python pin <version> # Set project Python version
uv run python script.py # Run with project environment
uvx <tool> # Run tool in isolated environment
uv tool install <package> # Install global tool
General approach: Code directly as you see fit.
Use TDD when: Facing issues or building complex components.
See references/pytest.md for comprehensive testing guide.
.opencode/skill/<skill>/
├── SKILL.md
└── scripts/
├── <script>.py
└── tests/
└── test_<script>.py
from pathlib import Path
import subprocess
SCRIPT_PATH = Path(__file__).parent.parent / "script.py"
def run_script(*args, env=None):
"""Execute script with uv run."""
cmd = ["uv", "run", str(SCRIPT_PATH)] + list(args)
result = subprocess.run(cmd, capture_output=True, text=True, env=env)
return result.stdout, result.stderr, result.returncode
class TestVersion:
"""Test --version flag."""
def test_version_flag(self):
"""--version should output version and exit with 0."""
stdout, stderr, code = run_script("--version")
assert code == 0
assert "version" in stdout.lower()
| Code | Meaning |
|---|---|
| 0 | Success (version, help, dry-run) |
| 1 | Runtime/API error |
| 2 | Validation error |
| 130 | Keyboard interrupt |
See references/pyright.md for comprehensive type checking guide.
def greet(name: str) -> str:
return f"Hello, {name}"
def find_user(id: int) -> str | None:
return None
def process(items: list[str]) -> dict[str, int]:
return {item: len(item) for item in items}
Use structured docstrings with Args, Returns, and Raises sections:
def calculate_total(items: list[dict], tax_rate: float = 0.0) -> float:
"""Calculate the total cost of items including tax.
Args:
items: List of item dictionaries with 'price' keys
tax_rate: Tax rate as decimal (e.g., 0.08 for 8%)
Returns:
Total cost including tax
Raises:
ValueError: If items is empty or tax_rate is negative
"""
if not items:
raise ValueError("Items list cannot be empty")
if tax_rate < 0:
raise ValueError("Tax rate cannot be negative")
subtotal = sum(item["price"] for item in items)
return subtotal * (1 + tax_rate)
python3 or pip directlyNever use mutable objects (lists, dicts) as default argument values:
# BAD - The list persists across calls!
def add_item(item, items=[]):
items.append(item)
return items
add_item("a") # ['a']
add_item("b") # ['a', 'b'] - Unexpected!
# GOOD - Use None and create inside function
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
Never use bare except: - always catch specific exceptions:
# BAD - Catches everything including KeyboardInterrupt