An open, self-hosted alternative to Cowork — run multiple concurrent Claude agent conversations with automatic lifecycle management, accessible from any interface you build.
Cowork is Anthropic's desktop product that brings Claude Code's agentic architecture to knowledge work. It runs autonomous multi-step tasks, coordinates parallel workstreams, reads and writes your local files, executes code in a sandboxed VM, schedules recurring tasks, and organizes everything into persistent projects — all from the Claude Desktop app.
claude-pool and claude-socket give you a similar foundation, but self-hosted and extensible. You get the same multi-conversation agent runtime, but you control the interface, the communication layer, and what the agents can connect to.
graph LR
B1[Your UI] <-->|WebSocket| CS1[claude-socket]
B2[Mobile App] <-->|WebSocket| CS2[claude-socket]
B3[Another Agent] <-->|WebSocket| CS3[claude-socket]
subgraph "claude-pool (your machine)"
CS1 <-->|MCP| S1[Conversation 1]
CS2 <-->|MCP| S2[Conversation 2]
CS3 <-->|MCP| S3[Conversation 3]
end
style B1 fill:#1a1a2e,stroke:#06b6d4,color:#e5e5e5
style B2 fill:#1a1a2e,stroke:#06b6d4,color:#e5e5e5
style B3 fill:#1a1a2e,stroke:#06b6d4,color:#e5e5e5
style CS1 fill:#1a1a2e,stroke:#7c3aed,color:#e5e5e5
style CS2 fill:#1a1a2e,stroke:#7c3aed,color:#e5e5e5
style CS3 fill:#1a1a2e,stroke:#7c3aed,color:#e5e5e5
style S1 fill:#1a1a2e,stroke:#06b6d4,color:#e5e5e5
style S2 fill:#1a1a2e,stroke:#06b6d4,color:#e5e5e5
style S3 fill:#1a1a2e,stroke:#06b6d4,color:#e5e5e5
claude-socket is the communication layer. It's a WebSocket bridge that lets anything connect to a Claude Code session — browsers, mobile apps, bots, other agents. The WebSocket is persistent and bidirectional, so it supports long-running conversations and can carry any kind of data, including messages from other agents.
claude-pool is the runtime layer. It manages multiple concurrent Claude Code agent processes, spinning them up on demand, idling them down when nobody's using them, and resuming them with full history when someone comes back. You're not locked into one conversation at a time, and you're not wasting resources on idle sessions.
Together they give you:
- Multiple concurrent agent conversations — each with its own context, each accessible from whatever interface you want
- Smart resource management — sessions spin up when needed, shut down when idle, and resume where they left off
- Extensible communication — because it's WebSocket, not a proprietary UI, you control the interface. Build a web dashboard, connect a Discord bot, pipe in data from other systems, or have agents talk to each other
- General-purpose agent hosting — Claude Code is the runtime, but the agents can be anything. A customer support bot, a devops assistant, a research agent, a home automation supervisor — claude-pool doesn't care what the agent does, it just manages the process. Bring your own CLAUDE.md, skills, MCP servers, and plugins to define what each agent is
- ToS compliance — everything runs through Claude Code's official MCP channel and plugin system. No API key workarounds, no harness replacement. If you were using OpenClaw before Anthropic shut that down, this is how you get that flexibility back within the rules
claude-pool wraps each Claude Code instance in a managed process with idle detection, crash recovery, and resume support. Think of it like a process pool for Claude Code sessions — serverless Claude on your own machine.
graph TD
CP[claude-pool]
CP --> S1[Session: junior]
CP --> S2[Session: project-a]
CP --> S3[Session: debug]
S1 -->|PTY| C1[claude --name junior]
S2 -->|PTY| C2[claude --name project-a]
S3 -->|PTY| C3[claude --name debug]
style CP fill:#1a1a2e,stroke:#7c3aed,color:#e5e5e5
style S1 fill:#1a1a2e,stroke:#7c3aed,color:#e5e5e5
style S2 fill:#1a1a2e,stroke:#7c3aed,color:#e5e5e5
style S3 fill:#1a1a2e,stroke:#7c3aed,color:#e5e5e5
style C1 fill:#1a1a2e,stroke:#06b6d4,color:#e5e5e5
style C2 fill:#1a1a2e,stroke:#06b6d4,color:#e5e5e5
style C3 fill:#1a1a2e,stroke:#06b6d4,color:#e5e5e5
- Multiple concurrent sessions from one manager
- Idle timeout — sessions automatically shut down after configurable inactivity
- Keep warm — designate primary sessions that never idle out
- Crash recovery — auto-restart crashed sessions (up to 3x in 5 minutes)
- Resume — stopped sessions pick up where they left off via
claude --resume - State persistence — session registry survives pool restarts
- Management API — REST + WebSocket for programmatic control
git clone https://github.com/cunicopia-dev/claude-pool.git
cd claude-pool
bun installStart the pool:
bun run startclaude-pool v0.1.0 | port 3200 | max 5 sessions
In another terminal, spawn a session:
bun run src/cli.ts spawn --name my-sessionCheck status:
bun run src/cli.ts statusclaude-pool | status: ok | uptime: 45s | active: 1/5 | mem: 50MB
ID Name Status PID Idle Time Keep Warm
-----------------------------------------------------------------------------------
3e8e89b8 my-session running 12345 10s no
docker compose up -dThis mounts your Claude Code credentials (~/.claude/.credentials.json) read-only into the container. The pool manager, Bun, and Claude Code CLI all run inside the container. Session state persists in a Docker volume.
The container runs as a non-root user (claude refuses --dangerously-skip-permissions as root). Your credentials are mounted read-only — the container never writes to them.
To run without compose:
docker build -t claude-pool .
docker run -d \
-v ~/.claude/.credentials.json:/home/claude-pool/.claude/.credentials.json:ro \
-v ~/.claude/settings.json:/home/claude-pool/.claude/settings.json:ro \
-v ./pool.config.json:/app/pool.config.json:ro \
-p 3200:3200 \
claude-poolCreate a pool.config.json in the working directory or at ~/.config/claude-pool/config.json:
{
"maxSessions": 5,
"idleTimeoutMinutes": 30,
"apiPort": 3200,
"primarySession": {
"name": "junior",
"keepWarm": true,
"channels": ["plugin:discord@claude-plugins-official"],
"developmentChannels": ["plugin:web@my-plugin"],
"pluginDirs": [],
"workingDirectory": "/home/user",
"dangerouslySkipPermissions": true
},
"defaults": {
"channels": [],
"developmentChannels": [],
"pluginDirs": [],
"dangerouslySkipPermissions": false,
"workingDirectory": "/home/user"
},
"claudePath": "claude",
"logLevel": "info"
}| Field | Default | Description |
|---|---|---|
maxSessions |
5 |
Maximum concurrent sessions |
idleTimeoutMinutes |
30 |
Kill sessions after this many minutes of inactivity |
apiPort |
3200 |
Management API port |
primarySession |
— | Auto-spawned session on pool start |
primarySession.keepWarm |
false |
Skip idle timeout for this session |
defaults |
— | Default config applied to all new sessions |
claudePath |
"claude" |
Path to the Claude Code binary |
logLevel |
"info" |
Log verbosity: debug, info, warn, error |
| Command | Description |
|---|---|
claude-pool start |
Start the pool manager (default) |
claude-pool status |
Show all sessions |
claude-pool spawn --name <name> |
Create a new session |
claude-pool kill <id> |
Kill a session |
claude-pool resume <id> |
Resume a stopped session |
claude-pool config |
Show resolved config |
Flags: --config <path> (start/config), --port <port> (status/spawn/kill/resume)
REST API on the configured port (default 3200):
| Method | Path | Description |
|---|---|---|
GET |
/health |
Pool health — uptime, active session count, memory |
GET |
/sessions |
List all sessions |
POST |
/sessions |
Create a new session |
GET |
/sessions/:id |
Get session details |
DELETE |
/sessions/:id |
Kill a session |
POST |
/sessions/:id/resume |
Resume a stopped session |
Connect to /ws for real-time session status updates:
{"type": "sessions", "sessions": [...]}
{"type": "session_update", "session": {...}}
{"type": "session_removed", "id": "abc123"}stateDiagram-v2
[*] --> starting: spawn
starting --> running: process alive
running --> stopping: kill / idle timeout
running --> crashed: non-zero exit
stopping --> stopped: process exited
crashed --> starting: auto-restart (≤3x / 5min)
crashed --> [*]: max restarts exceeded
stopped --> starting: resume
stopped --> [*]: removed
- Spawn — claude-pool launches
claudewrapped in a PTY viascript -qc - Running — process alive, stdout/stderr monitored for activity timestamps
- Idle detection — every 60 seconds, sessions past the timeout are killed (unless
keepWarm) - Crash recovery — non-zero exits trigger auto-restart, up to 3 times in 5 minutes
- Resume — stopped sessions restart with
claude --resume <session-id>, picking up full conversation history - State persistence — the session registry is saved to
pool.state.jsonso the pool can recover after its own restart
Each session maps to one Claude Code process. claude-pool:
- Captures Claude Code's native session ID from
~/.claude/sessions/<pid>.json - Uses
--resume <session-id>to restore conversations - Passes through channels (
--channels), development channels (--dangerously-load-development-channels), plugin directories (--plugin-dir), and permission flags - Wraps processes in a pseudo-TTY since Claude Code requires one for interactive mode
bun test- Bun 1.0+
- Claude Code CLI installed and authenticated
Apache 2.0
Not affiliated with Anthropic. claude-pool is an independent open source project that builds on top of the Claude Code CLI.