Skip to content

Getting started with uv

uv

uv handles Python installation, project setup, dependency management, and script execution in a single tool. This tutorial walks through each of those capabilities so you can start using uv for any Python project.

Prerequisites

You need a terminal (Terminal on macOS, PowerShell on Windows, or any Linux shell). No prior Python installation is required.

Installing uv

curl -LsSf https://astral.sh/uv/install.sh | sh

Alternatively, install with Homebrew:

brew install uv

Verify the installation:

$ uv --version
uv 0.7.x

If you see command not found: uv, the installer printed a hint about updating your shell PATH. Open a new terminal window (or restart the current shell) so the updated PATH takes effect.

For platform-specific details, see How to install uv.

Creating a project

Initialize a new project

$ uv init my-project
Initialized project `my-project` at `/path/to/my-project`
$ cd my-project

Examine the generated files

uv init creates a ready-to-use project structure:

    • pyproject.toml
    • .python-version
    • main.py
    • README.md

Open pyproject.toml to see your project metadata:

[project]
name = "my-project"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = []

The .python-version file records which Python version the project uses. uv reads this file automatically and downloads that interpreter if it isn’t already installed. See What is a Python version file? for more on how this works.

Run the starter script

$ uv run main.py
Using CPython 3.13.5
Creating virtual environment at: .venv
Hello from my-project!

uv run creates a virtual environment in .venv/, installs the correct Python version, syncs any dependencies, and then runs your script. All of that happens automatically on the first run. Subsequent invocations skip the setup lines and print only Hello from my-project!.

Notice the new .venv/ directory in the project. That is where the project’s Python interpreter and installed packages live. uv manages it for you, so there is no need to activate it manually.

Tip

uv init creates an application project by default. For libraries, CLI tools, or other structures, see Understanding uv init project types.

Adding dependencies

Add a package

If you see error: No pyproject.toml found in current directory or any parent directory, you are running uv add outside the project. cd into the my-project/ directory you created with uv init, then retry.

$ uv add requests
Resolved 6 packages in 101ms
Installed 5 packages in 9ms
 + certifi==2025.1.31
 + charset-normalizer==3.4.1
 + idna==3.10
 + requests==2.32.3
 + urllib3==2.3.0

This command does three things: updates dependencies in pyproject.toml, resolves compatible versions and writes a lockfile (uv.lock), and installs the package into the project’s virtual environment.

Notice the new uv.lock file in the project root. It pins the exact version of every direct and transitive dependency, so anyone running uv sync later gets the identical environment. Commit it alongside pyproject.toml.

Your pyproject.toml now includes:

dependencies = [
    "requests>=2.32.3",
]

Use the package in your code

Replace the contents of main.py with:

import requests

response = requests.get("https://httpbin.org/json")
data = response.json()
print(data["slideshow"]["title"])  # prints the title from the response

Run it:

$ uv run main.py
Sample Slide Show

Add a development dependency

Development tools like linters and test runners belong in a separate dependency group so they don’t ship with your project:

$ uv add --dev ruff
Resolved 7 packages in 83ms
Installed 1 package in 3ms
 + ruff==0.8.4

This adds ruff under a development dependency group in pyproject.toml. Run it with:

$ uv run ruff check .
All checks passed!

Remove a package

$ uv remove requests
Resolved 2 packages in 4ms
Uninstalled 5 packages in 6ms
 - certifi==2025.1.31
 - charset-normalizer==3.4.1
 - idna==3.10
 - requests==2.32.3
 - urllib3==2.3.0

This updates pyproject.toml, regenerates uv.lock, and uninstalls the package from the virtual environment.

Running code and tools

uv run is the primary way to execute anything inside your project’s environment. It ensures dependencies are synced before every invocation.

# Run a Python script
uv run main.py

# Run a module
uv run -m http.server 8000

# Run a tool installed as a dependency
uv run ruff format .

To run a CLI tool that isn’t part of your project (a one-off invocation), use uvx:

# Run a tool without adding it as a dependency
uvx cowsay "hello uv"

For a deeper comparison, see When to use uv run vs uvx.

Managing Python versions

uv downloads and manages Python interpreters directly. No separate tool like pyenv is needed.

List available versions

$ uv python list
cpython-3.14.0-macos-aarch64-none                 <download available>
cpython-3.13.5-macos-aarch64-none                 /Users/you/.local/share/uv/python/cpython-3.13.5-macos-aarch64-none/bin/python3.13
cpython-3.13.5+freethreaded-macos-aarch64-none    <download available>
cpython-3.12.7-macos-aarch64-none                 <download available>
...

The output lists every Python build uv can manage. Versions already on disk show a path; versions marked <download available> will be fetched on first use. Your output will differ based on platform, architecture, and which versions you have already installed.

Install a specific version

$ uv python install 3.12
Installed Python 3.12.7 in 80ms
 + cpython-3.12.7-macos-aarch64-none (python3.12)

If the version is already installed, uv prints Python 3.12 is already installed instead and exits without changes.

Pin a version to your project

The pinned version must satisfy the requires-python constraint in pyproject.toml. If requires-python = ">=3.13", pinning to 3.12 fails with error: The requested Python version 3.12is incompatible with the projectrequires-pythonvalue of>=3.13. Loosen requires-python first, or pin a compatible version.

$ uv python pin 3.12
Pinned `.python-version` to `3.12`

This writes 3.12 to the .python-version file. The next time you run uv run, uv uses that version (installing it first if necessary). Open .python-version to confirm the change; it contains a single line with the pinned version.

Test against a different version

You can run a single command with a different Python version without changing the project pin:

uv run --python 3.11 main.py

What to explore next

You now know how to install uv, scaffold a project, manage dependencies, run code, and switch Python versions. Each of these topics goes deeper:

Last updated on

Please submit corrections and feedback...