⚠️ HERE BE DRAGONS⚠️ This is very early alpha software. It might eat your commits, corrupt your repo, make questionable life choices with your filesystem, or spontaneously decide that
mainwas more of a suggestion than a branch name.What could possibly go wrong:
- Your repository (we use OverlayFS and merge things automatically)
- Your git history (we spawn agents that commit things)
- Your sanity (debugging parallel agent conflicts is a character-building exercise)
- Anything the agents touch (they're quite enthusiastic)
Recommended precautions: Use on toy projects first. Keep backups. Have
git reflogbookmarked. Consider a cup of tea and a moment of quiet reflection before runningcanopy runon anything you care about.You have been warned. Proceed with curiosity and caution.
Parallel agent orchestrator for Claude Code
Canopy coordinates multiple Claude Code agents working on different tasks simultaneously, each in an isolated sandbox. It handles task scheduling, workspace isolation, change merging, and conflict resolution automatically.
Human (You)
└── Claude Code (Root Agent)
└── canopy run
├── Worker 1 (isolated sandbox) → task A
├── Worker 2 (isolated sandbox) → task B
├── Worker 3 (isolated sandbox) → task C
└── ... up to N concurrent workers
Without Canopy, Claude Code processes tasks sequentially. A 10-task project takes 10x the time of a single task. Canopy enables:
- Parallel execution: Run N tasks simultaneously (default: 4 agents)
- Workspace isolation: Each agent works in an isolated copy of the repository
- Automatic merging: Changes merge back to the main repo after completion
- Conflict resolution: Spawns resolver agents when merge conflicts occur
- Retry logic: Automatically retries failed tasks (configurable)
- Real-time monitoring: TUI dashboard and WebSocket API for observability
- Linux or macOS (Linux uses OverlayFS; macOS uses APFS clones)
- Go 1.24+ for building
- Claude Code CLI (
claude) installed and authenticated - Beads-compatible CLI (
bd) for task tracking - any implementation conforming to the Beads Classic Protocol - bubblewrap (
bwrap) optional, for full sandbox isolation
If you have devenv installed, the development environment is fully automated:
# Clone repository
git clone https://github.com/jzila/canopy
cd canopy
# Allow direnv to load the environment automatically
direnv allow
# Or manually enter the devenv shell
devenv shellThis provides Go, beads (bd), git, sqlite, and fuse-overlayfs with a pre-commit hook that verifies Go compilation.
# Clone and build
git clone https://github.com/jzila/canopy
cd canopy
go build -o canopy ./cmd/canopy
# Add to PATH (or move to /usr/local/bin)
export PATH="$PATH:$(pwd)"
# Verify installation
canopy versionCanopy uses beads for task management:
# Initialize beads with a separate sync branch
# IMPORTANT: Must use --branch to avoid overlay conflicts
bd init --branch beads-sync
# Create some tasks
bd create --title "Implement user authentication" --type feature --priority 1
bd create --title "Add input validation" --type task --priority 2
bd create --title "Write unit tests" --type task --priority 2
# View ready tasks (no blockers)
bd ready# Execute all ready tasks with 4 concurrent agents (default)
canopy run
# Or with more concurrency
canopy run -c 8
# Dry run to preview what would execute
canopy run --dry-run
# With full sandbox isolation (requires bwrap)
canopy run --sandbox# Start the daemon with TUI dashboard
canopy daemon --tui
# Or check daemon status
canopy daemon status
# View logs
canopy daemon logs -f| Command | Description |
|---|---|
canopy run |
Execute ready tasks in parallel |
canopy daemon |
Start HTTP/IPC server for monitoring |
canopy daemon --tui |
Start daemon with TUI dashboard |
canopy daemon status |
Check if daemon is running |
canopy daemon logs |
View daemon logs |
canopy init |
Interactive sandbox configuration |
canopy history |
View past run records |
canopy stats |
Show run statistics |
canopy help --agent |
Detailed workflow for AI agents |
canopy run [flags]
-c, --concurrency N Max concurrent agents (default: 4)
-o, --output DIR Output directory for merged results
--sandbox Enable bubblewrap isolation (requires bwrap)
--max-retries N Retry limit (default: 3, -1 for infinite)
--dry-run Preview without executing
--prompt TEXT Soft guidance for task selection
--max-priority N Hard filter by priority (0-4)
-v, --verbose Verbose outputThe daemon is automatically started if not running. The run command requires daemon connectivity for monitoring and real-time updates.
┌─────────────────────────────────────────────────────────────────┐
│ Canopy Orchestrator │
├─────────────────────────────────────────────────────────────────┤
│ │
│ bd ready ────┬──────────────────────────────────────────────── │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Scheduler │ │
│ │ - Bounded concurrency (semaphore) │ │
│ │ - Per-agent contexts for kill support │ │
│ └──────────────┬──────────────────────────────────────────┘ │
│ │ │
│ ┌────────────┼────────────┐ │
│ ▼ ▼ ▼ │
│ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │Agent1│ │Agent2│ │Agent3│ ... up to N │
│ │Overlay│ │Overlay│ │Overlay│ │
│ └──┬───┘ └──┬───┘ └──┬───┘ │
│ │ │ │ │
│ └───────────┴───────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Merge Queue (Sequential) │ │
│ │ - Last-writer-wins for non-conflicting changes │ │
│ │ - Spawns resolver agents for conflicts │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ bd done (mark tasks complete) │
│ │
└─────────────────────────────────────────────────────────────────┘
Each agent operates in an isolated workspace. The isolation mechanism varies by platform:
Linux (OverlayFS): Uses copy-on-write filesystem for efficient isolation:
┌──────────────────────────────────────────────────────────────┐
│ MergedDir (Agent's View) │
│ ~/.cache/canopy/overlays/{id}/merged │
├──────────────────────────────────────────────────────────────┤
│ UpperDir (Agent's Changes) │
│ ~/.cache/canopy/overlays/{id}/upper │
├──────────────────────────────────────────────────────────────┤
│ LowerDir (Original Repo) │
│ /home/user/project (read-only) │
└──────────────────────────────────────────────────────────────┘
macOS (APFS Clone): Uses copy-on-write clones for efficient isolation:
┌──────────────────────────────────────────────────────────────┐
│ MergedDir (Agent View) │
│ ~/.cache/canopy/overlays/{id}/merged │
│ (APFS clone of original repo - COW copy) │
└──────────────────────────────────────────────────────────────┘
│
│ clonefile(2) / cp -c
▼
┌──────────────────────────────────────────────────────────────┐
│ Original Repo (Unmodified) │
│ /Users/user/project (read-only reference) │
└──────────────────────────────────────────────────────────────┘
On both platforms, agents cannot see each other's changes until merge.
Run canopy init to generate an interactive configuration:
[sandbox]
enabled = true
network = "allow"
[resources]
max_memory = "4GB"
max_processes = 100
max_open_files = 1024
[paths]
# Tool paths (read-only)
read_only = ["~/.cargo", "~/.nvm", "~/.rustup"]
# Config files (copied to overlay)
copy_configs = ["~/.gitconfig", "~/.npmrc"]
# Shared caches (read-write)
cache_mounts = ["~/.npm", "~/.cargo/registry"]
[security]
# Always blocked (in addition to built-in blocklist)
blocked = ["~/.ssh", "~/.aws", "~/.gnupg"]Default protections (always on):
- Environment filtering: only
ANTHROPIC_*,PATH,LANG,LC_*,TERM,TMPDIR,TZ .claude/directory hidden from workers- Process groups: workers die if orchestrator dies
With --sandbox flag (requires bwrap):
- Full namespace isolation (user, PID, IPC, UTS)
- All capabilities dropped
- Resource limits: 4GB memory, 100 processes, 1024 file descriptors
- Read-only system mounts
- Security blocklist:
~/.ssh,~/.aws,~/.gnupg, etc. never exposed
The daemon provides real-time monitoring:
# Start daemon (foreground)
canopy daemon
# Start daemon with TUI
canopy daemon --tui
# Start in background
canopy daemon start
# Connect TUI to running daemon
canopy daemon --tui --daemon-addr localhost:8080
# View logs
canopy daemon logs -fThe daemon exposes a REST API for monitoring and control:
| Endpoint | Method | Description |
|---|---|---|
/api/state |
GET | Full runtime state snapshot |
/api/agents |
GET | List all agents |
/api/agents |
PATCH | Update agent (archive) |
/api/agents/:id/kill |
POST | Terminate a running agent |
/api/tasks |
GET | List all tasks |
/api/tasks |
POST | Create a new task |
/api/tasks |
PATCH | Update task status |
/api/stats |
GET | Current run statistics |
/api/merge-queue |
GET | Merge queue state |
/api/orch/pause |
POST | Pause orchestrator |
/api/orch/resume |
POST | Resume orchestrator |
/api/runs |
GET | List historical runs |
/api/runs/:id |
GET | Get run details |
/api/runs/:id/agents |
GET | Get agents for a run |
/api/stats/history |
GET | Aggregate historical stats |
/api/repositories |
GET | List repositories |
/api/repositories/:id |
GET | Get repository details |
/api/repositories/:id/activate |
POST | Set active repository |
/api/beads/sync |
POST | Sync tasks from beads |
/ws |
GET | WebSocket for real-time updates |
/metrics |
GET | Prometheus metrics (see Metrics) |
See Commands for detailed request/response formats.
Canopy exposes Prometheus-compatible metrics at /metrics for monitoring and alerting:
# Fetch metrics
curl http://localhost:8080/metricsAvailable metrics:
| Metric | Type | Description |
|---|---|---|
canopy_active_agents |
Gauge | Current agents by status (running/completed/failed) |
canopy_merge_queue_depth |
Gauge | Items waiting in merge queue |
canopy_overlay_mounts |
Gauge | Active overlay filesystem mounts |
canopy_task_duration_seconds |
Histogram | Task execution duration by status |
canopy_merge_conflicts_total |
Counter | Total merge conflicts encountered |
canopy_resolver_success_total |
Counter | Successful conflict resolutions |
canopy_resolver_failure_total |
Counter | Failed conflict resolutions |
canopy_ipc_messages_total |
Counter | IPC messages by type |
A pre-configured Grafana dashboard is available at docs/grafana/canopy-dashboard.json.
All state lives in ~/.cache/canopy/ (or $XDG_CACHE_HOME/canopy/):
~/.cache/canopy/
├── runs.db # SQLite database for run history
├── repositories.json # Repository identity registry
├── daemon.log # Daemon log file
├── history/ # JSON run records (backup)
└── overlays/ # Temporary overlay mounts (auto-cleaned)
- Architecture - Detailed system design
- Getting Started - Step-by-step tutorial
- Commands - Complete CLI reference
- Configuration - Configuration options
- Dashboard - Web dashboard user guide
- Sandbox Design - Security architecture
Canopy requires a CLI tool (bd) that implements the Beads Classic Protocol—a minimal git-backed task tracking interface. The protocol defines the commands Canopy uses for task discovery, status updates, and dependency management.
Known implementations:
- beads - Original Go implementation
- beads_rust - Rust implementation
Any implementation conforming to the protocol will work with Canopy.
# Create tasks with dependencies
bd create --title "Design API" --type task --priority 0 # → canopy-a1b2
bd create --title "Implement API" --type task --priority 1 # → canopy-c3d4
bd dep add canopy-c3d4 canopy-a1b2 # Implement depends on Design
# Canopy respects dependencies
canopy run # Design runs first, then ImplementMIT License - see LICENSE for details.
