/commands/uv/uv-run-script-inline-dependencies
uv run script.py with inline dependencies (PEP 723)
- tool
- uv
- versions
- uv 0.4+
- os
- any
A single-file Python script can declare its own dependencies in a # /// script comment block (inline script metadata, PEP 723). uv add --script example.py requests writes that block, and uv run example.py creates a cached environment with those packages and runs the script in it, without a project, a requirements.txt or a manually created virtual environment.
Declare and run
cat > example.py <<'EOF'
from packaging.version import Version
print(Version("2.1.0rc1") < Version("2.1.0"))
EOF
uv add -q --script example.py "packaging==24.2"
cat example.py
uv run -q --python 3.13 example.pyOutput
# /// script
# requires-python = ">=3.13"
# dependencies = [
# "packaging==24.2",
# ]
# ///
from packaging.version import Version
print(Version("2.1.0rc1") < Version("2.1.0"))
Trueuv add --script inserted the metadata block at the top of the file. The same script runs with pipx run and other tools that read PEP 723 metadata.
The metadata block
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "requests<3",
# "rich",
# ]
# ///
import requests
from rich import printrequires-python makes uv pick, or download, a matching interpreter. Each line inside the block starts with # ; the TOML content is the same as in pyproject.toml.
Related commands
| Command | Effect |
|---|---|
| uv init --script example.py --python 3.12 | Create a new script with an empty metadata block |
| uv add --script example.py rich | Add a dependency to the block |
| uv remove --script example.py rich | Remove it again |
| uv run --with rich example.py | Add a dependency for one run only, without editing the file |
| uv lock --script example.py | Write example.py.lock to pin exact versions |
When to use it
Inline metadata fits one-file tools: a maintenance script in a repository, a data export you run once a month, an example you share in an issue. The script carries its own requirements, so whoever runs it needs only uv, not a requirements.txt and a set of setup instructions. For code split over several modules, or anything you package and publish, use a project with pyproject.toml instead (uv init).
Scripts without metadata
Without a # /// script block, uv run example.py behaves differently: inside a project it runs the script in the project's environment, and outside a project it uses the interpreter it finds. Pass --no-project before the script name to skip the project. Dependencies for a single run can still be added with --with, which leaves the file unchanged.
Reproducible runs
A dependency range such as requests>=2 resolves to whatever is newest on the day the script runs. Two options make the result repeatable:
uv lock --script example.pywritesexample.py.locknext to the script. Lateruv run --script,uv add --script,uv export --scriptanduv tree --scriptreuse the locked versions.exclude-newerin a[tool.uv]table inside the metadata block tells uv to ignore distributions published after a given date, which keeps an old script resolving the way it did when it was written.
Pitfalls
- A package that does not exist, or a version range nothing satisfies, stops the run before your code starts: see No solution found when resolving dependencies.
- The block must use the exact
# /// scriptand# ///markers, with every line inside starting with#. A typo turns it into an ordinary comment and the imports fail with ModuleNotFoundError: No module named, because uv then runs the script without installing anything. - Packages from a private index need
uv add --script --index URL, which records the index in the block.
FAQ
Does uv run download the packages again on every run?
No. uv keeps downloaded packages in its cache, so later runs of the same script reuse them; it only resolves and fetches again when the dependency block changes.
Can I use inline script metadata without uv?
Yes. PEP 723 is a packaging standard, so other runners that read it, such as pipx run, install the same dependencies. Plain python example.py ignores the block, because every line in it is a comment.
Why does uv run ignore my project's dependencies?
A script with a script metadata block is self-contained: uv uses only the dependencies declared in the block, even inside a project. Add the packages you need to the block with uv add --script.