claude-runner
The easiest way to build AI agents with Claude in Python. 5 lines to start.
The official SDK is an engine 🔧 — claude-runner is the car 🚗.
A thin, clean wrapper around the Anthropic SDK. Zero required dependencies.
from claude_runner import Runner
runner = Runner(api_key="sk-ant-...")
result = await runner.run("Analyze this codebase and suggest improvements")
print(result.text)
Also available as a TypeScript/npm package.
Install
# API Mode — no CLI needed, deploys anywhere
pip install claude-runner-py[api]
# Agent Mode — full Claude Code power (needs CLI)
pip install claude-runner-py[agent]
# Everything
pip install claude-runner-py[all]
Quick Start
Simple await
import asyncio
from claude_runner import Runner
async def main():
runner = Runner(api_key="sk-ant-...")
result = await runner.run("Fix the failing tests in this project")
print(result.text)
print(f"Cost: ${result.cost:.4f}")
print(f"Turns: {result.turns}")
asyncio.run(main())
Streaming
async for event in runner.stream("Refactor the auth module"):
match event.type:
case "text":
print(event.text, end="", flush=True)
case "tool_start":
print(f" → {event.tool}")
case "tool_end":
print(f" ← {event.tool} ({event.duration:.0f}ms)")
case "done":
print(f"\nCost: ${event.result.cost:.4f}")
Custom Tools
from claude_runner import Runner, define_tool, ToolResult
async def get_weather(city: str) -> ToolResult:
return ToolResult(content=[{"type": "text", "text": f"72°F and sunny in {city}"}])
weather = define_tool(
"get_weather",
"Get current weather for a city",
{"city": {"type": "string"}},
get_weather,
)
runner = Runner(api_key="sk-ant-...", tools=[weather])
result = await runner.run("What's the weather in San Francisco?")
CLI
# With API key
ANTHROPIC_API_KEY=sk-xxx claude-runner "Analyze this codebase"
claude-runner --api-key sk-xxx "Fix the tests"
# Choose model
claude-runner -m opus "Refactor the auth module"
# JSON output
claude-runner --json "What files are in this project?"
API Mode vs Agent Mode
| API Mode | Agent Mode | |
|---|---|---|
| Requires | API key only | Claude CLI |
| Built-in tools | Bring your own | Read, Write, Bash, Edit |
| Custom tools | define_tool() |
define_tool() |
| Deploys to | Anywhere | Machines with CLI |
| Cost model | Pay-per-token | Claude subscription |
Models
Runner(model="opus") # claude-opus-4-6
Runner(model="sonnet") # claude-sonnet-4-6
Runner(model="haiku") # claude-haiku-4-5
Runner(model="opus-4.5") # claude-opus-4-5-20250918
Runner(model="sonnet-4.5") # claude-sonnet-4-5-20250514
Real-World Use Cases
FastAPI endpoint
@app.post("/chat")
async def chat(message: str):
runner = Runner(api_key=os.environ["ANTHROPIC_API_KEY"])
result = await runner.run(message)
return {"reply": result.text, "cost": result.cost}
Data analysis
runner = Runner(api_key=key, model="haiku")
result = await runner.run(f"Analyze this CSV:\n{csv_data}")
Slack bot
@app.event("message")
async def handle(event):
runner = Runner(api_key=key, tools=[search_docs, query_db])
result = await runner.run(event["text"])
await say(result.text)
Examples
| Example | Description | Run |
|---|---|---|
| Code Reviewer | Reviews codebase for bugs | python examples/code_reviewer.py |
| Chatbot | Chat with custom tools | python examples/chatbot.py |
| FastAPI Agent | REST API endpoint | uvicorn examples.fastapi_agent:app |
API Reference
Runner
class Runner:
def __init__(self, **kwargs) -> None
async def run(self, prompt: str) -> RunResult
async def stream(self, prompt: str) -> AsyncIterator[RunEvent]
@property
def last_session_id(self) -> str | None
RunResult
@dataclass
class RunResult:
text: str
session_id: str
cost: float # USD
duration: float # ms
usage: dict # {"input": N, "output": N}
turns: int
tool_calls: list[ToolCallSummary]
error: str | None
RunEvent types
| Type | Fields | When |
|---|---|---|
text |
text |
Each streamed chunk |
tool_start |
tool, id, input |
Tool begins |
tool_end |
tool, id, duration |
Tool ends |
session_init |
session_id, model, tools |
Session started |
error |
message, code |
Error occurred |
done |
result |
Run complete |
RunnerOptions
| Option | Type | Default | Description |
|---|---|---|---|
api_key |
str |
— | Anthropic API key (enables API Mode) |
model |
str |
sonnet |
Model shorthand or full ID |
system_prompt |
str |
— | System prompt |
tools |
list |
— | Custom tools via define_tool() |
mcp |
dict |
— | MCP servers (shorthand strings supported) |
permissions |
str |
deny-unknown |
auto, prompt, deny-unknown |
max_turns |
int |
50 | Max agentic turns |
max_budget |
float |
— | Max cost in USD |
Links
- TypeScript version: github.com/SanthoshDhandapani/claude-runner
- npm: npmjs.com/package/claude-runner
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
claude_runner_py-0.1.1.tar.gz
(785.5 kB
view details)
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file claude_runner_py-0.1.1.tar.gz.
File metadata
- Download URL: claude_runner_py-0.1.1.tar.gz
- Upload date:
- Size: 785.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.10.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
952332f5701502cf01eae849975d2fd55f7c82b2bb3afe276c41c7af010a31d2
|
|
| MD5 |
e3d2a12485a295a5c194c5e4f282f92f
|
|
| BLAKE2b-256 |
1a31bf0d5b640cd3b7f516b4b97fbb56b2dc1163b75ec98c0b780bebb81a386e
|
File details
Details for the file claude_runner_py-0.1.1-py3-none-any.whl.
File metadata
- Download URL: claude_runner_py-0.1.1-py3-none-any.whl
- Upload date:
- Size: 15.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.10.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7482cce723977d7eddf7379de7cb5e6da7ff73160aabaf84a708cfc81f42ded2
|
|
| MD5 |
b3fdbe10e0e33dfa1a780a9bc094635e
|
|
| BLAKE2b-256 |
0325a4017349a42351b7d8a002acc69fefa985b7088939365c234fa535cefd29
|