A containerized platform for running Claude Code agents in isolated, security-hardened Docker containers. Provides a web UI for launching agents, streaming output in real time, browsing workspaces, tracking API costs, and voice input.
- Agent orchestration — Launch, monitor, and manage multiple Claude Code sessions from a single dashboard
- Security-hardened containers — Agents run in read-only containers with seccomp filtering, dropped capabilities, resource limits, and optional AppArmor profiles
- Real-time streaming — WebSocket-based live output from agent containers rendered in a terminal UI
- API cost tracking — Transparent proxy intercepts Anthropic API calls to log token usage, cache hit rates, and estimated costs
- Workspace browser — Navigate host directories and launch agents in any project
- Voice input — Local speech-to-text via Whisper (offline, no external API calls)
- Edit approval — Control whether agents can write files (off / per-turn / per-session)
- Docker with the daemon running
- Docker Compose v2 (
docker compose, not the legacydocker-compose) - Linux or macOS
Ensure your user is in the docker group:
sudo usermod -aG docker $USER # then log out and back ingit clone <repo-url> && cd claude-agent-manager
./install.shOpen http://localhost:8420, browse to a workspace directory, and launch an agent.
The install script builds both Docker images (agent + manager), creates the config directory at ~/.claude-docker, and starts the manager.
All commands are available via make:
| Command | Description |
|---|---|
make up |
Start the manager (builds if needed) |
make down |
Stop the manager |
make restart |
Restart the manager |
make logs |
Tail manager logs |
make status |
Show running containers |
make clean |
Stop everything including orphaned agent containers |
make build |
Rebuild all images |
make build-agent |
Rebuild only the agent image |
make build-manager |
Rebuild only the manager image |
make uninstall |
Stop services and remove installation |
Run the manager locally (without Docker) for faster iteration. The agent image still requires Docker.
pip install -r requirements.txt
make dev # starts uvicorn with --reload on port 8420Browser ──→ FastAPI Manager ──→ Docker Engine
│ │
│ REST + WebSocket │ spawns containers
│ ▼
│ Agent Container
│ ├─ Claude Code CLI
│ ├─ mitmproxy (API metrics)
│ └─ seccomp + resource limits
│
├─ /api/agents/* Agent CRUD + prompts
├─ /ws/agent/{id} Live streaming
├─ /api/fs/* Filesystem browsing
├─ /api/metrics/* Cost & usage data
└─ /api/voice/* Speech-to-text
├── agent/ # Agent container image
│ ├── Dockerfile # Multi-stage build (Ubuntu 24.04 base)
│ ├── entrypoint.sh # Starts proxy + Claude CLI
│ ├── claude-proxy.py # mitmproxy addon for API metrics
│ ├── seccomp-claude.json # Syscall whitelist
│ └── apparmor-claude # Optional AppArmor profile
├── server/ # FastAPI backend
│ ├── app.py # Application entry point
│ ├── agent_manager.py # Docker lifecycle management
│ ├── container_bridge.py # Stream parsing + WebSocket bridge
│ ├── config.py # Configuration loader
│ ├── models.py # Pydantic models
│ └── routes/
│ ├── agents.py # Agent endpoints
│ ├── ws.py # WebSocket streaming
│ ├── filesystem.py # Directory browsing
│ ├── metrics.py # Usage metrics
│ └── voice.py # Speech-to-text
├── static/ # Frontend SPA (vanilla JS)
│ ├── index.html
│ ├── css/theme.css
│ └── js/
│ ├── app.js # Router + state
│ ├── components/ # Terminal, charts
│ └── views/ # Browse, agents, metrics, config
├── docker-compose.yml
├── Dockerfile.manager
├── config.json # Manager configuration
├── requirements.txt
├── Makefile
└── install.sh
Configuration lives in config.json:
Voice settings can also be changed from the Config page in the web UI.
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/agents |
List all agents |
POST |
/api/agents |
Create an agent |
GET |
/api/agents/{id} |
Get agent details |
POST |
/api/agents/{id}/send |
Send a prompt |
POST |
/api/agents/{id}/approve-edits |
Set edit mode (off/turn/session) |
POST |
/api/agents/{id}/stop |
Stop agent container |
DELETE |
/api/agents/{id} |
Delete an agent |
GET |
/api/agents/{id}/history |
Get buffered events |
POST |
/api/agents/{id}/screenshot |
Upload a screenshot |
| Endpoint | Description |
|---|---|
ws://host:8420/ws/agent/{id} |
Real-time agent output stream |
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/fs/roots |
Configured browse roots |
GET |
/api/fs/list?path=... |
List directory contents |
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/metrics |
Raw metrics (JSONL) |
GET |
/api/metrics/summary |
Aggregated stats (cost, tokens, cache rates) |
GET |
/api/metrics/pricing |
Current pricing config |
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/voice/transcribe |
Upload audio for transcription |
GET |
/api/voice/status |
Whisper availability check |
Agent containers are hardened with multiple layers:
| Layer | Detail |
|---|---|
| Filesystem | Read-only rootfs, writable /tmp via tmpfs |
| Syscalls | seccomp whitelist (~130 allowed syscalls) |
| Capabilities | All capabilities dropped (cap_drop: ALL) |
| Resources | 4 GB RAM, 2 CPUs, 512 PIDs max |
| MAC | Optional AppArmor profile |
| Network | Hardened DNS (Cloudflare 1.1.1.3) |
| Privileges | Non-root user, no SUID/SGID binaries, no package manager |
Claude Code tool permissions are also gated by the manager:
- Always allowed: Read, Glob, Grep, WebFetch, WebSearch, and safe Bash commands (cat, ls, git status, linting, tests)
- Requires approval: Edit, Write (controlled via edit mode toggle)
- Backend: Python 3.12, FastAPI, Uvicorn, Docker SDK
- Frontend: Vanilla HTML/CSS/JS SPA, Chart.js
- Agent: Ubuntu 24.04, Claude Code CLI, mitmproxy
- Speech: faster-whisper (local, offline)
See LICENSE for details.
{ "claude_docker": { "image": "claude-code", // Agent Docker image "seccomp_profile": "/data/claude-docker/seccomp-claude.json", "apparmor_profile": "docker-claude" // Optional, requires profile loaded on host }, "browse_roots": ["/host/home"], // Directories exposed in the file browser "metrics_dir": "/data/claude-config/.claude-metrics", "voice": { "stt_model": "base", // Whisper model: tiny, base, small, medium, large "stt_language": "en", "auto_send": true, "silence_threshold_ms": 1500 }, "server": { "host": "0.0.0.0", "port": 8420 } }