This is a modern Python project template using uv for package management, doit for task automation, ruff for formatting/linting, and mypy for type checking. The template follows best practices for Python development with comprehensive CI/CD workflows and strict code quality standards.
AI Agent Compatibility:
- Codex CLI: This file is read directly by Codex CLI (use
/initto regenerate) - Gemini CLI: This file is read directly by Gemini CLI (also supports
GEMINI.md) - Claude Code: Referenced via
.claude/claude.md - Other AI tools: Can reference this as general project documentation
.
├── .github/
│ ├── workflows/ # CI/CD workflows
│ │ ├── ci.yml # Continuous Integration (test, lint, type-check)
│ │ ├── testpypi.yml # Dev releases (prerelease v* tags → TestPyPI)
│ │ └── release.yml # Production releases (v* tags → PyPI)
│ ├── ISSUE_TEMPLATE/ # GitHub issue templates
│ │ ├── bug_report.md # Bug report template
│ │ └── feature_request.md # Feature request template
│ ├── CODEOWNERS # Code ownership definitions
│ ├── SECURITY.md # Security policy
│ ├── dependabot.yml # Automated dependency updates
│ └── pull_request_template.md # PR template
├── .claude/ # Claude Code configuration
│ ├── claude.md # Imports AGENTS.md
│ └── settings.local.json # Command permissions
├── .codex/ # Codex CLI configuration
│ └── config.toml # Command whitelisting and approval policies
├── .devcontainer/ # VS Code Remote Containers configuration
│ └── devcontainer.json # Container development environment
├── .gemini/ # Gemini CLI configuration
│ └── settings.json # Tool allowlists and context files
├── .vscode/ # VS Code configuration
│ ├── settings.json # Editor settings
│ └── extensions.json # Recommended extensions
├── docs/ # Documentation
│ ├── index.md # Documentation home
│ ├── installation.md # Installation guide
│ ├── usage.md # Usage guide
│ ├── api.md # API reference
│ ├── extensions.md # Optional tools and extensions guide
│ └── migration.md # Migration guide
├── examples/ # Usage examples
│ ├── README.md # Examples overview
│ ├── basic_usage.py # Basic usage example
│ ├── advanced_usage.py # Advanced features example
│ └── cli_usage.py # CLI usage example
├── src/
│ └── bastproxy/ # Main package source code
│ ├── __init__.py # Package initialization, exports __version__
│ ├── _version.py # Version info (generated by hatch-vcs from git tags during build)
│ └── py.typed # PEP 561 type marker
├── tests/ # Test suite
│ └── test_example.py # Example tests
├── tmp/ # All temporary files (git-ignored)
│ ├── .ruff_cache/ # Ruff linting cache
│ ├── .mypy_cache/ # Mypy type checking cache
│ ├── .pytest_cache/ # Pytest cache
│ ├── htmlcov/ # HTML coverage reports
│ ├── coverage.xml # XML coverage for Codecov
│ ├── .coverage # Coverage data file
│ ├── .pre-commit/ # Pre-commit cache
│ └── .uv_cache/ # UV package cache
├── .editorconfig # Editor configuration
├── .envrc # direnv configuration (committed)
├── .envrc.local.example # direnv local overrides template
├── .gitignore # Git ignore patterns
├── .pre-commit-config.yaml # Pre-commit hooks configuration
├── .python-version # Python version specification (3.12)
├── AGENTS.md # AI agent documentation
├── AI_SETUP.md # AI tools setup guide
├── CHANGELOG.md # Release history
├── dodo.py # Task automation definitions
├── LICENSE # Project license (MIT by default)
├── pyproject.toml # Project metadata and tool configuration
└── README.md # Project documentation
Package Structure:
src/layout for proper package installation and imports_version.pyis a stub; the built version file is generated by hatch-vcs from git tags- Version is derived from git tags via hatch-vcs (no manual edits)
Temporary Files Pattern:
- All cache and temporary files go in
tmp/directory - Keeps project root clean and organized
- Configurable via environment variables in
.envrc
Environment Management:
direnvfor automatic environment variable loading.envrc(committed) contains project defaults.envrc.local(git-ignored) for personal overrides.envrc.local.exampleprovides template for local settings
- Source distributions:
dist/*.tar.gz(generated byuv build) - Wheel distributions:
dist/*.whl(generated byuv build) - Coverage reports:
tmp/htmlcov/index.html(HTML),tmp/coverage.xml(XML for Codecov)
- Developer creates git tag (prerelease
v1.0.0-alpha.1for TestPyPI,v1.0.0for PyPI) - GitHub Actions workflow triggered
- hatch-vcs reads the tag and injects the version into the build (no file rewrites)
- Package built with correct version
- Published to TestPyPI (prerelease v* tags) or PyPI (v* tags)
Important for AI Agents: The version = "0.0.0" in pyproject.toml is a placeholder. The Single Source of Truth for the project's version is the Git tag. AI agents should not attempt to manually update the pyproject.toml version during regular development. This is handled automatically by the CI/CD release workflow.
All caches stored in tmp/ and configured via environment variables in .envrc:
UV_CACHE_DIR→tmp/.uv_cache(uv package cache)RUFF_CACHE_DIR→tmp/.ruff_cache(ruff linting cache)MYPY_CACHE_DIR→tmp/.mypy_cache(mypy type checking cache)COVERAGE_FILE→tmp/.coverage(coverage data file)PRE_COMMIT_HOME→tmp/.pre-commit(pre-commit hooks cache)
The project uses direnv for automatic environment management:
- Allow direnv:
direnv allow - Optional - Create local overrides:
cp .envrc.local.example .envrc.local - Customize
.envrc.localwith personal settings (API keys, debug flags, etc.)
When you cd into the project directory, direnv automatically:
- Activates the virtual environment
- Sets all cache directories to
tmp/subdirectories - Loads
.envrc.localfor personal overrides (if it exists) - Adds
.venv/binto PATH
Cache Directories (set in .envrc):
UV_CACHE_DIR→tmp/.uv_cache(uv package cache)RUFF_CACHE_DIR→tmp/.ruff_cache(ruff linting cache)MYPY_CACHE_DIR→tmp/.mypy_cache(mypy type checking cache)COVERAGE_FILE→tmp/.coverage(coverage data file)PRE_COMMIT_HOME→tmp/.pre-commit(pre-commit hooks cache)
CI/CD Secrets (set in GitHub Actions):
PYPI_TOKEN: PyPI API token for publishingCODECOV_TOKEN: Codecov token for coverage upload
Custom Variables:
Add custom variables to .envrc.local (git-ignored, never committed)
# Install uv
curl -LsSf https://astral.sh/uv/install.sh | sh
# Create virtual environment and install dependencies
uv venv
source .venv/bin/activate
uv pip install -e ".[dev]"
# Install pre-commit hooks
doit pre_commit_install
# Optional: Install direnv for automatic environment management
doit install_direnv
# Then hook direnv into your shell and run:
direnv allow
# Optional: Create .envrc.local for personal settings
cp .envrc.local.example .envrc.localTesting:
doit test # Run all tests
doit coverage # Run tests with coverage reportCode Quality:
doit format # Format code with ruff
doit format_check # Check formatting without changes
doit lint # Run ruff linting
doit type_check # Run mypy type checking
doit check # Run all checks (format_check, lint, type_check, test)Pre-commit:
doit pre_commit_install # Install pre-commit hooks
doit pre_commit_run # Run pre-commit on all filesDependency Management:
doit update_deps # Update all dependencies and verify with testsBuild & Publish:
doit build # Build package distributions
doit publish # Publish to PyPI (requires PYPI_TOKEN)Release Management:
doit release # Release a new version (automatic version bump)Maintenance:
doit cleanup # Deep clean: remove all build artifacts, caches, and temp files
doit list # Show all available tasks
doit fmt_pyproject # Format and organize pyproject.tomlSecurity & Compliance:
doit audit # Run security audit with pip-audit (requires security extras)
doit security # Run security scan with bandit (requires security extras)
doit licenses # Check licenses of dependencies (requires security extras)
doit spell_check # Check for typos in code and documentationpyproject-fmt - Format pyproject.toml:
# Format and organize pyproject.toml automatically
doit fmt_pyproject
# The tool will:
# - Sort sections and dependencies alphabetically
# - Apply consistent formatting
# - Remove redundant entries
# - Organize project metadatacommitizen - Conventional Commits:
# Interactive commit creation (ensures proper format)
# 1. Stage your changes: git add .
# 2. Run the commit task:
doit commit
# 3. Follow the prompts to create a properly formatted commit
# Note: Configured in pyproject.toml under [tool.commitizen]pip-licenses - Check Dependency Licenses:
# View all dependency licenses (requires security extras)
doit licenses
# Output shows: Package | Version | License | Author
# Useful for compliance audits and OSS license reviews
# Results are formatted as a markdown table sorted by license type- Write tests in
tests/directory - Follow pytest conventions:
test_*.py,Test*classes,test_*functions - Use fixtures for common test setup
- Maintain test coverage ≥80% (configurable in CI)
- Run tests before committing:
doit check
The examples/ directory contains runnable example scripts demonstrating package usage:
examples/basic_usage.py - Getting started
- Package imports and version checking
- Basic operations and common patterns
- Simple error handling
python examples/basic_usage.pyexamples/advanced_usage.py - Advanced features
- Configuration and setup patterns
- File processing workflows
- Batch operations
- Logging best practices
python examples/advanced_usage.pyexamples/cli_usage.py - Command-line interface examples
- CLI command patterns
- Programmatic CLI usage
- Output formatting options
python examples/cli_usage.pySee examples/README.md for detailed documentation of each example.
The project includes VS Code configuration for an optimal development experience:
.vscode/settings.json - Editor settings
- Python interpreter configured to
.venv/bin/python - Ruff as default formatter with format-on-save enabled
- Test discovery configured for pytest
- Type checking enabled with mypy
- Line length set to 100 characters
.vscode/extensions.json - Recommended extensions
- Python (ms-python.python) - Python language support
- Ruff (charliermarsh.ruff) - Fast linting and formatting
- Mypy (ms-python.mypy-type-checker) - Type checking
- GitLens (eamodio.gitlens) - Git integration
- Better Comments (aaron-bond.better-comments) - Comment highlighting
- Markdown All in One (yzhang.markdown-all-in-one) - Markdown support
Opening the project in VS Code:
- VS Code will prompt to install recommended extensions
- Select the Python interpreter from
.venv/ - Format on save and linting work automatically
- Tests can be run through the Testing sidebar
The project includes VS Code Remote Containers support for consistent development environments:
.devcontainer/devcontainer.json - Container configuration
- Based on official Python 3.12 development container
- Includes git and GitHub CLI
- Pre-configured with VS Code extensions (Ruff, Pylance, etc.)
- Automatically installs dependencies with uv
- Sets up pre-commit hooks on container creation
- Mounts your local git config for seamless git operations
Using Remote Containers:
- Install the "Remote - Containers" extension in VS Code
- Open the project in VS Code
- Click "Reopen in Container" when prompted (or use Command Palette: "Remote-Containers: Reopen in Container")
- Container builds and configures automatically
- Development environment is ready to use with all tools installed
Benefits:
- Consistent environment across different machines
- No need to install Python, uv, or other tools locally
- Isolated from your host system
- Easy onboarding for new contributors
Trigger: Push to main/develop or pull requests
Steps:
- Test on multiple Python versions (3.12, 3.13)
- Run format check (
ruff format --check) - Run linting (
ruff check) - Run type checking (
mypy) - Run tests with coverage
- Upload coverage to Codecov (Python 3.12 only)
Requirements: All checks must pass before merge
Trigger: Push tags matching prerelease v* (e.g., v1.0.0-alpha.1, v1.2.3-rc.0)
Tag Format: Pre-release SemVer with v prefix (e.g., v1.0.0-alpha.1)
Process:
- hatch-vcs reads the tag version (no file rewrites)
- Build package
- Publish to TestPyPI
Use Case: Testing releases before production deployment
Installation:
pip install --index-url https://test.pypi.org/simple/ bastproxyTrigger: Push tags matching v* (e.g., v1.0.0)
Tag Format: v<version> (e.g., v1.0.0)
Process:
- hatch-vcs reads the tag version (no file rewrites)
- Build package
- Publish to TestPyPI (verification)
- Publish to PyPI (production)
Use Case: Official releases to PyPI
Installation:
pip install bastproxyUsing the automated release tasks (recommended):
# Production release (stable v*)
doit release
# Development/pre-release (prerelease v* for TestPyPI)
doit release_dev # defaults to alpha
doit release_dev --type beta # or rcThe doit release task will:
- Verify you're on the main branch (or ask for confirmation)
- Check for uncommitted changes
- Pull latest changes from remote
- Run all checks (format, lint, type-check, tests)
- Use commitizen to calculate the next version, update CHANGELOG.md (merging pre-release entries via
--merge-prerelease), and create av*git tag - Trigger the GitHub Actions release workflow
Manual release (if needed):
# Production release
git tag v1.0.0 -m "Release version 1.0.0"
git push origin v1.0.0
# Development release (TestPyPI only)
git tag v1.0.0-alpha.1 -m "Development release 1.0.0-alpha.1"
git push origin v1.0.0-alpha.1- uv - Fast Python package installer and dependency manager
- ruff - Extremely fast Python linter and formatter (replaces black, isort, flake8, etc.)
- mypy - Static type checker with strict mode enabled
- pytest - Testing framework with parallel execution (pytest-xdist)
- pre-commit - Git hooks for automated quality checks before commits
- codespell - Spell checker for code and documentation
- pyproject-fmt - Automatically format and organize pyproject.toml
- commitizen - Enforce conventional commit message standards
- bandit - Security vulnerability scanner for Python code
- pip-audit - Dependency vulnerability auditor (CVE scanning)
- pip-licenses - License compliance checker for dependencies
- MkDocs - Static documentation site generator
- mkdocs-material - Material Design theme for MkDocs
# Core development tools (default)
uv sync
# Include security tools
uv sync --extra security
# All extras
uv sync --all-extras- Python version: 3.12+ (using modern syntax)
- Type hints: Required for all public functions/methods
- Use modern syntax:
list[str],dict[str, Any],X | None - Avoid legacy
typing.List,typing.Optional
- Use modern syntax:
- Line length: Max 100 characters
- Docstrings: Google-style, required for public APIs
- Naming conventions:
snake_casefor functions, variables, modulesPascalCasefor classesUPPER_CASEfor constants
Organize imports in three groups (separated by blank lines):
# Standard library
import os
from pathlib import Path
from typing import Any
# Third-party
import click
import pytest
# Local
from bastproxy import __version__
from bastproxy.module import functionRequired for:
- Public classes, functions, methods
- Modules (module-level docstring)
Optional for:
- Private functions/methods (prefix
_) - Very simple/obvious functions
Format (Google-style):
def process_data(data: list[dict[str, Any]], validate: bool = True) -> dict[str, Any]:
"""Process input data and return results.
Args:
data: List of data dictionaries to process
validate: Whether to validate data before processing
Returns:
Dictionary containing processed results
Raises:
ValueError: If data validation fails
TypeError: If data is not in expected format
"""- Use
typing.Anysparingly; prefer specific types - Use
collections.abcfor abstract types (Sequence, Mapping, etc.) - Mark optional parameters with
| None, notOptional[T] - Use
TypeVarfor generic functions - Use
Protocolfor structural subtyping when appropriate
- Read before editing: Always read files before modifying them
- Maintain backward compatibility: Don't break public APIs without major version bump
- Early returns: Prefer early returns over deep nesting
- Explicit over implicit: Make intentions clear in code
- Single responsibility: Functions/classes should do one thing well
- Raise specific exceptions with clear messages
- Never catch
KeyboardInterruptorSystemExit - Log errors with context before raising
- Use custom exception classes for domain-specific errors
- Mutable default arguments: Never use
def foo(items=[])❌ - String concatenation for paths: Use
Pathobjects - Ignoring type hints: Type hints are enforced by mypy
- God classes: Keep classes focused and modular
- Silent failures: Always log and raise exceptions appropriately
- Blocking I/O in loops: Batch operations when possible
- Never log secrets or sensitive data
- Use
subprocesswith list args, avoidshell=True - Validate all user-provided paths (prevent path traversal)
- Use
yaml.safe_load(), neveryaml.load()
Follow Conventional Commits:
<type>: <subject>
[optional body]
[optional footer]
Commitizen Support: The project includes Commitizen to enforce conventional commit standards and automate versioning:
- Configured in
pyproject.tomlunder[tool.commitizen] - Helps maintain consistent commit message format
- Can be used to automatically bump versions and generate changelogs
Types:
feat: New featurefix: Bug fixrefactor: Code restructuring without behavior changedocs: Documentation updatestest: Adding or updating testschore: Dependency updates, tooling changesci: CI/CD configuration changesperf: Performance improvements
Rules:
- Subject must be lowercase, concise (no period at end)
- Use imperative mood ("add feature" not "added feature")
- Separate concerns: one commit per logical change
- Write clear, descriptive messages
Examples:
feat: add support for custom validators
fix: handle None values in data processing
refactor: extract common validation logic
docs: update installation instructions for direnv
test: add tests for edge cases in parser
chore: update dependencies to latest versions
For breaking changes, include BREAKING CHANGE: in commit footer:
refactor: change API to use async/await
Migrate to async for better concurrency handling.
BREAKING CHANGE: All public methods are now async and must be awaited.
Update calling code to use `await` or `asyncio.run()`.
Same as commit messages: <type>: <subject>
See .github/pull_request_template.md for the complete PR description template, which includes:
- Summary section
- Changes checklist
- Related issues
- Testing checklist
- Breaking changes section
- Documentation updates
Before submitting:
- Self-reviewed code
- All CI checks passing locally (
doit check) - Tests added/updated
- Documentation updated
- CHANGELOG.md updated (for notable changes)
Reviewers verify:
- Code follows project conventions
- Tests adequate and passing
- No security vulnerabilities
- Error handling appropriate
- Documentation clear and accurate
Ask the user when:
- Multiple valid implementation approaches exist
- Architectural decisions need to be made
- Breaking changes would impact users
- Requirements are ambiguous or incomplete
- Trade-offs between approaches are significant
- Custom configuration values are needed
Proceed without asking when:
- Clear conventions exist in the codebase
- Obvious bugs with single correct solution
- Documentation improvements (docstrings, README)
- Code refactoring that maintains behavior
- Adding missing test coverage
- Following established patterns
- Read before editing: Always read files first
- Follow patterns: Match existing code style
- Run tests: Verify changes with
doit check - Commit appropriately: Use conventional commit format
- Explain clearly: Provide context in commit messages
- Check CI: Ensure all checks pass
- Update docs: Keep documentation synchronized
- Review guidelines: See .github/CONTRIBUTING.md for detailed development guidelines and standards
- Maintain ≥80% test coverage (configurable)
- Test coverage enforced in CI
- View coverage report:
open tmp/htmlcov/index.html
- Write tests for all public APIs
- Use fixtures for common setup
- Use parametrized tests for multiple input cases
- Mock external dependencies
- Test edge cases and error conditions
- Keep tests focused and readable
# Run all tests (use doit for standard workflows)
doit test
# Run with coverage
doit coverage
# View coverage report
open tmp/htmlcov/index.html
# Advanced: Run specific test file or test (use pytest directly)
uv run pytest tests/test_example.py
uv run pytest tests/test_example.py::test_function -v
uv run pytest -v -s # Verbose with print outputuv not found:
curl -LsSf https://astral.sh/uv/install.sh | shdirenv not activating:
# Ensure direnv is hooked in your shell
echo 'eval "$(direnv hook bash)"' >> ~/.bashrc # or ~/.zshrc
source ~/.bashrc
direnv allowPre-commit hooks failing:
# Run pre-commit manually
doit pre_commit_run
# Or fix specific issues
doit format # Auto-fix formatting
doit lint # Check linting issuesTests failing:
# Run with verbose output
uv run pytest -v -s
# Run specific test
uv run pytest tests/test_example.py::test_function -vImport errors:
# Reinstall in development mode
doit devThe docs/ directory contains comprehensive documentation:
docs/index.md - Documentation home
- Overview of the project
- Key features and capabilities
- Quick navigation to other documentation
docs/installation.md - Installation guide
- Installing with pip
- Installing with uv
- Development setup
- Troubleshooting installation issues
docs/usage.md - Usage guide
- Getting started tutorial
- Common use cases and patterns
- Configuration options
- Best practices
docs/api.md - API reference documentation
- Module documentation
- Function and class references
- Type signatures
- Code examples
docs/extensions.md - Optional tools and extensions guide
- Testing extensions (pytest-watch, hypothesis, faker, factory-boy, mutmut, vcrpy)
- Performance & profiling tools (py-spy, memray, scalene, line_profiler)
- Configuration management (pydantic-settings, dynaconf, python-decouple)
- Logging & monitoring (loguru, structlog, Sentry, OpenTelemetry)
- Dependency management tools (pipdeptree)
- Additional code quality tools (vulture, radon, interrogate)
- Container support (Docker, docker-compose)
- Multi-version Testing (tox, nox)
- When to add each extension based on project needs
docs/migration.md - Migration guide
- How to migrate an existing project into this template
The documentation is built using MkDocs with the Material theme. View locally with doit docs_serve or build with doit docs_build.
The template includes a comprehensive guide for optional tools and extensions in docs/extensions.md. This guide covers:
When to extend: Add tools only when you have a specific need. The template is intentionally minimal to avoid bloat.
Available extensions:
- Testing: pytest-watch, hypothesis, faker, factory-boy, mutmut, vcrpy
- Profiling: py-spy, memray, scalene, line_profiler
- Configuration: pydantic-settings, dynaconf, python-decouple
- Logging: loguru, structlog, Sentry, OpenTelemetry
- Code Quality: vulture, radon, interrogate, pipdeptree
- Containers: Docker, docker-compose support
- Multi-version Testing: tox, nox
See docs/extensions.md for installation instructions, usage examples, and guidance on when to add each tool.
Consider creating separate template variants for different use cases:
- Web APIs: FastAPI/Flask with database support
- CLI Applications: Click/Typer-based command-line tools
- Data Science: Jupyter, pandas, numpy, visualization tools
- Libraries: Current template (general-purpose Python package)
- README.md: Project overview and quick start
- CHANGELOG.md: Release history and changes
- AGENTS.md: This file - comprehensive agent instructions
- AI_SETUP.md: Guide for setting up AI coding assistants (Codex CLI, Gemini CLI, Claude Code)
- LICENSE: Project license (MIT)
- .github/CONTRIBUTING.md: Development setup, coding standards, testing requirements, and contribution workflow
- .github/CODE_OF_CONDUCT.md: Contributor Covenant code of conduct for community guidelines
- .github/SECURITY.md: Security policy, vulnerability reporting, and supported versions
- .github/CODEOWNERS: Code ownership and review assignments
- dodo.py: All development tasks (see
doit listfor available commands)- Common tasks:
test,coverage,lint,format,type_check,check - Security:
audit,security,licenses,spell_check - Version management:
commit,bump,changelog - Maintenance:
cleanup,update_deps,release,fmt_pyproject - Build:
build,publish - Documentation:
docs_serve,docs_build,docs_deploy
- Common tasks:
- docs/index.md: Documentation home page
- docs/installation.md: Installation instructions
- docs/usage.md: Usage guide and examples
- docs/api.md: API reference documentation
- docs/extensions.md: Optional tools and extensions guide
- docs/migration.md: How to migrate an existing project into this template
- examples/README.md: Overview of available examples
- examples/basic_usage.py: Getting started examples
- examples/advanced_usage.py: Advanced usage patterns
- examples/cli_usage.py: CLI usage examples
- uv documentation: https://github.com/astral-sh/uv
- ruff documentation: https://docs.astral.sh/ruff/
- pytest documentation: https://docs.pytest.org/
- direnv documentation: https://direnv.net/
- Conventional Commits: https://www.conventionalcommits.org/
- Commitizen: https://commitizen-tools.github.io/commitizen/
- Contributor Covenant: https://www.contributor-covenant.org/
- Check GitHub Issues for similar problems
- Review CI logs for detailed error messages
- Run
doit listto see all available tasks - Check
.envrcand.envrc.localconfiguration for environment issues - Read .github/CONTRIBUTING.md for development guidelines
- See AI_SETUP.md for AI assistant configuration
This file provides comprehensive instructions for both human developers and AI agents working with this Python project template. Follow these guidelines to maintain code quality and consistency.