How uv-scripts Manages Single-File Python Scripts with Inline Dependencies
The uv-scripts crate in the astral-sh/uv repository implements PEP 723 to parse inline TOML metadata blocks from single-file Python scripts, enabling automatic dependency resolution and isolated environment creation without requiring a separate pyproject.toml file.
The uv-scripts crate serves as the internal Rust engine that powers uv's ability to treat single-file Python scripts as self-contained projects. By implementing PEP 723 (script metadata), it allows developers to declare dependencies and Python version requirements directly within a script's comments, eliminating the need for external configuration files when running standalone utilities.
What is uv-scripts?
The uv-scripts crate is a core component of the astral-sh/uv monorepo, written in Rust to handle the complete lifecycle of single-file Python scripts that carry inline metadata. It bridges the gap between simple "single file" workflows and uv's full project management capabilities by treating a script with a PEP 723 metadata block as a temporary, in-memory project.
When you execute uv run --script my_script.py, the uv-scripts crate reads the file, extracts the metadata block, and feeds the declared dependencies into uv's standard resolution and installation pipeline—identical to how it handles full pyproject.toml projects.
How Inline Dependencies Work in uv-scripts
Inline dependencies in uv-scripts rely on the PEP 723 specification, which defines a standardized TOML block embedded in Python script comments. The block is delimited by # /// script and # /// markers, allowing the script to declare its runtime requirements without external files.
Parsing PEP 723 Metadata Blocks
The heavy lifting of parsing occurs in ScriptTag::parse within crates/uv-scripts/src/lib.rs (lines 95-140). This function strips leading # characters from each line, validates the opening pragma (# /// script) and closing pragma (# ///), and extracts the TOML content between them.
The parser returns a structured representation containing the prelude (content before the block), the metadata TOML, and the postlude (content after the block), enabling uv to reconstruct the script if needed while processing the metadata separately.
The Pep723Metadata Structure
Once parsed, the TOML content is deserialized into the Pep723Metadata structure (defined around lines 61-67 in lib.rs). This struct captures three critical fields:
requires-python: A version specifier string defining the compatible Python interpreter range.dependencies: An array of PEP 508 dependency specifiers (e.g.,"requests>=2.28").tool.uv: An optional configuration table supportinguv-specific features like custom indexes, sources, and installer options.
This structure allows uv-scripts to feed the script's requirements directly into the existing dependency resolver, ensuring that a single-file script receives the same resolution logic as a full project.
Running Scripts with uv run --script
When you execute uv run --script my_script.py, the uv-scripts crate orchestrates a seamless workflow that treats the script as a temporary project. The process begins with Pep723Script::read (lines 71-99 in crates/uv-scripts/src/lib.rs), an async loader that extracts the metadata block from the file.
Once extracted, uv-scripts creates an ephemeral, in-memory project containing the declared dependencies. It then invokes uv's standard resolution and installation machinery to:
- Resolve the dependency tree against the specified Python version constraints.
- Install the required packages into an isolated environment.
- Execute the script with the correct interpreter and
PYTHONPATHconfigured.
This approach ensures that running a single-file script with inline dependencies is as reproducible and isolated as running a full uv project, without leaving behind a pyproject.toml or virtual environment in the working directory.
Creating Scripts with Inline Dependencies
The uv-scripts crate also supports generating new scripts with properly formatted metadata blocks through the serialize_metadata function (lines 334-351 in lib.rs). This functionality powers the uv init --script command, allowing developers to scaffold new executable scripts with inline dependency declarations.
When creating a script, serialize_metadata ensures that the TOML block is correctly formatted with the required # /// script prefix and # /// suffix, and that the content adheres to the PEP 723 specification. This guarantees that subsequent uv run --script commands will correctly parse the metadata without manual formatting errors.
For example, to create a new script with specific dependencies:
uv init --script my_tool.py --python 3.11
This generates a file containing a properly structured metadata block ready for editing, ensuring that the script will be recognized by Pep723Script::read when executed.
Summary
-
The
uv-scriptscrate inastral-sh/uvimplements PEP 723 to enable inline dependency metadata in single-file Python scripts. -
ScriptTag::parse(lines 95-140 incrates/uv-scripts/src/lib.rs) extracts and validates TOML blocks delimited by# /// scriptmarkers. -
Pep723Metadatastructures the parsed data, capturingrequires-python,dependencies, andtool.uvconfiguration. -
Pep723Script::readcreates temporary in-memory projects, allowinguv run --scriptto resolve and install dependencies in isolated environments. -
serialize_metadata(lines 334-351) supports script generation viauv init --script, ensuring correctly formatted metadata blocks.
Frequently Asked Questions
What is PEP 723 and how does uv-scripts implement it?
PEP 723 defines a standard for embedding TOML metadata within Python script comments using # /// script delimiters. The uv-scripts crate implements this through ScriptTag::parse in crates/uv-scripts/src/lib.rs, which validates these blocks and deserializes them into the Pep723Metadata structure, enabling uv to treat single files as complete project definitions.
How does uv run --script handle dependency resolution for single files?
When executing uv run --script, the Pep723Script::read function (lines 71-99) extracts the inline metadata and constructs an ephemeral, in-memory project. This project is then passed to uv's standard resolver, which installs the declared dependencies into an isolated environment before executing the script, ensuring reproducibility without modifying the working directory.
Can I use tool.uv configuration in inline script metadata?
Yes, the Pep723Metadata structure supports an optional tool.uv table that allows configuring indexes, sources, and installer options directly within the script metadata block. These settings are exposed through helper methods like Pep723ItemRef::indexes and are only respected when explicitly enabled, allowing the script to specify custom package sources alongside standard PEP 723 fields.
How do I create a new script with uv init --script?
The uv init --script command utilizes the serialize_metadata function (lines 334-351 in lib.rs) to generate a new Python file containing a properly formatted PEP 723 metadata block. This ensures the script includes the correct # /// script delimiters and TOML structure, making it immediately compatible with uv run --script without requiring manual formatting of the inline metadata.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →