claude-pool
Slot pool orchestration library for Claude CLI
Overview
claude-pool manages N Claude CLI slots behind a unified interface. A coordinator (typically an interactive Claude session) submits work, and the pool routes tasks by availability, tracks budgets, and handles slot lifecycle and session management.
Perfect for:
- Scaling Claude work across multiple slots
- Budget-aware task distribution
- Parallel and sequential task orchestration
- Slot isolation with optional Git worktrees
Architecture
Coordinator (your app or interactive session)
│
├─ pool.run("task") → synchronous
├─ pool.submit("task") → async, returns task ID
├─ pool.fan_out([tasks]) → parallel execution
└─ execute_chain(steps) → sequential pipeline
│
├── Pool (task queue, context, budget)
│
├── Slot-0 (Claude instance)
├── Slot-1 (Claude instance)
└── Slot-N (Claude instance)
Installation
Requires: claude-wrapper (included as dependency)
Quick Start
use Pool;
use Claude;
async
Core Concepts
Synchronous vs Asynchronous Tasks
Synchronous (blocking):
let result = pool.run.await?;
println!;
Asynchronous (non-blocking):
let task_id = pool.submit.await?;
// Do other work...
let result = pool.result.await??;
Budget Control
Track and limit spending:
let pool = builder
.slots
.config
.build
.await?;
Budget is tracked atomically per task. When the pool reaches its cap, subsequent tasks are rejected.
Slot Identity
Each slot has metadata for coordination:
pool.configure_slot
.await?;
pool.configure_slot
.await?;
Access slot info:
let status = pool.status.await?;
for slot in status.slots
Shared Context
Inject key-value pairs into all slot system prompts:
pool.context_set.await?;
pool.context_set.await?;
pool.context_set.await?;
// All slots now see these in their system prompts
Access context:
let value = pool.context_get.await??;
pool.context_delete.await?;
let all = pool.context_list.await?;
Pool Builder Configuration
use ;
let pool = builder
.slots
.config
.build
.await?;
Available config options:
with_model(name)- Default model for all slotswith_effort(level)- Effort: Min, Low, Medium, High, Maxwith_budget_usd(amount)- Total pool budgetwith_permission_mode(mode)- Permission defaultswith_system_prompt(text)- Base system promptwith_worktree(true)- Enable Git worktree per slot
Execution Patterns
Single Task (Synchronous)
let result = pool.run.await?;
println!;
println!;
Result includes:
output- Claude's responsespend_usd- Cost of this tasktokens_used- Input and output tokens
Async Task Submission
// Submit and get task ID immediately
let task_id = pool.submit.await?;
// Do other work...
// Poll for result later
let result = pool.result.await??;
Parallel Fan-Out
Execute multiple prompts in parallel, all at once:
let prompts = vec!;
let results = pool.fan_out.await?;
for in results.iter.enumerate
All tasks run concurrently. Returns when all complete (or timeout).
Sequential Chains with Failure Policies
Execute steps in order, with control over failures:
use ;
let steps = vec!;
let task_id = pool.submit_chain.await?;
let result = pool.result.await?;
Failure policies:
- retries - Number of retries before failing (default: 0)
- recovery_prompt - Optional prompt to run on failure instead of aborting
Access chain progress:
let progress = pool.chain_result.await?;
for step in progress.steps
Skills Registry
Register reusable task patterns with argument validation:
use ;
let mut registry = new;
registry.register;
Skills can be triggered via the MCP server or called programmatically.
Worktree Isolation
Enable optional Git worktree per slot for safe, isolated execution:
let pool = builder
.slots
.config
.build
.await?;
Each slot gets an isolated worktree:
- Independent filesystem
- Safe for parallel edits
- Cleanup on drain
Benefits:
- Parallel file edits without conflicts
- Isolated git state
- Safe cleanup
Slot Lifecycle
Spawning
Slots are created during build() and remain alive until drain().
Session Resumption
Slots automatically resume sessions if available, reducing startup cost.
Graceful Shutdown
let summary = pool.drain.await?;
println!;
println!;
println!;
All pending tasks are cancelled. Active tasks complete gracefully.
Status & Monitoring
Get current pool state:
let status = pool.status.await?;
println!;
println!;
println!;
println!;
Status includes:
- Slot list with ID, status, and active task count
- Active and pending task counts
- Total spend and budget
- Budget remaining
Error Handling
All operations return Result<T>:
use Error;
match pool.run.await
Common errors:
TaskFailed- Task execution failedBudgetExceeded- Pool exceeded spending capNoSlotsAvailable- All slots busy/offlineTaskNotFound- Invalid task ID
Testing
Requires the claude CLI binary:
License
MIT OR Apache-2.0