|
| 1 | +# DevContainer Maintenance Guide |
| 2 | + |
| 3 | +## About This Codebase |
| 4 | + |
| 5 | +- **Pydantic AI**: Agent framework for building LLM-powered applications with Pydantic |
| 6 | +- **Workspace structure**: uv monorepo with multiple packages |
| 7 | + - `pydantic-ai-slim`: Core framework (minimal dependencies) |
| 8 | + - `pydantic-evals`: Evaluation framework |
| 9 | + - `pydantic-graph`: Graph execution engine |
| 10 | + - `examples/`: Example applications |
| 11 | + - `clai/`: CLI tool |
| 12 | +- **Primary users**: Contributors, AI coding agents (Claude Code, Cursor), PR reviewers |
| 13 | + |
| 14 | +## DevContainer Purpose |
| 15 | + |
| 16 | +- Provides isolated, reproducible development environment |
| 17 | +- Matches exact dependencies and tools across all developers and AI agents |
| 18 | +- Prevents "works on my machine" issues |
| 19 | +- Ensures AI agents have proper access to testing/building tools |
| 20 | +- Security isolation for AI agents |
| 21 | + |
| 22 | +## Platform Configuration |
| 23 | + |
| 24 | +- **Default platform**: `linux/amd64` (x86_64) |
| 25 | +- **Why not ARM64**: Some Python packages (e.g., mlx) lack Linux ARM64 wheels |
| 26 | +- **Apple Silicon**: Uses Rosetta/QEMU emulation automatically (slightly slower but compatible) |
| 27 | +- **Change if needed**: Edit `docker-compose.yml` platform setting |
| 28 | + |
| 29 | +## Installation Modes |
| 30 | + |
| 31 | +### Standard Mode (Default) |
| 32 | +- Installs: Cloud API providers + dev tools |
| 33 | +- Excludes: PyTorch, transformers, vLLM, outlines ML extras |
| 34 | +- Use case: 95% of development (PR testing, features, bug fixes) |
| 35 | +- Why: Saves significant install time and disk space |
| 36 | +- Command: Uses explicit `--extra` flags in `install.sh` |
| 37 | + |
| 38 | +### Full Mode |
| 39 | +- Installs: Everything including ML frameworks |
| 40 | +- Use case: Working on outlines integration, local model features |
| 41 | +- Command: `--all-extras --all-packages` |
| 42 | + |
| 43 | +### Mode Selection |
| 44 | +- Interactive (VSCode): User prompted to choose |
| 45 | +- Non-interactive (agents/CI): Defaults to Standard |
| 46 | +- Override: Set `INSTALL_MODE=standard|full` environment variable |
| 47 | + |
| 48 | +## Key Files |
| 49 | + |
| 50 | +### `.devcontainer/devcontainer.json` |
| 51 | +- VSCode configuration for the devcontainer |
| 52 | +- Editor settings, extensions, port forwarding |
| 53 | +- Lifecycle commands (`postCreateCommand`, `postStartCommand`) |
| 54 | +- Environment variables (`UV_LINK_MODE`, `UV_PROJECT_ENVIRONMENT`, etc.) |
| 55 | +- Git identity for AI commits |
| 56 | + |
| 57 | +### `.devcontainer/Dockerfile` |
| 58 | +- Base image: `mcr.microsoft.com/devcontainers/base:debian-12` |
| 59 | +- System dependencies for Python builds |
| 60 | +- Installs: uv, deno, pre-commit, Python 3.12 |
| 61 | +- Runs as non-root user `vscode` |
| 62 | + |
| 63 | +### `.devcontainer/docker-compose.yml` |
| 64 | +- Service orchestration |
| 65 | +- Platform specification (`linux/amd64`) |
| 66 | +- Optional services (commented out): Ollama, PostgreSQL, pgvector, MCP proxy |
| 67 | +- Volume management for persistence |
| 68 | + |
| 69 | +### `.devcontainer/install.sh` |
| 70 | +- Interactive installation script |
| 71 | +- Detects interactive vs non-interactive mode |
| 72 | +- Implements Standard vs Full installation logic |
| 73 | +- Installs pre-commit hooks |
| 74 | +- Called by `postCreateCommand` in devcontainer.json |
| 75 | + |
| 76 | +## Environment Variables |
| 77 | + |
| 78 | +### Critical Variables (devcontainer.json) |
| 79 | +- `UV_PROJECT_ENVIRONMENT=/workspace/.venv`: Virtual environment location |
| 80 | +- `UV_LINK_MODE=copy`: Suppress hardlink warnings in Docker volumes |
| 81 | +- `PYTHONUNBUFFERED=1`: Ensure Python output appears immediately |
| 82 | +- `COLUMNS=150`: Terminal width for better output formatting |
| 83 | +- `GIT_AUTHOR_*`, `GIT_COMMITTER_*`: Git identity for AI commits |
| 84 | + |
| 85 | +### Optional Variables |
| 86 | +- `INSTALL_MODE=standard|full`: Override installation mode |
| 87 | +- API keys: Should be set in `.devcontainer/.env` (not committed) |
| 88 | + |
| 89 | +## Dependencies and Extras |
| 90 | + |
| 91 | +### Always Installed (Both Modes) |
| 92 | +- Core: pydantic, httpx, opentelemetry-api |
| 93 | +- Cloud APIs: openai, anthropic, google, groq, mistral, cohere, bedrock, huggingface |
| 94 | +- Dev tools: cli, mcp, fastmcp, logfire, retries, temporal, ui, ag-ui, evals |
| 95 | +- Build tools: lint group, docs group (ruff, mypy, pyright, mkdocs) |
| 96 | + |
| 97 | +### Only in Full Mode |
| 98 | +- `outlines-transformers`: PyTorch + Transformers library |
| 99 | +- `outlines-vllm-offline`: vLLM inference engine |
| 100 | +- `outlines-sglang`: SGLang framework |
| 101 | +- `outlines-mlxlm`: Apple MLX framework |
| 102 | +- `outlines-llamacpp`: LlamaCPP bindings |
| 103 | + |
| 104 | +## Common Maintenance Tasks |
| 105 | + |
| 106 | +### Adding New System Dependencies |
| 107 | +- Edit `Dockerfile`: Add to `apt-get install` command |
| 108 | +- Rebuild container required |
| 109 | + |
| 110 | +### Adding Python Packages |
| 111 | +- Use `uv add package-name` (not manual pyproject.toml edits) |
| 112 | +- For new extras: Add to `pydantic_ai_slim/pyproject.toml` optional-dependencies |
| 113 | +- Update `install.sh` if extra should be in Standard mode |
| 114 | + |
| 115 | +### Adding VSCode Extensions |
| 116 | +- Edit `devcontainer.json`: Add to `customizations.vscode.extensions` array |
| 117 | +- Rebuild container required |
| 118 | + |
| 119 | +### Updating Base Image/Tools |
| 120 | +- `Dockerfile`: Change base image tag |
| 121 | +- Update uv/deno install commands if needed |
| 122 | +- Test with both Standard and Full modes |
| 123 | + |
| 124 | +### Adding Optional Services |
| 125 | +- Uncomment service in `docker-compose.yml` |
| 126 | +- Uncomment corresponding volume if needed |
| 127 | +- Document in README.md optional services section |
| 128 | + |
| 129 | +## Troubleshooting |
| 130 | + |
| 131 | +### Container Build Fails |
| 132 | +- Check Docker daemon is running |
| 133 | +- Check internet connectivity |
| 134 | +- Try: `docker system prune -a` to clean cache |
| 135 | +- Check Dockerfile for syntax errors: `docker build -f .devcontainer/Dockerfile .` |
| 136 | + |
| 137 | +### Installation Script Fails |
| 138 | +- Check `install.sh` syntax: `bash -n .devcontainer/install.sh` |
| 139 | +- Run manually in container to see detailed errors |
| 140 | +- Check uv lockfile is up to date: `uv lock` |
| 141 | + |
| 142 | +### Performance Issues |
| 143 | +- Verify Docker resources (4+ GB RAM recommended) |
| 144 | +- Check platform setting (amd64 vs arm64) |
| 145 | +- Volume cache consistency setting in docker-compose.yml |
| 146 | + |
| 147 | +### UV Warnings |
| 148 | +- Hardlink warning: Ensure `UV_LINK_MODE=copy` is set |
| 149 | +- Lockfile conflicts: Run `uv lock` to regenerate |
| 150 | + |
| 151 | +## Best Practices |
| 152 | + |
| 153 | +### When Changing install.sh |
| 154 | +- Test both Standard and Full modes |
| 155 | +- Test interactive and non-interactive flows |
| 156 | +- Verify syntax with `bash -n install.sh` |
| 157 | +- Update README.md to match |
| 158 | + |
| 159 | +### When Changing Dependencies |
| 160 | +- Keep Standard mode lean (exclude heavy ML frameworks) |
| 161 | +- Update install.sh if adding new extras |
| 162 | +- Document in README.md what's included/excluded |
| 163 | +- Test install time impact |
| 164 | + |
| 165 | +### When Updating Documentation |
| 166 | +- Keep README.md user-facing and comprehensive |
| 167 | +- Keep CLAUDE.md maintainer-focused and concise |
| 168 | +- No time estimates (machine-dependent) |
| 169 | +- Link to official docs where applicable |
| 170 | + |
| 171 | +## Git Configuration |
| 172 | + |
| 173 | +- Credentials forwarded automatically by VSCode (no manual setup needed) |
| 174 | +- Git identity set via environment variables (not .gitconfig file) |
| 175 | +- Safe directory configured in `postStartCommand` |
| 176 | +- AI commits use identity from `GIT_AUTHOR_*` variables |
| 177 | + |
| 178 | +## Testing the Setup |
| 179 | + |
| 180 | +### Manual Test |
| 181 | +1. Make changes to devcontainer files |
| 182 | +2. Rebuild container: "Dev Containers: Rebuild Container" |
| 183 | +3. Test Standard mode installation |
| 184 | +4. Test Full mode: `INSTALL_MODE=full` or run `make install` |
| 185 | +5. Verify: `uv run pytest tests/test_agent.py::test_simple_sync` |
| 186 | + |
| 187 | +### CI Considerations |
| 188 | +- Container should work in non-interactive mode |
| 189 | +- Default Standard mode should cover 95% of test suite |
| 190 | +- Full mode needed only for outlines/ML framework tests |
0 commit comments