A CLAUDE.md Template for Python Projects Using uv
A ready-to-copy CLAUDE.md template for Python projects managed with uv, covering dependency commands, lockfile rules, virtual environment setup, and tests.
Updated 4 min read
A CLAUDE.md file in your Python project tells Claude Code that your team uses uv rather than pip or Poetry, which commands to run when adding a dependency, and what to do with the lockfile. Without that guidance, an assistant will often fall back to pip install, which bypasses the lockfile, the virtual environment that uv manages, and the version pinning your project depends on.
Tools like fenbs are a useful place for the tooling decisions that apply across your team: which package manager was chosen and why, which Python version is required, which linter configuration was agreed on. Your CLAUDE.md then covers the commands and constraints for the project at hand. This page gives you a template to copy and adapt.
What belongs in a CLAUDE.md for a uv project
The most important things to document are the commands Claude Code will need to run and the rules around the lockfile. uv keeps its own lockfile format (uv.lock) that is separate from pip's requirements files. If you do not explain this, an assistant may generate a requirements.txt manually or run pip freeze, which produces a different result.
- The Python version the project targets and how to confirm the right interpreter is in use.
- Commands for syncing the environment, adding a package, running the project, and running tests.
- The lockfile rule: always commit uv.lock; never edit it by hand.
- Whether the project uses a pyproject.toml with optional dependency groups (dev, test, docs).
- Any linting, formatting, or type-checking tools and the command for each.
The template
Copy this into a CLAUDE.md at your project root and fill in the bracketed sections. The uv documentation (opens in a new tab) covers the full command reference if you need to describe a workflow not shown here.
# [Project name] — Python project (uv) ## Package manager This project uses uv for dependency management. Do not use pip, pip-compile, or Poetry commands. Do not generate a requirements.txt manually. ## Python version Target: Python [3.11 / 3.12 / other]. uv selects the interpreter from the .python-version file or pyproject.toml. Run `uv python list` to see available interpreters and `uv python install 3.x` to add one. ## Common commands ``` # Install all dependencies (including dev group) uv sync --all-extras # Add a production dependency uv add [package-name] # Add a dev dependency uv add --dev [package-name] # Run the project uv run python src/[module].py # or if the project has a script entry point: uv run [script-name] # Run tests uv run pytest # Run linter and formatter uv run ruff check . uv run ruff format . # Type checking uv run mypy . ``` ## Lockfile uv.lock is committed to the repository. Never edit it by hand. After adding or removing a dependency, run `uv sync` to update it, then commit both pyproject.toml and uv.lock together. ## Dependency groups - `[project]` — production dependencies - `[dev]` or `[tool.uv.dev-dependencies]` — development tools (linters, test runner) - [Add any other groups your project uses] ## Environment uv creates and manages the virtual environment at .venv/ automatically. Do not activate the venv manually; use `uv run` for all commands. .venv/ is in .gitignore and must not be committed. ## Tests Tests live in tests/. Run the full suite with `uv run pytest` before committing. Test coverage is checked with `uv run pytest --cov`. Target coverage: [your threshold]. ## What Claude Code must not do - Run pip install or pip uninstall. - Edit uv.lock by hand. - Commit the .venv/ directory.
The lockfile rule matters most
The single most important instruction is to use uv add or uv remove rather than pip. When Claude Code adds a dependency correctly, uv updates both pyproject.toml and uv.lock atomically. If it uses pip instead, the lockfile drifts from the actual environment and the next developer to run uv sync may get a different set of packages.
Add a matching rule to never edit uv.lock by hand. The file is generated; manual edits will be overwritten and may introduce inconsistencies that are hard to diagnose. Claude Code will respect this rule if you state it clearly.
Virtual environment management
uv manages the virtual environment at .venv/ automatically when you run uv sync or uv run. You do not need to activate it with source .venv/bin/activate or the Windows equivalent. Telling Claude Code to use uv run for every command — running tests, the linter, the application — prevents it from trying to activate the environment manually and picking up the wrong Python interpreter.
Another common issue is Python version selection. uv can install and manage multiple Python interpreters, but if your CLAUDE.md does not specify which version the project requires, Claude Code may run commands against a different interpreter than expected. Add the target Python version and tell Claude Code how to verify it: "Run uv python list to confirm the correct version is available before running tests."
If your project uses dependency groups for optional extras — a test group, a docs group, a dev tools group — describe them briefly. The command uv sync --all-extras installs everything; uv sync --extra test installs only a subset. Tell Claude Code which groups are needed for the work it will do so it does not end up with a partial environment.
Tooling decisions for the whole team
The choice to use uv, ruff, mypy, or pytest usually comes from a team conversation rather than a solo decision. So does the Python version and the minimum test coverage threshold. Those agreements are worth recording somewhere more visible than a comment in pyproject.toml.
When a new team member joins or a new assistant session starts, the rationale behind "we use ruff instead of flake8" or "we require Python 3.12 minimum" is just as useful as the fact itself. Keeping those decisions in fenbs means they are readable alongside the current tasks and where the project stands.
Keep tooling decisions where every assistant can read them
Record your package manager choice, Python version floor, linter setup, and coverage target as Decisions and rules in fenbs. When a connected assistant starts a new session, it reads those rules before suggesting changes that would contradict a decision your team has already made.
Create a free accountFree for one person · No credit card · Works with Claude, ChatGPT, Cursor and more
How to do this with fenbs
- Create a free account. Start a project for your Python application and add the current development tasks.
- Record tooling decisions — uv as the package manager, ruff as the linter, the Python version floor — as Decisions and rules in fenbs.
- Connect Claude Code to fenbs from Integrations. Ask it to read the project context at the start of each session so it has the rules before making any changes.
- Copy the CLAUDE.md template above into your project root and fill in your specific Python version, commands, and test threshold.
- When a tooling decision changes — a new linter adopted, a Python version bumped — update the fenbs decision and the CLAUDE.md together so both records stay in sync.
If you work across multiple Python services that share the same tooling choices, see Claude Code with multiple projects and CLAUDE.md for how to place shared instructions at the workspace level so each service does not repeat them. For troubleshooting when uv commands are ignored, see CLAUDE.md not working.