Claude-skill-registry fastapi-reviewer
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/fastapi-reviewer" ~/.claude/skills/majiayu000-claude-skill-registry-fastapi-reviewer && rm -rf "$T"
manifest:
skills/data/fastapi-reviewer/SKILL.mdsource content
FastAPI Reviewer Skill
Purpose
Reviews FastAPI projects for API design, Pydantic usage, async patterns, and security.
When to Use
- FastAPI project code review
- Pydantic model review
- API endpoint design review
- Async/await pattern check
- Dependency injection review
Project Detection
in requirements.txt/pyproject.tomlfastapi
importsfrom fastapi import
with FastAPI() appmain.py
directory structurerouters/
Workflow
Step 1: Analyze Project
**FastAPI**: 0.100+ **Pydantic**: v2 **Database**: SQLAlchemy/Tortoise/Prisma **Auth**: OAuth2/JWT **Docs**: OpenAPI auto-generated
Step 2: Select Review Areas
AskUserQuestion:
"Which areas to review?" Options: - Full FastAPI review (recommended) - Pydantic models and validation - Dependency injection patterns - Async/await usage - Security and authentication multiSelect: true
Detection Rules
Pydantic Models
| Check | Recommendation | Severity |
|---|---|---|
| dict instead of model | Use Pydantic BaseModel | MEDIUM |
| Missing Field validation | Add Field constraints | MEDIUM |
| No Config class | Add model_config | LOW |
| Mutable default in Field | Use default_factory | HIGH |
# BAD: Plain dict response @app.get("/user") async def get_user() -> dict: return {"name": "John", "age": 30} # GOOD: Pydantic model class UserResponse(BaseModel): name: str = Field(..., min_length=1, max_length=100) age: int = Field(..., ge=0, le=150) model_config = ConfigDict(from_attributes=True) @app.get("/user") async def get_user() -> UserResponse: return UserResponse(name="John", age=30) # BAD: Mutable default class Config(BaseModel): items: list[str] = [] # Shared across instances! # GOOD: default_factory class Config(BaseModel): items: list[str] = Field(default_factory=list)
Dependency Injection
| Check | Recommendation | Severity |
|---|---|---|
| Repeated code in endpoints | Extract to Depends() | MEDIUM |
| Global state access | Use dependency injection | HIGH |
| No cleanup in deps | Use yield for cleanup | MEDIUM |
| Hardcoded dependencies | Use Depends for testability | MEDIUM |
# BAD: Repeated DB session code @app.get("/users") async def get_users(): db = SessionLocal() try: return db.query(User).all() finally: db.close() # GOOD: Dependency injection async def get_db() -> AsyncGenerator[AsyncSession, None]: async with async_session() as session: yield session @app.get("/users") async def get_users(db: AsyncSession = Depends(get_db)): result = await db.execute(select(User)) return result.scalars().all()
Async Patterns
| Check | Recommendation | Severity |
|---|---|---|
| sync def for I/O | Use async def | HIGH |
| Blocking call in async | Use run_in_executor | CRITICAL |
| No async DB driver | Use asyncpg/aiosqlite | HIGH |
| sync file I/O | Use aiofiles | MEDIUM |
# BAD: Blocking call in async @app.get("/data") async def get_data(): response = requests.get(url) # Blocks event loop! return response.json() # GOOD: Async HTTP client @app.get("/data") async def get_data(): async with httpx.AsyncClient() as client: response = await client.get(url) return response.json() # BAD: Sync file read @app.get("/file") async def read_file(): with open("data.txt") as f: return f.read() # GOOD: Async file read @app.get("/file") async def read_file(): async with aiofiles.open("data.txt") as f: return await f.read()
API Design
| Check | Recommendation | Severity |
|---|---|---|
| No response_model | Add response_model param | MEDIUM |
| Missing status codes | Add responses param | LOW |
| No tags | Add tags for grouping | LOW |
| Inconsistent naming | Use RESTful conventions | MEDIUM |
# BAD: Minimal endpoint @app.post("/user") async def create(data: dict): return {"id": 1} # GOOD: Full specification @app.post( "/users", response_model=UserResponse, status_code=status.HTTP_201_CREATED, responses={ 409: {"model": ErrorResponse, "description": "User exists"}, }, tags=["users"], summary="Create a new user", ) async def create_user( user: UserCreate, db: AsyncSession = Depends(get_db), ) -> UserResponse: """Create a new user with the provided details.""" return await user_service.create(db, user)
Security
| Check | Recommendation | Severity |
|---|---|---|
| No auth on endpoints | Add Depends(get_current_user) | CRITICAL |
| Secrets in code | Use environment variables | CRITICAL |
| No rate limiting | Add slowapi/fastapi-limiter | HIGH |
| Missing CORS config | Configure CORSMiddleware | HIGH |
# Security setup from fastapi.security import OAuth2PasswordBearer from fastapi.middleware.cors import CORSMiddleware oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") async def get_current_user( token: str = Depends(oauth2_scheme), db: AsyncSession = Depends(get_db), ) -> User: user = await verify_token(token, db) if not user: raise HTTPException(status_code=401, detail="Invalid token") return user # Protected endpoint @app.get("/me") async def get_me(user: User = Depends(get_current_user)): return user
Response Template
## FastAPI Code Review Results **Project**: [name] **FastAPI**: 0.109 | **Pydantic**: v2 | **DB**: SQLAlchemy async ### Pydantic Models | Status | File | Issue | |--------|------|-------| | HIGH | schemas.py:15 | Mutable default in Field | ### Dependency Injection | Status | File | Issue | |--------|------|-------| | MEDIUM | routers/users.py | Repeated DB session code | ### Async Patterns | Status | File | Issue | |--------|------|-------| | CRITICAL | services/external.py:34 | Blocking requests.get() call | ### Security | Status | File | Issue | |--------|------|-------| | CRITICAL | main.py | No CORS configuration | ### Recommended Actions 1. [ ] Replace blocking HTTP calls with httpx async 2. [ ] Add CORS middleware configuration 3. [ ] Extract repeated code to dependencies 4. [ ] Add response_model to all endpoints
Best Practices
- Pydantic v2: Use model_config, Field validators
- Async Everything: DB, HTTP, file I/O
- Dependencies: Extract common logic
- Security: OAuth2, CORS, rate limiting
- Documentation: OpenAPI auto-docs with examples
Integration
: General Python patternspython-reviewer
: API security auditsecurity-scanner
: OpenAPI enhancementapi-documenter