Content
1# CLAUDE.md — Python FastAPI Service
2
3## Project overview
4<!-- One-sentence description of this API -->
5
6## Tech stack
7- **Framework**: FastAPI
8- **Language**: Python 3.12+
9- **ORM**: SQLAlchemy 2.x (async, using `asyncpg`)
10- **Migrations**: Alembic
11- **Schemas**: Pydantic v2
12- **Tests**: pytest + httpx (async)
13- **Package manager**: uv
14
15## Development commands
16```bash
17uv run uvicorn app.main:app --reload # dev server on :8000
18uv run pytest # run test suite
19uv run alembic upgrade head # apply migrations
20uv run alembic revision --autogenerate -m "<name>" # new migration
21uv run ruff check . && uv run ruff format . # lint + format
22```
23
24## Project structure
25```
26app/
27 main.py # FastAPI app factory & lifespan
28 api/
29 v1/ # versioned routers
30 models/ # SQLAlchemy ORM models
31 schemas/ # Pydantic request/response schemas
32 services/ # business logic (no DB access in routers)
33 db/
34 session.py # async session factory
35 base.py # Base model class
36alembic/ # migration files
37tests/ # pytest tests
38```
39
40## Coding conventions
41- All route handlers are **async**
42- Routers only call service functions — no DB queries in routers
43- Services receive a `db: AsyncSession` dependency, not a global
44- Pydantic schemas are in `schemas/`, SQLAlchemy models in `models/`
45- Use `from __future__ import annotations` in all model files
46- HTTP errors: raise `HTTPException(status_code=..., detail=...)`
47- Never commit secrets; use `python-dotenv` + `.env` locally
48
49## Environment variables
50```
51DATABASE_URL=postgresql+asyncpg://user:pass@localhost/dbname
52SECRET_KEY=
53DEBUG=true
54```
55
56## Testing approach
57- Each test gets a fresh in-memory SQLite DB (via `pytest-anyio` fixtures)
58- Use `httpx.AsyncClient` with `app` as transport — no live server needed
59- Factory helpers live in `tests/factories.py`
60- Aim for 80%+ coverage; CI will fail below that threshold
61