Dependencies
How supypowers resolves per-script dependencies at runtime using uv inline script metadata.
Dependencies
Every supypowers script declares its own dependencies. There is no shared requirements.txt or virtual environment -- each script runs in complete isolation with exactly the packages it needs.
The Script Metadata Block
Dependencies are declared using the PEP 723 inline script metadata format:
# /// script
# dependencies = [
# "pydantic",
# "httpx",
# ]
# ///This block must appear at the top of the file, before any imports. The # /// script and # /// markers are required.
How Dependency Resolution Works
When supypowers runs a script, the following happens:
- The
# /// scriptblock is parsed to extract the dependency list uv run --with pydantic --with httpx ... python -c [runner_code]is executeduvresolves and installs the dependencies into a cached environment- The script runs in that environment
- Subsequent runs reuse the cached environment (near-instant startup)
supypowers run myscript:func '{}'
│
├─→ Parse # /// script block → ["pydantic", "httpx"]
├─→ uv run --with pydantic --with httpx python -c <code>
│ │
│ ├─→ Resolve + install deps (cached after first run)
│ └─→ Execute function in isolated environment
└─→ Return JSON resultPydantic is Always Required
Every script needs at least pydantic because the supypower contract requires BaseModel for input types:
# /// script
# dependencies = ["pydantic"]
# ///Version Pinning
You can pin specific versions using standard pip syntax:
# /// script
# dependencies = [
# "pydantic>=2.0",
# "httpx>=0.25,<1.0",
# "beautifulsoup4==4.12.3",
# "openai~=1.0",
# ]
# ///| Syntax | Meaning |
|---|---|
"httpx" | Latest compatible version |
"httpx>=0.25" | Version 0.25 or newer |
"httpx>=0.25,<1.0" | Between 0.25 and 1.0 |
"httpx==0.27.0" | Exact version |
"httpx~=0.25" | Compatible release (0.25 to 0.26) |
Complex Dependency Examples
HTTP API Client
# /// script
# dependencies = [
# "pydantic",
# "httpx",
# ]
# ///Web Scraping
# /// script
# dependencies = [
# "pydantic",
# "httpx",
# "beautifulsoup4",
# "markdownify",
# ]
# ///Database Access
# /// script
# dependencies = [
# "pydantic",
# "sqlalchemy>=2.0",
# "psycopg2-binary",
# ]
# ///Data Science / ML
# /// script
# dependencies = [
# "pydantic",
# "pandas>=2.0",
# "numpy",
# "scikit-learn",
# ]
# ///Browser Automation
# /// script
# dependencies = [
# "pydantic",
# "playwright",
# "beautifulsoup4",
# "markdownify",
# ]
# ///Image Processing
# /// script
# dependencies = [
# "pydantic",
# "Pillow>=10.0",
# ]
# ///Why Per-Script Isolation?
Traditional approaches share a virtual environment across all tools. This causes problems:
| Problem | Shared venv | Supypowers |
|---|---|---|
| Conflicting versions | toolA needs httpx==0.24, toolB needs httpx>=0.27 -- one breaks | Each script has its own deps |
| Heavy dependencies | Installing torch for one tool slows down everything | Only installed when that tool runs |
| Reproducibility | Works on your machine, breaks on mine | Dependencies are declared inline, always resolved fresh |
| Security | All tools share the same packages | Each tool is sandboxed |
Caching
uv caches resolved environments aggressively. The first run of a script may take a few seconds to install dependencies, but subsequent runs reuse the cached environment and start near-instantly.
The cache is stored in uv's global cache directory (typically ~/.cache/uv/ on Linux/macOS). You can clear it with:
uv cache cleanSecrets and Environment Variables
Scripts can access secrets passed via --secrets:
# Inline secret
supypowers run my_tool:func '{}' --secrets API_KEY=sk-abc123
# From a .env file
supypowers run my_tool:func '{}' --secrets .env
# Multiple secrets
supypowers run my_tool:func '{}' --secrets API_KEY=sk-abc --secrets .envAccess them in code with os.environ.get():
import os
api_key = os.environ.get("API_KEY")Troubleshooting
| Error | Cause | Fix |
|---|---|---|
ModuleNotFoundError: No module named 'X' | Package not in dependency list | Add it to # /// script dependencies |
Could not find a version that satisfies | Invalid version constraint | Check package name spelling and version range |
| Script takes too long on first run | Large packages being installed | Normal for first run; subsequent runs are cached |
ImportError after updating deps | Stale cache | Run uv cache clean and retry |
What's Next
- Creating Tools -- The supypower contract and function structure
- Testing -- Verify your tools work before handing them to agents
- Publishing -- Share tools across projects