Skip to main content

Pydantic AI model adapter for Claude Code CLI

Project description

claude-code-model

Pydantic AI model adapter for Claude Code CLI — type-safe agents on your Max subscription.

Use Pydantic AI's powerful agent framework with Claude Code CLI instead of API calls. Get structured outputs, tool calling, and full type safety without per-token costs.

Why Use This?

Approach Cost Type Safety Structured Output Tool Calling
Raw claude -p $0
Pydantic AI + API $$$ per token
claude-code-model $0

If you have a Claude Max subscription ($100-200/month), you get unlimited Claude access via CLI. This adapter lets you use that access with Pydantic AI's excellent developer experience.

Installation

# 1. Install Claude Code CLI (if not already installed)
npm install -g @anthropic-ai/claude-code

# 2. Authenticate
claude auth

# 3. Install this package
pip install claude-code-model

Quick Start

Structured Output

Get type-safe responses with automatic validation:

from pydantic import BaseModel
from pydantic_ai import Agent
from claude_code_model import ClaudeCodeModel

class ReviewResult(BaseModel):
    verdict: str  # APPROVE, REQUEST_CHANGES, COMMENT
    issues: list[str]
    suggestions: list[str]

agent = Agent(
    ClaudeCodeModel(),
    result_type=ReviewResult,
    system_prompt="You are a code reviewer. Return structured JSON."
)

result = agent.run_sync("Review this code: def add(a,b): return a+b")

# Result is fully typed!
print(result.data.verdict)  # IDE autocomplete works
print(result.data.issues)   # Type checking works

Tool Calling

Give your agent functions it can call:

from pydantic_ai import Agent
from claude_code_model import ClaudeCodeModel

agent = Agent(ClaudeCodeModel())

@agent.tool_plain
def read_file(path: str) -> str:
    """Read a file from disk."""
    return Path(path).read_text()

@agent.tool_plain
def list_files(directory: str = ".") -> list[str]:
    """List files in a directory."""
    return [f.name for f in Path(directory).iterdir()]

result = agent.run_sync("What Python files are in the current directory?")
# Agent automatically calls list_files() and uses the results

Multi-Agent Systems

Different models for different tasks:

from claude_code_model import ClaudeCodeModel

# Fast agent for quick tasks
researcher = Agent(
    ClaudeCodeModel(model="haiku"),
    system_prompt="Quick research"
)

# Powerful agent for analysis
analyst = Agent(
    ClaudeCodeModel(model="sonnet"),
    system_prompt="Deep analysis"
)

# Analyst can delegate to researcher
@analyst.tool_plain
async def research(topic: str) -> str:
    result = await researcher.run(f"Research {topic}")
    return result.data

Features

  • Zero API Costs: Uses your Claude Max subscription
  • Full Pydantic AI Compatibility: Structured outputs, tools, deps, async
  • Type Safety: Full IDE autocomplete and type checking
  • Multiple Models: sonnet (default), opus, haiku
  • Tool Calling: Give agents functions to call
  • Async Support: Full async/await support
  • Simple: <500 lines of code, easy to audit

Configuration

from claude_code_model import ClaudeCodeModel
from pathlib import Path

model = ClaudeCodeModel(
    model="sonnet",      # "sonnet" | "opus" | "haiku"
    timeout=300,         # seconds
    cwd=Path("/path"),   # working directory for CLI
)

Examples

The examples/ directory contains working examples:

  • simple.py: Structured output for code review
  • with_tools.py: File system tools with interactive chat
  • multi_agent.py: Multi-agent delegation pattern

Run them:

uv run python examples/simple.py
uv run python examples/with_tools.py

How It Works

┌─────────────────────────────────────────┐
│  Your Code                              │
│  agent = Agent(ClaudeCodeModel())       │
│  result = agent.run_sync("prompt")      │
└──────────────┬──────────────────────────┘
               │
               ▼
┌─────────────────────────────────────────┐
│  Pydantic AI                            │
│  - Manages conversation state           │
│  - Handles tool calls and retries       │
│  - Validates output against schema      │
└──────────────┬──────────────────────────┘
               │
               ▼
┌─────────────────────────────────────────┐
│  claude-code-model                      │
│  - Converts messages → prompt string    │
│  - Adds JSON schema instructions        │
│  - Calls CLI wrapper                    │
│  - Parses response → ModelResponse      │
└──────────────┬──────────────────────────┘
               │
               ▼
┌─────────────────────────────────────────┐
│  Claude Code CLI                        │
│  $ claude -p "prompt" --model sonnet    │
│  > {"verdict": "APPROVE", "issues": []} │
└─────────────────────────────────────────┘

The adapter translates between Pydantic AI's message format and Claude CLI's prompt-response model. It handles:

  • System prompts, user messages, tool calls, tool results
  • JSON extraction from various response formats
  • Tool call detection and parsing
  • Structured output validation

API Reference

ClaudeCodeModel

Main model class implementing Pydantic AI's Model interface.

@dataclass
class ClaudeCodeModel(Model):
    model: Literal["sonnet", "opus", "haiku"] = "sonnet"
    timeout: int = 300  # seconds
    cwd: Path | None = None

Exceptions

from claude_code_model import (
    ClaudeCodeError,           # Base exception
    ClaudeCodeNotFoundError,   # CLI not installed
    ClaudeCodeTimeoutError,    # Command timed out
    ClaudeCodeExecutionError,  # Non-zero exit code
)

Limitations

  • No streaming: CLI doesn't support streaming well
  • No token counting: CLI doesn't report usage (returns 0)
  • No concurrent calls: Run one request at a time
  • Text-only: No image inputs (CLI limitation)
  • Rate limits: Subject to Claude Max rate limits

Development

# Setup
git clone https://github.com/yourusername/claude-code-model.git
cd claude-code-model
uv sync

# Run tests
uv run pytest

# Run tests with coverage
uv run pytest --cov=claude_code_model

# Type check
uv run mypy src/

# Lint
uv run ruff check src/ tests/
uv run ruff format src/ tests/

# Run example
uv run python examples/simple.py

Requirements

  • Python 3.11+
  • Claude Code CLI installed and authenticated
  • Claude Max subscription (for unlimited CLI access)
  • pydantic-ai >= 0.1.0
  • pydantic >= 2.0.0

Contributing

Contributions welcome! Please:

  1. Keep changes focused and small (<200 lines)
  2. Add tests for new functionality
  3. Ensure pytest, mypy, and ruff all pass
  4. Update README if adding features

See CLAUDE.md for development guide.

License

MIT License - see LICENSE file for details.

Credits

Built with:

Disclaimer

This is an unofficial adapter, not affiliated with Anthropic. Use in accordance with Claude's Terms of Service. You are responsible for ensuring your usage complies with Anthropic's policies.

Support

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

claude_code_model-0.1.0.tar.gz (230.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

claude_code_model-0.1.0-py3-none-any.whl (9.9 kB view details)

Uploaded Python 3

File details

Details for the file claude_code_model-0.1.0.tar.gz.

File metadata

  • Download URL: claude_code_model-0.1.0.tar.gz
  • Upload date:
  • Size: 230.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.14 {"installer":{"name":"uv","version":"0.9.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for claude_code_model-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3fff26cc718af24ca1c6c77d7a67972f78c5198c6e76c4e2e41da3c28ae97966
MD5 f8c18b2fa0014820273307e8095b2442
BLAKE2b-256 9aa3848a45d2da015b6fe7da282b250cc53e9a4078d4d165c71ea899b8b7ab79

See more details on using hashes here.

File details

Details for the file claude_code_model-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: claude_code_model-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 9.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.14 {"installer":{"name":"uv","version":"0.9.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for claude_code_model-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b8ea47da0867746e1192041a8ea7e826af5ff5d1508b58682442b6299c64ab89
MD5 4b9c429d76647164b148ca19479a44b6
BLAKE2b-256 a5b836098e1d6bc1dcab1f9f738b64f04e7ab3bea478252fc0da519206d2dfd5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page