Skills fastapi
install
source · Clone the upstream repo
git clone https://github.com/TerminalSkills/skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/TerminalSkills/skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/fastapi" ~/.claude/skills/terminalskills-skills-fastapi && rm -rf "$T"
manifest:
skills/fastapi/SKILL.mdsafety · automated scan (low risk)
This is a pattern-based risk scan, not a security review. Our crawler flagged:
- pip install
Always read a skill's source content before installing. Patterns alone don't mean the skill is malicious — but they warrant attention.
source content
FastAPI
FastAPI is a Python web framework built on Starlette (ASGI) and Pydantic. It provides automatic request validation, serialization, and interactive API docs at
/docs (Swagger UI) and /redoc.
Installation
# Install FastAPI with uvicorn ASGI server pip install "fastapi[standard]"
Project Structure
# Typical FastAPI project layout app/ ├── main.py # Application entry point ├── config.py # Settings and configuration ├── models/ # SQLAlchemy / DB models ├── schemas/ # Pydantic schemas ├── routers/ # API route modules ├── dependencies.py # Shared dependencies ├── middleware.py # Custom middleware └── tests/
Application Setup
# main.py — FastAPI application entry point from fastapi import FastAPI from contextlib import asynccontextmanager @asynccontextmanager async def lifespan(app: FastAPI): # Startup: initialize DB pool, caches, etc. yield # Shutdown: close connections app = FastAPI( title="My API", version="1.0.0", lifespan=lifespan, )
Routes and Path Operations
# routers/items.py — CRUD router for items from fastapi import APIRouter, HTTPException, status, Query, Path from pydantic import BaseModel, Field router = APIRouter(prefix="/items", tags=["items"]) class ItemCreate(BaseModel): name: str = Field(..., min_length=1, max_length=100) price: float = Field(..., gt=0) description: str | None = None class ItemResponse(ItemCreate): id: int model_config = {"from_attributes": True} @router.get("/", response_model=list[ItemResponse]) async def list_items(skip: int = Query(0, ge=0), limit: int = Query(20, le=100)): return await db.fetch_items(skip=skip, limit=limit) @router.post("/", response_model=ItemResponse, status_code=status.HTTP_201_CREATED) async def create_item(item: ItemCreate): return await db.create_item(item) @router.get("/{item_id}", response_model=ItemResponse) async def get_item(item_id: int = Path(..., gt=0)): item = await db.get_item(item_id) if not item: raise HTTPException(status_code=404, detail="Item not found") return item
Dependency Injection
# dependencies.py — reusable dependencies from fastapi import Depends, Header, HTTPException from sqlalchemy.ext.asyncio import AsyncSession async def get_db() -> AsyncSession: async with async_session() as session: yield session async def get_current_user(authorization: str = Header(...)): token = authorization.removeprefix("Bearer ") user = await verify_token(token) if not user: raise HTTPException(status_code=401, detail="Invalid token") return user # Use in routes @router.get("/me") async def read_me(user=Depends(get_current_user), db=Depends(get_db)): return user
Pydantic Schemas and Validation
# schemas/user.py — request/response schemas with validation from pydantic import BaseModel, EmailStr, field_validator from datetime import datetime class UserCreate(BaseModel): email: EmailStr password: str = Field(..., min_length=8) username: str @field_validator("username") @classmethod def username_alphanumeric(cls, v: str) -> str: if not v.isalnum(): raise ValueError("must be alphanumeric") return v class UserResponse(BaseModel): id: int email: EmailStr username: str created_at: datetime model_config = {"from_attributes": True}
Middleware
# middleware.py — custom middleware example import time from fastapi import Request @app.middleware("http") async def add_timing_header(request: Request, call_next): start = time.perf_counter() response = await call_next(request) elapsed = time.perf_counter() - start response.headers["X-Process-Time"] = f"{elapsed:.4f}" return response
Background Tasks
# routers/notifications.py — background task example from fastapi import BackgroundTasks async def send_email(to: str, body: str): # Long-running email sending logic ... @router.post("/notify") async def notify(email: str, bg: BackgroundTasks): bg.add_task(send_email, email, "Welcome!") return {"status": "queued"}
WebSocket Support
# routers/ws.py — WebSocket endpoint from fastapi import WebSocket, WebSocketDisconnect @app.websocket("/ws/{client_id}") async def websocket_endpoint(websocket: WebSocket, client_id: str): await websocket.accept() try: while True: data = await websocket.receive_text() await websocket.send_text(f"Echo: {data}") except WebSocketDisconnect: pass
Testing
# tests/test_items.py — testing with httpx from httpx import AsyncClient, ASGITransport import pytest @pytest.mark.anyio async def test_create_item(): transport = ASGITransport(app=app) async with AsyncClient(transport=transport, base_url="http://test") as client: resp = await client.post("/items/", json={"name": "Widget", "price": 9.99}) assert resp.status_code == 201 assert resp.json()["name"] == "Widget"
Running
# Run development server with auto-reload uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
Key Patterns
- Use
to control output serialization and strip internal fieldsresponse_model - Group routes with
and include in main app viaAPIRouterapp.include_router(router) - Use
for DB sessions, auth, pagination — they compose and cache per-requestDepends() - Raise
for error responses; use custom exception handlers for global patternsHTTPException - Use
context manager for startup/shutdown instead of deprecated eventslifespan - Set
in Pydantic config to read from ORM objectsfrom_attributes = True