This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This is a Python development environment template using uv (fast Python package manager) and Ruff (linter/formatter). The repository serves dual purposes:
- A template for starting new Python projects
- A reusable
tools/package with production-ready utilities (Logger, Config, Timer)
# Install dependencies
uv sync
# Add new dependency
uv add <package>
# Add dev dependency
uv add --dev <package>
# Remove dependency
uv remove <package># Run all tests with coverage (75% minimum required)
uv run nox -s test
# Run specific test file
uv run pytest tests/tools/test__logger.py
# Run with JUnit XML output for CI
uv run nox -s test -- --cov_report xml --junitxml junit.xml
# Run pytest directly (bypasses nox)
uv run pytest# Format code with Ruff
uv run nox -s fmt -- --ruff
# Format SQL files with SQLFluff
uv run nox -s fmt -- --sqlfluff
# Format both Python and SQL
uv run nox -s fmt -- --ruff --sqlfluff
# Lint with all tools (Ruff, SQLFluff, ty)
uv run nox -s lint -- --ruff --sqlfluff --ty
# Lint with Ruff only
uv run nox -s lint -- --ruff
# Lint SQL files only
uv run nox -s lint -- --sqlfluff
# Lint with ty only
uv run nox -s lint -- --ty
# Run Ruff directly
uv run ruff check . --fix
uv run ruff format .
# Run SQLFluff directly
uv run sqlfluff lint .
uv run sqlfluff fix .
# Run ty directly
uv run ty check# Install hooks
uv run pre-commit install
# Run all hooks manually
uv run pre-commit run --all-files
# Run specific hook
uv run pre-commit run ruff-format# Serve docs locally at http://127.0.0.1:8000
uv run mkdocs serve
# Build documentation
uv run mkdocs build
# Deploy to GitHub Pages
uv run mkdocs gh-deployThe tools/ package provides three main utility modules:
Loggerclass extendslogging.Loggerwith environment-aware formatting- LogType.LOCAL: Colored console output via
LocalFormatterfor development - LogType.GOOGLE_CLOUD: Structured JSON via
GoogleCloudFormatterfor production - Key pattern: Use
Settings.IS_LOCALto switch between modes automatically
from tools.config import Settings
from tools.logger import Logger, LogType
settings = Settings()
logger = Logger(
__name__,
log_type=LogType.LOCAL if settings.IS_LOCAL else LogType.GOOGLE_CLOUD
)Settingsclass uses Pydantic for type-safe configuration- Loads from
.env(version controlled) and.env.local(local overrides, in .gitignore) FastAPIKwArgsprovides ready-to-use FastAPI initialization parameters- Pattern: Extend
Settingsto add project-specific configuration fields
from tools.config import Settings
settings = Settings()
api_url = settings.api_prefix_v1 # Loaded from environmentTimerclass works as both decorator and context manager- Automatically logs execution time in milliseconds at DEBUG level
- Uses the
Loggermodule for output (inherits logging configuration) - Pattern: Nest timers to measure both overall and component performance
from tools.tracer import Timer
@Timer("full_operation")
def process():
with Timer("step1"):
do_step1()
with Timer("step2"):
do_step2()Tests in tests/tools/ mirror the package structure:
- Naming convention:
test__*.py(double underscore) - Coverage requirement: 75% minimum (including branch coverage)
- Test files exempt from:
INP001(namespace packages),S101(assert usage)
Ruff (ruff.toml):
- ALL rules enabled by default with specific exclusions
- Line length: 88 (Black-compatible)
- Target Python: 3.14
- Per-file ignores for test files
ty (ty.toml):
- Includes
tools/,tests/packages, andnoxfile.py - Excludes cache directories (
__pycache__,.pytest_cache,.ruff_cache,.venv)
pytest (pytest.ini):
- Coverage: 75% minimum with branch coverage
- Reports: HTML + terminal
- Import mode: importlib
SQLFluff (.sqlfluff):
- Dialect: BigQuery
- Max line length: 80
- Tab space size: 2
- Custom rules for join qualification and unused joins
The noxfile.py uses a custom CLIArgs parser (Pydantic-based):
- All sessions use
python=False(rely onuv run) - Arguments passed via
-- --flag valuesyntax - Sessions:
fmt,lint,test
Example of the argument parsing pattern:
# noxfile.py
@nox.session(python=False)
def lint(session: nox.Session) -> None:
args = CLIArgs.parse(session.posargs)
if args.ty:
session.run("uv", "run", "ty", "check")
if args.ruff:
session.run("uv", "run", "ruff", "check", ".", "--fix")
if args.sqlfluff:
session.run("uv", "run", "sqlfluff", "lint", ".")Extend the Settings class in tools/config/settings.py:
class Settings(BaseSettings):
# Existing fields...
# Add your new fields
NEW_SETTING: str = "default_value"
ANOTHER_SETTING: int = 42Then add to .env.local:
NEW_SETTING=custom_value
ANOTHER_SETTING=100Create a new formatter in tools/logger/:
- Extend
logging.Formatter - Export from
tools/logger/__init__.py - Update
Logger.__init__()to support the new type
When testing the utilities themselves:
- Logger: Capture logs using
assertLogscontext manager - Config: Use Pydantic's model instantiation with kwargs to override values
- Timer: Check debug logs for execution time messages
The docs/ directory is organized for MkDocs:
- docs/index.md: Main landing page
- docs/getting-started/: Setup guides (Docker, VSCode, Dev Container)
- docs/guides/: Tool usage guides (uv, Ruff, ty, pre-commit, tools package)
- docs/configurations/: Detailed configuration references
- docs/usecases/: Real-world examples (Jupyter, FastAPI, OpenCV)
When adding new utilities to tools/, add corresponding documentation to docs/guides/tools/.
GitHub Actions workflows in .github/workflows/:
- actionlint.yml: Lint GitHub Actions workflows
- docker.yml: Validate Docker build
- devcontainer.yml: Validate Dev Container configuration
- format.yml: Check Ruff formatting
- labeler.yml: Add label in GitHub
- lint.yml: Run Ruff + ty linting
- test.yml: Run pytest with coverage
- gh-deploy.yml: Deploy documentation to GitHub Pages
All workflows use the same nox commands as local development.
For comprehensive contribution guidelines, including detailed steps for creating and reviewing Pull Requests, please refer to CONTRIBUTING.md in the repository root.
Code of Conduct: All contributors must follow our Code of Conduct. We maintain a welcoming, inclusive, and harassment-free environment for everyone.
Critical environment variables (set in .env.local):
IS_LOCAL: Boolean flag for local vs production (affects logging, configuration)DEBUG: Boolean for debug mode- FastAPI settings:
TITLE,VERSION,API_PREFIX_V1, etc.
- Coverage is enforced: Tests must maintain 75% coverage (configured in pytest.ini)
- uv replaces pip/poetry: Use
uv addnotpip install, useuv.locknotrequirements.txt - Ruff replaces multiple tools: No need for Black, isort, Flake8, etc.
- nox is the task runner: Prefer
uv run nox -s <session>over direct tool calls - Test naming: Use
test__*.pypattern (double underscore) - Type checking: ty checks both the
tools/andtests/packages
When using this as a template for a new project:
- Update
pyproject.tomlwith new project name/description - Modify or extend
tools/config/settings.pyfor project-specific configuration - Use the utilities from
tools/or remove if not needed - Update
.envwith base configuration,.env.localwith local overrides - Customize Ruff rules in
ruff.tomlif needed (but start with defaults)