
Fastapi Local Dev
- 235 installs
- 63 repo stars
- Updated July 18, 2026
- bobmatnyc/claude-mpm-skills
Bootstrap FastAPI local development with virtualenv, hot reload, routers, dependencies, and test-friendly project layout when starting or extending a Python HTTP API.
About
Helps Claude set up FastAPI for local backend development: environment isolation, dev server configuration, modular routers, dependency injection, settings management, and a structure suited to iterative API building and testing.
- Project and venv scaffolding
- Uvicorn dev server and reload
- Router and dependency injection layout
- Settings and env loading patterns
- Local testing and OpenAPI exposure
Fastapi Local Dev by the numbers
- 235 all-time installs (skills.sh)
- Ranked #56 of 290 Python skills by installs in the Skillselion catalog
- Data as of Aug 1, 2026 (Skillselion catalog sync)
npx skills add https://github.com/bobmatnyc/claude-mpm-skills --skill fastapi-local-devAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 235 |
|---|---|
| repo stars | ★ 63 |
| Last updated | July 18, 2026 |
| Repository | bobmatnyc/claude-mpm-skills ↗ |
What it does
Bootstrap FastAPI local development with virtualenv, hot reload, routers, dependencies, and test-friendly project layout when starting or extending a Python HTTP API.
Files
FastAPI Local Dev
- Dev:
uvicorn app.main:app --reload - Imports: run from repo root; use
python -m uvicorn ...orPYTHONPATH=. - WSL:
WATCHFILES_FORCE_POLLING=trueif reload misses changes - Prod:
gunicorn app.main:app -k uvicorn.workers.UvicornWorker -w <n> --bind :8000
Anti-patterns:
--reload --workers > 1- PM2
watch: truefor Python
References: references/.
{
"name": "fastapi-local-dev",
"version": "1.1.0",
"category": "toolchain",
"toolchain": "python",
"framework": "fastapi",
"tags": [
"api",
"python",
"fastapi",
"uvicorn",
"gunicorn",
"reload",
"docker",
"systemd",
"pm2",
"wsl",
"troubleshooting"
],
"entry_point_tokens": 173,
"full_tokens": 1845,
"author": "bobmatnyc",
"license": "MIT",
"requires": [],
"updated": "2025-12-17",
"source_path": "toolchains/python/frameworks/fastapi-local-dev/SKILL.md",
"source": "https://github.com/bobmatnyc/claude-mpm",
"created": "2025-11-21",
"modified": "2025-12-17",
"maintainer": "Claude MPM Team",
"attribution_required": true,
"repository": "https://github.com/bobmatnyc/claude-mpm-skills"
}
Dev Server (Uvicorn)
Recommended command
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000Add logging while debugging:
uvicorn app.main:app --reload --log-level debug --access-logImport hygiene (most common local-dev failure)
Rules:
- Run from the repo root so imports resolve consistently.
- Treat
app/as a real package (app/__init__.py).
Fix patterns:
# Run as a module (keeps import semantics consistent)
python -m uvicorn app.main:app --reload
# Or explicitly set PYTHONPATH
PYTHONPATH=. uvicorn app.main:app --reloadMinimal expected layout:
project/
├── app/
│ ├── __init__.py
│ └── main.py
└── pyproject.toml / requirements.txtReload tuning
Reload mode requires a single worker:
uvicorn app.main:app --reload --workers 1Control watch scope:
uvicorn app.main:app --reload \
--reload-dir ./app \
--reload-exclude ./app/tests \
--reload-include '*.py'WSL / network filesystems
If file events are unreliable, force polling:
WATCHFILES_FORCE_POLLING=true uvicorn app.main:app --reloadVirtual environments
Avoid “works locally but not in scripts” by invoking the venv binary explicitly:
./venv/bin/uvicorn app.main:app --reload
./venv/bin/python -m uvicorn app.main:app --reloadDocker (Dev + Prod)
Development image (reload)
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]If reload does not trigger inside containers (common on mounted volumes), set polling:
environment:
- WATCHFILES_FORCE_POLLING=trueProduction image (Gunicorn)
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["gunicorn", "app.main:app", "-k", "uvicorn.workers.UvicornWorker", "-w", "4", "--bind", "0.0.0.0:8000"]docker-compose (dev)
services:
api:
build: .
ports: ["8000:8000"]
volumes: ["./:/app"]
environment:
- PYTHONUNBUFFERED=1
- WATCHFILES_FORCE_POLLING=true
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reloadProcess Management (systemd vs PM2)
systemd (recommended on Linux)
[Unit]
Description=FastAPI Application
After=network.target
[Service]
User=www-data
WorkingDirectory=/opt/fastapi-app
Environment="PATH=/opt/fastapi-app/venv/bin"
ExecStart=/opt/fastapi-app/venv/bin/gunicorn -c /opt/fastapi-app/gunicorn_conf.py app.main:app
Restart=always
RestartSec=10
NoNewPrivileges=true
PrivateTmp=true
[Install]
WantedBy=multi-user.targetUseful commands:
sudo systemctl enable --now fastapi
sudo systemctl status fastapi
sudo journalctl -u fastapi -fPM2 (only if required)
Do not use PM2 watch mode for Python.
module.exports = {
apps: [
{
name: "fastapi-app",
script: "/opt/fastapi-app/venv/bin/gunicorn",
args: "-c gunicorn_conf.py app.main:app",
cwd: "/opt/fastapi-app",
exec_mode: "fork",
instances: 1,
autorestart: true,
watch: false
}
],
};Production (Gunicorn + UvicornWorker)
Baseline command
gunicorn app.main:app \
--worker-class uvicorn.workers.UvicornWorker \
--workers 4 \
--bind 0.0.0.0:8000 \
--timeout 120 \
--graceful-timeout 30Worker sizing
Start point: (2 × CPU cores) + 1, then load-test and adjust.
Common adjustments:
- Lower workers if the app is memory-heavy.
- Increase timeout for long-running endpoints or move work to background jobs.
gunicorn_conf.py (minimal)
import multiprocessing
bind = "0.0.0.0:8000"
worker_class = "uvicorn.workers.UvicornWorker"
workers = multiprocessing.cpu_count() * 2 + 1
timeout = 120
graceful_timeout = 30
keepalive = 5
accesslog = "-"
errorlog = "-"
loglevel = "info"Run it:
gunicorn -c gunicorn_conf.py app.main:appWorker timeouts (common under load)
If you see WORKER TIMEOUT, treat it as a symptom:
- Increase
timeoutonly if slow requests are expected. - Remove blocking I/O from
async defendpoints (usehttpx.AsyncClient). - Push long work to background tasks/queues.
Templates
requirements.txt (example)
fastapi
uvicorn[standard]
gunicorn
httpxMinimal app
from fastapi import FastAPI
app = FastAPI()
@app.get("/health")
def health():
return {"status": "ok"}gunicorn_conf.py (example)
import multiprocessing
bind = "0.0.0.0:8000"
worker_class = "uvicorn.workers.UvicornWorker"
workers = multiprocessing.cpu_count() * 2 + 1
timeout = 120
graceful_timeout = 30
keepalive = 5Troubleshooting Runbook
Port already in use
# macOS/Linux
lsof -ti:8000 | xargs kill -9Reload not working
Checklist:
- Confirm
--reloadis set. - Watch the correct directory (
--reload-dir ./app). - On WSL/mounted volumes, set
WATCHFILES_FORCE_POLLING=true.
WATCHFILES_FORCE_POLLING=true uvicorn app.main:app --reloadImport errors after reload
Signals:
ModuleNotFoundError: No module named 'app'ImportError: attempted relative import with no known parent package
Fixes:
python -m uvicorn app.main:app --reload
PYTHONPATH=. uvicorn app.main:app --reloadConfirm the package structure includes __init__.py:
test -f app/__init__.py && echo "ok"PM2 restart loops
Cause: watch: true (breaks Python module resolution).
Fix: disable watch or use systemd.
Worker timeouts
If requests are slow or blocking:
- increase
timeoutonly if needed - move long work to background tasks
- avoid blocking I/O in async endpoints