uvx --from: Run Any Python Tool Directly from GitHub
I’ve been using uvx (the tool runner from uv) to run Python CLI tools from PyPI for a while. You type uvx ruff check . and it downloads ruff into a temporary environment and runs it. No install, no virtualenv, just works.
What I didn’t realize until recently is that uvx --from works with GitHub URLs too. This changes how I think about distributing small tools.
The Basics
If you have a Python package on PyPI with a console script entry point, uvx can run it directly:
uvx black my_file.py
uvx ruff check .
uvx pytest
Each of these creates a temporary, isolated environment, installs the package, and runs the command. Nothing pollutes your system or project environment.
The --from flag lets you specify where the package comes from, and it accepts anything that pip would accept as a requirement specifier. Including git URLs.
Running from GitHub
Say you have a Python project on GitHub with a pyproject.toml that defines a script entry point:
[project.scripts]
mytool = "mypackage.main:run"
You can run it directly:
uvx --from git+https://github.com/user/repo mytool
That’s it. uv clones the repo, builds the package, installs it into a temporary environment, and runs the mytool command. No git clone, no pip install, no virtualenv management.
You can also pin to a specific branch, tag, or commit:
# Specific branch
uvx --from git+https://github.com/user/repo@main mytool
# Specific tag
uvx --from git+https://github.com/user/repo@v1.0.0 mytool
# Specific commit
uvx --from git+https://github.com/user/repo@a1b2c3d mytool
Why This Is Handy
For trying out tools. Someone shares a repo with a CLI tool. Instead of cloning it, figuring out the dependencies, setting up an environment, and installing, you just run it. One command. If you don’t like it, there’s nothing to clean up.
For tools that aren’t on PyPI. Not everything needs to be published to a package registry. Small internal tools, personal utilities, or early-stage projects can just live on GitHub and still be runnable by anyone with uv.
For MCP servers. This is where it clicked for me. MCP servers are typically configured in a JSON file with a command to run them:
{
"mcpServers": {
"my-tool": {
"command": "uvx",
"args": ["--from", "git+https://github.com/user/mcp-tool", "my-tool"]
}
}
}
Anyone can add your MCP server to their client config by pointing at a GitHub repo. No pip install step, no instructions for cloning and setting up. Just the URL.
For sharing scripts with colleagues. Push a properly packaged Python script to GitHub, share the one-liner, and they’re running it. Works the same on macOS, Linux, and Windows (assuming they have uv).
What You Need in Your Repo
For this to work, your repo needs a pyproject.toml with:
- A build system declaration
- A script entry point
Here’s a minimal example:
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "my-tool"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = []
[project.scripts]
mytool = "mypackage.cli:main"
[tool.hatch.build.targets.wheel]
packages = ["src/mypackage"]
And then a Python file at src/mypackage/cli.py with a main() function. That’s the minimum viable package.
Caching
uv caches the built package, so the first run downloads and builds, but subsequent runs are fast. If the repo changes and you want the latest version, you can force a refresh:
uvx --reinstall --from git+https://github.com/user/repo mytool
A Practical Example
I recently built Sentinel, a small MCP server that analyzes your tool setup for security risks. The entire install instruction is:
uvx --from git+https://github.com/wdm0006/mcp-sentinel sentinel
No PyPI release, no Docker image, no build step. The repo has a pyproject.toml with a script entry point and that’s all it takes.
For MCP client configuration, it’s equally clean:
{
"mcpServers": {
"sentinel": {
"command": "uvx",
"args": ["--from", "git+https://github.com/wdm0006/mcp-sentinel", "sentinel"]
}
}
}
When Not to Use This
Production deployments. You probably want pinned versions and reproducible builds, not HEAD of a GitHub repo. Use --from git+...@v1.0.0 at minimum, or publish to PyPI.
Large packages with compiled dependencies. The first run builds from source, which can be slow for packages with C extensions. PyPI wheels are pre-built and much faster.
Private repos without auth configured. Git authentication needs to be set up for uv to access private repos. For public repos it just works.
Getting Started with uv
If you don’t have uv yet:
# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Or with Homebrew
brew install uv
Then try running something:
uvx --from git+https://github.com/astral-sh/ruff ruff check .
That runs ruff directly from its GitHub source. Pointless for ruff (it’s on PyPI), but it proves the concept. The real value is for the tools that aren’t on PyPI yet, or never will be.
Stay in the loop
Get notified when I publish new posts. No spam, unsubscribe anytime.