Every team building Claude agents writes the same 300 lines of glue code. I got tired of it and built claude-runner — a thin TypeScript wrapper that turns the official Agent SDK into a 5-line experience.
The Problem
The official @anthropic-ai/claude-agent-sdk is powerful but low-level:
-
query()returns an async generator with 20+ message types - MCP server config requires nested objects
- Multi-turn needs manual async iterator coordination
- No sandbox, no permission shortcuts, no CLI
- Requires Claude CLI installed — can't deploy to cloud
Every developer ends up writing the same wrapper. So I published one.
5 Lines to Start
import { Runner } from 'claude-runner';
const runner = new Runner();
const result = await runner.run('Analyze this codebase and suggest improvements');
console.log(result.text);
That's a fully autonomous agent — reads files, runs commands, calls tools, and returns a typed result with cost, tokens, duration, and session ID.
What It Does
| Raw Agent SDK | claude-runner | |
|---|---|---|
| Lines to start | 20+ | 5 |
| Message types | 20+ nested | 7 flat events |
| MCP config | Object only | Shorthand strings |
| Sandbox | Manual spawner | sandbox: 'docker' |
| Cloud deployment | Needs CLI installed | API key only |
| Session resume |
resume: id option |
runner.resume(id) |
| Permissions |
canUseTool callback |
permissions: 'auto' |
NEW: API Mode — Deploy Anywhere
The biggest limitation of the Claude Agent SDK is that it requires the Claude CLI installed. That means no Lambda, no Cloud Run, no serverless.
API Mode fixes this. Just pass an API key — no CLI needed:
const runner = new Runner({
apiKey: process.env.ANTHROPIC_API_KEY,
model: 'sonnet',
});
const result = await runner.run('Summarize this data');
Or from the CLI:
ANTHROPIC_API_KEY=sk-xxx npx claude-runner "Summarize this data"
Agent Mode vs API Mode
| Agent Mode (default) | API Mode | |
|---|---|---|
| Requires | Claude CLI installed | API key only |
| Built-in tools | Read, Write, Bash, Edit | Bring your own |
| Custom tools | defineTool() |
defineTool() |
| Deploys to | Local, CI with CLI | Anywhere |
| Cost model | Claude subscription | Pay-per-token |
API Mode uses the raw Anthropic Messages API with an agentic tool loop — same RunEvent types, same RunResult, same streaming. Just no CLI dependency.
Streaming
for await (const event of runner.stream('Refactor the auth module')) {
switch (event.type) {
case 'text': process.stdout.write(event.text); break;
case 'tool_start': console.log(`> ${event.tool}`); break;
case 'tool_end': console.log(`< ${event.tool} (${event.duration}ms)`); break;
case 'done': console.log(`Cost: $${event.result.cost.toFixed(4)}`); break;
}
}
7 flat event types instead of 20+ nested SDK messages. No parsing, no filtering.
MCP in One Line
const runner = new Runner({
mcp: {
github: 'npx @modelcontextprotocol/server-github',
docs: 'https://api.example.com/mcp',
postgres: {
command: 'npx',
args: ['@modelcontextprotocol/server-postgres'],
env: { PGPASSWORD: process.env.PGPASSWORD },
},
},
});
Shorthand strings, URLs, or full config objects. Tools are auto-discovered.
Docker & E2B Sandbox
// Docker — filesystem isolation
const runner = new Runner({
sandbox: 'docker',
docker: { image: 'node:22-slim' },
permissions: 'auto',
});
// E2B — cloud VM sandbox
const runner = new Runner({
sandbox: 'e2b',
e2b: { apiKey: process.env.E2B_API_KEY },
});
Both validated — Docker on Rancher Desktop, E2B on real cloud VMs.
CLI Included
npx claude-runner "Fix all failing tests"
npx claude-runner -m opus "Refactor the auth module"
npx claude-runner --mcp github="npx @mcp/server-github" "List open issues"
npx claude-runner --api-key sk-xxx "Summarize this data"
Real-World Use Cases
Agent Mode (CLI):
- Code reviewer:
runner.run('Review src/ for bugs') - Test generator: analyze → resume → generate
- CI/CD agent:
npx claude-runner -p auto "Fix failing tests"
API Mode (no CLI):
- SaaS chatbot on Cloud Run
- Lambda function for data analysis
- Slack bot with custom tools
- GitHub webhook for PR reviews
- Content generation API
Install
# Agent Mode — full Claude Code power (needs CLI)
npm install claude-runner
# API Mode — no CLI needed, deploys anywhere
npm install claude-runner @anthropic-ai/sdk
Links
- GitHub: github.com/SanthoshDhandapani/claude-runner
- npm: npmjs.com/package/claude-runner
- Docs: Getting Started | API Mode | Use Cases
Now Available in Python 🐍
Same API, same simplicity — now on PyPI:
pip install claude-runner-py[api]
import asyncio
from claude_runner import Runner
async def main():
runner = Runner(api_key="sk-ant-...")
result = await runner.run("Analyze this codebase")
print(result.text)
asyncio.run(main())
Custom tools work the same way:
from claude_runner import define_tool, ToolResult
async def get_weather(city: str) -> ToolResult:
return ToolResult(content=[{"type": "text", "text": f"72F in {city}"}])
weather = define_tool("get_weather", "Get weather", {"city": {"type": "string"}}, get_weather)
runner = Runner(api_key="sk-ant-...", tools=[weather])
Feedback welcome — issues, PRs, or just tell me what'''s missing. 🚗


Top comments (0)