# Inspiration
| Tool | Date added | Version |
| ------------------------------------------------------------- | ---------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| [`pipx run`](https://pipx.pypa.io/latest/docs/#pipx-run) | [2019-01-27](https://github.com/pypa/pipx/releases/tag/0.11.0.0) | [0.11.0.0](https://pipx.pypa.io/latest/changelog/#:~:text=Replace%20pipx%20BINARY%20with%20pipx%20run%20BINARY) |
| [`uv tool`](https://docs.astral.sh/uv/reference/cli/#uv-tool) | [2024-08-24](https://astral.sh/blog/uv-unified-python-packaging) | [0.3](https://astral.sh/blog/uv-unified-python-packaging) |
## pipx
```
usage: pipx run [-h] [--quiet] [--verbose] [--global] [--no-cache] [--path]
[--pypackages] [--spec SPEC] [--python PYTHON]
[--fetch-missing-python] [--system-site-packages]
[--index-url INDEX_URL] [--editable] [--pip-args PIP_ARGS]
app ...
Download the latest version of a package to a temporary virtual environment,
then run an app from it. The environment will be cached
and re-used for up to 14 days. This
means subsequent calls to 'run' for the same package will be faster
since they can reuse the cached Virtual Environment.
In support of PEP 582 'run' will use apps found in a local __pypackages__
directory, if present. Please note that this behavior is experimental,
and acts as a companion tool to pythonloc. It may be modified or
removed in the future. See https://github.com/cs01/pythonloc.
positional arguments:
app ... app/package name and any arguments to be passed to it
options:
-h, --help show this help message and exit
--quiet, -q Give less output. May be used multiple times
corresponding to the ERROR and CRITICAL logging
levels. The count maxes out at 2.
--verbose, -v Give more output. May be used multiple times
corresponding to the INFO, DEBUG and NOTSET logging
levels. The count maxes out at 3.
--global Perform action globally for all users.
--no-cache Do not reuse cached virtual environment if it exists
--path Interpret app name as a local path
--pypackages Require app to be run from local __pypackages__
directory
--spec SPEC The package name or specific installation source
passed to pip. Runs `pip install -U SPEC`. For example
`--spec mypackage==2.0.0` or `--spec
git+https://github.com/user/repo.git@branch`
--python PYTHON Python to install with. Possible values can be the
executable name (python3.11), the version of an
available system Python or to pass to py launcher
(3.11), or the full path to the executable. Requires
Python 3.9 or above.
--fetch-missing-python
Whether to fetch a standalone python build from GitHub
if the specified python version is not found locally
on the system.
--system-site-packages
Give the virtual environment access to the system
site-packages dir.
--index-url, -i INDEX_URL
Base URL of Python Package Index
--editable, -e Install a project in editable mode
--pip-args PIP_ARGS Arbitrary pip arguments to pass directly to pip
install/upgrade commands
```
## uv
```
Run a command provided by a Python package
Usage: uv tool run [OPTIONS] [COMMAND]
Options:
--from <FROM>
Use the given package to provide the command
-w, --with <WITH>
Run with the given packages installed
--with-editable <WITH_EDITABLE>
Run with the given packages installed in editable mode
--with-requirements <WITH_REQUIREMENTS>
Run with the packages listed in the given files
-c, --constraints <CONSTRAINTS>
Constrain versions using the given requirements files [env:
UV_CONSTRAINT=]
-b, --build-constraints <BUILD_CONSTRAINTS>
Constrain build dependencies using the given requirements files when
building source distributions [env: UV_BUILD_CONSTRAINT=]
--overrides <OVERRIDES>
Override versions using the given requirements files [env:
UV_OVERRIDE=]
--isolated
Run the tool in an isolated virtual environment, ignoring any
already-installed tools [env: UV_ISOLATED=]
--env-file <ENV_FILE>
Load environment variables from a `.env` file [env: UV_ENV_FILE=]
--no-env-file
Avoid reading environment variables from a `.env` file [env:
UV_NO_ENV_FILE=]
--lfs
Whether to use Git LFS when adding a dependency from Git
--python-platform <PYTHON_PLATFORM>
The platform for which requirements should be installed [possible
values: windows, linux, macos, x86_64-pc-windows-msvc,
aarch64-pc-windows-msvc, i686-pc-windows-msvc,
x86_64-unknown-linux-gnu, aarch64-apple-darwin, x86_64-apple-darwin,
aarch64-unknown-linux-gnu, aarch64-unknown-linux-musl,
x86_64-unknown-linux-musl, riscv64-unknown-linux,
x86_64-manylinux2014, x86_64-manylinux_2_17, x86_64-manylinux_2_28,
x86_64-manylinux_2_31, x86_64-manylinux_2_32, x86_64-manylinux_2_33,
x86_64-manylinux_2_34, x86_64-manylinux_2_35, x86_64-manylinux_2_36,
x86_64-manylinux_2_37, x86_64-manylinux_2_38, x86_64-manylinux_2_39,
x86_64-manylinux_2_40, aarch64-manylinux2014, aarch64-manylinux_2_17,
aarch64-manylinux_2_28, aarch64-manylinux_2_31,
aarch64-manylinux_2_32, aarch64-manylinux_2_33,
aarch64-manylinux_2_34, aarch64-manylinux_2_35,
aarch64-manylinux_2_36, aarch64-manylinux_2_37,
aarch64-manylinux_2_38, aarch64-manylinux_2_39,
aarch64-manylinux_2_40, aarch64-linux-android, x86_64-linux-android,
wasm32-pyodide2024, arm64-apple-ios, arm64-apple-ios-simulator,
x86_64-apple-ios-simulator]
--torch-backend <TORCH_BACKEND>
The backend to use when fetching packages in the PyTorch ecosystem
(e.g., `cpu`, `cu126`, or `auto`) [env: UV_TORCH_BACKEND=] [possible
values: auto, cpu, cu130, cu129, cu128, cu126, cu125, cu124, cu123,
cu122, cu121, cu120, cu118, cu117, cu116, cu115, cu114, cu113, cu112,
cu111, cu110, cu102, cu101, cu100, cu92, cu91, cu90, cu80, rocm7.1,
rocm7.0, rocm6.4, rocm6.3, rocm6.2.4, rocm6.2, rocm6.1, rocm6.0,
rocm5.7, rocm5.6, rocm5.5, rocm5.4.2, rocm5.4, rocm5.3, rocm5.2,
rocm5.1.1, rocm4.2, rocm4.1, rocm4.0.1, xpu]
Index options:
--index <INDEX>
The URLs to use when resolving dependencies, in addition to the
default index [env: UV_INDEX]
--default-index <DEFAULT_INDEX>
The URL of the default package index (by default:
<https://pypi.org/simple>) [env: UV_DEFAULT_INDEX]
-i, --index-url <INDEX_URL>
(Deprecated: use `--default-index` instead) The URL of the Python
package index (by default: <https://pypi.org/simple>) [env:
UV_INDEX_URL]
--extra-index-url <EXTRA_INDEX_URL>
(Deprecated: use `--index` instead) Extra URLs of package indexes to
use, in addition to `--index-url` [env: UV_EXTRA_INDEX_URL]
-f, --find-links <FIND_LINKS>
Locations to search for candidate distributions, in addition to those
found in the registry indexes [env: UV_FIND_LINKS]
--no-index
Ignore the registry index (e.g., PyPI), instead relying on direct URL
dependencies and those provided via `--find-links`
--index-strategy <INDEX_STRATEGY>
The strategy to use when resolving against multiple index URLs [env:
UV_INDEX_STRATEGY=] [possible values: first-index, unsafe-first-match,
unsafe-best-match]
--keyring-provider <KEYRING_PROVIDER>
Attempt to use `keyring` for authentication for index URLs [env:
UV_KEYRING_PROVIDER=] [possible values: disabled, subprocess]
Resolver options:
-U, --upgrade
Allow package upgrades, ignoring pinned versions in any existing
output file. Implies `--refresh`
-P, --upgrade-package <UPGRADE_PACKAGE>
Allow upgrades for a specific package, ignoring pinned versions in any
existing output file. Implies `--refresh-package`
--resolution <RESOLUTION>
The strategy to use when selecting between the different compatible
versions for a given package requirement [env: UV_RESOLUTION=]
[possible values: highest, lowest, lowest-direct]
--prerelease <PRERELEASE>
The strategy to use when considering pre-release versions [env:
UV_PRERELEASE=] [possible values: disallow, allow, if-necessary,
explicit, if-necessary-or-explicit]
--fork-strategy <FORK_STRATEGY>
The strategy to use when selecting multiple versions of a given
package across Python versions and platforms [env: UV_FORK_STRATEGY=]
[possible values: fewest, requires-python]
--exclude-newer <EXCLUDE_NEWER>
Limit candidate packages to those that were uploaded prior to the
given date [env: UV_EXCLUDE_NEWER=]
--exclude-newer-package <EXCLUDE_NEWER_PACKAGE>
Limit candidate packages for specific packages to those that were
uploaded prior to the given date
--no-sources
Ignore the `tool.uv.sources` table when resolving dependencies. Used
to lock against the standards-compliant, publishable package metadata,
as opposed to using any workspace, Git, URL, or local path sources
[env: UV_NO_SOURCES=]
--no-sources-package <NO_SOURCES_PACKAGE>
Don't use sources from the `tool.uv.sources` table for the specified
packages [env: UV_NO_SOURCES_PACKAGE=]
Installer options:
--reinstall
Reinstall all packages, regardless of whether they're already
installed. Implies `--refresh`
--reinstall-package <REINSTALL_PACKAGE>
Reinstall a specific package, regardless of whether it's already
installed. Implies `--refresh-package`
--link-mode <LINK_MODE>
The method to use when installing packages from the global cache [env:
UV_LINK_MODE=] [possible values: clone, copy, hardlink, symlink]
--compile-bytecode
Compile Python files to bytecode after installation [env:
UV_COMPILE_BYTECODE=]
Build options:
-C, --config-setting <CONFIG_SETTING>
Settings to pass to the PEP 517 build backend, specified as
`KEY=VALUE` pairs
--config-settings-package <CONFIG_SETTINGS_PACKAGE>
Settings to pass to the PEP 517 build backend for a specific package,
specified as `PACKAGE:KEY=VALUE` pairs
--no-build-isolation
Disable isolation when building source distributions [env:
UV_NO_BUILD_ISOLATION=]
--no-build-isolation-package <NO_BUILD_ISOLATION_PACKAGE>
Disable isolation when building source distributions for a specific
package
--no-build
Don't build source distributions [env: UV_NO_BUILD=]
--no-build-package <NO_BUILD_PACKAGE>
Don't build source distributions for a specific package [env:
UV_NO_BUILD_PACKAGE=]
--no-binary
Don't install pre-built wheels [env: UV_NO_BINARY=]
--no-binary-package <NO_BINARY_PACKAGE>
Don't install pre-built wheels for a specific package [env:
UV_NO_BINARY_PACKAGE=]
Cache options:
-n, --no-cache
Avoid reading from or writing to the cache, instead using a temporary
directory for the duration of the operation [env: UV_NO_CACHE=]
--cache-dir <CACHE_DIR>
Path to the cache directory [env: UV_CACHE_DIR=]
--refresh
Refresh all cached data
--refresh-package <REFRESH_PACKAGE>
Refresh cached data for a specific package
Python options:
-p, --python <PYTHON> The Python interpreter to use to build the run
environment. [env: UV_PYTHON=]
--managed-python Require use of uv-managed Python versions [env:
UV_MANAGED_PYTHON=]
--no-managed-python Disable use of uv-managed Python versions [env:
UV_NO_MANAGED_PYTHON=]
--no-python-downloads Disable automatic downloads of Python. [env:
"UV_PYTHON_DOWNLOADS=never"]
Global options:
-q, --quiet...
Use quiet output
-v, --verbose...
Use verbose output
--color <COLOR_CHOICE>
Control the use of color in output [possible values: auto, always,
never]
--native-tls
Whether to load TLS certificates from the platform's native store
[env: UV_NATIVE_TLS=]
--offline
Disable network access [env: UV_OFFLINE=]
--allow-insecure-host <ALLOW_INSECURE_HOST>
Allow insecure connections to a host [env: UV_INSECURE_HOST=]
--no-progress
Hide all progress outputs [env: UV_NO_PROGRESS=]
--directory <DIRECTORY>
Change to the given directory prior to running the command [env:
UV_WORKING_DIR=]
--project <PROJECT>
Discover a project in the given directory [env: UV_PROJECT=]
--config-file <CONFIG_FILE>
The path to a `uv.toml` file to use for configuration [env:
UV_CONFIG_FILE=]
--no-config
Avoid discovering configuration files (`pyproject.toml`, `uv.toml`)
[env: UV_NO_CONFIG=]
-h, --help
Display the concise help for this command
Use `uvx` as a shortcut for `uv tool run`.
Use `uv help tool run` for more details.
```
# Purpose
Install and/or run tools from e.g. PyPI. This would provide functionality similar to `npm install -g`.
# Notes
Trickiest bit is the UI for installing versus running such that running is very short when you don't want to bother installing (`py x`?). Another is whether some version restriction could be picked up from `pyproject.toml` or `pylock.toml`?
- `--from`: specify what project to install
- Support specifiers
- `--spec` from pipx
- [`--from` from uv](https://docs.astral.sh/uv/reference/cli/#uv-tool-run--from)
- Fallback to `-m` if an entry point with the specified name isn't found?
- How long to keep around ephemeral environments?
- pipx is 14 days
- [uv keeps using the cached version indefinitely](https://docs.astral.sh/uv/concepts/tools/#tool-environments)
- Can use `@latest` to always check for a newer version
- Provide a way to force a fresh install
- If a date-based solution is used, provide a way to specify acceptable staleness?
- Use installed version from `tool install` or keep separate from `tool run`?
- uv shares, but only when a specifier wasn't used to get a specific thing for `run`
- Is it worth having a permanent install versus just supporting `py x`?
- It certainly looks cleaner to just say e.g. `nox` than `py x nox`
- A permanent install also avoids any network access in case the cached copy is too old
- How often do people do a permanent install?