← All posts
·7 min read

Claude Code with Python: The Complete Workflow

Claude CodePythonWorkflowSetup
Claude Code with Python: The Complete Workflow

Why Python projects benefit from dedicated Claude Code configuration

Claude Code is not Python-naive. It knows pip, Poetry, pytest, virtualenv, and every major framework. The problem is that without project-specific configuration, it uses that knowledge generically. It generates code that runs in isolation but ignores your project's import conventions, skips your test patterns, and produces virtual environment commands that assume a layout you do not have.

The fix is a Python-specific CLAUDE.md that tells Claude Code exactly how your project is structured. This guide covers that configuration layer, the pytest integration that catches bugs automatically, and the refactoring loops that save hours on large codebases. If you are new to Claude Code, start with what is Claude Code before continuing here.

The Python CLAUDE.md

The single highest-leverage configuration for any Python project is a CLAUDE.md that answers four questions: how is the environment managed, how are imports structured, how are tests run, and what is the type posture?

# Python project rules

## Environment
- Virtual environment: `source .venv/bin/activate` (venv in .venv/, not env/ or venv/)
- Package manager: uv (not pip directly)
- Install: `uv pip install -r requirements.txt`
- Python version: 3.12 (see .python-version)

## Imports
- Absolute imports only. Never relative imports outside the src/ tree.
- Internal packages under src/{package_name}/
- src/ added to sys.path via pyproject.toml [tool.pytest.ini_options]

## Tests
- Run: `pytest` from project root
- Coverage: `pytest --cov=src --cov-report=term-missing`
- New tests go in tests/ mirroring src/ structure
- Fixtures defined in tests/conftest.py

## Type checking
- `mypy src/` before committing
- No implicit Any. Annotate all public functions.
- Type stubs for external packages in typings/

## Hard rules
- Never modify .python-version
- Never commit with failing tests
- Never add a bare except: clause

This file loads every session. Claude reads it before writing a single line. The result is code that fits your project rather than code that needs retrofitting.

Virtual environment and dependency management

The most common breakage in Claude Code with Python is environment confusion. Claude generates a command referencing pip when you use uv, or activates the wrong directory, or installs into the global Python installation.

Prevent this with two explicit lines in CLAUDE.md:

- Use `uv pip install`, never `pip install` directly
- Activate with `source .venv/bin/activate` before any pip or python command

If your project uses Poetry instead of uv:

- Use `poetry run pytest` instead of activating the environment directly
- Dependency changes: `poetry add <package>`, never manual requirements.txt edits

Claude Code follows these instructions precisely once they are written. The virtualenv confusion disappears.

Pytest integration that catches bugs inside Claude's loop

The most productive Python workflow with Claude Code runs tests automatically after every change. You do not review code and then run tests. Claude runs them as part of its own loop.

Add this to your CLAUDE.md:

## After every code change

1. Run `pytest tests/unit/` for fast feedback
2. If tests pass, run `pytest` for the full suite
3. If tests fail, fix the failure before considering the task complete
4. Do not ask for review until `pytest --cov=src` passes at >80% coverage

This is the difference between Claude Code as a code generator (produces something that looks right) and Claude Code as a development partner (produces something that is right). The feedback loop is tight enough that most bugs surface and get fixed before you see the output.

Writing tests that Claude can maintain

The other half of this is writing tests in a style Claude understands well. Pytest fixtures work better than unittest setUp/tearDown. Parametrize is well-supported. Mocking with unittest.mock.patch works reliably.

What does not work well: deeply nested class-based test hierarchies that Claude has to reconstruct from context every session. Keep tests flat. One class per module under test. Fixtures in conftest.py, not scattered across test files.

Handling large codebases and multi-file refactoring

Python projects accumulate technical debt fast. Changing a base class propagates through dozens of subclasses. Renaming a module requires updates across imports, tests, and sometimes config files. Claude Code handles this well, but only if you tell it the scope upfront.

The pattern that works:

  1. Start with a plan session: "We are renaming UserService to UserRepository across the codebase. Before making any changes, list every file that imports or instantiates UserService."

  2. Review the scope before Claude touches anything.

  3. Approve the plan, then let Claude execute.

  4. Run pytest and mypy src/ after the full refactor.

This is the multi-file editing workflow applied to Python. The failure mode is skipping step one and letting Claude start editing immediately. It will miss imports. The plan pass costs two minutes and saves twenty.

Type annotation workflows

Python's type system is opt-in, which means Claude will happily generate code without annotations unless you ask. And "ask" in this context means CLAUDE.md rules, not per-prompt requests.

With mypy in your CLAUDE.md configuration, Claude Code annotates as it goes. But mypy catches more than missing annotations. It catches:

  • Functions returning the wrong type for their annotation
  • Dictionary accesses on Optional[dict] without None-checks
  • Missing return branches in Union types

Configure mypy to run automatically:

## Type checking

After modifying any .py file in src/, run `mypy src/` and fix all
errors before the task is complete. Use --strict for new modules,
--ignore-missing-imports only as a last resort.

The goal is a clean mypy run in your CI pipeline. Claude Code will get you most of the way there if the rules are explicit.

Debugging workflows

Python debugging with Claude Code works best when you provide error output directly. Not "it's crashing" but the full traceback. Claude Code reads tracebacks the way a senior developer does, identifying the root cause rather than the symptom.

For interactive debugging, the pdb workflow:

## Debugging

When debugging, prefer adding `breakpoint()` to the exact line
of failure and running `pytest -s tests/path_to_test.py::test_name`
rather than adding print statements. Remove breakpoints before
completing any task.

This gives Claude a clear pattern to follow when you ask it to debug. It knows to use breakpoints, run the targeted test, and clean up when done.

For async code (asyncio, aiohttp, FastAPI), add:

## Async debugging

Use `asyncio.run(main())` patterns in debug scripts.
For FastAPI routes, use `httpx.AsyncClient` in tests rather than
the standard requests library.

FastAPI and Django configuration

Two frameworks dominate Python backend development in 2026. Both benefit from explicit Claude Code configuration beyond generic Python rules.

For FastAPI projects:

## FastAPI rules

- Route handlers use async def always
- Pydantic models in models/ directory
- Dependency injection via Depends(), not global state
- Tests use `httpx.AsyncClient(app=app, base_url="http://test")` pattern
- OpenAPI schema must remain valid after every change

For Django projects, the key rules are around management commands, migration handling, and ORM patterns. Our Claude Code Django guide covers that in full.

The weekly refactoring session

One workflow pattern that compounds over time: a weekly refactoring session where Claude Code cleans up the debt accumulated during feature development.

The prompt that works:

"Scan src/ and identify: functions longer than 40 lines, modules with cyclomatic complexity above 10, and any TODO comments older than 7 days. List them with line numbers. Then we will work through them in order."

Claude Code reads the entire src/ tree, produces the inventory, and you work through it methodically. On a project with 20,000 lines of Python, this session takes 90 minutes and keeps the codebase manageable. Without it, complexity accumulates until the velocity cost becomes noticeable.

What Python developers get wrong first

Three mistakes come up consistently when Python developers start using Claude Code:

Not specifying the Python version. Claude may generate code using syntax from a version you are not running. .python-version in the repo root plus an explicit note in CLAUDE.md prevents this.

Letting Claude manage requirements files directly. If you use uv or Poetry, Claude should not touch requirements.txt or pyproject.toml manually unless you instruct it to. These files have lock semantics that manual edits can break. Specify: "Dependency changes require explicit approval before adding to pyproject.toml."

Missing conftest.py. Without a conftest.py that defines shared fixtures, Claude generates standalone test files with duplicated setup. One well-structured conftest.py cuts test file boilerplate by half and keeps Claude's output consistent.

Getting more from your Python workflow

The configuration in this guide produces a Claude Code setup where Python-specific tools run automatically, tests gate every change, and the codebase stays typed. The underlying principle is the same as any Claude Code best practices guide: Claude Code's quality is a direct function of how much information you give it about your project.

Start with the CLAUDE.md template above. Add pytest enforcement. Add mypy rules. Each layer reduces the corrections you need to make and moves Claude Code from a code-generator to a genuine development partner on your Python project.

For the setup and authentication steps before any of this applies, the Claude Code setup guide covers installation from scratch.

More like this

Ready to upgrade your Claude Code setup?

Get Claudify
Featured on Dofollow.Tools AI Toolz Dir