Skip to content

Latest commit

 

History

History
100 lines (68 loc) · 4.07 KB

File metadata and controls

100 lines (68 loc) · 4.07 KB

CLAUDE.md

Project overview

Python monorepo managed with uv workspaces. The core framework lives in agents-core/ and plugins live in plugins/ (37+ packages). Python >= 3.10, 3.12 recommended.

Commands

All commands use uv. Never use python -m. If you run into dependency issues, stop and ask.

# Full check (ruff + mypy + unit tests)
uv run --no-sync dev.py check

# Unit tests only (--no-sync avoids uv panic in sandboxed environments)
uv run --no-sync pytest -m "not integration"

# Integration tests (needs .env secrets)
uv run --no-sync pytest -m "integration"

# Lint & format
uv run --no-sync ruff check .
uv run --no-sync ruff format .

# Type check
uv run --no-sync mypy

Testing

  • Framework: pytest. Never mock.
  • @pytest.mark.asyncio is not needed (asyncio_mode = auto).
  • Integration tests use @pytest.mark.integration.
  • Never adjust sys.path.
  • Keep unit-tests for the class under the same test class. Do not spread them around different test classes. For example, tests for Agent must be inside TestAgent, etc.

Python rules

  • Never use from __future__ import annotations.
  • Never write except Exception as e. Catch specific exceptions.
  • Avoid getattr, hasattr, delattr, setattr; prefer normal attribute access.
  • Docstrings: Google style, keep them short.
  • Do not use section comments like # -- some section --
  • Prefer logger.exception() when logging an error with a traceback instead of logger.error("Error: {exc}")
  • Do not use local imports, import at the top of the module
  • Avoid # type: ignore comments.
  • Avoid using Any type.
  • When adding code to an existing file, follow the patterns already established in that file (e.g. error handling style, import guards, naming).

Code style

Imports:

  • ordered as: stdlib, third-party, local package, relative. Use TYPE_CHECKING guard for imports only needed by type annotations.
  • Never import from private modules (_foo) outside of the package's own __init__.py. Use the public re-export (e.g. from vision_agents.testing import TestResponse, not from vision_agents.testing._run_result import TestResponse).

Naming:

  • private attributes and methods use a leading underscore (_sessions, _warmup_agent). Public API is plain snake_case.

Type annotations:

  • use them everywhere. Modern syntax: X | Y unions, dict[str, T] generics, full Callable signatures, Optional for nullable params.

Logging: module-level logger = logging.getLogger(__name__). Use debug for lifecycle, info for notable events, error for failures without a traceback, exception for errors with traceback.

  • In hot paths (audio processing, event handling), guard debug logging behind if logger.isEnabledFor(logging.DEBUG): to avoid formatting overhead when debug is disabled.

Constructor validation:

  • raise ValueError with a descriptive message for invalid args. Prefer custom domain exceptions over generic ones.

Async patterns:

  • async-first lifecycle methods (start/stop). Support __aenter__/__aexit__ for context manager usage.
  • Use asyncio.Lock, asyncio.Task, asyncio.gather for concurrency.
  • Clean up resources in finally blocks.

Method order:

  • __init__, public lifecycle methods, properties, public feature methods, private helpers, dunder methods.

Token efficiency

  • When making multiple related changes to the same file, combine them into fewer Edit calls with enough surrounding context, rather than one edit per change.
  • Run tests with Bash directly. Only use subagents for test runs when you need to do other work in parallel.
  • Only use TodoWrite for tasks with 5+ steps. Don't update it after every individual edit.

Changelog

  • Lives in CHANGELOG.md at the repo root.
  • Organised by version heading (# v0.4.0), then sections: Breaking Changes, New Features, Bug Fixes.
  • Only include user-facing changes (public API breaks, features, fixes). Skip docs-only and CI-only commits.
  • Reference PR numbers inline, e.g. (#374).
  • To generate: git log <last-tag>..HEAD --oneline --no-merges, then classify each commit.