Streamlined Script Execution with uvr
uv is a blazing fast, modern Python package manager and workflow tool. However, its project-centric design (uv run) prioritizes the current working directory (CWD) when looking for virtual environments and pyproject.toml files. This makes it cumbersome to execute a project-dependent script from outside its root directory, as it forces you to manually pass the --project flag with the absolute path to the script's home.
uvr (uv-runner) acts as an intelligent wrapper that resolves this pain point. It automatically detects the correct project context relative to the script being executed, allowing you to use a clean shebang (#!/usr/bin/env uvr) or call:
uvr [options] script.py
instead of:
uv run --project /path/to/script/project [options] /path/to/script/project/script.py
Key Value: It restores the true portability of standalone and project-tied Python scripts without polluting your command line or breaking your workflow when moving between directories.
Installation
Prerequisite: uv must be installed and available on your PATH.
To install uvr, use the following command:
uv tool install uvr
To upgrade uvr, use the following command:
uv tool upgrade uvr
Windows Console Modes
Two entry points are installed:
uvr— console application. Use from a terminal or for scripts that need a command-line window.uvr-gui— GUI application. Use for scripts started by double-click or for GUI-only programs that must not open a console window.
On Linux and macOS both commands behave the same.
Usage
Several ways to run your Python scripts with uv:
-
Using
uv run --project <project_path> <script_path>:-
This command explicitly tells
uvto run the specified Python script within the context of the project located at<project_path>. -
This is useful when your script relies on dependencies defined within a specific project directory but is executed from elsewhere.
-
Example:
uv run --project /path/to/project [options] /path/to/project/script.py [script_options]
-
-
Using
uvr script.py:-
This is a more direct way to execute your Python script (
script.py) usinguvr. -
uvrautomatically determines the project directory based on the script path, effectively mimicking the--projectflag's behavior. -
Example:
uvr [options] [--] script.py [script_options]
-
For ambiguity and edge cases, use
--(see the section General Rule for Using the--Separator).
-
-
Shebang Usage:
-
Example:
#!/usr/bin/env -S uvr [options] [--] # Your Python code here...
-
Note on
-Sflag: The-Sflag allows passing multiple arguments to the interpreter. It is optional if yourenvimplementation supports it (most modern systems do). However:- Without
-S: You can only use#!/usr/bin/env uvrwithout additional options or parameters - With
-S: You can pass options like#!/usr/bin/env -S uvr --with dep1 -- - Some older or minimal Unix-like systems may not support the
-Sflag inenv
- Without
-
If you pass script arguments, use
--to separateuvr/uvoptions from script arguments.
-
-
Scripts without
.pyor.pywextension:-
Automatic
--scriptoption is added if not already present (--scriptor--gui-script) in options. -
Without this,
uvcan in some cases mis-handle execution flow. -
Example: For a
fooscript:#!/usr/bin/env -S uvr [options] [--] # Your Python code here...
This will be executed as
uv run [options] --script ...if[options]do not already contain--scriptor--gui-script. -
Or, to be more explicit, you can include the
--scriptflag directly in the shebang:#!/usr/bin/env -S uvr --script -
Important Exception for Non-Files: If the identified
script_path(the argument immediately following options or--) does not point to an actual file on disk,uvrwill not automatically add the--scriptor--gui-scriptoption. This behavior ensuresuvrcan correctly pass through commands that are executables within the virtual environment (e.g.,uvr black .,uvr pytest), rather than a Python script file.
-
-
Debug usage:
- Example:
uvr -v [options] [--] script.py [script_options] uvr -vv [options] [--] script.py [script_options]
- Example:
General Rule for Using the -- Separator
The -- argument functions as a standard command-line delimiter. It explicitly separates options intended for uvr (and its underlying uv process) from arguments specifically designated for the Python script being executed.
Arguments appearing before the -- are processed by uvr (uv). Arguments appearing after the -- are passed directly to the invoked Python script.
This explicit separation is crucial for:
-
Preventing Ambiguity:
uvremploys a basic heuristic to identify the script path (the first non-hyphenated argument). This can lead to misinterpretation if the script itself accepts options that resembleuvr/uvarguments. -
Ensuring Precise Argument Passing: By using
--, users guarantee that all subsequent arguments are correctly delivered to their script, bypassinguvr'sargument parsing logic.
Recommendation: Utilize the -- separator whenever precise control over argument distribution between uvr/uv and the target script is required.
Ctrl+C (SIGINT) Handling
uvr handles KeyboardInterrupt to provide clean CLI behavior when interrupted with Ctrl+C.
- It suppresses Python traceback noise (unwanted junk output) on user interruption.
- It exits with status code
130, following the common Unix convention:128 + 2(SIGINTis signal number2). - This keeps output clean while still signaling to the parent shell/process that execution was interrupted.
Platform note:
- On Linux and macOS,
130matches the common signal-derived convention (128 + SIGINT 2). - On Windows,
130is used intentionally as a consistent, cross-platform interruption code foruvr.
Security Notes
uvr is a convenience wrapper around uv run. It does not add privileges by itself, but it will execute the script/command you pass to it.
Main risks:
- Running untrusted scripts can execute arbitrary code.
- Untrusted dependency sources can introduce supply-chain risk.
- Running as root/Administrator increases impact if something goes wrong.
- A compromised
PATHcould resolve a maliciousuvbinary.
Recommended protections:
- Run only trusted scripts and trusted dependency sources.
- Do not run
uvras root/Administrator unless strictly required. - In CI, pin dependencies and use a lockfile where possible.
- Prefer explicit script paths for automation (
script.py) over ambiguous invocations. - Keep build/runtime environments isolated (virtual environments, containers, CI runners).
- Ensure your
PATHresolves to the expecteduvexecutable.
Scope note:
uvris not a sandbox. It is a command runner helper and should be used with standard secure development practices.
Metadata
Release files for uvr 0.1.38
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| uvr-0.1.38.tar.gz | 5.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| uvr-0.1.38-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 12.7 kB
Release files / uvr-0.1.38.tar.gz
| Download URL | uvr-0.1.38.tar.gz |
|---|---|
| Size | 5.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
79ab9f4ea8693aed426898345192e08daf9a33fb7e4f5d3779a3f39e6bd2f6a6
|
|
BLAKE2b-256 checksum How to use checksums |
5bb4add4d508f592b2afc5cb3a58bfb887618624af90e0c6705d8d7514105967
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.24
|
Release files / uvr-0.1.38-py3-none-any.whl
| Download URL | uvr-0.1.38-py3-none-any.whl |
|---|---|
| Size | 6.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0539caf81e09d3231d841d6b5fc2f1153fde61d47b615aac5bd2accba51cbb42
|
|
BLAKE2b-256 checksum How to use checksums |
78b6e185502d10da05c0c52641671830acc6ae232c474bb481271b1d9f590313
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.24
|