python-deploy
The python-deploy skill automates building and deploying Python applications by detecting the package manager (uv, Poetry, PDM, Pipenv, or pip), resolving the Python version from configuration files, installing dependencies with the appropriate command, and determining the start command and port based on framework detection (Flask, Django, FastAPI, Streamlit, Gradio, and others). Use this skill when deploying any Python project or when configuration files like requirements.txt, pyproject.toml, or Pipfile are detected in the repository.
git clone --depth 1 https://github.com/nixopus/nixopus /tmp/python-deploy && cp -r /tmp/python-deploy/api/skills/python-deploy ~/.claude/skills/python-deploySKILL.md
# Python Deployment
## Detection
Project is Python if any of these exist:
| File | Package manager / style |
|---|---|
| `pyproject.toml` | Modern (PEP 517/518), uv, poetry, pdm, or pip |
| `requirements.txt` | pip |
| `setup.py` | setuptools |
| `Pipfile` | Pipenv |
Entry point files (checked in order): `app.py`, `main.py`, `server.py`, `run.py`, `wsgi.py`, `asgi.py`
## Versions
Python version priority:
1. `.python-version` file or `mise.toml` / `.tool-versions`
2. `pyproject.toml` → `[project].requires-python` (e.g. `>=3.11`)
3. `Pipfile` → `[requires].python_version`
4. `runtime.txt`
5. Defaults to **3.13**
## Package Managers
Detect in order:
1. **Lock files:** `poetry.lock` → Poetry, `pdm.lock` → PDM, `Pipfile.lock` → Pipenv, `uv.lock` → uv
2. **Manifest:** `pyproject.toml` (poetry/pdm/uv) or `Pipfile` (pipenv) or `requirements.txt` (pip)
3. **Default:** pip with `requirements.txt`
### Install Commands
| Manager | Install command |
|---|---|
| pip | `pip install --no-cache-dir -r requirements.txt` |
| Poetry | `poetry install --only main --no-interaction` |
| PDM | `pdm install --prod --no-lock` |
| uv | `uv sync --frozen --no-dev` |
| Pipenv | `pipenv install --deploy --system` |
## Runtime Variables
Configure the Python runtime for production: enable the fault handler for crash diagnostics (`PYTHONFAULTHANDLER=1`), disable output buffering for real-time logs (`PYTHONUNBUFFERED=1`), randomize hash seeds (`PYTHONHASHSEED=random`), and skip bytecode generation (`PYTHONDONTWRITEBYTECODE=1`). Suppress pip version checks with `PIP_DISABLE_PIP_VERSION_CHECK=1`.
## Build & Start
### Start Command Resolution
1. Framework-specific (see below)
2. `pyproject.toml` → `[project.scripts]` or `[tool.poetry.scripts]`
3. `setup.py` → `entry_points`
4. `manage.py` → Django
5. Root entry files (first found): `app.py`, `main.py`, `server.py`, `run.py` → `python <file>`
6. Conventions: `wsgi.py`, `asgi.py`
Most Python web apps have no build step (interpreted).
## Port Detection
1. `PORT` from `.env` or `.env.example`
2. Framework defaults:
| Framework | Default port |
|---|---|
| Flask | 5000 |
| Django / FastAPI / Starlette / Gunicorn / Uvicorn | 8000 |
| Streamlit | 8501 |
| Gradio | 7860 |
| Default | 8000 |
## Framework Detection
From dependencies in `pyproject.toml`, `requirements.txt`, or `Pipfile`:
| Package pattern | Framework | Category |
|---|---|---|
| `flask` | Flask | Backend |
| `django` | Django | FullStack |
| `fastapi` | FastAPI | Backend |
| `starlette` | Starlette | Backend |
| `python-fasthtml` | FastHTML | Backend |
| `uvicorn` | ASGI server | Backend |
| `gunicorn` | WSGI server | Backend |
| `streamlit` | Streamlit | App |
| `gradio` | Gradio | App |
| `pelican` | Pelican | Static |
| `mkdocs` | MkDocs | Docs |
### Framework-Specific Start Commands
**Flask** — `gunicorn <module>:app -b 0.0.0.0:${PORT:-5000}` if `gunicorn` is a dependency, else `flask run`
**Django** — `python manage.py migrate && gunicorn <wsgi_module>:application -b 0.0.0.0:${PORT:-8000} --workers 2`. Detect app from `WSGI_APPLICATION` in settings.
**FastAPI** — `uvicorn <module>:app --host 0.0.0.0 --port ${PORT:-8000} --workers 1`
**FastHTML** — `uvicorn <module>:app --host 0.0.0.0 --port ${PORT:-8000}`
**Streamlit** — `streamlit run <entry>.py --server.port ${PORT:-8501} --server.address 0.0.0.0`
## System Dependencies
| Package | Build-time | Runtime |
|---|---|---|
| `psycopg2` | `libpq-dev`, `gcc` | `libpq5` |
| `mysqlclient` | `default-libmysqlclient-dev`, `gcc` | `libmariadb3` |
| `pillow` | `libjpeg-dev`, `zlib1g-dev`, `libfreetype6-dev` | — |
| `cryptography` | `libssl-dev`, `libffi-dev` | — |
| `pycairo` | `libcairo2-dev`, `pkg-config` | `libcairo2` |
| `lxml` | `libxml2-dev`, `libxslt1-dev` | `libxml2`, `libxslt1.1` |
| `pycurl` | `libcurl4-openssl-dev` | — |
| `pdf2image` | — | `poppler-utils` |
| `pydub` | — | `ffmpeg` |
| `playwright` | — | Chromium headless shell |
## Install Stage Optimization
Copy `pyproject.toml` + lockfile first for layer caching, then full source.
## Caching
Leverage BuildKit cache mounts to speed up rebuilds:
- pip: `RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt`
- uv: `RUN --mount=type=cache,target=/root/.cache/uv uv sync --frozen`
## Environment Variable Semantics
| Pattern | Likely dependency |
|---|---|
| `DATABASE_URL` | PostgreSQL, MySQL |
| `REDIS_URL` | Redis |
| `SECRET_KEY` | Django, Flask |
| `DJANGO_SETTINGS_MODULE` | Django |
| `AWS_*` / `S3_*` | AWS |
## Dockerfile Patterns
### uv (with lockfile)
```dockerfile
FROM python:3.13-slim AS base
FROM base AS deps
WORKDIR /app
COPY pyproject.toml uv.lock ./
RUN pip install uv && uv sync --frozen
FROM base AS runtime
WORKDIR /app
ENV PYTHONUNBUFFERED=1 PYTHONDONTWRITEBYTECODE=1
COPY --from=deps /app/.venv /app/.venv
ENV PATH="/app/.venv/bin:$PATH"
COPY . .
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
```
### pip + requirements.txt
```dockerfile
FROM python:3.13-slim AS base
FROM base AS deps
WORKDIR /app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
FROM base AS runtime
WORKDIR /app
ENV PYTHONUNBUFFERED=1 PYTHONDONTWRITEBYTECODE=1
COPY --from=deps /usr/local/lib/python3.13/site-packages /usr/local/lib/python3.13/site-packages
COPY . .
EXPOSE 8000
CMD ["gunicorn", "wsgi:app", "-b", "0.0.0.0:8000"]
```
### Django with collectstatic
```dockerfile
FROM python:3.13-slim AS base
FROM base AS deps
WORKDIR /app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
FROM base AS build
WORKDIR /app
COPY --from=deps /usr/local/lib/python3.13/site-packages /usr/local/lib/python3.13/site-packages
COPY . .
ENV DJANGO_SETTINGS_MODULE=project.settings
RUN python manage.py collectstatic --noinput
FROM base AS runtime
WORKDIR /app
ENV PYTHONUNBUFFERED=1 PYTHONDONTWRITEBYTECODE=1
COPY --from=build /usr/local/lib/python3.13/site-packages /usr/local/lib/python3.13/site-packaReference for all Nixopus API operations callable via nixopus_api(method, path, body)
Generate Caddyfile configurations for static sites and reverse proxies — SPA fallback routing, cache headers, compression, redirects, and error pages. Use when deploying a static site that needs custom Caddy configuration, or when the user needs SPA routing, caching, or redirect rules.
Generate docker-compose.yml for multi-service setups including databases, caches, and service dependencies. Use when the app needs a database, cache, message broker, or has multiple independently deployable services.
Size container memory and CPU limits, diagnose OOM kills and CPU throttling, and recommend resource adjustments by ecosystem. Use when containers are being OOM-killed, running slowly, or when setting initial resource limits for a deployment.
Build and deploy C/C++ applications — CMake, Meson, Ninja, and Dockerfile patterns. Use when deploying a C or C++ project, or when CMakeLists.txt or meson.build is detected.
Run database migrations safely during deployment — framework-specific commands, pre-deploy vs post-deploy timing, health gates, and rollback strategies. Use when the app has a database migration system and needs migrations run during deployment.
Build and deploy Deno applications — version detection, dependency caching, and Dockerfile patterns. Use when deploying a Deno project, or when deno.json or deno.jsonc is detected.
Sub-agent routing table — which agent handles diagnostics, machine health, infrastructure, GitHub, billing, and notifications. Load when the current task is not a direct deployment.