Skip to content

/commands/uv/uv-run-script-inline-dependencies

uv run script.py with inline dependencies (PEP 723)

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash) · uv 0.12.19 (bea138450 2026-09-24 aarch64-pc-windows-msvc)updated
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

bash
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.py

Output

# /// script
# requires-python = ">=3.13"
# dependencies = [
#     "packaging==24.2",
# ]
# ///
from packaging.version import Version
print(Version("2.1.0rc1") < Version("2.1.0"))
True

uv 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

example.py
# /// script
# requires-python = ">=3.12"
# dependencies = [
#   "requests<3",
#   "rich",
# ]
# ///
import requests
from rich import print

requires-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.

CommandEffect
uv init --script example.py --python 3.12Create a new script with an empty metadata block
uv add --script example.py richAdd a dependency to the block
uv remove --script example.py richRemove it again
uv run --with rich example.pyAdd a dependency for one run only, without editing the file
uv lock --script example.pyWrite 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.py writes example.py.lock next to the script. Later uv run --script, uv add --script, uv export --script and uv tree --script reuse the locked versions.
  • exclude-newer in 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 # /// script and # /// 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.

Sources