pydantic-claude-code
Use your Claude Code subscription from a plain pydantic-ai Agent, with full
pydantic-ai tool support. No API key, no separate billing: if Claude Code works
from your terminal, this wheel works too.
The repo is mpfaffenberger/pydantic-ai-claude-code and the import is
pydantic_ai_claude_code; the PyPI project is pydantic-claude-code
(pip install pydantic-claude-code).
Why
pydantic-ai gained a Codex OAuth path where openai-codex:gpt-6-astra just
works against a ChatGPT subscription. This wheel brings the same experience to
Claude: authenticate once, then run pydantic-ai agents against your Claude
subscription, using claude-fable-5-1, claude-sonnet-5, claude-opus-5, or
whatever model you subscribe to.
Two deliberate design choices distinguish this from a fork of pydantic-ai:
- pydantic-ai owns the loop. We don't hand the whole agent loop to the
Claude Code CLI. pydantic-ai's own
Agentmachinery drives the conversation, executes your tools, and validates structured output. The wheel is a model- provider, not a second agent fighting for control.
- Object-only resolution. Instead of a
claude-code:model-name string (which would require patching pydantic-ai's internals), construct aClaudeCodeModel('claude-fable-5-1')directly; it wires itself up to aClaudeCodeProviderby default.
Quick start
import asyncio
from pydantic_ai import Agent
from pydantic_ai_claude_code import ClaudeCodeModel, login
async def main() -> None:
# One-time: opens your browser, mints tokens, stores them
# (only needs to run again when tokens are revoked).
await login()
agent = Agent(ClaudeCodeModel('claude-fable-5-1'))
result = await agent.run('Say hi in three words.')
print(result.data)
asyncio.run(main())
With tools
from pydantic_ai import Agent
from pydantic_ai_claude_code import ClaudeCodeModel
agent = Agent(ClaudeCodeModel('claude-fable-5-1'))
@agent.tool_plain
def add(a: int, b: int) -> int:
"""Add two numbers."""
return a + b
Tools defined on the agent are passed to the API as standard Anthropic tool
definitions, and structured output works the same way as with the built-in
anthropic provider. That's the whole point of the wheel.
Structured output
from pydantic import BaseModel
from pydantic_ai import Agent
from pydantic_ai_claude_code import ClaudeCodeModel
class Weather(BaseModel):
city: str
temperature_c: float
agent = Agent(ClaudeCodeModel('claude-fable-5-1'), output_type=Weather)
result = await agent.run('Weather in Paris right now?')
assert result.output.city == 'Paris'
Streaming
from pydantic_ai import Agent
from pydantic_ai_claude_code import ClaudeCodeModel
agent = Agent(ClaudeCodeModel('claude-fable-5-1'))
async with agent.run_stream('Count from 1 to 3.') as stream:
async for chunk in stream.stream_text():
print(chunk, end='', flush=True)
How auth works
The flow uses the same shared OAuth client the Claude Code CLI uses:
- Authorization URL:
https://claude.ai/oauth/authorize - Token URL:
https://platform.claude.com/v1/oauth/token - Scopes:
org:create_api_key user:profile user:inference
Tokens are saved to the OS keyring by default: the Keychain on macOS, Credential
Manager on Windows, and Secret Service on Linux. On machines without a keychain,
credentials fall back to a JSON file (overridable via CLAUDE_CODE_AUTH_FILE):
~/.local/share/pydantic-ai-claude-code/auth.json
The fallback file is written with 0644 permissions and only ever contains what
the issuer gave us. We never read the CLI's own credential files.
Force a backend with the CLAUDE_CODE_CREDENTIALS env var: keyring or file.
Refreshes happen automatically in the background: the auth shim refreshes before expiry and retries once on a 401, exactly like the codex provider does.
Requests identify as Claude Code: "You are Claude Code, Anthropic's official CLI for Claude." is prepended to the system context (position 0), the same
persona the CLI sends. The subscription backend expects it and rate-gates
premium models without it.
Security and scope
This is a plain Anthropic Messages API client authenticated by your Claude subscription tokens. It does not run the Claude Code CLI in a subprocess, so it does not inherit Claude Code's sandboxing, permission prompts, or hooks. Treat it like any code-executing agent: only give it tools you trust.
Projects using this are responsible for following Anthropic's rules for using Claude Code credentials in their own products.
Development
uv sync --extra dev # or: source .venv/bin/activate && pip install -e ".[dev]"
ruff check src tests
pytest
Prior art
The OAuth mechanics (shared client id, PKCE, token storage and refresh) are
lifted from the claude_code_oauth plugin in
code_puppy_core_plugins,
cleaned up and reshaped around the provider pattern in pydantic-ai.
Metadata
Release files for pydantic-claude-code 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pydantic_claude_code-0.3.0.tar.gz | 16.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pydantic_claude_code-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 32.9 kB
Release files / pydantic_claude_code-0.3.0.tar.gz
| Download URL | pydantic_claude_code-0.3.0.tar.gz |
|---|---|
| Size | 16.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8672bc27b16e599e98b2ad2a2647a3b24507c56a22305055a8efea15e1f5b179
|
|
BLAKE2b-256 checksum How to use checksums |
5797eae2467dbaf10e541daba2b5d64bfa925c2d2fcd21bcdec274bd41f1ab2f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","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}
|
Release files / pydantic_claude_code-0.3.0-py3-none-any.whl
| Download URL | pydantic_claude_code-0.3.0-py3-none-any.whl |
|---|---|
| Size | 16.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
115835b451a24532237b6024dba51825a89b7ed2a04c78547dd0e57e53c9675a
|
|
BLAKE2b-256 checksum How to use checksums |
f082db939d324744d9625d329b92f59f1526b6bdc520e1f7aad39a05ecea0895
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","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}
|