# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## What is agentbudget

A lightweight Python library for tracking LLM costs (OpenAI + Anthropic) in multi-step pipelines and AI agents. Zero required dependencies — `openai` and `anthropic` are optional extras. Target: Python 3.9+, distributed via PyPI.

Full spec: `AGENTBUDGET_SPEC.md` — read it entirely before writing any code.

## Commands

```bash
# Install in dev mode with all extras
uv pip install -e ".[all,dev]"

# Run all tests
uv run pytest

# Run a single test file
uv run pytest tests/test_session.py

# Run with coverage
uv run pytest --cov=agentbudget --cov-report=term-missing

# Build for PyPI
uv run python -m build
```

## Architecture

```
agentbudget/          # main package
├── __init__.py       # public API: CostSession, CostTracker, track, BudgetExceededWarning, BudgetExceededError
├── session.py        # CostSession context manager — tracks steps, enforces budget, prints summary
├── tracker.py        # CostTracker — reads/writes ~/.agentbudget/sessions.json, generates aggregate reports
├── decorators.py     # @track decorator wrapping CostSession
├── exceptions.py     # BudgetExceededWarning, BudgetExceededError
├── pricing.py        # MODEL_PRICING dict: {model: {input: $/M, output: $/M}}
└── providers/
    ├── base.py       # BaseProvider (abstract) + detect_provider(response) auto-detection logic
    ├── openai.py     # OpenAIProvider: extracts prompt_tokens, completion_tokens, model
    └── anthropic.py  # AnthropicProvider: extracts input_tokens, output_tokens, model
tests/
examples/
    openai_example.py
    anthropic_example.py
```

### Key design rules

- **No `print()` directly** — use an internal `_log(verbose, message)` helper that checks the `verbose` flag.
- **Provider auto-detection** order: isinstance check for `openai.types.chat.ChatCompletion` → check for `usage.input_tokens` (Anthropic) → model name prefix fallback ("gpt-", "o1", "o3" → OpenAI; "claude-" → Anthropic) → raise `ValueError`.
- **Missing model pricing** → cost = 0.0, emit warning: `"[agentbudget] Warning: pricing not found for model '{model}'. Cost will be $0.00."`
- **Storage**: `~/.agentbudget/sessions.json` — flat JSON list of session objects (schema in spec §8).
- **Budget enforcement**: default is `BudgetExceededWarning`; `strict=True` raises `BudgetExceededError`.
- **Optional imports**: guard `import openai` and `import anthropic` with try/except inside provider files — never at module top-level.

### Data flow

`session.track(response)` → `detect_provider(response)` → `provider.extract_usage(response)` → lookup `MODEL_PRICING` → accumulate cost on session → check budget → on `__exit__`, persist to JSON via `CostTracker` and print summary.

## Code conventions

- Type hints on all public functions and methods
- Docstrings (English) on all public classes and methods
- Coverage target ≥ 80%
- `pyproject.toml` build backend: `hatchling`
