All skills
Skillintermediate
PEP 723: Inline Script Metadata
PEP 723 allows embedding dependency metadata directly in Python scripts, eliminating the need for separate `requirements.txt` or `pyproject.toml` files for simple scripts.
Claude Code Knowledge Pack7/10/2026
Overview
PEP 723: Inline Script Metadata
PEP 723 allows embedding dependency metadata directly in Python scripts, eliminating the need for separate requirements.txt or pyproject.toml files for simple scripts.
When to Use PEP 723
Use for:
- Single-file scripts with external dependencies
- Quick automation scripts
- Utility scripts shared between projects
- Scripts that need to be self-contained
Don't use for:
- Multi-file projects (use
pyproject.toml) - Reusable packages/libraries
- Projects requiring complex configuration
Basic Syntax
The metadata block uses TOML format embedded in a special comment:
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "requests",
# "rich",
# ]
# ///
from rich import print
response = requests.get("https://api.example.com/data")
print(response.json())
Running Scripts
# With uv (recommended)
uv run script.py
# Script handles its own dependencies automatically
./script.py # If shebang is set
Metadata Fields
Required Python Version
# /// script
# requires-python = ">=3.11"
# ///
Dependencies
# /// script
# dependencies = [
# "requests",
# "click",
# "rich",
# ]
# ///
Private Package Index
# /// script
# dependencies = ["httpx"]
#
# [tool.uv]
# extra-index-url = ["https://pypi.company.com/simple/"]
# ///
Complete Example
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "httpx",
# "rich",
# "typer",
# ]
# ///
"""Fetch and display API data with nice formatting."""
from rich.console import Console
from rich.table import Table
console = Console()
app = typer.Typer()
@app.command()
def fetch(url: str, format: str = "table"):
"""Fetch data from URL and display it."""
with httpx.Client() as client:
response = client.get(url)
response.raise_for_status()
data = response.json()
if format == "table" and isinstance(data, list):
table = Table()
if data:
for key in data[0].keys():
table.add_column(key)
for item in data:
table.add_row(*[str(v) for v in item.values()])
console.print(table)
else:
console.print_json(data=data)
if __name__ == "__main__":
app()
Creating Scripts with uv
# Create new script with metadata
uv init --script myscript.py
# Add dependency to existing script
uv add --script myscript.py requests
# Remove dependency from script
uv remove --script myscript.py requests
Shebang Options
Basic (requires uv in PATH)
#!/usr/bin/env -S uv run --script
With specific Python version
#!/usr/bin/env -S uv run --python 3.12 --script
Quiet mode (suppress uv output)
#!/usr/bin/env -S uv run --quiet --script
Examples by Use Case
Data Processing Script
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.11"
# dependencies = ["pandas", "openpyxl"]
# ///
df = pd.read_excel(sys.argv[1])
print(df.describe())
Web Scraping Script
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.11"
# dependencies = ["httpx", "beautifulsoup4", "lxml"]
# ///
from bs4 import BeautifulSoup
response = httpx.get("https://example.com")
soup = BeautifulSoup(response.text, "lxml")
print(soup.title.string)
CLI Tool Script
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.11"
# dependencies = ["typer", "rich"]
# ///
from rich import print
app = typer.Typer()
@app.command()
def greet(name: str):
print(f"[green]Hello, {name}![/green]")
if __name__ == "__main__":
app()
Async Script
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.11"
# dependencies = ["httpx"]
# ///
async def main():
async with httpx.AsyncClient() as client:
urls = ["https://api1.example.com", "https://api2.example.com"]
tasks = [client.get(url) for url in urls]
responses = await asyncio.gather(*tasks)
for r in responses:
print(r.status_code)
asyncio.run(main())
Best Practices
- Always specify
requires-python- Ensures compatibility - Pin major versions for Python - Use
>=3.11not==3.11 - Omit version constraints for dependencies - Use
uv add --scriptto add dependencies; let uv select versions - Keep scripts focused - One script, one purpose
- Add docstring - Document what the script does
- Use type hints - Improves readability and catches errors
Limitations
- No support for dependency groups
- No support for editable installs
- No support for local dependencies (use relative imports)
- No lockfile (versions may vary between runs)
For projects needing these features, use a full pyproject.toml setup instead.