# ADR-006: Python Virtual Environment Management with uv ## Status Accepted ## Context StarPunk is a Python-based web application that requires dependency management and virtual environment isolation. Developer agents (AI assistants like Claude Code) need clear, unambiguous standards for: - Creating and managing Python virtual environments - Installing and tracking dependencies - Ensuring reproducible development environments - Avoiding common pitfalls (polluting global Python, dependency conflicts) - Maintaining consistency across development and deployment Traditional tools (pip, venv, virtualenv, poetry, pipenv) have various limitations: - **pip + venv**: Slow dependency resolution, manual requirements.txt management - **poetry**: Complex configuration, slow, dependency lock issues - **pipenv**: Abandoned maintenance, slow performance - **conda**: Heavyweight, non-standard for web development We need a tool that is fast, simple, and provides excellent developer experience while maintaining compatibility with standard Python packaging. ## Decision Use **uv** for all Python virtual environment and dependency management in StarPunk. uv will be the standard tool for: - Creating virtual environments - Installing dependencies - Managing requirements - Running Python commands in the virtual environment - Synchronizing dependencies ## Rationale ### Simplicity Score: 10/10 - Single tool for all environment management - Simple command syntax (uv venv, uv pip install, uv run) - Drop-in replacement for pip and virtualenv - No complex configuration files - Works with standard requirements.txt - Written in Rust, installed as single binary ### Performance Score: 10/10 - 10-100x faster than pip for dependency resolution - Parallel downloads and installations - Efficient caching mechanism - Near-instant virtual environment creation - Minimal overhead for running commands ### Fitness Score: 9/10 - Perfect for small to medium Python projects - Excellent for single-developer projects - Works with standard Python packaging (PEP 517/518) - Compatible with requirements.txt workflow - Supports editable installs for development - Works seamlessly with Flask and all our dependencies ### Maintenance Score: 9/10 - Actively developed by Astral (creators of ruff) - Strong community adoption - Excellent documentation - Regular updates and improvements - Modern codebase (Rust) - Backed by funding and commercial support ### Standards Compliance: Pass - Full compatibility with pip - Works with PyPI and all standard package indices - Supports PEP 440 version specifiers - Compatible with requirements.txt format - Works with standard Python virtual environments - No proprietary lock files (uses standard formats) ## Implementation Details ### 1. Installation Standards #### System-Level uv Installation Developer agents MUST ensure uv is installed before creating environments: ```bash # Check if uv is installed which uv # If not installed, install via pip (fallback) pip install uv # Or install via official installer (preferred on Linux/macOS) curl -LsSf https://astral.sh/uv/install.sh | sh ``` #### Verification ```bash # Verify uv installation uv --version # Expected output: uv 0.x.x (or newer) ``` ### 2. Virtual Environment Creation Standards #### Location and Naming - **Standard location**: `/home/phil/Projects/starpunk/.venv` - **Name**: Always use `.venv` (hidden directory) - **DO NOT** use: `venv`, `env`, `virtualenv`, or custom names #### Creation Command ```bash # Create virtual environment with uv cd /home/phil/Projects/starpunk uv venv .venv # Specify Python version (recommended) uv venv .venv --python 3.11 ``` #### Post-Creation Verification ```bash # Verify .venv directory exists ls -la /home/phil/Projects/starpunk/.venv # Verify Python executable /home/phil/Projects/starpunk/.venv/bin/python --version ``` ### 3. Dependency Installation Standards #### Using requirements.txt (Primary Method) ```bash # Install all dependencies from requirements.txt uv pip install -r /home/phil/Projects/starpunk/requirements.txt # Verify installation uv pip list ``` #### Installing Individual Packages ```bash # Install a single package uv pip install flask==3.0.* # Install multiple packages uv pip install flask markdown feedgen ``` #### Development Dependencies ```bash # Install dev dependencies (if requirements-dev.txt exists) uv pip install -r /home/phil/Projects/starpunk/requirements-dev.txt ``` ### 4. Running Commands in Virtual Environment #### Using uv run (Recommended) ```bash # Run Python script uv run /home/phil/Projects/starpunk/.venv/bin/python script.py # Run Flask development server uv run /home/phil/Projects/starpunk/.venv/bin/flask run # Run pytest uv run /home/phil/Projects/starpunk/.venv/bin/pytest # Run Python REPL uv run /home/phil/Projects/starpunk/.venv/bin/python ``` #### Direct Execution (Alternative) ```bash # Execute using absolute path to venv Python /home/phil/Projects/starpunk/.venv/bin/python script.py /home/phil/Projects/starpunk/.venv/bin/flask run /home/phil/Projects/starpunk/.venv/bin/pytest ``` ### 5. Dependency Tracking Standards #### Generating requirements.txt ```bash # Freeze current environment to requirements.txt uv pip freeze > /home/phil/Projects/starpunk/requirements.txt # Freeze with sorted output for consistency uv pip freeze | sort > /home/phil/Projects/starpunk/requirements.txt ``` #### Adding New Dependencies When adding a new dependency: 1. Install the package: `uv pip install package-name` 2. Update requirements.txt: `uv pip freeze | sort > requirements.txt` 3. Verify installation: `uv pip list | grep package-name` ### 6. Environment Updates and Maintenance #### Updating Dependencies ```bash # Update a specific package uv pip install --upgrade flask # Update all packages (use with caution) uv pip install --upgrade -r requirements.txt # Regenerate requirements.txt after updates uv pip freeze | sort > requirements.txt ``` #### Cleaning and Rebuilding ```bash # Remove virtual environment rm -rf /home/phil/Projects/starpunk/.venv # Recreate from scratch uv venv .venv --python 3.11 uv pip install -r requirements.txt ``` ## Developer Agent Standards ### Critical Rules for AI Assistants #### Rule 1: ALWAYS Check for Existing Virtual Environment Before creating a new virtual environment, ALWAYS check: ```bash # Check if .venv exists if [ -d "/home/phil/Projects/starpunk/.venv" ]; then echo "Virtual environment exists" /home/phil/Projects/starpunk/.venv/bin/python --version else echo "Virtual environment does not exist" fi ``` **NEVER** create a new virtual environment if one already exists without explicit user permission. #### Rule 2: ALWAYS Use Absolute Paths Agent threads reset cwd between bash calls. ALWAYS use absolute paths: **CORRECT:** ```bash uv venv /home/phil/Projects/starpunk/.venv /home/phil/Projects/starpunk/.venv/bin/python script.py uv pip install -r /home/phil/Projects/starpunk/requirements.txt ``` **INCORRECT:** ```bash uv venv .venv # Relative path - WRONG ./venv/bin/python script.py # Relative path - WRONG uv pip install -r requirements.txt # Relative path - WRONG ``` #### Rule 3: Verify Before Executing Before running Python commands, verify the virtual environment: ```bash # Verification checklist [ -d "/home/phil/Projects/starpunk/.venv" ] && echo "✓ venv exists" || echo "✗ venv missing" [ -f "/home/phil/Projects/starpunk/.venv/bin/python" ] && echo "✓ Python exists" || echo "✗ Python missing" /home/phil/Projects/starpunk/.venv/bin/python --version ``` #### Rule 4: Handle Errors Gracefully If virtual environment operations fail: 1. **Check uv installation**: `which uv` 2. **Check Python version**: `python3 --version` 3. **Check disk space**: `df -h /home/phil/Projects/starpunk` 4. **Report specific error** to user with context 5. **DO NOT** silently continue with global Python #### Rule 5: Never Modify Global Python **NEVER** run these commands: ```bash # FORBIDDEN - modifies global Python pip install package python3 -m pip install package sudo pip install package ``` **ALWAYS** use virtual environment: ```bash # CORRECT - uses virtual environment uv pip install package /home/phil/Projects/starpunk/.venv/bin/pip install package ``` #### Rule 6: Track Dependency Changes After installing or removing packages: 1. Update requirements.txt: `uv pip freeze | sort > requirements.txt` 2. Verify changes: `git diff requirements.txt` (if applicable) 3. Inform user of changes made ### Standard Agent Workflow #### Scenario 1: First-Time Setup ```bash # 1. Check if venv exists if [ ! -d "/home/phil/Projects/starpunk/.venv" ]; then echo "Creating virtual environment..." uv venv /home/phil/Projects/starpunk/.venv --python 3.11 fi # 2. Verify creation /home/phil/Projects/starpunk/.venv/bin/python --version # 3. Install dependencies (if requirements.txt exists) if [ -f "/home/phil/Projects/starpunk/requirements.txt" ]; then uv pip install -r /home/phil/Projects/starpunk/requirements.txt fi # 4. Verify installation uv pip list ``` #### Scenario 2: Running Development Server ```bash # 1. Verify venv exists [ -d "/home/phil/Projects/starpunk/.venv" ] || echo "ERROR: Virtual environment missing" # 2. Verify Flask is installed /home/phil/Projects/starpunk/.venv/bin/python -c "import flask; print(flask.__version__)" # 3. Run Flask development server /home/phil/Projects/starpunk/.venv/bin/flask --app /home/phil/Projects/starpunk/app.py run ``` #### Scenario 3: Adding New Dependency ```bash # 1. Install package uv pip install httpx # 2. Verify installation uv pip show httpx # 3. Update requirements.txt uv pip freeze | sort > /home/phil/Projects/starpunk/requirements.txt # 4. Confirm to user echo "Added httpx to project dependencies" ``` #### Scenario 4: Running Tests ```bash # 1. Verify pytest is installed /home/phil/Projects/starpunk/.venv/bin/python -c "import pytest; print(pytest.__version__)" # 2. Run tests /home/phil/Projects/starpunk/.venv/bin/pytest /home/phil/Projects/starpunk/tests/ # 3. Run tests with coverage (if pytest-cov installed) /home/phil/Projects/starpunk/.venv/bin/pytest --cov=/home/phil/Projects/starpunk/src /home/phil/Projects/starpunk/tests/ ``` ## Project-Specific Standards ### Python Version Requirements - **Minimum**: Python 3.11 - **Recommended**: Python 3.11 or 3.12 - **Rationale**: Modern Python features, improved performance, security updates ### Directory Structure ``` /home/phil/Projects/starpunk/ ├── .venv/ # Virtual environment (NEVER commit) ├── requirements.txt # Production dependencies ├── requirements-dev.txt # Development dependencies (optional) ├── src/ # Application source code ├── tests/ # Test files └── docs/ # Documentation ``` ### .gitignore Requirements The following MUST be in .gitignore: ``` # Virtual Environment .venv/ venv/ env/ ENV/ # Python __pycache__/ *.py[cod] *$py.class *.so .Python ``` ### Environment Variables Use python-dotenv for configuration: ```bash # .env file (NEVER commit to git) FLASK_APP=app.py FLASK_ENV=development SECRET_KEY=your-secret-key DATABASE_PATH=/home/phil/Projects/starpunk/data/starpunk.db ``` Load in application: ```python from dotenv import load_dotenv load_dotenv() ``` ### Requirements.txt Format Follow these conventions: ``` # Requirements.txt - StarPunk Dependencies # Generated: 2025-11-18 # Web Framework flask==3.0.* # Content Processing markdown==3.5.* # Feed Generation feedgen==1.0.* # HTTP Client httpx==0.27.* # Configuration python-dotenv==1.0.* ``` ## Consequences ### Positive - **10-100x faster** dependency resolution and installation - **Consistent environments** across development and deployment - **Simple workflow** - one tool for all Python environment tasks - **No activation required** - uv run handles environment automatically - **Excellent caching** - faster subsequent installations - **Standard compatibility** - works with all existing Python tools - **Clear agent guidelines** - reduces errors in automated workflows - **Isolated dependencies** - no conflicts with system Python ### Negative - **Additional tool dependency** - requires uv installation - **Less familiar** - newer tool, smaller community than pip - **Rust dependency** - uv is written in Rust (but distributed as binary) ### Mitigation - uv is easy to install (single binary, no compilation needed) - uv is pip-compatible (drop-in replacement) - Fallback to pip + venv is always possible - Documentation and agent standards make adoption easy - Active development and growing adoption reduce risk ### Trade-offs Accepted - **uv vs poetry**: We chose simplicity over advanced features - **uv vs pipenv**: We chose active maintenance and speed - **uv vs pip**: We chose performance over ubiquity - **Single tool complexity**: Better than managing multiple tools ## Verification Checklist Before considering the environment correctly set up, verify: - [ ] uv is installed and accessible: `which uv` - [ ] Virtual environment exists: `ls -la /home/phil/Projects/starpunk/.venv` - [ ] Python version is 3.11+: `/home/phil/Projects/starpunk/.venv/bin/python --version` - [ ] Dependencies installed: `uv pip list` shows Flask, markdown, feedgen, httpx - [ ] requirements.txt exists and is up to date - [ ] .venv is in .gitignore - [ ] Flask runs: `/home/phil/Projects/starpunk/.venv/bin/flask --version` ## Integration with Development Workflow ### Running Flask Application ```bash # Development server /home/phil/Projects/starpunk/.venv/bin/flask --app app.py run --debug # Production server (using gunicorn) /home/phil/Projects/starpunk/.venv/bin/gunicorn app:app ``` ### Running Tests ```bash # All tests /home/phil/Projects/starpunk/.venv/bin/pytest # Specific test file /home/phil/Projects/starpunk/.venv/bin/pytest tests/test_api.py # With coverage /home/phil/Projects/starpunk/.venv/bin/pytest --cov=src tests/ ``` ### Code Quality Tools ```bash # Format code with black /home/phil/Projects/starpunk/.venv/bin/black src/ # Lint with flake8 /home/phil/Projects/starpunk/.venv/bin/flake8 src/ # Type checking with mypy (if added) /home/phil/Projects/starpunk/.venv/bin/mypy src/ ``` ## Alternatives Considered ### pip + venv (Rejected) - **Simplicity**: 8/10 - Standard Python tools, well-known - **Performance**: 4/10 - Very slow dependency resolution - **Fitness**: 7/10 - Works but painful for larger dependency trees - **Maintenance**: 10/10 - Built into Python, always maintained - **Verdict**: Too slow, poor developer experience, but acceptable fallback ### poetry (Rejected) - **Simplicity**: 5/10 - Complex pyproject.toml, lock file management - **Performance**: 5/10 - Slow dependency resolution - **Fitness**: 6/10 - Overkill for simple project, lock files add complexity - **Maintenance**: 7/10 - Maintained but has had reliability issues - **Verdict**: Too complex for "minimal code" philosophy ### pipenv (Rejected) - **Simplicity**: 6/10 - Simpler than poetry, but still adds abstraction - **Performance**: 4/10 - Known performance issues - **Fitness**: 5/10 - Previously recommended, now effectively abandoned - **Maintenance**: 2/10 - Minimal maintenance, community has moved on - **Verdict**: Dead project, poor performance ### conda (Rejected) - **Simplicity**: 3/10 - Heavy, complex environment management - **Performance**: 5/10 - Slower than uv, larger downloads - **Fitness**: 2/10 - Designed for data science, not web development - **Maintenance**: 9/10 - Well maintained, large ecosystem - **Verdict**: Wrong tool for web application development ### PDM (Considered) - **Simplicity**: 7/10 - Modern, PEP 582 support - **Performance**: 8/10 - Fast, but not as fast as uv - **Fitness**: 7/10 - Good for modern Python projects - **Maintenance**: 8/10 - Actively maintained, growing community - **Verdict**: Good alternative, but uv is faster and simpler ## References - uv Documentation: https://docs.astral.sh/uv/ - uv GitHub: https://github.com/astral-sh/uv - Python Virtual Environments: https://docs.python.org/3/library/venv.html - PEP 405 (Python Virtual Environments): https://peps.python.org/pep-0405/ - requirements.txt format: https://pip.pypa.io/en/stable/reference/requirements-file-format/ - Astral (uv creators): https://astral.sh/ ## Change Log - 2025-11-18: Initial version - Established uv as standard tool for StarPunk Python environment management