claude-codemode


Nameclaude-codemode JSON
Version 0.1.4 PyPI version JSON
download
home_pageNone
SummaryPython implementation of Cloudflare's Code Mode using Claude AI, pydantic-ai, and Anthropic Agent SDK
upload_time2025-10-08 08:43:12
maintainerNone
docs_urlNone
authorClaude Codemode Contributors
requires_python<4.0,>=3.10
licenseMIT
keywords ai claude pydantic-ai code-mode agent anthropic
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Claude Codemode 🚀

A Python implementation of [Cloudflare's Code Mode](https://blog.cloudflare.com/code-mode/), enabling AI agents to write code that calls tools instead of directly invoking them. Built on [pydantic-ai](https://ai.pydantic.dev) and Claude AI.

## What is Claude Code Mode

**Traditional Tool Calling Agents:**

Input → LLM → loop(Tool Call → Execute Tool → Result → LLM) → output

**Claude Code Mode Agent:**

Input → loop(Claude Codes w/ access to your tools) → Execute Code → output

## Why it's better

Each time tool output is passed to the LLM, and output is introduced, it leaves some possibility of mistake. As the number of iterations your agent does *n* increases, the better Code Mode gets compared to traditional iterative tool calling agents.

LLMs are better at generating code files & verifying & running that code they generate than calling tools to create output.

## How It Works

```
┌─────────────────────────────────────────────────────────────────┐
│                         Your Application                        │
│                                                                 │
│  agent = Agent('claude-sonnet-4-5-20250929')                    │
│                                                                 │
│  @agent.tool                                                    │
│  def search_docs(query: str) -> list[database_rows]: ...        │
│                                                                 │
│  @agent.tool                                                    │
│  def analyze_blueprints(file_location: str) -> dict: ...        │
│                                                                 │
│  @agent.tool                                                    │
│  def report_blueprint(pdf_location: str) -> None: ...           │
│                                                                 │
│  result = agent.codemode("verify structural integrity")         │
│             │                                                   │
└─────────────┼───────────────────────────────────────────────────┘
              │
              │ 1. Extract tools from agent
              ▼
┌─────────────────────────────────────────────────────────────────┐
│                      Claude Codemode                            │
│                                                                 │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  2. Generate agentRunner.py with tool definitions        │   │
│  │                                                          │   │
│  │  def search_docs(query: str) -> list[database_rows]:     │   │
│  │      """Search documentation, returns database rows."""  │   │
│  │      "... implementation ..."                            │   │
│  │                                                          │   │
│  │  def analyze_blueprints(file_location: str) -> dict:     │   │
│  │      """Analyze blueprints for issues."""                │   │
│  │      "... implementation ..."                            │   │
│  │                                                          │   │
│  │  def report_blueprint(pdf_location: str) -> None:        │   │
│  │      """Report a blueprint for failing standards."""     │   │
│  │      "... implementation ..."                            │   │
│  │                                                          │   │
│  │  def main(params: str = "verify structural integrity")   │   │
│  │      "TODO: Implement task using above tools"            │   │
│  │      pass                                                │   │
│  └──────────────────────────────────────────────────────────┘   │
│                          │                                      │
└──────────────────────────┼──────────────────────────────────────┘
                           │ 3. Spawn Claude Code
                           ▼
┌─────────────────────────────────────────────────────────────────┐
│                        Claude Code                              │
│                                                                 │
│  Instructions:                                                  │
│  "Implement the main() function to accomplish the task.         │
│   Use the provided tools by writing Python code."               │
│                                                                 │
│  ┌────────────────────────────────────────────────────────┐     │
│  │ Claude reads agentRunner.py                            │     │
│  │ Claude writes implementation:                          │     │
│  │                                                        │     │
│  │ def find_database_files_on_disk(database_row):         │     │
│  │     "Claude wrote this helper function!"               │     │
│  │     return database_row['file'].download().path        │     │
│  │                                                        │     │
│  │ def main():                                            │     │
│  │     "Search docs - returns database rows"              │     │
│  │     database_rows = search_docs("structural integrity")│     │
│  │                                                        │     │
│  │     "Analyze each blueprint and report failures"       │     │
│  │     analyses = []                                      │     │
│  │     for row in database_rows:                          │     │
│  │         file_path = find_database_files_on_disk(row)   │     │
│  │         result = analyze_blueprints(file_path)         │     │
│  │         analyses.append(result)                        │     │
│  │         if not result.passes:                          │     │
│  │             report_blueprint(file_path)                │     │
│  │                                                        │     │
│  │     return {"analyses": analyses}                      │     │
│  └────────────────────────────────────────────────────────┘     │
│                          │                                      │
│                          │ 4. Execute agentRunner.py            │
│                          ▼                                      │
│              ┌────────────────────────┐                         │
│              │  python agentRunner.py │                         │
│              └────────────────────────┘                         │
│                          │                                      │
└──────────────────────────┼──────────────────────────────────────┘
                           │ 5. Return result
                           ▼
┌─────────────────────────────────────────────────────────────────┐
│                      CodeModeResult                             │
│                                                                 │
│  {                                                              │
│    "output": {...},                                             │
│    "success": true,                                             │
│    "execution_log": "..."                                       │
│  }                                                              │
└─────────────────────────────────────────────────────────────────┘
```

### More Specifically Why It's Better

This problem has a lot of elements of what an agent excels at: some ambiguity, needing to integrate pieces together, formatting a nice output.

I tried to also exemplify claude code's ability to figure out how to piece any two pieces of software together on the fly, it figures out here how to grab `database_row['file'].download().path` and puts that in a function. This is something that I feel like is more likely to be figured out by claude code rather than any other way to make a tool that would try to do the same.

As the amount of functions needed to be called by the agents becomes very large, then the amount of advantage that the Code Mode Agent has keeps increasing. The best LLM agents today can call tools in parallel, but it's difficult for them to call > 10 tools in parallel. They can call tools in serially, but after 20 iterations, they lose track of where they are even with a todo list. 

With Code Mode Agent, you can call an essentially unlimited amount of functions provided to you by the original agent definition, without waiting for a ridiculous number of agent iterations because of for serial or parallel limitations of agents.  

## Installation

Install with support for your preferred agent framework:

```bash
# For pydantic-ai support
pip install claude-codemode[pydantic-ai]

# For Claude Agent SDK support
pip install claude-codemode[anthropic-sdk]

# For both
pip install claude-codemode[all]
```

Or install from source:

```bash
git clone https://github.com/ryx2/claude-codemode.git
cd claude-codemode

# Using pip
pip install -e ".[all]"

# Or using poetry (recommended for development)
poetry install --extras pydantic-ai
# Then run examples with: poetry run python examples/basic_example.py
```

### Prerequisites

- Python 3.10+
- [Claude Code](https://claude.com/claude-code) CLI installed
- Anthropic API key set up for Claude Code
- Either `pydantic-ai` or `claude-agent-sdk` (installed via extras above)

## Quick Start

### Basic Usage

```python
from pydantic_ai import Agent
from claude_codemode import codemode

# Create an agent with tools
agent = Agent('claude-sonnet-4-5-20250929')

@agent.tool
def get_weather(city: str) -> str:
    """Get weather for a city."""
    return f"Weather in {city}: Sunny, 72°F"

@agent.tool
def calculate_temp_diff(temp1: str, temp2: str) -> str:
    """Calculate temperature difference."""
    import re
    t1 = int(re.search(r'(\d+)', temp1).group(1))
    t2 = int(re.search(r'(\d+)', temp2).group(1))
    return f"{abs(t1 - t2)}°F"

# Use codemode instead of run
result = codemode(
    agent,
    "Compare weather between San Francisco and New York"
)

print(result.output)
```

### Using the Monkey-Patched Method

```python
from pydantic_ai import Agent
import claude_codemode  # This adds .codemode() to Agent

agent = Agent('claude-sonnet-4-5-20250929')

@agent.tool
def search_docs(query: str) -> str:
    """Search documentation."""
    return f"Results for: {query}"

# Call codemode directly on the agent
result = agent.codemode("Search for authentication docs")
print(result.output)
```

### Using Claude Agent SDK

```python
import asyncio
from claude_agent_sdk import ClaudeSDKClient
import claude_codemode  # This adds .codemode() to ClaudeSDKClient

async def main():
    async with ClaudeSDKClient() as client:
        # Register tools using the codemode extension
        @client.register_codemode_tool
        def search_docs(query: str) -> str:
            """Search documentation."""
            return f"Results for: {query}"

        @client.register_codemode_tool
        def analyze_code(code: str) -> dict:
            """Analyze code for issues."""
            return {"issues": [], "quality": "good"}

        # Use codemode
        result = await client.codemode(
            "Search for authentication docs and analyze the examples"
        )
        print(result.output)

asyncio.run(main())
```

### With Configuration

```python
from claude_codemode import codemode, CodeModeConfig

config = CodeModeConfig(
    verbose=True,              # Print detailed logs
    preserve_workspace=True,   # Keep workspace for inspection
    timeout=300,               # 5 minute timeout
    workspace_dir="/tmp/my-workspace"  # Custom workspace location
)

result = codemode(agent, "Your complex task here", config=config)
```

## Architecture

### Components

```
claude_codemode/
├── core.py          # Main CodeMode class and codemode() function
├── converter.py     # Extracts and converts pydantic-ai tools
├── template.py      # Generates agentRunner.py templates
├── runner.py        # Manages Claude Code subprocess
└── types.py         # Type definitions
```

### Flow Diagram

```
User Code → Extract Tools → Generate Template → Spawn Claude Code → Execute → Return Result
    ↓           ↓                ↓                    ↓              ↓           ↓
  Agent    ToolConverter   TemplateGenerator   ClaudeCodeRunner  agentRunner.py CodeModeResult
```

## Advanced Examples

### With Dependencies

```python
from dataclasses import dataclass
from pydantic_ai import Agent, RunContext

@dataclass
class DatabaseContext:
    connection_string: str

agent = Agent('claude-sonnet-4-5-20250929', deps_type=DatabaseContext)

@agent.tool
def query_db(ctx: RunContext[DatabaseContext], sql: str) -> list:
    """Execute database query."""
    # Use ctx.deps.connection_string
    return [{"id": 1, "name": "Alice"}]

deps = DatabaseContext("postgresql://localhost/mydb")
result = codemode(agent, "Get all users from database", deps=deps)
```

### Complex Multi-Step Tasks

```python
agent = Agent('claude-sonnet-4-5-20250929')

@agent.tool
def fetch_data(source: str) -> dict:
    """Fetch data from source."""
    pass

@agent.tool
def transform_data(data: dict, rules: list) -> dict:
    """Transform data according to rules."""
    pass

@agent.tool
def validate_data(data: dict) -> bool:
    """Validate transformed data."""
    pass

@agent.tool
def store_data(data: dict, destination: str) -> bool:
    """Store data to destination."""
    pass

# Code Mode handles the complex orchestration
result = codemode(
    agent,
    """
    Create an ETL pipeline:
    1. Fetch data from 'api_source'
    2. Transform using rules: ['normalize', 'deduplicate']
    3. Validate the transformed data
    4. If valid, store to 'warehouse'
    5. Return success status and record count
    """
)
```

## API Reference

### `codemode(agent, prompt, deps=None, config=None)`

Execute an agent in code mode.

**Parameters:**
- `agent` (Agent): The pydantic-ai agent with tools
- `prompt` (str): Task description for Claude
- `deps` (Any, optional): Dependencies for the agent
- `config` (CodeModeConfig, optional): Configuration options

**Returns:**
- `CodeModeResult`: Result object with output, success status, and logs

### `CodeModeConfig`

Configuration for codemode execution.

```python
@dataclass
class CodeModeConfig:
    workspace_dir: Optional[str] = None       # Custom workspace directory
    claude_code_path: str = "claude"          # Path to Claude Code CLI
    timeout: int = 300                        # Execution timeout in seconds
    verbose: bool = False                     # Enable detailed logging
    preserve_workspace: bool = False          # Keep workspace after execution
```

### `CodeModeResult`

Result from codemode execution.

```python
@dataclass
class CodeModeResult:
    output: Any                # The result from the agent
    execution_log: str         # Complete execution logs
    success: bool              # Whether execution succeeded
    error: Optional[str] = None  # Error message if failed
```

## Comparison: Traditional vs Code Mode

### Traditional Tool Calling

```python
# Agent directly calls tools
result = agent.run("Compare weather in SF and NY")

# Behind the scenes:
# 1. LLM decides to call get_weather("San Francisco")
# 2. LLM decides to call get_weather("New York")
# 3. LLM decides to call calculate_difference(...)
# Limited by tool calling training data
```

### Code Mode

```python
# Agent writes code that calls tools
result = agent.codemode("Compare weather in SF and NY")

# Behind the scenes:
# 1. Claude sees available tools as Python functions
# 2. Claude writes: sf_weather = get_weather("San Francisco")
# 3. Claude writes: ny_weather = get_weather("New York")
# 4. Claude writes: diff = calculate_difference(sf_weather, ny_weather)
# Leverages extensive Python training data
```

## Benefits

### 🎯 Better Tool Usage
Claude is trained on millions of Python examples and knows how to compose functions naturally.

### 🔄 Complex Workflows
Multi-step tasks with conditionals, loops, and error handling become trivial.

### 🐛 Easier Debugging
Generated Python code can be inspected, modified, and tested independently.

### 🚀 More Reliable
Reduces errors from unfamiliar tool-calling formats.

### 💡 Flexible
Claude can use Python's full capabilities (data structures, libraries, etc.)

## Examples

See the `examples/` directory for complete examples:

- [`basic_example.py`](examples/basic_example.py) - Simple weather comparison with pydantic-ai
- [`advanced_example.py`](examples/advanced_example.py) - Complex ETL with dependencies
- [`monkey_patch_example.py`](examples/monkey_patch_example.py) - Using `agent.codemode()` method
- [`claude_sdk_example.py`](examples/claude_sdk_example.py) - Using Claude Agent SDK with codemode

Run an example:

```bash
cd examples
python basic_example.py
# or for Claude SDK
python claude_sdk_example.py
```

## Limitations

- Requires Claude Code CLI to be installed
- Spawns a subprocess for each codemode execution
- Tools must be serializable to Python source code
- Currently only supports Python tools (not TypeScript like Cloudflare's version)

## Contributing

Contributions welcome! Please feel free to submit a Pull Request.

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

## License

MIT License - see [LICENSE](LICENSE) file for details.


## Inspirations

- [Cloudflare's blog post](https://blog.cloudflare.com/code-mode/) introducing the code mode concept
- [Theo's t3 chat video](https://youtu.be/bAYZjVAodoo?si=ouW-gfrrBsaz5LSj) for making me aware of this approach
- [Early MCP implementation](https://github.com/jx-codes/codemode-mcp) by jx-codes

## Acknowledgments

- Inspired by [Cloudflare's Code Mode](https://blog.cloudflare.com/code-mode/)
- Built on [pydantic-ai](https://ai.pydantic.dev)
- Powered by [Claude AI](https://claude.ai)

## Related Projects

- [pydantic-ai](https://github.com/pydantic/pydantic-ai) - Data validation using Python type hints
- [Claude Code](https://claude.com/claude-code) - Official Claude CLI
- [Anthropic Agent SDK](https://docs.claude.com/en/api/agent-sdk/python) - Agent development framework

---

Made with ❤️ by the Claude Codemode Contributors

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "claude-codemode",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<4.0,>=3.10",
    "maintainer_email": null,
    "keywords": "ai, claude, pydantic-ai, code-mode, agent, anthropic",
    "author": "Claude Codemode Contributors",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/be/9d/d03a95babe32ff8067913d96d61001b5c4e6f6424bc2f3ccaef09d5b679a/claude_codemode-0.1.4.tar.gz",
    "platform": null,
    "description": "# Claude Codemode \ud83d\ude80\n\nA Python implementation of [Cloudflare's Code Mode](https://blog.cloudflare.com/code-mode/), enabling AI agents to write code that calls tools instead of directly invoking them. Built on [pydantic-ai](https://ai.pydantic.dev) and Claude AI.\n\n## What is Claude Code Mode\n\n**Traditional Tool Calling Agents:**\n\nInput \u2192 LLM \u2192 loop(Tool Call \u2192 Execute Tool \u2192 Result \u2192 LLM) \u2192 output\n\n**Claude Code Mode Agent:**\n\nInput \u2192 loop(Claude Codes w/ access to your tools) \u2192 Execute Code \u2192 output\n\n## Why it's better\n\nEach time tool output is passed to the LLM, and output is introduced, it leaves some possibility of mistake. As the number of iterations your agent does *n* increases, the better Code Mode gets compared to traditional iterative tool calling agents.\n\nLLMs are better at generating code files & verifying & running that code they generate than calling tools to create output.\n\n## How It Works\n\n```\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502                         Your Application                        \u2502\n\u2502                                                                 \u2502\n\u2502  agent = Agent('claude-sonnet-4-5-20250929')                    \u2502\n\u2502                                                                 \u2502\n\u2502  @agent.tool                                                    \u2502\n\u2502  def search_docs(query: str) -> list[database_rows]: ...        \u2502\n\u2502                                                                 \u2502\n\u2502  @agent.tool                                                    \u2502\n\u2502  def analyze_blueprints(file_location: str) -> dict: ...        \u2502\n\u2502                                                                 \u2502\n\u2502  @agent.tool                                                    \u2502\n\u2502  def report_blueprint(pdf_location: str) -> None: ...           \u2502\n\u2502                                                                 \u2502\n\u2502  result = agent.codemode(\"verify structural integrity\")         \u2502\n\u2502             \u2502                                                   \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n              \u2502\n              \u2502 1. Extract tools from agent\n              \u25bc\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502                      Claude Codemode                            \u2502\n\u2502                                                                 \u2502\n\u2502  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510   \u2502\n\u2502  \u2502  2. Generate agentRunner.py with tool definitions        \u2502   \u2502\n\u2502  \u2502                                                          \u2502   \u2502\n\u2502  \u2502  def search_docs(query: str) -> list[database_rows]:     \u2502   \u2502\n\u2502  \u2502      \"\"\"Search documentation, returns database rows.\"\"\"  \u2502   \u2502\n\u2502  \u2502      \"... implementation ...\"                            \u2502   \u2502\n\u2502  \u2502                                                          \u2502   \u2502\n\u2502  \u2502  def analyze_blueprints(file_location: str) -> dict:     \u2502   \u2502\n\u2502  \u2502      \"\"\"Analyze blueprints for issues.\"\"\"                \u2502   \u2502\n\u2502  \u2502      \"... implementation ...\"                            \u2502   \u2502\n\u2502  \u2502                                                          \u2502   \u2502\n\u2502  \u2502  def report_blueprint(pdf_location: str) -> None:        \u2502   \u2502\n\u2502  \u2502      \"\"\"Report a blueprint for failing standards.\"\"\"     \u2502   \u2502\n\u2502  \u2502      \"... implementation ...\"                            \u2502   \u2502\n\u2502  \u2502                                                          \u2502   \u2502\n\u2502  \u2502  def main(params: str = \"verify structural integrity\")   \u2502   \u2502\n\u2502  \u2502      \"TODO: Implement task using above tools\"            \u2502   \u2502\n\u2502  \u2502      pass                                                \u2502   \u2502\n\u2502  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518   \u2502\n\u2502                          \u2502                                      \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n                           \u2502 3. Spawn Claude Code\n                           \u25bc\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502                        Claude Code                              \u2502\n\u2502                                                                 \u2502\n\u2502  Instructions:                                                  \u2502\n\u2502  \"Implement the main() function to accomplish the task.         \u2502\n\u2502   Use the provided tools by writing Python code.\"               \u2502\n\u2502                                                                 \u2502\n\u2502  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510     \u2502\n\u2502  \u2502 Claude reads agentRunner.py                            \u2502     \u2502\n\u2502  \u2502 Claude writes implementation:                          \u2502     \u2502\n\u2502  \u2502                                                        \u2502     \u2502\n\u2502  \u2502 def find_database_files_on_disk(database_row):         \u2502     \u2502\n\u2502  \u2502     \"Claude wrote this helper function!\"               \u2502     \u2502\n\u2502  \u2502     return database_row['file'].download().path        \u2502     \u2502\n\u2502  \u2502                                                        \u2502     \u2502\n\u2502  \u2502 def main():                                            \u2502     \u2502\n\u2502  \u2502     \"Search docs - returns database rows\"              \u2502     \u2502\n\u2502  \u2502     database_rows = search_docs(\"structural integrity\")\u2502     \u2502\n\u2502  \u2502                                                        \u2502     \u2502\n\u2502  \u2502     \"Analyze each blueprint and report failures\"       \u2502     \u2502\n\u2502  \u2502     analyses = []                                      \u2502     \u2502\n\u2502  \u2502     for row in database_rows:                          \u2502     \u2502\n\u2502  \u2502         file_path = find_database_files_on_disk(row)   \u2502     \u2502\n\u2502  \u2502         result = analyze_blueprints(file_path)         \u2502     \u2502\n\u2502  \u2502         analyses.append(result)                        \u2502     \u2502\n\u2502  \u2502         if not result.passes:                          \u2502     \u2502\n\u2502  \u2502             report_blueprint(file_path)                \u2502     \u2502\n\u2502  \u2502                                                        \u2502     \u2502\n\u2502  \u2502     return {\"analyses\": analyses}                      \u2502     \u2502\n\u2502  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518     \u2502\n\u2502                          \u2502                                      \u2502\n\u2502                          \u2502 4. Execute agentRunner.py            \u2502\n\u2502                          \u25bc                                      \u2502\n\u2502              \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510                         \u2502\n\u2502              \u2502  python agentRunner.py \u2502                         \u2502\n\u2502              \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518                         \u2502\n\u2502                          \u2502                                      \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n                           \u2502 5. Return result\n                           \u25bc\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502                      CodeModeResult                             \u2502\n\u2502                                                                 \u2502\n\u2502  {                                                              \u2502\n\u2502    \"output\": {...},                                             \u2502\n\u2502    \"success\": true,                                             \u2502\n\u2502    \"execution_log\": \"...\"                                       \u2502\n\u2502  }                                                              \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\n### More Specifically Why It's Better\n\nThis problem has a lot of elements of what an agent excels at: some ambiguity, needing to integrate pieces together, formatting a nice output.\n\nI tried to also exemplify claude code's ability to figure out how to piece any two pieces of software together on the fly, it figures out here how to grab `database_row['file'].download().path` and puts that in a function. This is something that I feel like is more likely to be figured out by claude code rather than any other way to make a tool that would try to do the same.\n\nAs the amount of functions needed to be called by the agents becomes very large, then the amount of advantage that the Code Mode Agent has keeps increasing. The best LLM agents today can call tools in parallel, but it's difficult for them to call > 10 tools in parallel. They can call tools in serially, but after 20 iterations, they lose track of where they are even with a todo list. \n\nWith Code Mode Agent, you can call an essentially unlimited amount of functions provided to you by the original agent definition, without waiting for a ridiculous number of agent iterations because of for serial or parallel limitations of agents.  \n\n## Installation\n\nInstall with support for your preferred agent framework:\n\n```bash\n# For pydantic-ai support\npip install claude-codemode[pydantic-ai]\n\n# For Claude Agent SDK support\npip install claude-codemode[anthropic-sdk]\n\n# For both\npip install claude-codemode[all]\n```\n\nOr install from source:\n\n```bash\ngit clone https://github.com/ryx2/claude-codemode.git\ncd claude-codemode\n\n# Using pip\npip install -e \".[all]\"\n\n# Or using poetry (recommended for development)\npoetry install --extras pydantic-ai\n# Then run examples with: poetry run python examples/basic_example.py\n```\n\n### Prerequisites\n\n- Python 3.10+\n- [Claude Code](https://claude.com/claude-code) CLI installed\n- Anthropic API key set up for Claude Code\n- Either `pydantic-ai` or `claude-agent-sdk` (installed via extras above)\n\n## Quick Start\n\n### Basic Usage\n\n```python\nfrom pydantic_ai import Agent\nfrom claude_codemode import codemode\n\n# Create an agent with tools\nagent = Agent('claude-sonnet-4-5-20250929')\n\n@agent.tool\ndef get_weather(city: str) -> str:\n    \"\"\"Get weather for a city.\"\"\"\n    return f\"Weather in {city}: Sunny, 72\u00b0F\"\n\n@agent.tool\ndef calculate_temp_diff(temp1: str, temp2: str) -> str:\n    \"\"\"Calculate temperature difference.\"\"\"\n    import re\n    t1 = int(re.search(r'(\\d+)', temp1).group(1))\n    t2 = int(re.search(r'(\\d+)', temp2).group(1))\n    return f\"{abs(t1 - t2)}\u00b0F\"\n\n# Use codemode instead of run\nresult = codemode(\n    agent,\n    \"Compare weather between San Francisco and New York\"\n)\n\nprint(result.output)\n```\n\n### Using the Monkey-Patched Method\n\n```python\nfrom pydantic_ai import Agent\nimport claude_codemode  # This adds .codemode() to Agent\n\nagent = Agent('claude-sonnet-4-5-20250929')\n\n@agent.tool\ndef search_docs(query: str) -> str:\n    \"\"\"Search documentation.\"\"\"\n    return f\"Results for: {query}\"\n\n# Call codemode directly on the agent\nresult = agent.codemode(\"Search for authentication docs\")\nprint(result.output)\n```\n\n### Using Claude Agent SDK\n\n```python\nimport asyncio\nfrom claude_agent_sdk import ClaudeSDKClient\nimport claude_codemode  # This adds .codemode() to ClaudeSDKClient\n\nasync def main():\n    async with ClaudeSDKClient() as client:\n        # Register tools using the codemode extension\n        @client.register_codemode_tool\n        def search_docs(query: str) -> str:\n            \"\"\"Search documentation.\"\"\"\n            return f\"Results for: {query}\"\n\n        @client.register_codemode_tool\n        def analyze_code(code: str) -> dict:\n            \"\"\"Analyze code for issues.\"\"\"\n            return {\"issues\": [], \"quality\": \"good\"}\n\n        # Use codemode\n        result = await client.codemode(\n            \"Search for authentication docs and analyze the examples\"\n        )\n        print(result.output)\n\nasyncio.run(main())\n```\n\n### With Configuration\n\n```python\nfrom claude_codemode import codemode, CodeModeConfig\n\nconfig = CodeModeConfig(\n    verbose=True,              # Print detailed logs\n    preserve_workspace=True,   # Keep workspace for inspection\n    timeout=300,               # 5 minute timeout\n    workspace_dir=\"/tmp/my-workspace\"  # Custom workspace location\n)\n\nresult = codemode(agent, \"Your complex task here\", config=config)\n```\n\n## Architecture\n\n### Components\n\n```\nclaude_codemode/\n\u251c\u2500\u2500 core.py          # Main CodeMode class and codemode() function\n\u251c\u2500\u2500 converter.py     # Extracts and converts pydantic-ai tools\n\u251c\u2500\u2500 template.py      # Generates agentRunner.py templates\n\u251c\u2500\u2500 runner.py        # Manages Claude Code subprocess\n\u2514\u2500\u2500 types.py         # Type definitions\n```\n\n### Flow Diagram\n\n```\nUser Code \u2192 Extract Tools \u2192 Generate Template \u2192 Spawn Claude Code \u2192 Execute \u2192 Return Result\n    \u2193           \u2193                \u2193                    \u2193              \u2193           \u2193\n  Agent    ToolConverter   TemplateGenerator   ClaudeCodeRunner  agentRunner.py CodeModeResult\n```\n\n## Advanced Examples\n\n### With Dependencies\n\n```python\nfrom dataclasses import dataclass\nfrom pydantic_ai import Agent, RunContext\n\n@dataclass\nclass DatabaseContext:\n    connection_string: str\n\nagent = Agent('claude-sonnet-4-5-20250929', deps_type=DatabaseContext)\n\n@agent.tool\ndef query_db(ctx: RunContext[DatabaseContext], sql: str) -> list:\n    \"\"\"Execute database query.\"\"\"\n    # Use ctx.deps.connection_string\n    return [{\"id\": 1, \"name\": \"Alice\"}]\n\ndeps = DatabaseContext(\"postgresql://localhost/mydb\")\nresult = codemode(agent, \"Get all users from database\", deps=deps)\n```\n\n### Complex Multi-Step Tasks\n\n```python\nagent = Agent('claude-sonnet-4-5-20250929')\n\n@agent.tool\ndef fetch_data(source: str) -> dict:\n    \"\"\"Fetch data from source.\"\"\"\n    pass\n\n@agent.tool\ndef transform_data(data: dict, rules: list) -> dict:\n    \"\"\"Transform data according to rules.\"\"\"\n    pass\n\n@agent.tool\ndef validate_data(data: dict) -> bool:\n    \"\"\"Validate transformed data.\"\"\"\n    pass\n\n@agent.tool\ndef store_data(data: dict, destination: str) -> bool:\n    \"\"\"Store data to destination.\"\"\"\n    pass\n\n# Code Mode handles the complex orchestration\nresult = codemode(\n    agent,\n    \"\"\"\n    Create an ETL pipeline:\n    1. Fetch data from 'api_source'\n    2. Transform using rules: ['normalize', 'deduplicate']\n    3. Validate the transformed data\n    4. If valid, store to 'warehouse'\n    5. Return success status and record count\n    \"\"\"\n)\n```\n\n## API Reference\n\n### `codemode(agent, prompt, deps=None, config=None)`\n\nExecute an agent in code mode.\n\n**Parameters:**\n- `agent` (Agent): The pydantic-ai agent with tools\n- `prompt` (str): Task description for Claude\n- `deps` (Any, optional): Dependencies for the agent\n- `config` (CodeModeConfig, optional): Configuration options\n\n**Returns:**\n- `CodeModeResult`: Result object with output, success status, and logs\n\n### `CodeModeConfig`\n\nConfiguration for codemode execution.\n\n```python\n@dataclass\nclass CodeModeConfig:\n    workspace_dir: Optional[str] = None       # Custom workspace directory\n    claude_code_path: str = \"claude\"          # Path to Claude Code CLI\n    timeout: int = 300                        # Execution timeout in seconds\n    verbose: bool = False                     # Enable detailed logging\n    preserve_workspace: bool = False          # Keep workspace after execution\n```\n\n### `CodeModeResult`\n\nResult from codemode execution.\n\n```python\n@dataclass\nclass CodeModeResult:\n    output: Any                # The result from the agent\n    execution_log: str         # Complete execution logs\n    success: bool              # Whether execution succeeded\n    error: Optional[str] = None  # Error message if failed\n```\n\n## Comparison: Traditional vs Code Mode\n\n### Traditional Tool Calling\n\n```python\n# Agent directly calls tools\nresult = agent.run(\"Compare weather in SF and NY\")\n\n# Behind the scenes:\n# 1. LLM decides to call get_weather(\"San Francisco\")\n# 2. LLM decides to call get_weather(\"New York\")\n# 3. LLM decides to call calculate_difference(...)\n# Limited by tool calling training data\n```\n\n### Code Mode\n\n```python\n# Agent writes code that calls tools\nresult = agent.codemode(\"Compare weather in SF and NY\")\n\n# Behind the scenes:\n# 1. Claude sees available tools as Python functions\n# 2. Claude writes: sf_weather = get_weather(\"San Francisco\")\n# 3. Claude writes: ny_weather = get_weather(\"New York\")\n# 4. Claude writes: diff = calculate_difference(sf_weather, ny_weather)\n# Leverages extensive Python training data\n```\n\n## Benefits\n\n### \ud83c\udfaf Better Tool Usage\nClaude is trained on millions of Python examples and knows how to compose functions naturally.\n\n### \ud83d\udd04 Complex Workflows\nMulti-step tasks with conditionals, loops, and error handling become trivial.\n\n### \ud83d\udc1b Easier Debugging\nGenerated Python code can be inspected, modified, and tested independently.\n\n### \ud83d\ude80 More Reliable\nReduces errors from unfamiliar tool-calling formats.\n\n### \ud83d\udca1 Flexible\nClaude can use Python's full capabilities (data structures, libraries, etc.)\n\n## Examples\n\nSee the `examples/` directory for complete examples:\n\n- [`basic_example.py`](examples/basic_example.py) - Simple weather comparison with pydantic-ai\n- [`advanced_example.py`](examples/advanced_example.py) - Complex ETL with dependencies\n- [`monkey_patch_example.py`](examples/monkey_patch_example.py) - Using `agent.codemode()` method\n- [`claude_sdk_example.py`](examples/claude_sdk_example.py) - Using Claude Agent SDK with codemode\n\nRun an example:\n\n```bash\ncd examples\npython basic_example.py\n# or for Claude SDK\npython claude_sdk_example.py\n```\n\n## Limitations\n\n- Requires Claude Code CLI to be installed\n- Spawns a subprocess for each codemode execution\n- Tools must be serializable to Python source code\n- Currently only supports Python tools (not TypeScript like Cloudflare's version)\n\n## Contributing\n\nContributions welcome! Please feel free to submit a Pull Request.\n\n1. Fork the repository\n2. Create your feature branch (`git checkout -b feature/amazing-feature`)\n3. Commit your changes (`git commit -m 'Add amazing feature'`)\n4. Push to the branch (`git push origin feature/amazing-feature`)\n5. Open a Pull Request\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n\n\n## Inspirations\n\n- [Cloudflare's blog post](https://blog.cloudflare.com/code-mode/) introducing the code mode concept\n- [Theo's t3 chat video](https://youtu.be/bAYZjVAodoo?si=ouW-gfrrBsaz5LSj) for making me aware of this approach\n- [Early MCP implementation](https://github.com/jx-codes/codemode-mcp) by jx-codes\n\n## Acknowledgments\n\n- Inspired by [Cloudflare's Code Mode](https://blog.cloudflare.com/code-mode/)\n- Built on [pydantic-ai](https://ai.pydantic.dev)\n- Powered by [Claude AI](https://claude.ai)\n\n## Related Projects\n\n- [pydantic-ai](https://github.com/pydantic/pydantic-ai) - Data validation using Python type hints\n- [Claude Code](https://claude.com/claude-code) - Official Claude CLI\n- [Anthropic Agent SDK](https://docs.claude.com/en/api/agent-sdk/python) - Agent development framework\n\n---\n\nMade with \u2764\ufe0f by the Claude Codemode Contributors\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Python implementation of Cloudflare's Code Mode using Claude AI, pydantic-ai, and Anthropic Agent SDK",
    "version": "0.1.4",
    "project_urls": {
        "Documentation": "https://github.com/ryx2/claude-codemode#readme",
        "Homepage": "https://github.com/ryx2/claude-codemode",
        "Repository": "https://github.com/ryx2/claude-codemode"
    },
    "split_keywords": [
        "ai",
        " claude",
        " pydantic-ai",
        " code-mode",
        " agent",
        " anthropic"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "2f07ff1622e6de83f51c934e63c2cdaa71f89d54357c1fc21c67302a9f09bd85",
                "md5": "170028a455cb78c9c6271410d0ac9a74",
                "sha256": "6092709255181c44d925d7b038659b087990dd8b6494a66bc45958dde219d879"
            },
            "downloads": -1,
            "filename": "claude_codemode-0.1.4-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "170028a455cb78c9c6271410d0ac9a74",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<4.0,>=3.10",
            "size": 16305,
            "upload_time": "2025-10-08T08:43:11",
            "upload_time_iso_8601": "2025-10-08T08:43:11.124146Z",
            "url": "https://files.pythonhosted.org/packages/2f/07/ff1622e6de83f51c934e63c2cdaa71f89d54357c1fc21c67302a9f09bd85/claude_codemode-0.1.4-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "be9dd03a95babe32ff8067913d96d61001b5c4e6f6424bc2f3ccaef09d5b679a",
                "md5": "23896795827c4111120ceec8524e9afe",
                "sha256": "01ac7bfd7df29901390cf1b04cf0e4bcb691e17d93e11ae1625c3fdccb4e4c47"
            },
            "downloads": -1,
            "filename": "claude_codemode-0.1.4.tar.gz",
            "has_sig": false,
            "md5_digest": "23896795827c4111120ceec8524e9afe",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4.0,>=3.10",
            "size": 19681,
            "upload_time": "2025-10-08T08:43:12",
            "upload_time_iso_8601": "2025-10-08T08:43:12.141622Z",
            "url": "https://files.pythonhosted.org/packages/be/9d/d03a95babe32ff8067913d96d61001b5c4e6f6424bc2f3ccaef09d5b679a/claude_codemode-0.1.4.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-08 08:43:12",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "ryx2",
    "github_project": "claude-codemode#readme",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "claude-codemode"
}
        
Elapsed time: 2.83831s