Colony Templates
Configure colony environments with colony.toml — define services, ports, environment setup, and provisioning.
Colony templates define the structure, environment, and services for a colony. Everything lives in colony.toml files — Node.js versions, service ports, build commands, the whole setup.
colony.toml Format
A colony.toml file has four main sections:
- [colony] — Metadata and template selection
- [colony.environment] — Provisioning configuration (runtime versions, package managers)
- [colony.ports] — Named port mappings (deprecated, use
[services]instead) - [services] — Service definitions with commands and ports
- [terminal] — Terminal session configuration
Minimal Example
[colony]
name = "hello-colony"
[services.web]
command = "python3 -m http.server 4001"
port = 4001
One web service on port 4001. That’s it.
Full Example (seed/hello-colony)
[services.web]
command = "python3 -m http.server 4001"
port = 4001
[terminal]
command = "bash"
You get:
- web service on port 4001 (serves static files via Python’s built-in HTTP server)
- terminal running bash (accessible via Bloom’s terminal tab)
Each [services.*] entry creates a dedicated tab in Bloom’s preview panel. Services named web or api get specialized chrome (iframe sandbox for web, JSON viewer for API).
Section Reference
[colony]
Metadata and template selection.
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Human-readable colony name (alphanumeric + hyphens) |
template | string | No | Template identifier (web-app, api-service, full-stack) |
description | string | No | Brief summary of colony purpose |
Example:
[colony]
name = "my-app"
template = "web-app"
description = "Frontend application with API backend"
Templates are pre-configured setups stored in ~/.colony/templates/. When you specify a template, Colony copies its colony.toml and merges your overrides.
[colony.environment]
Environment provisioning. Mycelium uses this to install runtimes, package managers, and tooling.
| Field | Type | Required | Description |
|---|---|---|---|
node_version | string | No | Node.js version (e.g., “22”, “20.11.0”) |
package_manager | string | No | Package manager (npm, yarn, pnpm, bun) |
python_version | string | No | Python version (e.g., “3.12”, “3.11.5”) |
ruby_version | string | No | Ruby version (e.g., “3.3”, “3.2.1”) |
rust_version | string | No | Rust toolchain (e.g., “stable”, “1.75.0”) |
Example:
[colony.environment]
node_version = "22"
package_manager = "bun"
python_version = "3.12"
Provisioning Process:
- Clone repository into
~/.colony/workspaces/{name} - Install requested runtime versions (via mise, asdf, or direct download)
- Install dependencies (
npm install,pip install -r requirements.txt, etc.) - Create isolated network namespace
- Initialize Jujutsu workspace
- Spawn SQLite database
If provisioning fails, we roll back and report the error via logs.
If a colony gets stuck in provisioning, check logs via Bloom’s log viewer or Mycelium’s log stream endpoint. Common issues: missing runtime versions, network timeouts, invalid package.json.
[colony.ports] (Deprecated)
Legacy port mapping. Use [services] instead.
| Field | Type | Required | Description |
|---|---|---|---|
web | integer | No | Web service port (e.g., 3000) |
api | integer | No | API service port (e.g., 8080) |
Migrating to [services]:
# Old (deprecated)
[colony.ports]
web = 3000
api = 8080
# New (recommended)
[services.web]
command = "npm run dev"
port = 3000
[services.api]
command = "npm run api"
port = 8080
The [services] section gives you more flexibility — custom service names and explicit commands.
[services]
Service definitions. Each [services.{name}] block defines a long-running process.
| Field | Type | Required | Description |
|---|---|---|---|
command | string | Yes | Shell command to execute |
port | integer | Yes | Port number (1024-65535) |
path | string | No | Default path to append to URL (e.g., “/api/health”) |
cwd | string | No | Working directory (default: workspace root) |
env | table | No | Environment variables for this service |
Example with multiple services:
[services.frontend]
command = "npm run dev"
port = 5173
path = "/"
[services.backend]
command = "npm run server"
port = 3000
path = "/api"
[services.worker]
command = "npm run worker"
port = 3001
env = { REDIS_URL = "redis://localhost:6379" }
Service Lifecycle:
Services spawn when the colony transitions to running. Each service runs in a dedicated Erlang port owned by a supervisor process. The supervisor:
- Spawns the service process
- Monitors OS PID via
erlang:port_info(Port, os_pid) - Registers Caddy route for the port (e.g.,
frontend-5173.colony.local) - Streams stdout/stderr to RingLogger
When a service crashes, the supervisor attempts restart (configurable via restart_strategy).
[terminal]
Terminal session configuration for Bloom’s terminal tab.
| Field | Type | Required | Description |
|---|---|---|---|
command | string | No | Shell command (default: /bin/bash) |
env | table | No | Environment variables for terminal |
Example:
[terminal]
command = "zsh"
env = { PS1 = "colony> " }
The terminal command runs in a PTY session managed by Mycelium’s pty_session actor. Access it via Bloom’s terminal tab.
Caddy Routing
Colony automatically registers Caddy routes for each service. URL pattern:
{colony-name}-{port}.colony.local
For example:
- Service
webon port 4001 →hello-colony-4001.colony.local - Service
apion port 4002 →hello-colony-4002.colony.local
Caddy handles TLS termination (self-signed cert for .local domains) and proxies requests to the service’s port in the colony’s network namespace.
Run ./scripts/setup-dns.sh to configure dnsmasq for *.colony.local resolution. Without it, you’ll need to access services via localhost:{port} with manual port forwarding.
Template Library
Colony ships with built-in templates:
web-app
Single-page application with frontend framework (React, Vue, Svelte, SolidJS).
[colony]
template = "web-app"
[colony.environment]
node_version = "22"
package_manager = "bun"
[services.web]
command = "npm run dev"
port = 5173
api-service
Backend API server (Express, Fastify, Hono).
[colony]
template = "api-service"
[colony.environment]
node_version = "22"
[services.api]
command = "npm start"
port = 3000
path = "/api"
full-stack
Combined frontend + backend.
[colony]
template = "full-stack"
[colony.environment]
node_version = "22"
package_manager = "bun"
[services.web]
command = "npm run dev"
port = 5173
[services.api]
command = "npm run server"
port = 3000
python-app
Python application with virtual environment.
[colony]
template = "python-app"
[colony.environment]
python_version = "3.12"
[services.web]
command = "python -m uvicorn main:app --host 0.0.0.0 --port 8000"
port = 8000
Creating Custom Templates
Store custom templates in ~/.colony/templates/{name}/colony.toml.
Example: rust-api template
# ~/.colony/templates/rust-api/colony.toml
[colony]
template = "rust-api"
[colony.environment]
rust_version = "stable"
[services.api]
command = "cargo run --release"
port = 8080
path = "/api"
Use it:
curl -X POST http://localhost:8000/api/colonies \
-H "Content-Type: application/json" \
-d '{
"name": "my-rust-api",
"config": {
"template": "rust-api"
}
}'
Environment Variables
Services inherit environment variables from three sources:
- System environment (PATH, HOME, etc.)
- Colony-level variables (
[colony.env]) - Service-level variables (
[services.{name}.env])
Example:
[colony.env]
DATABASE_URL = "postgres://localhost:5432/colony"
[services.api]
command = "npm start"
port = 3000
env = { PORT = "3000", LOG_LEVEL = "debug" }
The api service gets:
DATABASE_URLfrom colony-levelPORTandLOG_LEVELfrom service-level- All system variables
Validation
Colony validates colony.toml on creation:
- Port conflicts — No two services can use the same port
- Invalid commands — Commands must be non-empty strings
- Missing runtimes — Requested runtime versions must be available
- Name conflicts — Colony names must be unique
Validation errors come back immediately via the API.
Next Steps
- Explore the Bloom dashboard — Visualize your templates in action
- Set up agent backends — Connect AI agents to colonies
- Read the architecture guide — Understand provisioning internals
Templates are the foundation of reproducible, isolated development environments. Master them to unlock Colony’s full potential.