Fleet is an AI IDE platform that distributes software development work across a pool of ephemeral virtual machines. You write a high-level plan describing what you want built — Fleet breaks it into structured tasks, dispatches them to worker VMs running an AI coding agent, verifies the results against acceptance criteria, and surfaces the output as commits or pull requests.
- What problem does this solve?
- Core workflow
- Features
- Prerequisites
- Installation
- Running Fleet
- Typical workflow
- Technical architecture
AI coding tools like OpenCode are powerful, but they run sequentially on a single machine. Fleet lets you parallelize that work: spin up multiple VMs, describe your plan once, and have several AI agents implement different parts of it simultaneously. Dependent tasks are automatically serialized; independent tasks run in parallel across the VM pool.
You write a plan
│
▼
Fleet sends it to OpenCode (running on a VM)
│
▼
OpenCode parses the plan into structured JSON tasks
- each task has a title, body, acceptance criteria, and verification steps
│
▼
Fleet clusters dependent tasks using Union-Find
- tasks that depend on each other stay on the same VM
- independent task clusters spread across worker VMs
│
▼
Dispatch loop runs tasks in parallel across VMs
- each task is executed by OpenCode on its assigned VM
- acceptance criteria are verified automatically
│
▼
Output: committed code, opened PRs, or in-VM changes
Write a natural-language plan describing your implementation goals. Fleet sends it to OpenCode, which converts it into a structured task list with explicit acceptance criteria and verification steps. You can review, edit, and reassign tasks before executing.
Tasks run concurrently across multiple worker VMs. Fleet's dispatch loop tracks dependencies between tasks: a task waits until all its dependencies are DONE, then starts immediately. Independent tasks begin in parallel as soon as VMs are available.
Fleet uses a Union-Find algorithm to cluster tasks that share dependencies onto the same VM (so they can share a codebase and run in sequence), then distributes independent clusters evenly across the worker pool by load.
Every task carries a list of acceptance criteria and verification steps. After OpenCode executes a task, it checks each criterion and runs the verification steps. A task is only marked DONE if all criteria pass and verification succeeds — otherwise it surfaces as ERROR for inspection.
Each task can be configured with one of three output modes:
commit— push a commit to the VM's configured remote and record the commit URLpr— create a git branch, push it, and open a GitHub pull request viaghnone— leave changes in the VM without pushing
Every VM is built from a base image that has a Nix home-manager environment applied. This guarantees identical tool versions across all worker VMs. You can edit Nix configurations in the UI, validate them before applying, and rebuild base images when the environment changes.
Base images are stopped VM snapshots. Launching a new worker VM clones from a base image rather than provisioning from scratch — taking ~30 seconds instead of several minutes. The base image includes Docker, git, Go, Node.js, and an auto-starting OpenCode server.
Tasks and runs have full lifecycle control:
- Cancel individual tasks or clear an entire queue
- Retry a failed task (and unblock its dependents automatically)
- Restart a run from scratch, resetting all task state
Fleet ships both a Streamlit web dashboard and an argparse-based CLI (fl.py). The dashboard has live status updates and an embedded OpenCode iframe; the CLI covers VM and base image management.
Fleet requires the following tools installed on the host machine (not inside VMs):
| Tool | Purpose | Install |
|---|---|---|
| Multipass | Provision and manage Ubuntu VMs | brew install multipass |
| OpenCode | AI coding agent CLI | See opencode.ai |
| Nix | Reproducible package management | See nixos.org/download |
| home-manager | Apply Nix environments to VMs | See home-manager docs |
| Python 3.9+ | Run Fleet itself | brew install python |
You'll also need an Anthropic or OpenAI API key to power the OpenCode agent.
git clone <repo>
cd ai-ide
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtstreamlit run app.pyOpens at http://localhost:8501. The dashboard has five tabs:
- VMs — launch, list, delete, rename, and SSH into VMs
- Base Images — create and rebuild base VM snapshots
- Nix Configs — edit and validate Nix home-manager configurations
- Settings — configure API keys and OpenCode settings
- Orchestrator — write plans, compile them into tasks, execute them, and view history
python fl.py --helpBase image commands:
python fl.py base create --type lite --cpus 2 --memory 4G --disk 20G
python fl.py base rebuild --type lite
python fl.py base delete --type liteVM commands:
python fl.py vm launch worker1 --type lite --cpus 4 --memory 8G --disk 50G
python fl.py vm list
python fl.py vm ssh worker1
python fl.py vm rename worker1 worker1-new
python fl.py vm delete worker1Package commands:
python fl.py packages apply worker1 --type liteStep 1 — Create a base image (one-time setup, ~5-10 minutes)
In the Base Images tab or via CLI:
python fl.py base create --type liteThis launches an Ubuntu VM, installs the Nix environment (git, Go, Node.js, Docker, OpenCode), stops the VM, and saves it as a cloneable snapshot.
Step 2 — Launch worker VMs (~30 seconds each)
python fl.py vm launch worker1 --type lite
python fl.py vm launch worker2 --type liteEach VM clones the base image and starts immediately with an OpenCode server listening on port 4096.
Step 3 — Configure API keys
Open the Settings tab in the UI and enter your Anthropic or OpenAI API key. This is stored in ~/.fl/fleet.db and pushed to VMs as the OpenCode configuration.
Step 4 — Write and compile a plan
Open the Orchestrator tab. Select a planning VM (the VM that will parse the plan) and worker VMs (the VMs that will execute tasks). Write your plan in the editor:
Implement a REST API for user authentication.
1. Add a POST /register endpoint that accepts email and password,
hashes the password with bcrypt, and stores the user in SQLite.
2. Add a POST /login endpoint that validates credentials and
returns a JWT token.
3. Add a GET /me endpoint that validates the JWT and returns
the current user's profile.
Click Compile. Fleet sends the plan to OpenCode on the planning VM, which returns structured tasks with acceptance criteria and verification steps. You can review and edit the tasks before executing.
Step 5 — Execute
Click Execute. Fleet's dispatch loop starts. Tasks with no pending dependencies start immediately on their assigned VMs. As tasks finish, dependent tasks unlock and begin. Monitor progress in the task list — each task shows its status, log, and verification results in real time.
Step 6 — Review output
Completed tasks show commit URLs or PR links. Failed tasks show the verification log and which acceptance criteria didn't pass. You can retry individual tasks or restart the entire run.
Fleet (fleet/fleet.py) is the central facade that wires all services together. Services depend on abstract protocols rather than concrete implementations:
Repository— all persistence (implemented byFleetRepositoryusing SQLite)VMProvider— VM provisioning (implemented byMultipassClient)CodeRunner— AI task execution (implemented byOpenCodeClient)
Services:
| Service | Responsibility |
|---|---|
VMService |
VM lifecycle: launch, delete, rename, SSH, apply Nix configs |
BaseImageService |
Create and rebuild base VM snapshots |
NixConfigService |
Manage versioned Nix home-manager configs with validation |
SettingsService |
Persist and distribute API keys and OpenCode config |
PlanExecutorService |
Orchestration engine: parse → assign → dispatch → verify |
PlanExecutorService (fleet/plan_executor_service.py) runs the full pipeline:
- Parse — sends the raw plan to OpenCode using a structured prompt; extracts the JSON task list from the response
- Assign — runs Union-Find clustering on task dependencies; assigns each cluster to the least-loaded worker VM
- Launch — starts a background
_dispatch_loopthread for the run - Dispatch — the loop polls for
PENDINGtasks whose dependencies are allDONEand whose assigned VM is idle; starts a worker thread per task - Execute — each worker thread streams OpenCode output for the task, appending logs to the DB in real time
- Verify — parses the structured JSON result from OpenCode; marks the task
DONEorERRORbased on criteria results, verification status, and push/commit state - Cascade — the dispatch loop re-evaluates blocked tasks after each completion; the run ends when all tasks reach a terminal state
DRAFT → PENDING → RUNNING → DONE
↘ ERROR
↘ BLOCKED (dependency failed)
↘ CANCELLED
SQLite database at ~/.fl/fleet.db (WAL mode, schema v11). Tables: virtual_machines, base_images, nix_configs, app_settings, plan_runs, plan_tasks.
Logs are written to ~/.fl/fleet.log at DEBUG level (rotating).