uv & PEP 723 Scripts
PEP 723 defines inline script metadata, allowing Python scripts to declare their dependencies directly in the file. Combined with uv, this enables zero-setup script execution.
Why PEP 723 + uv?
-
No virtual environment setup - Dependencies resolved and cached automatically
-
Single-file distribution - Share scripts without requirements.txt
-
Reproducible execution - Pinned Python version and dependencies
-
Instant execution - uv caches dependencies globally
Script Template
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "requests>=2.28",
# "click>=8.0",
# ]
# ///
"""
tool-name - Brief description of what this tool does
Usage:
tool-name [options] <args>
Examples:
tool-name --verbose input.txt
tool-name --format json data.csv
"""
import sys
import click
@click.command()
@click.argument('input_file')
@click.option('--verbose', '-v', is_flag=True)
def main(input_file, verbose):
"""Process input file."""
if verbose:
click.echo(f"Processing: {input_file}")
# ... implementation ...
if __name__ == "__main__":
main()
Shebang Explained
#!/usr/bin/env -S uv run --script
-
#!/usr/bin/env- Portable interpreter lookup -
-S- Pass the rest as arguments to the found program -
uv run --script- Execute with uv, reading inline metadata
Metadata Block
The metadata block must appear at the top of the file (after shebang/encoding):
# /// script
# requires-python = ">=3.11"
# dependencies = ["requests", "click"]
# ///