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.md
source 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

  • fastapi
    in requirements.txt/pyproject.toml
  • from fastapi import
    imports
  • main.py
    with FastAPI() app
  • routers/
    directory structure

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

CheckRecommendationSeverity
dict instead of modelUse Pydantic BaseModelMEDIUM
Missing Field validationAdd Field constraintsMEDIUM
No Config classAdd model_configLOW
Mutable default in FieldUse default_factoryHIGH
# 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

CheckRecommendationSeverity
Repeated code in endpointsExtract to Depends()MEDIUM
Global state accessUse dependency injectionHIGH
No cleanup in depsUse yield for cleanupMEDIUM
Hardcoded dependenciesUse Depends for testabilityMEDIUM
# 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

CheckRecommendationSeverity
sync def for I/OUse async defHIGH
Blocking call in asyncUse run_in_executorCRITICAL
No async DB driverUse asyncpg/aiosqliteHIGH
sync file I/OUse aiofilesMEDIUM
# 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

CheckRecommendationSeverity
No response_modelAdd response_model paramMEDIUM
Missing status codesAdd responses paramLOW
No tagsAdd tags for groupingLOW
Inconsistent namingUse RESTful conventionsMEDIUM
# 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

CheckRecommendationSeverity
No auth on endpointsAdd Depends(get_current_user)CRITICAL
Secrets in codeUse environment variablesCRITICAL
No rate limitingAdd slowapi/fastapi-limiterHIGH
Missing CORS configConfigure CORSMiddlewareHIGH
# 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

  1. Pydantic v2: Use model_config, Field validators
  2. Async Everything: DB, HTTP, file I/O
  3. Dependencies: Extract common logic
  4. Security: OAuth2, CORS, rate limiting
  5. Documentation: OpenAPI auto-docs with examples

Integration

  • python-reviewer
    : General Python patterns
  • security-scanner
    : API security audit
  • api-documenter
    : OpenAPI enhancement