# How to write install instructions for a Python library

A library's README is the first place a new user lands, and the install command in that README is the first thing they copy. AI coding agents copy it too. If the only command shown is `pip install mylib`, every uv user has to translate, and every agent learns one more reason to default to pip. Lead with [uv](https://pydevtools.com/handbook/reference/uv.md), keep [pip](https://pydevtools.com/handbook/reference/pip.md) as the fallback, and the snippet works for everyone.

## Lead with `uv add`

Put the uv command first in the install section. Keep pip as a clearly labeled fallback.

````markdown
## Installation

```bash
uv add mylib
```

Or with pip:

```bash
pip install mylib
```
````

Order matters because both readers and AI assistants tend to copy the first runnable command they see. Putting `uv add` first nudges new projects toward [pyproject.toml](https://pydevtools.com/handbook/reference/pyproject.toml.md) and a [lock file](https://pydevtools.com/handbook/explanation/what-is-a-lock-file.md) without forcing anyone who prefers pip to do extra work.

## Show the extras syntax explicitly

Any time the library exposes [optional dependencies](https://pydevtools.com/handbook/explanation/what-are-optional-dependencies-and-dependency-groups.md), give the uv command for them. The shell needs the package-and-extras expression quoted because square brackets are glob characters in most shells:

```bash
uv add 'mylib[async]'
uv add 'mylib[async,redis]'
```

The pip equivalent uses the same quoting rule:

```bash
pip install 'mylib[async,redis]'
```

Document the extras list itself the same way it appears under `[project.optional-dependencies]` in `pyproject.toml`. Readers should not have to read source code to find which extras exist.

## Cover git and source installs

Users who want a pre-release fix or a fork need an install command that doesn't go through PyPI. uv's syntax differs from pip's enough to be worth showing.

```bash
uv add git+https://github.com/you/mylib
uv add git+https://github.com/you/mylib --tag 1.2.0
uv add git+https://github.com/you/mylib --branch main
```

For local development against a checkout:

```bash
uv add --editable ./mylib
```

The pip equivalents stay one line each:

```bash
pip install git+https://github.com/you/mylib@1.2.0
pip install git+https://github.com/you/mylib@main
pip install -e ./mylib
```

## Tell CLI users to install with `uv tool` or `uvx`

If the library ships an entry-point command (anything declared under `[project.scripts]`), most users want the CLI on their `PATH`, not added as a project dependency. Recommend [uv's tool commands](https://pydevtools.com/handbook/explanation/when-to-use-uv-run-vs-uvx.md) instead of `uv add`:

```bash
uvx mylib            # one-off run, no install
uv tool install mylib   # persistent install on PATH
```

The pip-world equivalent is [pipx](https://pydevtools.com/handbook/reference/pipx.md):

```bash
pipx run mylib
pipx install mylib
```

`uv add mylib` would still work, but it locks the CLI into one project's dependencies, which is not what someone reaching for `mylib --help` from any directory expects.

## Skip the version-pinning examples

Resist the urge to pad the install section with `uv add 'mylib>=2.0,<3'` examples. Readers landing on a README almost always want the latest release; the few who need a constraint already know how to write one. Reserve version syntax for a separate "compatibility" or "supported versions" section if the library has a real story there.

## Call out Python version requirements

If the library only supports specific Python versions, say so once, near the install commands, where a uv user would look:

> [!NOTE]
> mylib requires Python 3.10 or newer. If `uv add` reports a `requires-python` mismatch, point your project at a compatible interpreter with `uv python pin 3.10` (or `3.11`, `3.12`, and so on) and re-run the add.

That points the reader at the one command that resolves the most common install failure for a version-restricted library.

## Adapt this README install block

Here is what the recommended pattern looks like end to end. Edit the extras and CLI lines to match what the library actually exposes.

````markdown
## Installation

```bash
uv add mylib
```

If the project uses extras:

```bash
uv add 'mylib[async,redis]'
```

Or with pip:

```bash
pip install 'mylib[async,redis]'
```

mylib also ships a CLI. Run it directly with [uv](https://docs.astral.sh/uv/):

```bash
uvx mylib --help
```
````

This works for any reader: the [uv](https://pydevtools.com/handbook/explanation/why-you-should-try-uv-if-you-use-python.md) user copies the first block, the pip user copies the labeled fallback, and an AI assistant scanning the README sees uv as the primary path.

## Related

- [uv: A Complete Guide](https://pydevtools.com/handbook/explanation/uv-complete-guide.md) covers what uv does, how fast it is, the core workflows, and recent releases.
- [Why you should try uv if you use Python](https://pydevtools.com/handbook/explanation/why-you-should-try-uv-if-you-use-python.md) explains the case for uv as a default
- [What's the difference between pip and uv?](https://pydevtools.com/handbook/explanation/whats-the-difference-between-pip-and-uv.md) compares the two package managers
- [When to use uv run vs uvx](https://pydevtools.com/handbook/explanation/when-to-use-uv-run-vs-uvx.md) covers the CLI execution model
- [What are optional dependencies and dependency groups?](https://pydevtools.com/handbook/explanation/what-are-optional-dependencies-and-dependency-groups.md) explains how extras are declared
- [pyproject.toml reference](https://pydevtools.com/handbook/reference/pyproject.toml.md) documents the metadata fields a library declares
