colonizer.dev · HARNESS · the open-source core
Coding agents are good enough to work on their own for a long time. Most setups still make you pick between safe (a sandbox, one task at a time, an approval every few seconds) and fast (an agent with your credentials loose on your laptop). This is the setup that doesn't make you pick.
Every task gets a colony: its own KVM microVM with a fresh git worktree and an agent inside. The agent can do anything in there. Every colony joins a private mesh with the machine that launched it, so its chat and a real terminal are one hop away. When the agent needs you, it asks with choices. When the work is done, your machine, the mothership, commits it and opens the pull request.
This repository is the open-source core, MIT, and it runs on one Linux machine today. colonizer.dev is the name for everything around it. Nothing is live there yet, and nothing in this README pretends otherwise.
Colonies only ever hold placeholders. The GitHub token never enters a colony. The agent's API credential is swapped in by the sandbox's host-side TLS proxy, for one host, on the way out. A colony that goes rogue can wreck its own worktree, and that's all.
The design is in docs/architecture.md. The wire format between agent, microVM, mothership and browser is in docs/protocol.md. Why any of this exists, and where it's going, is in docs/vision.md.
| What it is | Status | |
|---|---|---|
| Harness | This repository: the mothership, the in-VM daemon, the agent module, the web UI, the bundled mesh. Runnable today on your own machine. | SHIPPING |
| Colonizer | Anything beyond one machine: remote outposts, a fleet view, a hosted offering. | PLANNED |
Two labels are used everywhere below, and they set the tense of the sentence around them:
SHIPPING: merged, in this repository, and exercised on a real machine.PLANNED: named, not specified, not started.
Real, from a colony working on this repository. Unedited apart from line breaks.
{"type": "question", "seq": 14,
"question_id": "toolu_01Kz2S34mniQ6KJ476Twd2X3",
"questions": [{
"header": "README tweak", "multi_select": false,
"question": "Which small README improvement do you prefer?",
"options": [
{"label": "Add a table of contents",
"description": "Insert a short linked ToC near the top (Requirements, Install, Trust model, Configuration, Development, Run as a service) so readers can jump to a section in this fairly long README."},
{"label": "Add a Quick Start block",
"description": "Add a 3-line 'Quick Start' snippet right under the intro paragraph (clone, install.sh --install, open the URL) so skimmers get running before reading Requirements/Trust model/Configuration."}
]}]}The web UI renders that as a card with both options and an Other… answer. One click sends
question_answered back through the mothership, over the mesh, to the agent that is waiting for it.
Agents never ask in plain text. The Claude Code module routes AskUserQuestion into this event, and if a
turn still ends on a plain-text question, the runner holds the turn open and has the agent ask again as
a card. Autopilot can't publish in the middle of a question.
%%{init: {"theme":"base","themeVariables":{
"background":"transparent",
"fontFamily":"ui-monospace, SFMono-Regular, Menlo, monospace",
"fontSize":"13px",
"primaryColor":"#141821","primaryTextColor":"#EDEBE6","primaryBorderColor":"#3A3A3F",
"lineColor":"#6E6E76","textColor":"#8A8A8E",
"clusterBkg":"transparent","clusterBorder":"#3A3A3F",
"edgeLabelBackground":"#0E121A"
}} }%%
flowchart LR
U(["browser"]):::req --> M
subgraph HOST["YOUR MACHINE · THE MOTHERSHIP"]
M["<b>colonizer</b><br/>modules · colonies · publish"]:::core
HS["headscale<br/>bundled control plane"]:::mod
TS["tailscaled<br/>userspace node"]:::mod
M --> HS & TS
end
subgraph C["ONE TASK · ONE MICROVM · ONE WORKTREE"]
AD["<b>colonizer-agentd</b><br/>events · terminals"]:::port
AG["agent runner<br/>Claude Code"]:::mod
WT[("/workspace<br/>git worktree")]:::vendor
AD --> AG --> WT
end
TS == "private mesh" ==> AD
M --> GH["GitHub<br/>issues · pull requests"]:::vendor
AG -. "placeholder, swapped at the edge" .-> API["api.anthropic.com"]:::vendor
C2["another colony"]:::ghost
TS -.-> C2
classDef req fill:#0E121A,stroke:#FF6B35,stroke-width:1.5px,color:#EDEBE6
classDef core fill:#141821,stroke:#FF6B35,stroke-width:1.5px,color:#EDEBE6
classDef mod fill:#0E121A,stroke:#3A3A3F,color:#EDEBE6
classDef port fill:#141821,stroke:#EDEBE6,stroke-width:1.5px,color:#EDEBE6
classDef vendor fill:#0E121A,stroke:#3A3A3F,color:#A9A8A5
classDef ghost fill:transparent,stroke:#55555A,stroke-dasharray:4 3,color:#8A8A8E
1. A colony is a machine, not a container. Each task runs in a KVM microVM (microsandbox, libkrun) with its own kernel. The agent runs without permission prompts because there is nothing on the other side of the wall worth protecting.
2. Secrets stay home. Git objects are mounted read-only, so the agent can read history but not
rewrite it. The mothership commits, pushes and opens the pull request after the microVM is gone, and it
treats everything the colony left behind as untrusted: .git is rewritten, nested repositories are
removed, and git runs with hooks and fsmonitor disabled.
3. Every colony is one hop away. The mothership runs its own Headscale and a userspace tailscaled,
both bundled. Every colony joins with a single-use key. The network is separate from any tailnet the
machine is already on. The mothership can reach colonies, and colonies can't reach each other. One narrow
UDP rule per colony keeps WireGuard direct (about 1 ms) instead of relayed.
4. Decisions, not prose. Agents bring you choices. Your job is to pick one, not to parse a paragraph that ends in a question mark.
5. Everything is a module. Source, sandbox, mesh, agent, interfaces and publish are providers behind
small contracts, selected in the UI and saved in modules.json. The agent contract is a JSON Lines
protocol on stdio, so an agent module can be written in anything.
| Path | What it is | Status |
|---|---|---|
crates/colonizer |
The mothership: HTTP and WebSocket API, module registry, colony lifecycle, mesh supervision, publish | SHIPPING |
crates/colonizer-agentd |
The daemon inside every colony: runner supervision, event log with replay, PTY terminals. Static musl binary | SHIPPING |
modules/agents/claude-code |
Claude Code through the Claude Agent SDK, speaking the runner protocol | SHIPPING |
web |
The UI: colonies, chat on assistant-ui, choice cards, xterm.js terminal, settings | SHIPPING |
vendor |
Pinned, sha256-verified microsandbox, Headscale and Tailscale, plus a DERP map snapshot | SHIPPING |
scripts |
install.sh, vendoring, the in-microVM agentd build |
SHIPPING |
| Kind | Providers today | Next |
|---|---|---|
source |
GitHub issues and repositories | GitLab, Linear, Jira PLANNED |
sandbox |
microsandbox (KVM microVMs), with presets for Node, Python, Rust and Go | other VMMs PLANNED |
mesh |
Private mesh (bundled Headscale), or a loopback port | remote outposts PLANNED |
agent |
Claude Code, with subagents on any Anthropic-compatible provider (DeepSeek, a local model) | more agents behind the same protocol PLANNED |
interfaces |
Chat with choice cards, terminal | dev-server previews PLANNED |
publish |
GitHub pull request from the colony's own branch, opened automatically when the agent finishes (autopilot, on by default) | review-comment follow-ups PLANNED |
memory |
Shared notes per repository, org and globally; agents propose, you approve | semantic search PLANNED |
watchdog |
Nudges colonies that stop making progress, flags the ones that need you | automatic restarts PLANNED |
Every GitHub org is a workspace with its own overrides for models, the parallel limit, memory and the watchdog. Model providers (DeepSeek, a server on your LAN or tailnet, any Anthropic-compatible endpoint) are added in Settings. Colonies reach them through the mothership's provider gateway, which holds the keys, queues requests for servers that handle one at a time, allows slow prefill, and falls back to Claude when a provider is down or busy.
Linux x86_64 with /dev/kvm readable and writable by your user, or an Apple Silicon Mac. Either way:
git, gh, Node.js ≥ 20 and a Rust toolchain of 1.88 or newer — Homebrew's rust can lag a long way
behind, so rustup is the safe bet. On Linux you also need a native Claude Code install;
microsandbox ships with the app like the mesh binaries, so there is
nothing else to install.
On a Mac, scripts/install.sh additionally fetches the linux-arm64 build of Claude Code — pinned
to the stable channel and checked against Anthropic's own manifest — because a colony is a Linux
microVM and the Mac's own binary is Mach-O. colonizer-agentd is built for the guest's architecture.
A colony has been taken end to end on Apple Silicon, from install to an open pull request
(#36); an Intel Mac cannot run this at all,
because microsandbox's libkrun backend is aarch64-only. The one gap is the bundled private mesh:
Tailscale publishes no macOS tailscaled to vendor, so colonies are reached on a loopback port
instead (#32).
git clone https://github.com/Colonizer-dev/harness && cd harness
scripts/install.sh # builds everything into ./dist; nothing is downloaded at runtime
dist/bin/colonizer # open http://127.0.0.1:7878In Settings, connect GitHub (your gh login is picked up automatically) and press Log in with
Claude subscription. Then Launch a colony on an issue, or on a repository with nothing but a
sentence of instructions. Launch as many as you like: past the parallel limit (Settings → Modules →
sandbox) a colony is queued, and starts on its own when one ahead of it finishes.
scripts/install.sh --install additionally copies the app to ~/.local/share/colonizer/app and links
~/.local/bin/colonizer.
Stated here rather than buried.
- One machine. Colonies run on the host that launched them: Linux x86_64 with KVM, or an Apple Silicon Mac — where the private mesh does not work yet, so colonies use a loopback port (#32).
- One agent, one forge. Claude Code is the only agent module and GitHub the only source and publisher.
- The web UI has no login. It binds to
127.0.0.1, checksHostandOriginheaders, and should stay there. - Colony images need glibc. A Linux Claude Code binary is mounted read-only into the microVM: the
host's own on Linux, the
linux-arm64build fetched at install time on a Mac. - Relays are Tailscale's. Direct connections don't need them; when a colony falls back to a relay, encrypted traffic crosses Tailscale's public DERP servers.
install.sh --installis not exercised yet. It is implemented, but it hasn't been run against the real world. Colonies opening pull requests has been.- Cross-provider subagents are off the beaten path. Anthropic doesn't support routing Claude Code to
non-Claude models. Routing and the gateway are tested with stub Anthropic-compatible providers inside
real colonies and against a local
ds4-serveron the operator's tailnet, not against DeepSeek's hosted API, and Claude-specific request fields are forwarded as they are. - Memory search is plain text matching, not semantic search.
- No CI yet, and nothing is published to crates.io or npm.
| Capability | Status |
|---|---|
| Colonies, private mesh, choice cards, terminal, Claude Code module, GitHub source and publish | SHIPPING |
| Orchestrator and subagents on different providers (#1) | SHIPPING |
| Org workspaces (#2) | SHIPPING |
| Shared memory with review (#3) | SHIPPING |
| Watchdog for stalled colonies (#4) | SHIPPING |
| Provider gateway: private-network models, queues, long timeouts, health, Claude fallback (#5) | SHIPPING |
| CI running the Rust, runner and UI test suites | PLANNED |
| Local Claude Code plugins mounted read-only into colonies, with ECC's skills and agents vendored (#6) | SHIPPING |
| Skillsets switched on and off in Settings, globally and per org (#46) | SHIPPING |
| superpowers vendored, with its bootstrap in the system prompt instead of a hook (#44) | SHIPPING |
| Google's skills vendored and loaded on demand from a pinned local catalog (#43) | SHIPPING |
| Daily proposals for vendored plugin updates, described in skills added, removed and changed (#43) | SHIPPING |
| More agent modules behind the runner protocol | PLANNED |
| GitLab, Linear and Jira sources; review comments as follow-up tasks | PLANNED |
| Remote outposts: other machines joining the mesh to host colonies | PLANNED |
| Fleet view, per-colony budgets and network policies | PLANNED |
| Dev-server previews over the mesh | PLANNED |
The roadmap is the issue tracker. There is no private version of it.
| What | Where it lives |
|---|---|
| GitHub token | Mothership only. Commit, push and gh pr create run on the host after the colony is gone. |
| Claude token | Mothership only (0600). The colony sees a placeholder; microsandbox's TLS proxy substitutes the real value for api.anthropic.com only. |
| Model provider keys | Mothership only (0600). Colonies send provider requests to the gateway with a per-colony token; the gateway adds the key. |
| Worktree | Mounted read-write at /workspace. |
| Git objects and worktree metadata | Mounted read-only: git status, diff and log work in the colony, commits don't. |
| Colony output | Untrusted until published: .git rewritten, nested .git removed, no hooks or fsmonitor, pr.md must be a regular file. |
| Mesh | Own Headscale and userspace tailscaled, own state and socket, --no-logs-no-support. Mothership reaches colonies; colonies can't reach each other. |
| colonizer-agentd | Per-colony bearer token, even inside the mesh. |
Colonies are detached: they keep running when the mothership restarts, and it reconnects to them.
Module settings live in ~/.config/colonizer/modules.json and are edited in the UI. Process settings
come from the environment:
| Variable | Default | Meaning |
|---|---|---|
COLONIZER_BIND |
127.0.0.1:7878 |
Listen address |
COLONIZER_ALLOWED_HOSTS |
– | Extra Host names to accept, comma separated |
COLONIZER_GATEWAY_BIND |
127.0.0.1:41750 |
Provider gateway; colonies reach it through host.microsandbox.internal |
COLONIZER_DATA_DIR |
~/.local/share/colonizer |
Clones, worktrees, colonies, mesh state |
COLONIZER_CONFIG_DIR |
~/.config/colonizer |
Module config and saved tokens |
COLONIZER_CLAUDE_BIN |
auto-detected | Native Claude Code binary to mount |
COLONIZER_HOME |
next to the binary, or dist/ |
Bundled app assets |
A few things belong in neither the UI nor the environment. They live in ~/.config/colonizer/colonizer.toml,
which you write and Colonizer only reads — a missing file means the defaults:
[publish]
# Colonizer signs the commit it publishes a colony's work as:
# Co-Authored-By: Colonizer <noreply@colonizer.dev>
co_author = truecargo test --workspace # mothership and agentd
(cd modules/agents/claude-code && node --test test/)
(cd web && npm run dev) # UI dev server; proxies /api to 127.0.0.1:7878
# http://127.0.0.1:5173/?mock=1 # the UI against an in-browser mock backendVendor logos in the UI are CC0 artwork from Simple Icons; the marks stay their owners' trademarks. See NOTICE.
colonizer.dev
·
Vision
·
Architecture
·
Protocol
MIT license · Colonize your backlog.