Agent skill
python-uv-scripts
Python single-file script development using uv and PEP 723 inline metadata. Prevents invalid patterns like [tool.uv.metadata]. Use when creating standalone Python utilities, converting scripts to uv format, managing script dependencies, implementing script testing, or establishing team standards for script development.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/development/python-uv-scripts-basher83-lunar-claude
SKILL.md
Python Single-File Scripts with uv
Expert guidance for creating production-ready, self-contained Python scripts using uv's inline dependency management (PEP 723).
Quick Start
Create Your First uv Script
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "httpx>=0.27.0",
# "rich>=13.0.0",
# ]
# ///
import httpx
from rich import print
response = httpx.get("https://api.github.com")
print(f"[green]Status: {response.status_code}[/green]")
Make it executable:
chmod +x script.py
./script.py # uv automatically installs dependencies
Convert Existing Script
# Add inline metadata to existing script
./tools/convert_to_uv.py existing_script.py
# Validate PEP 723 metadata
./tools/validate_script.py script.py
Core Concepts
What is PEP 723?
PEP 723 defines inline script metadata for Python files:
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "package>=1.0.0",
# ]
# ///
Benefits:
- ✅ Dependencies live with the code
- ✅ No separate
requirements.txt - ✅ Reproducible execution
- ✅ Version constraints included
- ✅ Self-documenting
uv Script Execution Modes
Mode 1: Inline Dependencies (Recommended for utilities)
#!/usr/bin/env -S uv run --script
# /// script
# dependencies = ["httpx"]
# ///
Mode 2: Project Mode (For larger scripts)
uv run script.py # Uses pyproject.toml
Mode 3: No Dependencies
#!/usr/bin/env -S uv run
# Standard library only
Critical Anti-Patterns: What NOT to Do
❌ NEVER Use [tool.uv.metadata]
WRONG - This will cause errors:
# /// script
# requires-python = ">=3.11"
# [tool.uv.metadata] # ❌ THIS DOES NOT WORK
# purpose = "testing"
# ///
Error:
error: TOML parse error at line 3, column 7
unknown field `metadata`
Why: [tool.uv.metadata] is not part of PEP 723 and is not supported by uv.
CORRECT - Use Python docstrings for metadata:
# /// script
# requires-python = ">=3.11"
# dependencies = []
# ///
"""
Purpose: Testing automation
Team: DevOps
Author: team@example.com
"""
Valid tool.uv fields (if needed):
# /// script
# requires-python = ">=3.11"
# dependencies = []
# [tool.uv]
# exclude-newer = "2025-01-01T00:00:00Z" # For reproducibility
# ///
Real-World Examples from This Repository
Example 1: Cluster Health Checker
See examples/03-production-ready/check_cluster_health_enhanced.py
Current version (basic):
#!/usr/bin/env python3
import subprocess
# Manual dependency installation required
Enhanced with uv (production-ready):
#!/usr/bin/env -S uv run --script --quiet
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "rich>=13.0.0",
# "typer>=0.9.0",
# ]
# ///
"""
Purpose: Cluster health monitoring
Team: Infrastructure
"""
import typer
from rich.console import Console
from rich.table import Table
Example 2: CEPH Health Monitor
See examples/03-production-ready/ceph_health.py
Pattern: JSON API interaction with structured output
Best Practices from This Repository
1. Security Patterns
See reference/security-patterns.md for complete security guide including:
- Secrets management (environment variables, keyring, Infisical)
- Input validation
- Dependency security
- File operations security
- Command execution security
2. Version Pinning Strategy
Following this repository's approach (from pyproject.toml):
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "httpx>=0.27.0", # Minimum version for compatibility
# "rich>=13.0.0", # Known good version
# "ansible>=11.1.0", # Match project requirements
# ]
# ///
Pinning levels:
>=X.Y.Z- Minimum version (most flexible)~=X.Y.Z- Compatible release (patch updates only)==X.Y.Z- Exact version (most strict)
See reference/dependency-management.md.
3. Team Standards
File naming:
check_cluster_health.py # ✅ Descriptive, snake_case
validate_template.py # ✅ Action-oriented
cluster.py # ❌ Too generic
Shebang pattern:
#!/usr/bin/env -S uv run --script --quiet
# --quiet suppresses uv's own output
Documentation template:
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.11"
# dependencies = []
# ///
"""
Check Proxmox cluster health
Purpose: cluster-monitoring
Team: infrastructure
Author: devops@spaceships.work
Usage:
python check_cluster_health.py [--node NODE] [--json]
Examples:
python check_cluster_health.py --node foxtrot
python check_cluster_health.py --json
"""
4. Error Handling Patterns
Following Ansible best practices from this repository:
import sys
import subprocess
def run_command(cmd: str) -> str:
"""Execute command with proper error handling"""
try:
result = subprocess.run(
cmd.split(),
capture_output=True,
text=True,
check=True
)
return result.stdout
except subprocess.CalledProcessError as e:
print(f"Error: Command failed: {cmd}", file=sys.stderr)
print(f" {e.stderr}", file=sys.stderr)
sys.exit(1)
except FileNotFoundError:
print(f"Error: Command not found: {cmd.split()[0]}", file=sys.stderr)
sys.exit(1)
See patterns/error-handling.md.
5. Testing Patterns
Inline testing (for simple scripts):
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.11"
# dependencies = []
# ///
def validate_ip(ip: str) -> bool:
"""Validate IP address format"""
import re
pattern = r'^(\d{1,3}\.){3}\d{1,3}$'
return bool(re.match(pattern, ip))
# Inline tests
if __name__ == "__main__":
import sys
# Run tests if --test flag provided
if len(sys.argv) > 1 and sys.argv[1] == "--test":
assert validate_ip("192.168.1.1") == True
assert validate_ip("256.1.1.1") == False
print("All tests passed!")
sys.exit(0)
# Normal execution
print(validate_ip("192.168.3.5"))
See workflows/testing-strategies.md.
When NOT to Use Single-File Scripts
See anti-patterns/when-not-to-use.md for details.
Use a proper project instead when:
- ❌ Script exceeds 500 lines
- ❌ Multiple modules/files needed
- ❌ Complex configuration management
- ❌ Requires packaging/distribution
- ❌ Shared library code across multiple scripts
- ❌ Web applications or long-running services
Example - Too Complex for Single File:
# This should be a uv project, not a script:
# - 15+ dependencies
# - Database models
# - API routes
# - Background workers
# - Configuration management
# - Multiple environments
Common Patterns
See pattern guides for complete examples:
- CLI Applications - Typer, Click, argparse patterns
- API Clients - httpx, requests, authentication
- Data Processing - Polars, pandas, analysis
- System Automation - psutil, subprocess, system admin
CI/CD Integration
GitHub Actions
name: Run Health Checks
on:
schedule:
- cron: '0 */6 * * *' # Every 6 hours
jobs:
health-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v3
- name: Check cluster health
run: |
uv run --script tools/check_cluster_health.py --json
env:
PROXMOX_TOKEN: ${{ secrets.PROXMOX_TOKEN }}
GitLab CI
cluster-health:
image: ghcr.io/astral-sh/uv:python3.11-bookworm-slim
script:
- uv run --script tools/check_cluster_health.py
only:
- schedules
See workflows/ci-cd-integration.md.
Tools Available
Script Validation
# Validate PEP 723 metadata
./tools/validate_script.py script.py
# Output:
# ✓ Valid PEP 723 metadata
# ✓ Python version specified
# ✓ Dependencies properly formatted
Script Conversion
# Convert requirements.txt-based script to uv
./tools/convert_to_uv.py old_script.py
# Creates:
# - old_script_uv.py with inline dependencies
# - Preserves original script
Progressive Disclosure
For deeper knowledge:
Reference Documentation
- PEP 723 Specification - Complete inline metadata spec
- Dependency Management - Version pinning strategies
- Security Patterns - Secrets, validation, input sanitization
Pattern Guides
- CLI Applications - Typer, Click, argparse patterns
- API Clients - httpx, requests, authentication
- Data Processing - Polars, pandas, analysis
- System Automation - psutil, subprocess, system admin
- Error Handling - Exception handling, logging
Note: See Common Patterns section above for quick access to these guides.
Working Examples
- NetBox API Client - Production-ready API client with Infisical, validation, error handling, and Rich output
- Cluster Health Checker - Production-ready monitoring script with Typer, Rich, and JSON output
Anti-Patterns
- When NOT to Use - Signs you need a proper project
- Common Mistakes - Pitfalls and how to avoid them
Workflows
- Team Adoption - Rolling out uv scripts across teams
- CI/CD Integration - GitHub Actions, GitLab CI
- Testing Strategies - Inline tests, pytest integration
Related Skills
- Ansible Best Practices - Many Ansible modules could be standalone uv scripts
- Proxmox Infrastructure - Validation tools use this pattern
- NetBox + PowerDNS Integration - API interaction scripts
Quick Reference
Shebang Options
# Standard script execution
#!/usr/bin/env -S uv run --script
# Quiet mode (suppress uv output)
#!/usr/bin/env -S uv run --script --quiet
# With Python version
#!/usr/bin/env -S uv run --script --python 3.11
Common Dependencies
# CLI applications
"typer>=0.9.0" # Modern CLI framework
"click>=8.0.0" # Alternative CLI framework
"rich>=13.0.0" # Rich text and formatting
# API clients
"httpx>=0.27.0" # Modern async HTTP client
"requests>=2.31.0" # Traditional HTTP client
# Data processing
"polars>=0.20.0" # Fast dataframe library
"pandas>=2.0.0" # Traditional dataframe library
# Infrastructure
"ansible>=11.1.0" # Automation (from this repo)
"infisical-python>=2.3.3" # Secrets (from this repo)
# System automation
"psutil>=5.9.0" # System monitoring
Metadata Template
#!/usr/bin/env -S uv run --script --quiet
# /// script
# requires-python = ">=3.11"
# dependencies = [
# # Add dependencies here
# ]
# ///
"""
One-line description
Purpose: describe-purpose
Team: team-name
Author: email@example.com
Usage:
python script.py [OPTIONS]
Examples:
python script.py --help
"""
Best Practices Summary
- Always specify Python version -
requires-python = ">=3.11" - Pin dependencies appropriately - Use
>=X.Y.Zfor utilities - Add metadata in docstrings - Put team info, purpose, and author in module docstring
- Include comprehensive docstrings - Document purpose, usage, and examples
- Handle errors gracefully - Use try/except with clear messages
- Validate inputs - Check arguments before processing
- Use quiet mode -
--quietflag for production scripts - Keep it focused - Single file, single purpose
- Test inline - Add
--testflag for simple validation - Secure secrets - Never hardcode, use env vars or keyring
Didn't find tool you were looking for?