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
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' |
| Session resume |
resume: id option |
runner.resume(id) |
| Permissions |
canUseTool callback |
permissions: 'auto' |
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 },
});
Your project is bind-mounted into the container. All tool calls operate inside. Container destroyed on exit.
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"
Session Resume & Multi-Turn
const r1 = await runner.run('Create a test plan');
const r2 = await runner.resume(r1.sessionId, 'Approved. Generate the tests.').result;
Full conversation context preserved across turns.
The Numbers
- ~1,500 lines of source code
-
1 dependency (
@anthropic-ai/claude-agent-sdk) - 34 KB published package size
- 61 tests passing
- MIT license
Install
npm install claude-runner
Requires Claude Code CLI installed and authenticated.
Links
- GitHub: github.com/SanthoshDhandapani/claude-runner
- npm: npmjs.com/package/claude-runner
- Docs: Getting Started
Feedback welcome — issues, PRs, or just tell me what's missing. 🚗


Top comments (0)