Skip to content

How to configure Claude Code to use uv

Claude Code already reaches for uv add and uv run inside a project that has a pyproject.toml. Two things still go wrong: it falls back to python3 script.py in a directory with no project metadata, and it stops for an approval prompt on every uv command it does run.

Both are observed defaults rather than documented contracts, so both can shift under you. A project CLAUDE.md and a permission allowlist put the behavior in your repository instead.

Prerequisites

  • Claude Code installed
  • uv installed on your system
  • A project directory. The allowlist check at the end adds a dependency, so run uv init first if the directory has no pyproject.toml.

Pin uv as the only way to run Python

1. Write the uv rules into CLAUDE.md

Create CLAUDE.md in your project root with these rules. Claude Code loads the file at the start of every session, so the rules survive a restart and reach teammates who clone the repo.

# Python tooling

Use uv for every Python command in this project.

- Run scripts and tools with `uv run`, never bare `python` or `python3`.
- Add and remove dependencies with `uv add` and `uv remove`, never `pip install`.
- Sync and lock the environment with `uv sync` and `uv lock`.
- Run a one-off tool without adding it to the project: `uvx ruff check`.
- For a standalone script, use `uv run script.py` and add its dependencies with
  `uv add --script script.py <package>`.

2. Confirm Claude reaches for uv

Drop a throwaway script in the project root and ask Claude Code to run it:

echo 'print("hello")' > hello.py
claude -p "Run hello.py and show me the output."

Claude runs uv run hello.py. In a directory that has neither pyproject.toml nor these rules, the same request gets python3 hello.py, which is the gap the file closes. Delete hello.py once you have seen the difference.

Stop the approval prompts

1. Allowlist the uv commands in .claude/settings.json

Create .claude/settings.json to pre-approve the uv commands and deny pip. Commit it so teammates inherit the same prompts, or keep the rules to yourself in .claude/settings.local.json.

.claude/settings.json
{
  "permissions": {
    "allow": [
      "Bash(uv run:*)",
      "Bash(uv add:*)",
      "Bash(uv remove:*)",
      "Bash(uv sync:*)",
      "Bash(uv lock:*)",
      "Bash(uvx:*)"
    ],
    "deny": [
      "Bash(pip install:*)",
      "Bash(pip3 install:*)",
      "Bash(python -m pip install:*)",
      "Bash(python3 -m pip install:*)"
    ]
  }
}

Every rule matches the literal start of a command, so Bash(uv run:*) covers uv run pytest, uv run ruff check, and uv run python. That same literal matching is why pip takes four deny rules: block only pip install and python -m pip install sails through, which is the spelling Claude picks once the short one is refused.

2. Accept the workspace trust dialog

Allow rules from a project you have not trusted are skipped, so the file you just wrote does nothing yet. Start an interactive session in the project root and accept the dialog before going further:

claude

claude -p skips the trust dialog rather than showing it, so print mode alone can never get you past this point.

3. Confirm the allowlist changed what Claude does

Ask Claude Code to add a dependency and watch whether it needs you:

claude -p "Add idna as a dependency to this project."

uv add idna runs unattended and idna appears under dependencies in pyproject.toml. Run uv remove idna to undo it.

If dependencies is unchanged and Claude reports that uv add idna needed approval, the rules did not load. Claude Code says so on startup:

Ignoring 6 permissions.allow entries from .claude/settings.json: this workspace has not been trusted.

Repeat the trust step from the directory the message names. Trust is keyed to the git repository root, or to the directory you started Claude Code in when there is no repository, so accepting the dialog in a subdirectory leaves the root untrusted.

Apply the rules to every project

Personal defaults that follow you across repositories go in your user-level files, which Claude Code reads regardless of working directory.

~/.claude/CLAUDE.md
~/.claude/settings.json

Project files win over user files, so a repository that needs different rules can override them.

Learn More

Last updated on