Simple script execution with uv - run Python scripts without explicit --project flag
Project description
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
or
uv tool install --from git+https://github.com/karnigen/uvr uvr
To upgrade uvr, use the following command:
uv tool upgrade uvr
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.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file uvr-0.1.28.tar.gz.
File metadata
- Download URL: uvr-0.1.28.tar.gz
- Upload date:
- Size: 7.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.24
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aa3b693c0c4427c77b8f0cc2c5773862110945d5a656f4f32eb782e607f363a2
|
|
| MD5 |
27690809de3716fd3514b41dc093139a
|
|
| BLAKE2b-256 |
5c412bf0546971943030fb6f7afd400116e26736acbe9fdd487dc82b818b5979
|
File details
Details for the file uvr-0.1.28-py3-none-any.whl.
File metadata
- Download URL: uvr-0.1.28-py3-none-any.whl
- Upload date:
- Size: 6.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.24
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2cb8877f4d3d3ffc22b11dc0d3a02df9d43fd3534f175bf972008a38fd6288eb
|
|
| MD5 |
084ff908cc29daf9578a7e968f1fb1bb
|
|
| BLAKE2b-256 |
24d711c204b4cac97d68380abaaa04f91b39d163b97b13a42c1bfc1caeb31d87
|