Technical Documentation: builderz-labs/mission-control
ℹ️ Provenance: Multi-Tier Ingestion · CodeWiki Reference
Overview (`README.md`)
[!WARNING]
Mission Control is alpha software. APIs, schemas, and configuration may change between
releases. Read the security guidance before exposing it to a network.
Start locally
Node.js 22 or newer and pnpm are required for a source install.
git clone https://github.com/builderz-labs/mission-control.git
cd mission-control
bash install.sh --localOpen http://localhost:3000/setup, create the first admin account, then copy the API key
from Settings if an agent or script needs headless access.
The manual path is useful when you already manage Node and pnpm:
nvm use 22
pnpm install
pnpm devWindows users can run ./install.ps1 -Mode local in PowerShell.
Start with Docker
docker compose upOr run the published multi-architecture image:
docker pull ghcr.io/builderz-labs/mission-control:latest
docker run --rm -p 3000:3000 ghcr.io/builderz-labs/mission-control:latestUse the hardened Compose overlay for a network-accessible deployment:
docker compose -f docker-compose.yml -f docker-compose.hardened.yml up -dThe deployment guide covers persistent data, TLS termination,
gateway connectivity, and standalone builds.
What Mission Control governs
The control plane sits above agent runtimes. It does not replace their reasoning or tool
loops. It gives operators one place to see and govern the work around those loops.
| Area | Shipped surface |
|---|---|
| Tasks | Inbox, assignment, execution, review, Aegis quality gate, and completion receipts |
| Agents | Registration, presence, sessions, runtime adapters, configuration, and workspace sync |
| Operations | Activity stream, schedules, alerts, webhooks, logs, token use, and cost views |
| Knowledge | Memory browser, relationship graph, skills registry, and local skill synchronization |
| Governance | Roles, API keys, security events, trust signals, approvals, audits, and evals |
| Interfaces | Web UI, CLI, MCP server, OpenAPI-described REST API, WebSocket, and SSE |
The runtime is self-hosted and workspace-aware. SQLite stores local control-plane state.
Shared workspaces can use deployment-level runtime integrations. Strict workspaces block
those integrations until the underlying resources carry workspace ownership. A gateway is
optional for task, project, agent, scheduler, webhook, alert, and cost work; live session
messaging needs a connected runtime gateway.
Operator field notes
Dashboards compress a sequence into current state. When a run needs review, record the
identity, task, tool call, approval, result, and verification evidence before changing it.
Keep unresolved items distinct from accepted risk.
Logs show what ran. A completion receipt or inspected artifact shows what finished.
Pick the right fit
Use Mission Control when multiple agents or runtimes make it hard to answer who owns a
task, what executed, which result passed review, or where spend and failures accumulated.
It is probably the wrong tool when:
- one agent on one machine already stays understandable from its native CLI;
- you need a managed multi-tenant SaaS rather than a self-hosted control plane;
- you want an agent framework to define planning and tool use;
- your deployment cannot tolerate alpha schema or API changes.
Adapters and observation surfaces cover OpenClaw, Claude Code, Codex,
CrewAI, LangGraph, AutoGen, and Claude SDK workflows. Adapter depth varies by runtime; see
agent setup and CLI integration before
assuming feature parity.
Connect an agent
The shortest gateway-free loop uses the REST API. Export the URL and API key shown in
Settings:
export MC_URL=http://localhost:3000
export MC_API_KEY=replace-with-your-api-keyRegister an agent and create work:
curl -s -X POST "$MC_URL/api/agents/register" \
-H "Authorization: Bearer $MC_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"scout","role":"researcher"}'
curl -s -X POST "$MC_URL/api/tasks" \
-H "Authorization: Bearer $MC_API_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"Review open incidents","assigned_to":"scout","priority":"medium"}'The agent can then claim its queue:
curl -s "$MC_URL/api/tasks/queue?agent=scout" \
-H "Authorization: Bearer $MC_API_KEY"Continue with the first-agent quickstart for heartbeats, task results,
queue behavior, CLI equivalents, and MCP setup.
CLI
pnpm mc agents list --json
pnpm mc tasks queue --agent scout --json
pnpm mc events watch --types agent,taskMCP server
claude mcp add mission-control -- \
env MC_URL=http://127.0.0.1:3000 MC_API_KEY=replace-with-your-api-key \
node /absolute/path/to/mission-control/scripts/mc-mcp-server.cjsUse the CLI and MCP reference for the current command and tool
surface. The REST contract lives in openapi.json. A running instance serves
the interactive reference at /docs and the OpenAPI JSON at /api/docs.
Product surfaces
Tasks and quality review
The task board tracks work through inbox, assignment, execution, review, quality review,
and completion. Aegis review requires an approval record before a task reaches done.
Agents and runtimes
Agent views combine registration state, heartbeats, sessions, configuration, local runtime
discovery, and workspace files.
Memory and skills
The memory browser and relationship graph inspect filesystem-backed memory and linked
session knowledge. The Skills Hub discovers local skill roots and scans registry content
before installation.
Schedules and activity
Recurring task templates create dated work on a cron schedule. The activity stream combines
agent, task, and system events for operator review.
Documentation
| Guide | Use it for |
|---|---|
| Quickstart | Register an agent and run the first task loop |
| Agent setup | Sources, identities, SOUL files, and heartbeats |
| Orchestration | Dispatch, handoffs, workflows, and review gates |
| CLI and MCP | Headless commands and agent tools |
| CLI integration | Claude Code, Codex, and gateway-free connections |
| Deployment | Local, Docker, standalone, reverse proxy, and VPS setup |
| Security hardening | Network, container, CSP, and secret controls |
| Support | Questions, bugs, feature proposals, and security-report routing |
| OpenClaw compatibility | Config and state-directory behavior |
| Release process | Versioning, tags, images, and release checks |
Architecture
Web UI ─┐
CLI ────┼── auth ─ dispatch ─ events ─ policy ─ receipts
MCP ────┤ │
REST ───┘ SQLite + agent runtimes| Layer | Technology |
|---|---|
| Application | Next.js 16 App Router, React 19, TypeScript 5 |
| Interface | Tailwind CSS 4, Zustand, Recharts, xterm.js |
| State | SQLite through better-sqlite3, with WAL mode |
| Boundaries | REST/OpenAPI, MCP, CLI, WebSocket, and SSE |
| Access | Session cookies, API keys, Google sign-in, and role checks |
| Validation | Zod at input boundaries |
| Verification | Vitest, Playwright, ESLint, TypeScript, build, and API parity checks |
Runtime data defaults to .data/. Set MISSION_CONTROL_DATA_DIR to an absolute persistent
path for standalone deployments. The complete environment contract is in.env.example.
Security boundary
- Keep Mission Control on a trusted network unless a TLS reverse proxy and
MC_ALLOWED_HOSTSare configured. - Replace or securely store generated credentials before broader access.
- Use the hardened Compose overlay for production-like container deployments.
- Treat agent messages, skill packages, webhooks, and MCP content as untrusted input.
- Report vulnerabilities through SECURITY.md, not a public issue.
Access controls and security inspection surfaces are included, but alpha status
still applies. Read SECURITY-HARDENING.md before relying on a
network-accessible deployment.
Develop
pnpm install --frozen-lockfile
pnpm lint
pnpm typecheck
pnpm test
pnpm build
pnpm test:e2epnpm quality:gate runs the full repository gate. Useful diagnostics:
bash scripts/station-doctor.sh
bash scripts/security-audit.sh
pnpm api:parityCommon local failures:
| Symptom | Check |
|---|---|
| Login returns an internal error after changing Node versions | Run pnpm rebuild better-sqlite3 |
| Docker cannot reach the gateway | Set OPENCLAW_GATEWAY_HOST=host.docker.internal |
| Browser WebSocket cannot connect | Leave NEXT_PUBLIC_GATEWAY_HOST empty or set a browser-reachable host |
Password text after # disappears |
Quote AUTH_PASS or use AUTH_PASS_B64 |
See CONTRIBUTING.md for contribution scope, coding standards, and review
expectations. Community conduct is defined in CODE_OF_CONDUCT.md.
Project status and support
Release notes live in CHANGELOG.md. Open issues are the current roadmap;
the project does not promise dates for unassigned work.
- Bugs and feature proposals: GitHub Issues
- Vulnerabilities: private reporting instructions
- Builderz Labs: builderz.dev
- Maintained by Nyk. Sponsor Nyk or Builderz Labs. Follow @nykdotdev.
License
MIT © 2026 Builderz Labs
Overview (`tests/README.md`)
E2E Tests
Playwright end-to-end specs for Mission Control API and UI.
Running
# Start the dev server first (or let Playwright auto-start via reuseExistingServer)
pnpm dev --hostname 127.0.0.1 --port 3005
# Run all tests
pnpm test:e2e
# Run offline OpenClaw harness (no OpenClaw install required)
pnpm test:e2e:openclaw
# Run a specific spec
pnpm exec playwright test tests/tasks-crud.spec.tsTest Environment
Tests require .env.local with:
API_KEY=test-api-key-e2e-12345MC_DISABLE_RATE_LIMIT=1(bypasses mutation/read rate limits, keeps login rate limit active)
OpenClaw Offline Harness
The harness runs Mission Control against fixture data and mock binaries/gateway:
- fixtures:
tests/fixtures/openclaw/ - mock CLI:
scripts/e2e-openclaw/bin/{openclaw,clawdbot} - mock gateway:
scripts/e2e-openclaw/mock-gateway.mjs
Profiles:
pnpm test:e2e:openclaw:local- local mode (gateway not running)pnpm test:e2e:openclaw:gateway- gateway mode (mock gateway running)
Spec Files
Security & Auth
auth-guards.spec.ts— All API routes return 401 without authcsrf-validation.spec.ts— CSRF origin header validationlegacy-cookie-removed.spec.ts— Old cookie format rejectedlogin-flow.spec.ts— Login, session, redirect lifecyclerate-limiting.spec.ts— Login brute-force protectiontiming-safe-auth.spec.ts— Constant-time API key comparisonworkspace-isolation.spec.ts— Real HTTP denial of cross-workspace list, search, read, update, and delete attempts
CRUD Lifecycle
tasks-crud.spec.ts— Tasks POST/GET/PUT/DELETE with filters, Aegis gateagents-crud.spec.ts— Agents CRUD, lookup by name/id, admin-only deletetask-comments.spec.ts— Threaded comments on tasksworkflows-crud.spec.ts— Workflow template CRUDwebhooks-crud.spec.ts— Webhooks with secret masking and regenerationalerts-crud.spec.ts— Alert rule CRUD with full lifecycleuser-management.spec.ts— User admin CRUD
Features
notifications.spec.ts— Notification delivery and read trackingquality-review.spec.ts— Quality reviews with batch lookupsearch-and-export.spec.ts— Global search, data export, activity feed
Infrastructure
limit-caps.spec.ts— Endpoint limit caps enforceddelete-body.spec.ts— DELETE body standardization
Shared
helpers.ts— Factory functions (createTestTask,createTestAgent, etc.) and cleanup helpers
Overview (`skills/mission-control-installer/README.md`)
Mission Control Installer Skill
Install and configure Mission Control on any Linux or macOS system.
What This Skill Does
- Detects the target OS and available runtimes (Docker or Node.js 20+)
- Clones or updates the Mission Control repository
- Generates a secure
.envwith random credentials - Starts the dashboard via Docker Compose or local Node.js
- Runs an OpenClaw fleet health check (cleans stale PIDs, old logs, validates gateway)
- Prints the access URL and admin credentials
Usage
Run the installer script:
# Auto-detect deployment mode (prefers Docker)
bash install.sh
# Force Docker deployment
bash install.sh --docker
# Force local deployment (Node.js + pnpm)
bash install.sh --local
# Custom port
bash install.sh --port 8080
# Skip OpenClaw fleet check
bash install.sh --skip-openclawOr as a one-liner:
curl -fsSL https://raw.githubusercontent.com/builderz-labs/mission-control/main/install.sh | bashPrerequisites
- Docker mode: Docker Engine with Docker Compose v2
- Local mode: Node.js 20+, pnpm (auto-installed via corepack if missing)
- Both: git (to clone the repository)
Post-Install
After installation:
- Open
http://localhost:3000(or your configured port) - Log in with the credentials printed by the installer (also in
.env) - Configure your OpenClaw gateway connection in Settings
- Register agents via the Agents panel
Environment Configuration
The installer generates a .env from .env.example with secure random values for:
AUTH_PASS— 24-character random passwordAPI_KEY— 32-character hex API keyAUTH_SECRET— 32-character session secret
To regenerate credentials independently:
bash scripts/generate-env.sh --forceOverview (`skills/mission-control-manage/README.md`)
Mission Control Management Skill
Manage a running Mission Control instance programmatically.
API Endpoints
All endpoints require authentication via x-api-key header or session cookie.
Health Check
# Quick health status
curl -H "x-api-key: $API_KEY" http://localhost:3000/api/status?action=health
# Response: { "status": "healthy", "version": "1.3.0", "checks": [...] }Possible statuses: healthy, degraded, unhealthy
System Overview
# Full system status (memory, disk, sessions, processes)
curl -H "x-api-key: $API_KEY" http://localhost:3000/api/status?action=overviewDiagnostics (Admin Only)
# Comprehensive diagnostics including security posture
curl -H "x-api-key: $API_KEY" http://localhost:3000/api/diagnostics
# Response includes:
# - system: node version, platform, memory, docker detection
# - security: score (0-100) with individual checks
# - database: size, WAL mode, migration version
# - gateway: configured, reachable, host/port
# - agents: total count, by status
# - retention: configured retention policiesCheck for Updates
curl -H "x-api-key: $API_KEY" http://localhost:3000/api/releases/check
# Response: { "updateAvailable": true, "currentVersion": "1.3.0", "latestVersion": "1.4.0", ... }Trigger Update
# Apply available update (bare-metal only; Docker returns instructions)
curl -X POST -H "x-api-key: $API_KEY" http://localhost:3000/api/releases/updateDatabase Backup
curl -X POST -H "x-api-key: $API_KEY" http://localhost:3000/api/backupAgent Management
# List agents
curl -H "x-api-key: $API_KEY" http://localhost:3000/api/agents
# Register an agent
curl -X POST -H "x-api-key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "my-agent", "type": "openclaw"}' \
http://localhost:3000/api/agentsStation Doctor
For local diagnostics without API access:
bash scripts/station-doctor.shChecks: Docker health, port availability, disk space, DB integrity, backup age.
Common Workflows
Automated Health Monitoring
# Check health and alert if unhealthy
STATUS=$(curl -sf -H "x-api-key: $API_KEY" http://localhost:3000/api/status?action=health | jq -r '.status')
if [ "$STATUS" != "healthy" ]; then
echo "ALERT: Mission Control is $STATUS"
fiPre-Upgrade Checklist
- Check for updates:
GET /api/releases/check - Create backup:
POST /api/backup - Run diagnostics:
GET /api/diagnostics(verify no active tasks) - Apply update:
POST /api/releases/update(ordocker pull+ recreate for Docker) - Verify health:
GET /api/status?action=health
Quickstart (`docs/quickstart.md`)
Quickstart: Your First Agent in 5 Minutes
Get from zero to a working agent loop with nothing but Mission Control and curl. No gateway, no OpenClaw, no extra dependencies.
Prerequisites
- Mission Control running (
pnpm devor Docker) - An admin account (visit
/setupon first run) - Your API key (auto-generated on first run, shown in Settings)
Step 1: Start Mission Control
pnpm devOpen http://localhost:3000 and log in. If this is your first run, visit http://localhost:3000/setup to create your admin account.
Your API key is displayed in Settings > API Key. Export it for the commands below:
export MC_URL=http://localhost:3000
export MC_API_KEY=your-api-keyStep 2: Register an Agent
Agents can self-register via the API. This is how autonomous agents announce themselves to Mission Control:
curl -s -X POST "$MC_URL/api/agents/register" \
-H "Authorization: Bearer $MC_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "scout", "role": "researcher"}' | jqExpected response:
{
"agent": {
"id": 1,
"name": "scout",
"role": "researcher",
"status": "idle",
"created_at": 1711234567
},
"registered": true,
"message": "Agent registered successfully"
}Note the id — you'll need it for heartbeats. The registration is idempotent: calling it again with the same name just updates the agent's status to idle.
Valid roles: coder, reviewer, tester, devops, researcher, assistant, agent
Step 3: Create a Task
curl -s -X POST "$MC_URL/api/tasks" \
-H "Authorization: Bearer $MC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Research competitor pricing",
"description": "Find pricing pages for the top 3 competitors and summarize their tiers.",
"priority": "medium",
"assigned_to": "scout"
}' | jqExpected response:
{
"task": {
"id": 1,
"title": "Research competitor pricing",
"status": "assigned",
"priority": "medium",
"assigned_to": "scout",
"tags": [],
"metadata": {}
}
}The task starts in assigned status because you specified assigned_to. If you omit it, the task goes to inbox for manual triage.
Step 4: Poll the Task Queue
This is how your agent picks up work. The queue endpoint atomically claims the highest-priority available task:
curl -s "$MC_URL/api/tasks/queue?agent=scout" \
-H "Authorization: Bearer $MC_API_KEY" | jqExpected response:
{
"task": {
"id": 1,
"title": "Research competitor pricing",
"status": "in_progress",
"assigned_to": "scout"
},
"reason": "assigned",
"agent": "scout",
"timestamp": 1711234600
}The task status automatically moved from assigned to in_progress. The reason field tells you why this task was returned:
| Reason | Meaning |
|---|---|
assigned |
Claimed a new task from the queue |
continue_current |
Agent already has a task in progress |
at_capacity |
Agent is at max concurrent tasks |
no_tasks_available |
Nothing in the queue for this agent |
Step 5: Complete the Task
When your agent finishes work, update the task status and add a resolution:
curl -s -X PUT "$MC_URL/api/tasks/1" \
-H "Authorization: Bearer $MC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"status": "done",
"resolution": "Found pricing for Acme ($29/49/99), Widget Corp ($19/39/79), and Gadget Inc ($25/50/100). All use 3-tier SaaS model. Summary doc attached."
}' | jqStep 6: Send a Heartbeat
Heartbeats tell Mission Control your agent is alive. Without them, agents are marked offline after 10 minutes:
curl -s -X POST "$MC_URL/api/agents/1/heartbeat" \
-H "Authorization: Bearer $MC_API_KEY" \
-H "Content-Type: application/json" \
-d '{}' | jqExpected response:
{
"success": true,
"token_recorded": false,
"work_items": [],
"timestamp": 1711234700
}In a real agent, you'd send heartbeats every 30 seconds in a background loop. The work_items array returns any pending tasks, mentions, or notifications.
The Agent Loop
Here's the complete pattern your agent should follow:
┌─────────────────────────────────┐
│ 1. Register with MC │
│ POST /api/agents/register │
└──────────────┬──────────────────┘
│
v
┌─────────────────────────────────┐
│ 2. Poll for work │◄──────┐
│ GET /api/tasks/queue │ │
└──────────────┬──────────────────┘ │
│ │
v │
┌─────────────────────────────────┐ │
│ 3. Do the work │ │
│ (your agent logic here) │ │
└──────────────┬──────────────────┘ │
│ │
v │
┌─────────────────────────────────┐ │
│ 4. Report result │ │
│ PUT /api/tasks/{id} │ │
└──────────────┬──────────────────┘ │
│ │
v │
┌─────────────────────────────────┐ │
│ 5. Heartbeat + repeat │───────┘
│ POST /api/agents/{id}/hb │
└─────────────────────────────────┘Using the CLI Instead
If you prefer the CLI over curl, the same flow works with pnpm mc:
# List agents
node scripts/mc-cli.cjs agents list --json
# Create an agent
node scripts/mc-cli.cjs agents create --name scout --role researcher --json
# Create a task
node scripts/mc-cli.cjs tasks create --title "Research competitors" --body '{"assigned_to":"scout","priority":"medium"}' --json
# Poll the queue
node scripts/mc-cli.cjs tasks queue --agent scout --json
# Watch events in real time
node scripts/mc-cli.cjs events watch --types task,agentSee CLI Reference for the full command list.
Using the MCP Server (for Claude Code agents)
For agents built with Claude Code, the MCP server is the recommended integration:
claude mcp add mission-control -- node /path/to/mission-control/scripts/mc-mcp-server.cjsSet MC_URL and MC_API_KEY in your environment. The MCP server exposes 35+ tools for agents, tasks, sessions, memory, and more. See CLI Integration for details.
What's Next?
- Agent Setup Guide — Configure SOUL personalities, agent sources, and heartbeat settings
- Orchestration Patterns — Multi-agent workflows, auto-dispatch, quality review gates
- CLI Reference — Full CLI command reference
- CLI Integration — Direct CLI and gateway-free connections
- Deployment Guide — Production deployment options
SCREENSHOT GUIDE (`docs/SCREENSHOT-GUIDE.md`)
Screenshot Guide
This document explains how to capture and review public screenshots without publishing
operator data. Treat every screenshot as a public release artifact.
Screenshots in the README
The README uses conceptual artwork by default. Product screenshots may be added only when
they come from a disposable demo instance and pass the privacy review below.
When to Refresh
Screenshots should be updated when:
- A new page, panel, or major UI component is added
- An existing page layout changes noticeably
- The color scheme or branding updates
- A GitHub Actions
screenshot-driftlabel is applied to a PR (see automation)
How to Take New Screenshots
Prerequisites
- Mission Control running against a new disposable database (
pnpm devor Docker) - Browser with at least 1440×900 viewport recommended
Steps
Start a disposable demo instance. Never capture an operator or production database.
bashpnpm dev # or docker compose upSeed synthetic data only. Use fictional names and values that cannot be mistaken for
production claims.Populate the demo through the UI or a reviewed fixture script. Do not copy an existing
database into the demo environment.Before capture, remove private state. The frame must contain no real names, handles,
email addresses, IDs, tokens, hostnames, paths, workspace names, sessions, logs, costs,
alerts, timestamps, avatars, notifications, or browser profile chrome.Crop and optimise to reduce file size:
bash# macOS pngcrush -reduce -brute input.png output.png # Linux optipng -o5 input.png # or pngquant --quality=80-95 --output output.png input.pngReview the final pixels at full resolution. A second reviewer should inspect every
visible label and value. Strip image metadata, then add the approved file underdocs/.bashcp ~/Downloads/sanitized-demo.png docs/mission-control-demo.png git add docs/ git commit -m "docs: refresh README screenshots"
Automation
The repository has a GitHub Actions workflow (.github/workflows/screenshot-drift.yml) that:
- Detects changes to files under
src/app/,src/components/, andpublic/ - Adds a
screenshot-driftlabel to the PR as a reminder - Posts a checklist comment listing which screenshots may need updating
This does not auto-capture screenshots — it just flags the PR so a human can decide whether the change is visually significant enough to warrant a refresh.
Tips
- Use a consistent browser zoom level (100%) and window size
- Use a clean browser profile and hide bookmarks, extensions, account controls, and dev tools
- Light mode and dark mode screenshots can coexist — add a
*-dark.pngvariant if useful - Prefer PNG for UI screenshots (lossless); JPEG for photos/illustrations
- Do not blur or crop private data as the primary safeguard; regenerate the screenshot from
synthetic state instead
SECURITY HARDENING (`docs/SECURITY-HARDENING.md`)
Security Hardening Guide
Comprehensive security hardening guide for Mission Control and OpenClaw Gateway deployments.
Quick Assessment
Run the automated security audit:
bash scripts/security-audit.sh # Check .env and configuration
bash scripts/station-doctor.sh # Check runtime healthOr use the diagnostics API (admin only):
curl -H "x-api-key: $API_KEY" http://localhost:3000/api/diagnostics
curl -H "x-api-key: $API_KEY" http://localhost:3000/api/security-audit?timeframe=dayThe posture.score field (0-100) gives a quick posture assessment. The Security Audit Panel (/security in the dashboard) provides a full real-time view with timeline charts, agent trust scores, and eval results.
Mission Control Hardening
1. Credentials
Generate strong credentials using the included script:
bash scripts/generate-env.sh # Generates .env with random secrets
chmod 600 .env # Lock down permissionsThe installer (install.sh) does this automatically. If you set up manually, ensure:
AUTH_PASSis 12+ characters, not a dictionary wordAPI_KEYis 32+ hex charactersAUTH_SECRETis a unique random string.envfile permissions are600
2. Network Access Control
Mission Control uses a host allowlist in production:
# Only allow connections from these hosts (comma-separated)
MC_ALLOWED_HOSTS=localhost,127.0.0.1
# For Tailscale: MC_ALLOWED_HOSTS=localhost,127.0.0.1,100.*
# For a domain: MC_ALLOWED_HOSTS=mc.example.com,localhost
# NEVER set this in production:
# MC_ALLOW_ANY_HOST=1Deploy behind a reverse proxy with TLS (Caddy, nginx, Tailscale Funnel) for any network-accessible deployment.
3. HTTPS & Cookies
For HTTPS deployments:
MC_COOKIE_SECURE=1 # Cookies only sent over HTTPS
MC_COOKIE_SAMESITE=strict # CSRF protection
MC_ENABLE_HSTS=1 # HTTP Strict Transport Security4. Rate Limiting
Rate limiting is enabled by default:
| Endpoint Type | Limit |
|---|---|
| Login | 5 attempts/min (always active) |
| Mutations | 60 requests/min |
| Reads | 120 requests/min |
| Heavy operations | 10 requests/min |
| Agent heartbeat | 30/min per agent |
| Agent task polling | 20/min per agent |
Never set MC_DISABLE_RATE_LIMIT=1 in production.
5. Docker Hardening
Use the production compose overlay:
docker compose -f docker-compose.yml -f docker-compose.hardened.yml up -dThis enables:
- Read-only filesystem with tmpfs for
/tmpand/app/.next/cache - Capability dropping — all Linux capabilities dropped, only
NET_BIND_SERVICEretained - No new privileges — prevents privilege escalation
- PID limit — prevents fork bombs
- Memory/CPU limits — prevents resource exhaustion
- Log rotation — prevents disk filling from verbose logging
- HSTS, secure cookies — forced via environment
6. Security Headers
Mission Control sets these headers automatically:
| Header | Value |
|---|---|
Content-Security-Policy |
default-src 'self'; script-src 'self' 'nonce-' 'strict-dynamic'; style-src 'self' 'nonce-' |
X-Frame-Options |
DENY |
X-Content-Type-Options |
nosniff |
Referrer-Policy |
strict-origin-when-cross-origin |
Permissions-Policy |
camera=(), microphone=(), geolocation=() |
X-Request-Id |
Unique per-request UUID for log correlation |
Strict-Transport-Security |
Set when MC_ENABLE_HSTS=1 |
7. Audit Logging
All security-relevant events are logged to the audit trail:
- Login attempts (success and failure)
- Task mutations
- User management actions
- Settings changes
- Update operations
Additionally, the security event system automatically logs:
- Auth failures (invalid passwords, expired tokens, access denials)
- Rate limit hits (429 responses with IP/agent correlation)
- Injection attempts (prompt injection, command injection, exfiltration)
- Secret exposures (AWS keys, GitHub tokens, Stripe keys, JWTs, private keys detected in agent messages)
- MCP tool calls (agent, tool, duration, success/failure)
These events feed into the Security Audit Panel (/security) which provides:
- Posture score (0-100) with level badges (hardened/secure/needs-attention/at-risk)
- Agent trust scores — weighted calculation based on auth failures, injection attempts, and task success rates
- MCP call audit — tool-use frequency, success/failure rates per agent
- Timeline visualization — event density over selected timeframe
Configure retention: MC_RETAIN_AUDIT_DAYS=365 (default: 1 year).
8. Hook Profiles
Security strictness is tunable via hook profiles in Settings > Security Profiles:
| Profile | Secret Scanning | MCP Auditing | Block on Secrets | Rate Limit Multiplier |
|---|---|---|---|---|
| minimal | Off | Off | No | 2x (relaxed) |
| standard (default) | On | On | No | 1x |
| strict | On | On | Yes (blocks messages) | 0.5x (tighter) |
Set via the Settings panel or the hook_profile key in the settings API.
9. Agent Eval Framework
The four-layer eval stack helps detect degrading agent quality:
- Output evals — score task completion against golden datasets
- Trace evals — convergence scoring (>3.0 indicates looping behavior)
- Component evals — tool reliability from MCP call logs (p50/p95/p99 latency)
- Drift detection — 10% threshold vs 4-week rolling baseline triggers alerts
Access via /api/agents/evals or the Security Audit Panel's eval section.
10. Data Retention
MC_RETAIN_ACTIVITIES_DAYS=90 # Activity feed
MC_RETAIN_AUDIT_DAYS=365 # Security audit trail
MC_RETAIN_LOGS_DAYS=30 # Application logs
MC_RETAIN_NOTIFICATIONS_DAYS=60 # Notifications
MC_RETAIN_PIPELINE_RUNS_DAYS=90 # Pipeline logs
MC_RETAIN_TOKEN_USAGE_DAYS=90 # Token/cost records
MC_RETAIN_GATEWAY_SESSIONS_DAYS=90 # Gateway session history11. Runtime Installer Integrity
Dashboard-triggered OpenClaw and Hermes installations execute third-party
shell installers. Local runtime installation is disabled by default. Enable it
only after reviewing the source and rollback path. Mission Control also
requires an operator-approved SHA-256 digest before either remote script can
run:
MC_ENABLE_RUNTIME_INSTALLS=1
MC_OPENCLAW_INSTALLER_SHA256=<64 lowercase hex characters>
MC_HERMES_INSTALLER_SHA256=<64 lowercase hex characters>
# Required only for per-user installs from the super-admin organization flow:
MC_OPENCLAW_GIT_COMMIT=<reviewed 40-character commit SHA>
MC_CLAUDE_CODE_VERSION=<exact semver>
MC_CODEX_VERSION=<exact semver>Download the installer separately through a trusted channel, inspect it, and
calculate its digest with sha256sum install.sh (Linux) orshasum -a 256 install.sh (macOS). If the publisher changes the installer,
the dashboard install fails closed until you review the new bytes and update
the configured digest. Regex and optional AI review remain defense-in-depth;
they do not replace provenance verification.
OpenClaw Gateway Hardening
Mission Control acts as the mothership for your OpenClaw fleet. The installer automatically checks and repairs common OpenClaw configuration issues.
1. Network Security
- Never expose the gateway publicly. It runs on port 18789 by default.
- Bind to localhost: Set
gateway.bind: "loopback"inopenclaw.json. - Use SSH tunneling or Tailscale for remote access.
- Docker users: Be aware that Docker can bypass UFW rules. Use
DOCKER-USERchain rules.
2. Authentication
- Always enable gateway auth with a strong random token.
- Generate:
openclaw doctor --generate-gateway-token - Store in
OPENCLAW_GATEWAY_TOKENenv var (never inNEXT_PUBLIC_*variables). - Rotate regularly.
3. Hardened Gateway Configuration
{
"gateway": {
"mode": "local",
"bind": "loopback",
"auth": {
"mode": "token",
"token": "replace-with-long-random-token"
}
},
"session": {
"dmScope": "per-channel-peer"
},
"tools": {
"profile": "messaging",
"deny": ["group:automation", "group:runtime", "group:fs", "sessions_spawn", "sessions_send"],
"fs": { "workspaceOnly": true },
"exec": { "security": "deny", "ask": "always" }
},
"elevated": { "enabled": false }
}4. File Permissions
chmod 700 ~/.openclaw
chmod 600 ~/.openclaw/openclaw.json
chmod 600 ~/.openclaw/credentials/*5. Tool Security
- Apply the principle of least privilege — only grant tools the agent needs.
- Audit third-party skills before installing (Mission Control's Skills Hub runs automatic security scans).
- Run agents processing untrusted content in a sandbox with a minimal toolset.
6. Monitoring
- Enable comprehensive logging:
logging.redactSensitive: "tools" - Store logs separately where agents cannot modify them.
- Use Mission Control's diagnostics API to monitor gateway health.
- Have an incident response plan: stop gateway, revoke API keys, review audit logs.
7. Known CVEs
Keep OpenClaw updated. Notable past vulnerabilities:
| CVE | Severity | Description | Fixed In |
|---|---|---|---|
| CVE-2026-25253 | Critical | RCE via Control UI token hijack | v2026.1.29 |
| CVE-2026-26327 | High | Auth bypass via gateway spoofing | v2026.2.25 |
| CVE-2026-26322 | High | SSRF | v2026.2.25 |
| CVE-2026-26329 | High | Path traversal | v2026.2.25 |
| CVE-2026-26319 | Medium | Missing webhook auth | v2026.2.25 |
Deployment Architecture
For production, the recommended architecture is:
Internet
|
[Reverse Proxy (Caddy/nginx) + TLS]
|
[Mission Control :3000] ---- [SQLite .data/]
|
[OpenClaw Gateway :18789 (localhost only)]
|
[Agent Workspaces]- Reverse proxy handles TLS termination, rate limiting, and access control
- Mission Control listens on localhost or a private network
- OpenClaw Gateway is bound to loopback only
- Agent workspaces are isolated per-agent directories
Agent Auth: Least-Privilege Key Guidance
The Problem
The global API key (API_KEY env var) grants full admin access. When agents use it, they can:
- Create/delete other agents
- Modify any task or project
- Rotate the API key itself
- Access all workspaces
This violates least-privilege. A compromised agent session leaks admin access.
Recommended: Agent-Scoped Keys
Create per-agent keys with limited scopes:
# Create a scoped key for agent "Aegis" (via CLI)
pnpm mc raw --method POST --path /api/agents/5/keys --body '{
"name": "aegis-worker",
"scopes": ["viewer", "agent:self", "agent:diagnostics", "tasks:write"],
"expires_in_days": 30
}' --jsonScoped keys:
- Can only act as the agent they belong to (no cross-agent access)
- Have explicit scope lists (viewer, agent:self, tasks:write, etc.)
- Auto-expire after a set period
- Can be revoked without affecting other agents
- Are logged separately in the audit trail
Auth Hierarchy
| Method | Role | Use Case |
|---|---|---|
Agent-scoped key (mca_...) |
Per-scope | Autonomous agents (recommended) |
| Global API key | admin | Admin scripts, CI/CD, initial setup |
| Session cookie | Per-user role | Human operators via web UI |
| Proxy header | Per-user role | SSO/gateway-authenticated users |
Monitoring Global Key Usage
Mission Control logs a security event (global_api_key_used) every time the global API key is used. Monitor these in the audit log:
pnpm mc raw --method GET --path '/api/security-audit?event_type=global_api_key_used&timeframe=day' --jsonGoal: drive global key usage to zero in production by replacing with scoped agent keys.
Rate Limiting by Agent Identity
Agent-facing endpoints use per-agent rate limiters (keyed by x-agent-name header):
- Heartbeat: 30/min per agent
- Task polling: 20/min per agent
- Self-registration: 5/min per IP
This prevents a runaway agent from consuming the entire rate limit budget.
Rate Limit Backend Strategy
Current: in-memory Map per process (suitable for single-instance deployments).
For multi-instance deployments, the rate limiter supports a pluggable backend via the createRateLimiter factory. Future options:
- Redis: shared state across instances (use Upstash or self-hosted)
- SQLite WAL: leverage the existing DB for cross-process coordination
- Edge KV: for edge-deployed instances
The current implementation includes:
- Periodic cleanup (60s interval)
- Capacity-bounded maps (default 10K entries, LRU eviction)
- Trusted proxy IP parsing (
MC_TRUSTED_PROXIES)
No action needed for single-instance deployments. For multi-instance, implement a custom RateLimitStore interface when scaling beyond 1 node.
Agent Setup (`docs/agent-setup.md`)
Agent Setup Guide
This guide covers everything you need to configure agents in Mission Control: registration methods, SOUL personalities, working files, configuration, and liveness monitoring.
Agent Registration
There are three ways to register agents with Mission Control.
Method 1: API Self-Registration (Recommended for Autonomous Agents)
Agents register themselves at startup. This is the simplest path and requires no manual setup:
curl -X POST http://localhost:3000/api/agents/register \
-H "Authorization: Bearer $MC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "scout",
"role": "researcher",
"capabilities": ["web-search", "summarization"],
"framework": "claude-sdk"
}'Name rules: 1-63 characters, alphanumeric plus ., -, _. Must start with a letter or digit.
Valid roles: coder, reviewer, tester, devops, researcher, assistant, agent
The endpoint is idempotent — registering the same name again updates the agent's status to idle and refreshes last_seen. Rate-limited to 5 registrations per minute per IP.
Method 2: Manual Creation (UI or API)
Create agents through the dashboard UI or the API:
curl -X POST http://localhost:3000/api/agents \
-H "Authorization: Bearer $MC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "aegis",
"role": "reviewer",
"status": "offline",
"soul_content": "You are Aegis, the quality reviewer...",
"config": {
"dispatchModel": "9router/cc/claude-opus-4-6",
"openclawId": "aegis"
}
}'This requires operator role and supports additional fields like soul_content, config, and template.
Method 3: Config Sync (OpenClaw or Local Discovery)
Mission Control can auto-discover agents from:
OpenClaw config sync — Reads agents from your openclaw.json file:
curl -X POST http://localhost:3000/api/agents/sync \
-H "Authorization: Bearer $MC_API_KEY" \
-H "Content-Type: application/json" \
-d '{"source": "config"}'Set OPENCLAW_CONFIG_PATH to point to your openclaw.json.
Local agent discovery — Scans standard directories for agent definitions:
curl -X POST http://localhost:3000/api/agents/sync \
-H "Authorization: Bearer $MC_API_KEY" \
-H "Content-Type: application/json" \
-d '{"source": "local"}'Scanned directories:
~/.agents/— Top-level agent directories or.mdfiles~/.codex/agents/— Codex agent definitions~/.claude/agents/— Claude Code agent definitions~/.hermes/skills/— Hermes skill definitions
Agent directories are detected by the presence of marker files: soul.md, AGENT.md, identity.md, config.json, or agent.json.
Flat markdown files (Claude Code format) are also supported:
---
name: my-agent
description: A research assistant
model: claude-opus-4
tools: ["read", "write", "web-search"]
---
You are a research assistant specializing in competitive analysis...SOUL.md — Agent Personality
SOUL is the personality and capability definition for an agent. It's a markdown file that gets injected into dispatch prompts, shaping how the agent approaches tasks.
What Goes in a SOUL
A SOUL defines:
- Identity — Who the agent is, its name, role
- Expertise — What domains it specializes in
- Behavior — How it approaches problems, communication style
- Constraints — What it should avoid, limitations
Example: Developer Agent
# Scout — Developer
You are Scout, a senior developer agent specializing in full-stack TypeScript development.
## Expertise
- Next.js, React, Node.js
- Database design (PostgreSQL, SQLite)
- API architecture and testing
## Approach
- Read existing code before proposing changes
- Write tests alongside implementation
- Keep changes minimal and focused
## Constraints
- Never commit secrets or credentials
- Ask for clarification on ambiguous requirements
- Flag security concerns immediatelyExample: Researcher Agent
# Iris — Researcher
You are Iris, a research agent focused on gathering and synthesizing information.
## Expertise
- Web research and source verification
- Competitive analysis
- Data synthesis and report writing
## Approach
- Always cite sources with URLs
- Present findings in structured format
- Distinguish facts from inferences
## Output Format
- Use bullet points for key findings
- Include a "Sources" section at the end
- Highlight actionable insightsExample: Reviewer Agent
# Aegis — Quality Reviewer
You are Aegis, the quality gate for all agent work in Mission Control.
## Role
Review completed tasks for correctness, completeness, and quality.
## Review Criteria
- Does the output address all parts of the task?
- Are there factual errors or hallucinations?
- Is the work actionable and well-structured?
## Verdict Format
Respond with EXACTLY one of:
VERDICT: APPROVED
NOTES: <brief summary>
VERDICT: REJECTED
NOTES: <specific issues to fix>Managing SOUL Content
Read an agent's SOUL:
curl -s http://localhost:3000/api/agents/1/soul \
-H "Authorization: Bearer $MC_API_KEY" | jqResponse:
{
"soul_content": "# Scout — Developer\n...",
"source": "workspace",
"available_templates": ["developer", "researcher", "reviewer"],
"updated_at": 1711234567
}The source field tells you where the SOUL was loaded from:
workspace— Read from the agent's workspacesoul.mdfile on diskdatabase— Read from the MC database (no workspace file found)none— No SOUL content set
Update a SOUL:
curl -X PUT http://localhost:3000/api/agents/1/soul \
-H "Authorization: Bearer $MC_API_KEY" \
-H "Content-Type: application/json" \
-d '{"soul_content": "# Scout — Developer\n\nYou are Scout..."}'Apply a template:
curl -X PUT http://localhost:3000/api/agents/1/soul \
-H "Authorization: Bearer $MC_API_KEY" \
-H "Content-Type: application/json" \
-d '{"template_name": "developer"}'Templates support substitution variables: {{AGENT_NAME}}, {{AGENT_ROLE}}, {{TIMESTAMP}}.
SOUL content syncs bidirectionally — edits in the UI write back to the workspace soul.md file, and changes on disk are picked up on the next sync.
WORKING.md — Runtime Scratchpad
WORKING.md is an agent's runtime state file. It tracks:
- Current task context
- Intermediate results
- Session notes from the agent's perspective
Do not hand-edit WORKING.md — it's written and managed by the agent during task execution. If you need to give an agent persistent instructions, use SOUL.md instead.
Agent Configuration
Each agent has a JSON config object stored in the database. Key fields:
| Field | Type | Description |
|---|---|---|
openclawId |
string | Gateway agent identifier (falls back to agent name) |
dispatchModel |
string | Model override for auto-dispatch (e.g., 9router/cc/claude-opus-4-6) |
capabilities |
string[] | List of agent capabilities |
framework |
string | Framework that created the agent (e.g., claude-sdk, crewai) |
Example config:
{
"openclawId": "scout",
"dispatchModel": "9router/cc/claude-sonnet-4-6",
"capabilities": ["code-review", "testing", "documentation"],
"framework": "claude-sdk"
}Update via API:
curl -X PUT http://localhost:3000/api/agents \
-H "Authorization: Bearer $MC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"id": 1,
"config": {
"dispatchModel": "9router/cc/claude-opus-4-6"
}
}'Heartbeat and Liveness
Mission Control tracks agent health through heartbeats.
How It Works
- Agent sends
POST /api/agents/{id}/heartbeatevery 30 seconds - MC updates
statustoidleand refresheslast_seen - If no heartbeat for 10 minutes (configurable), agent is marked
offline - Stale tasks (in_progress for 10+ min with offline agent) are requeued
Heartbeat Request
curl -X POST http://localhost:3000/api/agents/1/heartbeat \
-H "Authorization: Bearer $MC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"token_usage": {
"model": "claude-sonnet-4-6",
"inputTokens": 1500,
"outputTokens": 300
}
}'The heartbeat response includes pending work items (assigned tasks, mentions, notifications), so agents can use it as both a keepalive and a lightweight work check.
Agent Status Values
| Status | Meaning |
|---|---|
offline |
No recent heartbeat, agent is unreachable |
idle |
Online and ready for work |
busy |
Currently executing a task |
sleeping |
Paused by user (wake with POST /api/agents/{id}/wake) |
error |
Agent reported an error state |
Agent Sources
The source field on each agent indicates how it was registered:
| Source | Origin |
|---|---|
manual |
Created through UI or direct API call |
self |
Agent self-registered via /api/agents/register |
local |
Discovered from ~/.agents/, ~/.claude/agents/, etc. |
config |
Synced from openclaw.json |
gateway |
Registered by a gateway connection |
Agent Templates
When creating agents via API, you can specify a template name to pre-populate the config:
curl -X POST http://localhost:3000/api/agents \
-H "Authorization: Bearer $MC_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "scout", "role": "coder", "template": "developer"}'Templates define model tier, tool permissions, and default configuration. Available templates include:
developer— Full coding toolset (read, write, edit, exec, bash)researcher— Read-only tools plus web and memory accessreviewer— Read-only tools for code review and quality checks
What's Next
- Quickstart — 5-minute first agent tutorial
- Orchestration Patterns — Multi-agent workflows, auto-dispatch, quality review
- CLI Reference — Full CLI command reference
Cli Agent Control (`docs/cli-agent-control.md`)
Mission Control CLI for Agent-Complete Operations (v2)
This repository includes a first-party CLI at:
- scripts/mc-cli.cjs
Designed for autonomous/headless usage first:
- API key auth support
- Profile persistence (~/.mission-control/profiles/*.json)
- Stable JSON mode (
--json) with NDJSON for streaming - Deterministic exit code categories
- SSE streaming for real-time event watching
- Compound subcommands for memory, soul, comments
Quick start
- Ensure Mission Control API is running.
- Set environment variables or use profile flags:
- MC_URL=http://127.0.0.1:3000
- MC_API_KEY=your-key
- Run commands:
node scripts/mc-cli.cjs agents list --json
node scripts/mc-cli.cjs tasks queue --agent Aegis --max-capacity 2 --json
node scripts/mc-cli.cjs sessions control --id <session-id> --action terminateCommand groups
auth
- login --username --password
- logout
- whoami
agents
- list
- get --id
- create --name --role [--body '{}']
- update --id [--body '{}']
- delete --id
- wake --id
- diagnostics --id
- heartbeat --id
- attribution --id [--hours 24] [--section identity,cost] [--privileged]
- memory get --id
- memory set --id --content "..." [--append]
- memory set --id --file ./memory.md
- memory clear --id
- soul get --id
- soul set --id --content "..."
- soul set --id --file ./soul.md
- soul set --id --template operator
- soul templates --id [--template name]
tasks
- list
- get --id
- create --title [--body '{}']
- update --id [--body '{}']
- delete --id
- queue --agent
[--max-capacity 2] - broadcast --id --message "..."
- comments list --id
- comments add --id --content "..." [--parent-id 5]
sessions
- list
- control --id --action monitor|pause|terminate
- continue --kind claude-code|codex-cli --id --prompt "..."
- transcript --kind claude-code|codex-cli|hermes --id [--limit 40] [--source]
connect
- register --tool-name --agent-name [--body '{}']
- list
- disconnect --connection-id
tokens
- list [--timeframe hour|day|week|month|all]
- stats [--timeframe]
- by-agent [--days 30]
- agent-costs [--timeframe]
- task-costs [--timeframe]
- trends [--timeframe]
- export [--format json|csv] [--timeframe] [--limit]
- rotate (shows current key info)
- rotate --confirm (generates new key -- admin only)
skills
- list
- content --source --name
- check --source --name
- upsert --source --name --file ./skill.md
- delete --source --name
cron
- list
- create/update/pause/resume/remove/run [--body '{}']
events
watch [--types agent,task] [--timeout-ms 3600000]
Streams SSE events to stdout. In
--jsonmode, outputs NDJSON (one JSON object per line). Press Ctrl+C to stop.
status
- health (no auth required)
- overview
- dashboard
- gateway
- models
- capabilities
export (admin)
- audit [--format json|csv] [--since ] [--until ] [--limit]
- tasks [--format json|csv] [--since] [--until] [--limit]
- activities [--format json|csv] [--since] [--until] [--limit]
- pipelines [--format json|csv] [--since] [--until] [--limit]
raw
- raw --method GET --path /api/... [--body '{}']
Exit code contract
- 0 success
- 2 usage error
- 3 auth error (401)
- 4 permission error (403)
- 5 network/timeout
- 6 server error (5xx)
API contract parity gate
To detect drift between Next.js route handlers and openapi.json, use:
node scripts/check-api-contract-parity.mjs \
--root . \
--openapi openapi.json \
--ignore-file scripts/api-contract-parity.ignoreMachine output:
node scripts/check-api-contract-parity.mjs --jsonThe checker scans src/app/api/**/route.ts(x), derives operations (METHOD + /api/path), compares against OpenAPI operations, and exits non-zero on mismatch.
Baseline policy in this repo:
scripts/api-contract-parity.ignorecurrently stores a temporary baseline of known drift.- CI enforces no regressions beyond baseline.
- When you fix a mismatch, remove its line from ignore file in the same PR.
- Goal is monotonic burn-down to an empty ignore file.
Next steps
- Promote script to package.json bin entry (
mc). - Add retry/backoff for transient failures.
- Add integration tests that run the CLI against a test server fixture.
- Add richer pagination/filter flags for list commands.
Cli Integration (`docs/cli-integration.md`)
Direct CLI Integration
Connect CLI tools (Claude Code, Codex, custom agents) directly to Mission Control without a gateway.
Quick Start
1. Register a connection
curl -X POST http://localhost:3000/api/connect \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"tool_name": "claude-code",
"tool_version": "1.0.0",
"agent_name": "my-agent",
"agent_role": "developer"
}'Response:
{
"connection_id": "550e8400-e29b-41d4-a716-446655440000",
"agent_id": 42,
"agent_name": "my-agent",
"status": "connected",
"sse_url": "/api/events",
"heartbeat_url": "/api/agents/42/heartbeat",
"token_report_url": "/api/tokens"
}- If
agent_namedoesn't exist, it's auto-created. - Previous connections for the same agent are automatically deactivated.
2. Heartbeat loop
Send heartbeats to stay alive and optionally report token usage:
curl -X POST http://localhost:3000/api/agents/42/heartbeat \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"connection_id": "550e8400-e29b-41d4-a716-446655440000",
"token_usage": {
"model": "claude-sonnet-4",
"inputTokens": 1500,
"outputTokens": 800
}
}'Response includes work items (mentions, assigned tasks, notifications) plus "token_recorded": true if usage was reported.
Recommended heartbeat interval: 30 seconds.
3. Subscribe to events (SSE)
curl -N http://localhost:3000/api/events \
-H "x-api-key: YOUR_API_KEY"Receives real-time events: task assignments, mentions, agent status changes, etc.
4. Report token usage
For bulk token reporting (separate from heartbeat):
curl -X POST http://localhost:3000/api/tokens \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"model": "claude-sonnet-4",
"sessionId": "my-agent:chat",
"inputTokens": 5000,
"outputTokens": 2000
}'5. Disconnect
curl -X DELETE http://localhost:3000/api/connect \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{"connection_id": "550e8400-e29b-41d4-a716-446655440000"}'Sets the agent offline if no other active connections exist.
API Reference
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| POST | /api/connect |
operator | Register CLI connection |
| GET | /api/connect |
viewer | List all connections |
| DELETE | /api/connect |
operator | Disconnect by connection_id |
| POST | /api/agents/{id}/heartbeat |
operator | Heartbeat with optional token reporting |
| GET | /api/events |
viewer | SSE event stream |
| POST | /api/tokens |
operator | Report token usage |
Connection Lifecycle
POST /api/connect → Agent set online
↓
Heartbeat loop (30s) → Reports tokens, receives work items
↓
DELETE /api/connect → Agent set offline (if no other connections)Notes
- Each agent can only have one active connection at a time. A new
POST /api/connectfor the same agent deactivates the previous connection. - The
sessionIdformat for token reporting follows{agentName}:{chatType}convention (e.g.,my-agent:chat,my-agent:cli). - Heartbeat responses include pending work items (assigned tasks, mentions, notifications) so CLI tools can act on them.
Deployment (`docs/deployment.md`)
Deployment Guide
Prerequisites
- Node.js >= 20 (LTS recommended)
- pnpm (installed via corepack:
corepack enable && corepack prepare pnpm@latest --activate)
Ubuntu / Debian
better-sqlite3 requires native compilation tools:
sudo apt-get update
sudo apt-get install -y python3 make g++macOS
Xcode command line tools are required:
xcode-select --installQuick Start (Development)
cp .env.example .env.local
pnpm install
pnpm devOpen http://localhost:3000. Login with AUTH_USER / AUTH_PASS from your .env.local.
Production (Direct)
pnpm install --frozen-lockfile
pnpm build
pnpm startThe pnpm start script binds to 0.0.0.0:3005. Override with:
PORT=3000 pnpm startImportant: The production build bundles platform-specific native binaries. You must run pnpm install and pnpm build on the same OS and architecture as the target server. A build created on macOS will not work on Linux.
Production (Standalone)
Use this for bare-metal deployments that run Next's standalone server directly.
This path is preferred over ad hoc node .next/standalone/server.js because it
syncs .next/static and public/ into the standalone bundle before launch.
pnpm install --frozen-lockfile
pnpm build
pnpm start:standaloneFor a full in-place update on the target host:
BRANCH=fix/refactor PORT=3000 pnpm deploy:standaloneWhat deploy:standalone does:
- fetches and fast-forwards the requested branch
- reinstalls dependencies with the lockfile
- rebuilds from a clean
.next/ - stops the old process bound to the target port
- starts the standalone server through
scripts/start-standalone.sh - verifies that the rendered login page references a CSS asset and that the CSS is served as
text/css
Production (Docker)
Preferred operator flow (Make controls docker compose):
# 1) choose mode in .env
# MC_MODE=prod # or dev
# OPENCLAW_ENABLED=1 # set 0 to run MC without OpenClaw stack
# 2) run universal verbs
make up
make restart
make down
make statusMode-aware Make workflow (minimal commands)
For day-to-day operations, see the Daily Ops Cheatsheet.
Use .env + .env.openclaw as the single source of truth for mode/host/port/token values.
MC_MODE=prod→docker-compose.ymlMC_MODE=dev→docker-compose-dev.ymlOPENCLAW_ENABLED=1→make <verb> allincludes OpenClawOPENCLAW_ENABLED=0→make <verb> allmanages MC only
Command grammar:
make <verb> [all|mc|openclaw] [dev|prod]allis default scope.dev/prodoverrideMC_MODEfor one command invocation.- Why no
--dev/--prod: GNU Make consumes unknown--xxxtokens as Make options before Makefile goals are parsed, so mode overrides use positional tokens for deterministic behavior. make restart [scope]is deterministic and always executesmake down [scope]followed bymake up [scope].- With default
allscope,OPENCLAW_ENABLED=1includes OpenClaw in both the down and up phases;OPENCLAW_ENABLED=0skips OpenClaw in both phases.
Primary operator commands:
| Workflow | Command |
|---|---|
| Start selected component(s) | `make up [all |
| Restart selected component(s) | `make restart [all |
| Stop selected component(s) | `make down [all |
| Mode + endpoint health summary | `make status [all |
| Refresh source/state only | `make update [all |
| Force rebuild selected component(s) | `make rebuild [all |
Full maintenance (update + rebuild + restart) |
`make upgrade [all |
Mode override examples:
make restart dev
make restart mc dev
make status openclaw
make upgrade prod`update` vs `upgrade`
make update [scope]- Fast-forwards the current Mission Control branch from origin.
- For
scope=all, ifOPENCLAW_ENABLED=1, also refreshes OpenClaw source state. - For
scope=openclaw, refreshes OpenClaw source state regardless ofOPENCLAW_ENABLED. - Does not force an MC image rebuild and does not force restart.
make upgrade [scope]- Runs update + rebuild + restart for selected scope.
scope=mc: MC-only flow.scope=openclaw: OpenClaw update flow (make openclaw-update).scope=all: both flows; OpenClaw path runs whenOPENCLAW_ENABLED=1.
Minimum .env / .env.openclaw keys for this flow:
# .env
MC_MODE=prod
OPENCLAW_ENABLED=1
MC_URL_SCHEME=http
MC_HOST=127.0.0.1
MC_PORT=7012
OPENCLAW_GATEWAY_TOKEN=...
TELEGRAM_BOT_TOKEN=...
TELEGRAM_NUMERIC_USER_ID=123456789
TELEGRAM_DM_POLICY=pairing
TELEGRAM_ALLOW_FROM=
TELEGRAM_OWNER_ALLOW_FROM=
# .env.openclaw (or keep in .env)
OPENCLAW_GATEWAY_PORT=18789
OPENCLAW_CONTROL_UI_PORT=18791
OPENCLAW_GATEWAY_INTERNAL_PORT=18789
OPENCLAW_STATUS_HOST=127.0.0.1docker compose up # with gateway connectivity
docker compose --profile standalone up # without gateway (standalone mode)Or build and run manually:
docker build -t mission-control .
docker run -p 3000:3000 \
-v mission-control-data:/app/.data \
-e AUTH_USER=admin \
-e AUTH_PASS=your-secure-password \
-e API_KEY=your-api-key \
-e OPENCLAW_GATEWAY_HOST=host.docker.internal \
--add-host=host.docker.internal:host-gateway \
mission-controlThe Docker image:
- Builds from
node:22-slimwith multi-stage build - Compiles
better-sqlite3natively inside the container (Linux x64) - Uses Next.js standalone output for minimal image size
- Runs as non-root user
nextjs - Exposes port 3000 (override with
-e PORT=8080)
Gateway Connectivity from Docker
MC inside Docker needs to reach the gateway running on the host. There are two connections:
Server-side (MC backend → gateway): Set
OPENCLAW_GATEWAY_HOST=host.docker.internal.
Docker Desktop (macOS/Windows) resolves this automatically. On Linux,docker-compose.yml
maps it viaextra_hosts.Browser-side (user's browser → gateway WebSocket): When the gateway host is a
Docker-internal name (likehost.docker.internal), MC automatically rewrites the WebSocket
URL to the browser's own hostname. No extra config needed for local Docker usage.
For remote access, setNEXT_PUBLIC_GATEWAY_HOSTto the public hostname.
If your gateway runs in another container, put both on the same Docker network and setOPENCLAW_GATEWAY_HOST to the gateway container name.
Local Security Scan Expectations (HTTP dev vs HTTPS prod)
For local Docker development over plain http://, the following defaults are expected:
- Keep
MC_COOKIE_SECUREunset - Keep
MC_ENABLE_HSTSunset - Use
OPENCLAW_GATEWAY_HOST=host.docker.internalwhen MC runs in Docker and gateway runs on host
MC_COOKIE_SECURE=1 and MC_ENABLE_HSTS=1 are HTTPS-only hardening flags. Enabling them on plain HTTP can break login/session behavior and create misleading local warnings.
Mission Control's security scan treats host.docker.internal as a valid local Docker topology (not a public exposure) and should not be interpreted as a production misconfiguration by itself.
Persistent Data
SQLite database is stored in /app/.data/ inside the container. Mount a volume to persist data across restarts:
docker run -v /path/to/data:/app/.data ...Automatic backups
- Set
MC_AUTO_BACKUP=1(accepts1/true/yes/on) in your.envto enable automatic daily backups without toggling it in the UI. - The backup directory is created automatically when scheduled backups run, so the backup warning clears once the task executes.
Self-contained Operator Setup (Linux host with existing Claude Code / Codex CLIs)
For an operator running MC on a Linux/Docker host who already has authenticatedclaude / codex / opencode CLIs in ~/.local/bin, the defaultdocker-compose.yml projects the host configuration into the container so MC
can drive those same authenticated CLIs without re-login. This path runs MC
without OpenClaw gateway (which is macOS-only).
What the default compose does for this case:
- Image bakes
claudeandcodexas a fallback — if the host doesn't
have them in~/.local/bin, the container's installed copies are used.
The host's~/.local/bincomes first inPATH, so an authenticated host
install transparently shadows the baked one. - Host home is bind-mounted —
${HOME}/.local/bin,${HOME}/.bun,${HOME}/.claude,${HOME}/.claude.json, and${HOME}/.local/share/claude
are mounted under/home/nextjs/...inside the container, plus${HOME}
itself and/mntare mounted at the same absolute paths so file paths the
user sees on the host work identically inside the container. - Container runs as uid 1000 (the slim image's existing
nodeuser,
renamednextjs) so bind-mounted host files (typical Linux uid 1000) are
read/written withoutchown.
Ports. docker-compose.yml maps ${MC_PORT} on the host to ${PORT} in
the container. The bundled Makefile computes its readiness/status URL fromMC_URL_SCHEME, MC_HOST, and MC_PORT loaded from .env.
uid mismatch. If your host user has uid ≠ 1000 (common on macOS, or
multi-user Linux), edit docker-compose.yml:
user: "$(id -u):$(id -g)" # or hard-code your uid:gidOtherwise bind-mounted files in ${HOME} will be read-only inside the
container and Claude Code will fail to write its config.
Memory. The compose file sets memory: 2G deploy limit. The upstream
default of 512M OOM-kills MC when /chat opens a node-pty terminal and the
task-dispatch loop is running concurrently. Do not lower this limit unless
you are sure neither feature is in use.
Direct API dispatch (gateway-free)
When OpenClaw is not present, MC dispatches tasks via direct provider APIs.
Provider is picked by the agent's dispatchModel prefix:
dispatchModel pattern |
Provider | Auth |
|---|---|---|
claude-*, anthropic/* |
Anthropic API | ANTHROPIC_API_KEY |
gpt-*, o1-*, o3-*, openai/* |
OpenAI API | OPENAI_API_KEY |
local/*, ollama/*, lmstudio/*, litellm/* |
OpenAI-compatible | LOCAL_LLM_ENDPOINT (+ optional LOCAL_LLM_API_KEY) |
The "local" provider speaks the OpenAI /v1/chat/completions REST shape, so
LMStudio, Ollama, vLLM, and a liteLLM
proxy all work behind it. For multiple local backends behind one endpoint,
run liteLLM as a sidecar container and point LOCAL_LLM_ENDPOINT at it.
Shared host Claude Code session (`MC_HOST_SESSION_MODE`)
/chat can drive a Claude Code session that the operator has open in a host
terminal — both processes share the same ~/.claude/projects/<encoded>/.jsonl
transcript. Pick the policy via env:
| Mode | Behaviour |
|---|---|
coexist (default) |
Both MC and the host CLI append to the jsonl. Each side picks up the other's writes on its next prompt. Possible interleaving on simultaneous writes — fine for a single operator switching between the two surfaces. |
block-active |
Returns 409 from /api/sessions/continue if the jsonl was touched in the last 60s (heuristic: a live host CLI updates mtime frequently). Forces MC to act only on idle sessions. |
nudge |
Same as coexist plus a best-effort utimes() on the jsonl after the reply, so a tail-watching host CLI sees a fresh mtime. |
Production Hardening
docker compose -f docker-compose.yml -f docker-compose.hardened.yml up -dThis adds: JSON logging, strict hostname allowlist, secure cookies, HSTS, internal-only network.
Host hardening (Ubuntu quick actions)
- Firewall (ufw):
sudo apt-get install -y ufw && sudo ufw allow OpenSSH && sudo ufw enable && sudo ufw status - Time sync (NTP):
timedatectl set-ntp true && timedatectl status(ensures systemd-timesyncd is active) - Automatic security updates:
sudo apt-get install -y unattended-upgrades && sudo dpkg-reconfigure -plow unattended-upgrades && sudo unattended-upgrade -d - Brute-force protection (fail2ban):
sudo apt-get install -y fail2ban && sudo systemctl enable --now fail2ban(tune/etc/fail2ban/jail.localas needed) - /tmp noexec: add
tmpfs /tmp tmpfs defaults,noexec,nosuid,nodev 0 0to/etc/fstab, thensudo mount -o remount /tmp - Encrypted data (LUKS): create/attach a LUKS volume for data (
sudo cryptsetup luksFormat /dev/sdX && sudo cryptsetup open /dev/sdX mc-data && sudo mkfs.ext4 /dev/mapper/mc-data) and mount it for.data/or backups - MAC framework: keep AppArmor enabled (
sudo systemctl enable --now apparmor && sudo aa-status);
Ubuntu SELinux users can installselinux-basics selinux-policy-defaultand enable per Ubuntu guidance- sudo apt update
- sudo apt install selinux-basics selinux-policy-default
- sudo selinux-activate
- sudo reboot
- sudo apt install policycoreutils; sestatus # check status
Environment Variables
See .env.example for the full list. Key variables:
| Variable | Required | Default | Description |
|---|---|---|---|
AUTH_USER |
Yes | admin |
Admin username (seeded on first run) |
AUTH_PASS |
Yes | - | Admin password |
AUTH_PASS_B64 |
No | - | Base64-encoded admin password (overrides AUTH_PASS if set) |
API_KEY |
Yes | - | API key for headless access |
PORT |
No | 3005 (direct) / 3000 (Docker) |
Server port |
OPENCLAW_HOME |
No | - | Legacy: parent home directory containing .openclaw/. Use OPENCLAW_STATE_DIR instead (see note below) |
OPENCLAW_STATE_DIR |
No | ~/.openclaw |
Exact path to the OpenClaw state directory. Preferred over OPENCLAW_HOME — avoids double-nesting when the path already ends in .openclaw |
OPENCLAW_TOOLS_PROFILE |
No | coding |
Tool profile projected into OpenClaw config when the env var is present (compose injects the default) |
OPENCLAW_SECURITY_WORKSPACE_ONLY |
No | 1 |
Restrict filesystem tools to the workspace when set (env-driven) |
OPENCLAW_SECURITY_DENY_AUTOMATION |
No | 1 |
Deny automation tool group via env-driven bootstrap |
OPENCLAW_SECURITY_DENY_RUNTIME |
No | 1 |
Deny runtime tool group via env-driven bootstrap |
OPENCLAW_SECURITY_DENY_FS |
No | 0 |
Deny filesystem tool group (opt-in; can block file workflows) |
OPENCLAW_SECURITY_SANDBOX_ALL |
No | 1 |
Force agents.defaults.sandbox.mode="all" when set (env-driven) |
MISSION_CONTROL_DATA_DIR |
No | .data/ |
Directory for all Mission Control data files (DB, tokens, etc.). Use an absolute path with the standalone server to survive rebuilds. |
MC_ALLOWED_HOSTS |
No | localhost,127.0.0.1 |
Allowed hosts in production |
MC_PORT |
No | 3000 |
Host-side port that the bundled docker-compose.yml publishes the container's PORT on. The bundled Makefile expects 7012. |
ANTHROPIC_API_KEY |
No (Yes for direct dispatch) | - | Used when dispatchModel matches claude-* / anthropic/* and no gateway is available. |
OPENAI_API_KEY |
No | - | Used when dispatchModel matches gpt-* / o1-* / o3-* / openai/*. |
LOCAL_LLM_ENDPOINT |
No | http://host.docker.internal:1234/v1 |
OpenAI-compatible base URL (LMStudio default shown). Override for Ollama (:11434/v1) or a liteLLM proxy. |
LOCAL_LLM_API_KEY |
No | - | Bearer token sent to LOCAL_LLM_ENDPOINT. Only needed for proxies that require auth (e.g. liteLLM with master key). |
MC_HOST_SESSION_MODE |
No | coexist |
Policy when MC --resumes a host Claude Code session that may have a live CLI attached. One of coexist, block-active, nudge. |
NEXT_PUBLIC_CHAT_POLL_INTERVAL_MS |
No | 1500 (code) / 1000 (docker-compose) |
/chat transcript poll cadence (ms) when the SSE channel drops. Baked at build time, so changing it requires make rebuild. |
Sandbox runtime requirement
Enabling sandbox mode via
OPENCLAW_SECURITY_SANDBOX_ALL=1requires Docker access. Ensure themc-openclaw-gatewayservice bind-mounts the host Docker socket (/var/run/docker.sock) as shown indocker-compose-openclaw.yml.
Note —
OPENCLAW_HOMEvsOPENCLAW_STATE_DIRMission Control supports two env vars for locating OpenClaw:
OPENCLAW_HOME— treated as the parent home directory;.openclawis appended automatically.
SettingOPENCLAW_HOME=/root/.openclawwill resolve to/root/.openclaw/.openclaw(double-nesting bug).OPENCLAW_STATE_DIR— treated as the exact state directory path. Always prefer this.Recommended
.envfor a standard install:envOPENCLAW_STATE_DIR=/root/.openclaw MISSION_CONTROL_DATA_DIR=/absolute/path/to/.dataUsing an absolute path for
MISSION_CONTROL_DATA_DIRensures your
database and data survivenpm run build/ standalone server rebuilds.
Kubernetes Sidecar Deployment
When running Mission Control alongside a gateway as containers in the same pod (sidecar pattern), agents are not discovered via the filesystem. Instead, use the gateway's agent registration API.
Architecture
┌──────────────── Pod ────────────────┐
│ ┌─────────┐ ┌───────────────┐ │
│ │ MC │◄───►│ Gateway │ │
│ │ :3000 │ │ :18789 │ │
│ └─────────┘ └───────────────┘ │
│ ▲ ▲ │
│ │ localhost │ │
│ └──────────────────┘ │
└─────────────────────────────────────┘Required Configuration
Environment variables for the MC container:
AUTH_USER=admin
AUTH_PASS=<secure-password>
API_KEY=<your-api-key>
OPENCLAW_GATEWAY_HOST=127.0.0.1
NEXT_PUBLIC_GATEWAY_PORT=18789Agent Registration
The gateway must register its agents with MC on startup. Include the agents array in the gateway registration request:
curl -X POST http://localhost:3000/api/gateways \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json" \
-d '{
"name": "sidecar-gateway",
"host": "127.0.0.1",
"port": 18789,
"is_primary": true,
"agents": [
{ "name": "developer-1", "role": "developer" },
{ "name": "researcher-1", "role": "researcher" }
]
}'To update the agent list on reconnect, use PUT /api/gateways with the same agents field.
Alternatively, each agent can register itself via the direct connection endpoint:
curl -X POST http://localhost:3000/api/connect \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json" \
-d '{
"tool_name": "openclaw-gateway",
"agent_name": "developer-1",
"agent_role": "developer"
}'Health Checks
Agents must send heartbeats to stay visible:
curl http://localhost:3000/api/agents/<agent-id>/heartbeat \
-H "Authorization: Bearer <API_KEY>"Without heartbeats, agents will be marked offline after 10 minutes (configurable via general.agent_timeout_minutes setting).
Troubleshooting
"Internal server error" on login / NODE_MODULE_VERSION mismatch
better-sqlite3 is a native addon compiled for a specific Node.js version.
If you switch Node versions (e.g. via nvm), the compiled binary won't load.
pnpm rebuild better-sqlite3The health endpoint (/api/status?action=health) will report this error explicitly.
"Module not found: better-sqlite3"
Native compilation failed. On Ubuntu/Debian:
sudo apt-get install -y python3 make g++
rm -rf node_modules
pnpm installDocker: gateway unreachable / WebSocket not connecting
Checklist:
Verify the gateway is reachable from inside the container:
bashdocker exec mission-control curl -s http://host.docker.internal:18789Check env vars are set:
bashdocker exec mission-control env | grep -i gatewayYou should see
OPENCLAW_GATEWAY_HOST=host.docker.internal.If using a mounted
~/.openclawdirectory, theopenclaw.jsoninside may havegateway.host = "127.0.0.1"— this is the host's loopback, not reachable from the
container. Environment variables take precedence overopenclaw.json, so setOPENCLAW_GATEWAY_HOST=host.docker.internalin your.envor docker-compose.Browser WebSocket: MC automatically rewrites Docker-internal hostnames
(host.docker.internal,host-gateway) to the browser's hostname. If the browser
still can't connect, setNEXT_PUBLIC_GATEWAY_HOSTto a hostname your browser can reach.Linux-specific:
host.docker.internalrequires Docker 20.10+. Theextra_hosts
entry indocker-compose.ymlhandles this. If usingdocker rundirectly, add--add-host=host.docker.internal:host-gateway.
AUTH_PASS with "#" is not working
In dotenv files, # starts a comment unless the value is quoted.
Use one of these:
AUTH_PASS="my#password"AUTH_PASS_B64=$(echo -n 'my#password' | base64)
"pnpm-lock.yaml not found" during Docker build
If your deployment context omits pnpm-lock.yaml, Docker build now falls back topnpm install --no-frozen-lockfile.
For reproducible builds, include pnpm-lock.yaml in the build context.
"Invalid ELF header" or "Mach-O" errors
The native binary was compiled on a different platform. Rebuild:
rm -rf node_modules .next
pnpm install
pnpm buildDatabase locked errors
Ensure only one instance is running against the same .data/ directory. SQLite uses WAL mode but does not support multiple writers.
"Gateway error: origin not allowed"
Your gateway is rejecting the Mission Control browser origin. Add the Control UI origin
to your gateway config allowlist, for example:
{
"gateway": {
"controlUi": {
"allowedOrigins": ["http://YOUR_HOST:3000"]
}
}
}Then restart the gateway and reconnect from Mission Control.
"Gateway error: device identity required"
Device identity signing uses WebCrypto and requires a secure browser context.
Open Mission Control over HTTPS (or localhost), then reconnect.
"Gateway shows offline on VPS deployment"
Browser WebSocket connections to non-standard ports (like 18789/18790) are often blocked by VPS firewall/provider rules.
Quick option:
NEXT_PUBLIC_GATEWAY_OPTIONAL=trueThis runs Mission Control in standalone mode (core features available, live gateway streams unavailable).
Production option: reverse-proxy gateway WebSocket over 443.
nginx example:
location /gateway-ws {
proxy_pass http://127.0.0.1:18789;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 86400;
}Then point UI to:
NEXT_PUBLIC_GATEWAY_URL=wss://your-domain.com/gateway-wsMission Control now retries common reverse-proxy websocket paths (/gateway-ws, /gw) automatically when root-path handshake fails, but setting NEXT_PUBLIC_GATEWAY_URL is still recommended for deterministic production behavior.
Next Steps
Once deployed, set up your agents and orchestration:
- Quickstart — Register your first agent and complete a task in 5 minutes
- Agent Setup — SOUL personalities, heartbeats, config sync, agent sources
- Orchestration Patterns — Auto-dispatch, quality review, multi-agent workflows
- CLI Reference — Full CLI command list for headless/scripted usage
Openclaw Config Compatibility (`docs/openclaw-config-compatibility.md`)
OpenClaw Config Compatibility Note
Date: 2026-04-01
Incident
An OpenClaw install failed to start the gateway because ~/.openclaw/openclaw.json
contained a legacy top-level fallbacks key inside agents.list[*].
The runtime schema rejected entries like:
{
"id": "coder",
"model": "anthropic/claude-sonnet-4-6",
"fallbacks": []
}Doctor output showed:
Invalid config:
- agents.list.0: Unrecognized key: "fallbacks"Root Cause
Mission Control still normalized model.fallbacks, but it also preserved any old
top-level agent.fallbacks already present in openclaw.json during write-back.
That meant any agent edited from the dashboard could keep re-saving an invalid
gateway config even if the current UI no longer depended on that field.
Fix
The write-back normalizer in src/lib/agent-sync.ts now removes legacy
top-level agent.fallbacks before writing back to openclaw.json.
Regression coverage lives in:
src/lib/__tests__/agent-sync.test.ts
Recovery
If this happens again on a live install:
- Remove
fallbacksfrom each entry inagents.listinside~/.openclaw/openclaw.json. - Run
openclaw doctor. - Verify with
openclaw gateway status.
Expected result:
openclaw doctorno longer reportsUnrecognized key: "fallbacks".openclaw gateway statusshowsRuntime: runningandRPC probe: ok.
Orchestration (`docs/orchestration.md`)
Orchestration Patterns
This guide covers the task orchestration patterns available in Mission Control, from simple manual assignment to fully automated multi-agent workflows.
Task Lifecycle
Every task in Mission Control follows this status flow:
inbox ──► assigned ──► in_progress ──► review ──► done
│ │ │ │
│ │ │ └──► rejected ──► assigned (retry)
│ │ │
│ │ └──► failed (max retries or timeout)
│ │
│ └──► cancelled
│
└──► assigned (triaged by human or auto-dispatch)Key transitions:
- inbox → assigned: Human triages or auto-dispatch picks it up
- assigned → in_progress: Agent claims via queue poll or auto-dispatch sends it
- in_progress → review: Agent completes work, awaits quality check
- review → done: Aegis approves the work
- review → assigned: Aegis rejects, task is requeued with feedback
Pattern 1: Manual Assignment
The simplest pattern. A human creates a task and assigns it to a specific agent.
# Create and assign in one step
curl -X POST "$MC_URL/api/tasks" \
-H "Authorization: Bearer $MC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Fix login page CSS",
"description": "The login button overlaps the form on mobile viewports.",
"priority": "high",
"assigned_to": "scout"
}'The agent picks it up on the next queue poll:
curl "$MC_URL/api/tasks/queue?agent=scout" \
-H "Authorization: Bearer $MC_API_KEY"When to use: Small teams, well-known agent capabilities, human-driven task triage.
Pattern 2: Queue-Based Dispatch
Agents poll the queue and MC assigns the highest-priority available task. No human triage needed.
Setup
- Create tasks in
inboxstatus (noassigned_to):
curl -X POST "$MC_URL/api/tasks" \
-H "Authorization: Bearer $MC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Update API documentation",
"priority": "medium"
}'- Agents poll the queue. MC atomically claims the best task:
# Agent "scout" asks for work
curl "$MC_URL/api/tasks/queue?agent=scout" \
-H "Authorization: Bearer $MC_API_KEY"
# Agent "iris" also asks — gets a different task (no race condition)
curl "$MC_URL/api/tasks/queue?agent=iris" \
-H "Authorization: Bearer $MC_API_KEY"Priority Ordering
Tasks are assigned in this order:
- Priority: critical > high > medium > low
- Due date: Earliest due date first (null = last)
- Created at: Oldest first (FIFO within same priority)
Capacity Control
Each agent can set max_capacity to limit concurrent tasks:
# Agent can handle 3 tasks at once
curl "$MC_URL/api/tasks/queue?agent=scout&max_capacity=3" \
-H "Authorization: Bearer $MC_API_KEY"If the agent already has max_capacity tasks in in_progress, the response returns "reason": "at_capacity" with no task.
When to use: Multiple agents with overlapping capabilities, want automatic load balancing.
Pattern 3: Auto-Dispatch (Gateway Required)
The scheduler automatically dispatches assigned tasks to agents through the OpenClaw gateway. This is the fully hands-off mode.
How It Works
- Tasks are created with
assigned_toset - The scheduler's
dispatchAssignedTasksjob runs periodically - For each task, MC:
- Marks it
in_progress - Classifies the task complexity to select a model
- Sends the task prompt to the agent via the gateway
- Parses the response and stores the resolution
- Moves the task to
reviewstatus
- Marks it
Model Routing
MC automatically selects a model based on task content:
| Tier | Model | Signals |
|---|---|---|
| Complex | Opus | debug, diagnose, architect, security audit, incident, refactor, migration |
| Routine | Haiku | status check, format, rename, ping, summarize, translate, simple, minor |
| Default | Agent's configured model | Everything else |
Critical priority tasks always get Opus. Low priority with routine signals get Haiku.
Override per-agent by setting config.dispatchModel:
curl -X PUT "$MC_URL/api/agents" \
-H "Authorization: Bearer $MC_API_KEY" \
-H "Content-Type: application/json" \
-d '{"id": 1, "config": {"dispatchModel": "9router/cc/claude-opus-4-6"}}'Retry Handling
- Failed dispatches increment
dispatch_attemptsand revert toassigned - After 5 failed attempts, task moves to
failed - Each failure is logged as a comment on the task
When to use: Fully autonomous operation with an OpenClaw gateway. Best for production agent fleets.
Pattern 4: Quality Review (Aegis)
Aegis is MC's built-in quality gate. When a task reaches review status, the scheduler sends it to the Aegis reviewer agent for sign-off.
Flow
in_progress ──► review ──► Aegis reviews ──► APPROVED ──► done
└─► REJECTED ──► assigned (with feedback)How Aegis Reviews
- Scheduler's
runAegisReviewsjob picks up tasks inreviewstatus - Builds a review prompt with the task description and agent's resolution
- Sends to the Aegis agent (configurable via
MC_COORDINATOR_AGENT) - Parses the verdict:
VERDICT: APPROVED→ task moves todoneVERDICT: REJECTED→ feedback is attached as a comment, task reverts toassigned
- Rejected tasks are re-dispatched with the feedback included in the prompt
Retry Limits
- Up to 3 Aegis review cycles per task
- After 3 rejections, task moves to
failedwith accumulated feedback - All review results are stored in the
quality_reviewstable
Setting Up Aegis
Aegis is just a regular agent with a reviewer SOUL. Create it:
# Register the Aegis agent
curl -X POST "$MC_URL/api/agents/register" \
-H "Authorization: Bearer $MC_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "aegis", "role": "reviewer"}'
# Set its SOUL
curl -X PUT "$MC_URL/api/agents/1/soul" \
-H "Authorization: Bearer $MC_API_KEY" \
-H "Content-Type: application/json" \
-d '{"template_name": "reviewer"}'When to use: When you want automated quality checks before tasks are marked complete.
Pattern 5: Recurring Tasks (Cron)
Schedule tasks to be created automatically on a recurring basis using natural language or cron expressions.
CLI
node scripts/mc-cli.cjs cron create --body '{
"name": "daily-standup-report",
"schedule": "0 9 * * 1-5",
"task_template": {
"title": "Generate daily standup report",
"description": "Summarize all completed tasks from the past 24 hours.",
"priority": "medium",
"assigned_to": "iris"
}
}'API
curl -X POST "$MC_URL/api/cron" \
-H "Authorization: Bearer $MC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "weekly-security-scan",
"schedule": "0 2 * * 0",
"task_template": {
"title": "Weekly security audit",
"priority": "high",
"assigned_to": "aegis"
}
}'The scheduler spawns dated child tasks from the template on each trigger. Manage cron jobs with pause, resume, and remove actions.
When to use: Reports, health checks, periodic audits, maintenance tasks.
Pattern 6: Multi-Agent Handoff
Agent A completes a task, then creates a follow-up task assigned to Agent B. This chains agents into a pipeline.
Example: Research → Implement → Review
# Step 1: Research task for iris
curl -X POST "$MC_URL/api/tasks" \
-H "Authorization: Bearer $MC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Research caching strategies for API layer",
"priority": "high",
"assigned_to": "iris"
}'When iris completes the research, create the implementation task:
# Step 2: Implementation task for scout (after iris finishes)
curl -X POST "$MC_URL/api/tasks" \
-H "Authorization: Bearer $MC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Implement Redis caching for /api/products",
"description": "Based on research in TASK-1: Use cache-aside pattern with 5min TTL...",
"priority": "high",
"assigned_to": "scout"
}'After scout finishes, Aegis reviews automatically (if auto-dispatch is active), or you create a review task:
# Step 3: Review task for aegis
curl -X POST "$MC_URL/api/tasks" \
-H "Authorization: Bearer $MC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Review caching implementation in TASK-2",
"priority": "high",
"assigned_to": "aegis"
}'When to use: Complex workflows where different agents have different specializations.
Pattern 7: Stale Task Recovery
MC automatically recovers from stuck agents. The requeueStaleTasks scheduler job:
- Finds tasks stuck in
in_progressfor 10+ minutes with an offline agent - Reverts them to
assignedwith a comment explaining the stall - After 5 stale requeues, moves the task to
failed
This happens automatically — no configuration needed.
Combining Patterns
In practice, you'll combine these patterns. A typical production setup:
- Cron creates recurring tasks (Pattern 5)
- Queue-based dispatch distributes tasks to available agents (Pattern 2)
- Model routing picks the right model per task (Pattern 3)
- Aegis reviews all completed work (Pattern 4)
- Stale recovery handles agent failures (Pattern 7)
Cron ──► inbox ──► Queue assigns ──► Agent works ──► Aegis reviews ──► done
│ │
└── timeout ───────┘── requeueEvent Streaming
Monitor orchestration in real time with SSE:
# Watch all task and agent events
node scripts/mc-cli.cjs events watch --types task,agent --jsonOr via API:
curl -N "$MC_URL/api/events" \
-H "Authorization: Bearer $MC_API_KEY" \
-H "Accept: text/event-stream"Events include: task.created, task.updated, task.completed, agent.created, agent.status_changed, and more.
Reference
- Quickstart — 5-minute first agent tutorial
- Agent Setup — Registration, SOUL, configuration
- CLI Reference — Full CLI command list
- CLI Integration — Direct connections without a gateway
Home (`wiki/Home.md`)
Mission Control Wiki
Last reviewed: 2026-03-05
Mission Control is an open-source dashboard for orchestrating AI agents: agents, tasks, costs, workflows, and gateway connectivity in one place.
Start Here
- Product overview: README
- Local + production setup: docs/deployment.md
- Direct CLI integration (without gateway): docs/cli-integration.md
- Security policy: SECURITY.md
- Contribution guide: CONTRIBUTING.md
- Release history: CHANGELOG.md
Quick Start (5 Minutes)
git clone https://github.com/builderz-labs/mission-control.git
cd mission-control
pnpm install
cp .env.example .env
pnpm devThen open http://localhost:3000 and sign in with the seeded AUTH_USER/AUTH_PASS values from your environment.
Core Concepts
- Agent: A worker connected to Mission Control that executes tasks and reports status/usage.
- Task: A unit of work tracked across workflow columns (
inbox -> done) with comments and ownership. - Gateway: Real-time connection layer (OpenClaw and compatible providers) for session/event streaming.
- Workspace/Tenant: Isolated environment for multi-client operations, managed via
/api/super/*endpoints.
Recommended Wiki Structure
Home(this page)Getting-Started- install, auth, first login, and initial checksArchitecture- runtime model, data flow, and component mapOperations-Runbook- backups, upgrades, troubleshooting, incident stepsAPI-Guide- endpoint groups, auth patterns, and examplesSecurity-Model- auth, RBAC, API keys, host/network controlsIntegrations- webhooks, GitHub sync, direct CLI, multi-gateway setupFAQ- common operator/admin questions
Notes For Maintainers
- Keep wiki pages aligned with shipped behavior in the same PR when features change.
- Add a
Last reviewedline to each operational page. - Prefer linking to source-of-truth docs in this repo when possible.
STYLE GUIDE (`wiki/STYLE_GUIDE.md`)
Mission Control Style Guide
"Mission Control in the Void" — a futuristic command center floating in a digital void.
1. Design Philosophy
Mission Control uses a deep-navy void aesthetic with luminous cyan accents. The visual language evokes a space-age command center: dark surfaces, glowing edges, monospace readouts, and subtle grid patterns that anchor UI elements in a digital void.
Key principles:
- Dark by default — app defaults to dark mode (
enableSystem={false}) - Semantic tokens — all colors flow through CSS custom properties
- Additive light — glow effects and luminous borders create depth without bright fills
- Motion with purpose — animations signal state, never decoration
2. Color System
Void Palette (Dark Mode)
| Token | CSS Variable | HSL | Hex | Usage |
|---|---|---|---|---|
| Background | --background |
215 27% 4% |
#07090C | Page background, deepest layer |
| Card | --card |
220 30% 8% |
#0F141C | Panel/card surfaces |
| Primary | --primary |
187 82% 53% |
#22D3EE | Primary actions, focus rings |
| Secondary | --secondary |
220 25% 11% |
— | Secondary surfaces |
| Muted | --muted |
220 20% 14% |
— | Disabled states, subtle fills |
| Border | --border |
220 20% 14% |
— | Card/panel borders |
| Foreground | --foreground |
210 20% 92% |
— | Primary text |
Accent Colors
| Name | CSS Variable | HSL | Hex | Usage |
|---|---|---|---|---|
| Cyan | --void-cyan |
187 82% 53% |
#22D3EE | Primary accent, active states |
| Mint | --void-mint |
160 60% 52% |
#34D399 | Success, healthy states |
| Amber | --void-amber |
38 92% 50% |
#F59E0B | Warning, idle states |
| Violet | --void-violet |
263 90% 66% |
#A78BFA | Lead agents, special roles |
| Crimson | --void-crimson |
0 72% 51% |
#DC2626 | Errors, destructive actions |
Surface Hierarchy
| Level | CSS Variable | HSL | Usage |
|---|---|---|---|
| 0 | --surface-0 |
215 27% 4% |
Deepest void (page bg) |
| 1 | --surface-1 |
222 35% 7% |
Dark navy (elevated cards) |
| 2 | --surface-2 |
220 30% 10% |
Secondary panels |
| 3 | --surface-3 |
220 25% 14% |
Raised elements, borders |
Using Colors in Code
Tailwind classes (preferred):
<div class="bg-card text-foreground border-void-cyan">Inline styles (ReactFlow, recharts):
import { hsl, voidAccents } from '@/styles/design-tokens'
const stroke = hsl(voidAccents.cyan) // "hsl(187 82% 53%)"
const dim = hsl(voidAccents.cyan, 0.4) // "hsl(187 82% 53% / 0.4)"3. Typography
| Role | Font | CSS Variable | Tailwind Class |
|---|---|---|---|
| Body/UI | Inter | --font-sans |
font-sans |
| Code/Data | JetBrains Mono | --font-mono |
font-mono |
Both fonts are loaded via next/font/google (self-hosted, no external requests).
Type Scale
Follow Tailwind's default scale. Key usage:
text-2xl font-bold font-mono— stat card valuestext-sm font-medium— labels, nav itemstext-xs font-mono— metadata, timestamps, model namestext-[10px] tracking-wider font-semibold— section headers (OBSERVE, AUTOMATE, etc.)
4. Spacing
Base grid: 4px
Use Tailwind's spacing scale (1 = 0.25rem = 4px). Panel padding is typically p-4 (16px) or p-6 (24px). Gaps between grid items use gap-6 (24px).
5. Border Radius
| Token | Value | Usage |
|---|---|---|
rounded-xl |
16px | Large panels, modals |
rounded-lg |
12px | Standard panels, cards |
rounded-md |
10px | Buttons, inputs |
rounded-sm |
8px | Small elements |
rounded-xs |
6px | Badges, tags |
6. Elevation & Glow
Glow Utilities
| Class | Color | Usage |
|---|---|---|
.glow-cyan |
Cyan | Active states, primary focus |
.glow-mint |
Mint | Success states |
.glow-amber |
Amber | Warning states |
.glow-violet |
Violet | Special/lead roles |
Badge Glow
| Class | Usage |
|---|---|
.badge-glow-success |
Success status badges |
.badge-glow-warning |
Warning status badges |
.badge-glow-error |
Error status badges |
Panel Classes
| Class | Description |
|---|---|
.void-panel |
Glass card with luminous border, inner highlight, float shadow |
.void-border-glow |
Animated gradient border via ::before pseudo-element |
.panel |
Basic card: bg-card border rounded-xl |
.btn-neon |
Button with cyan glow on hover |
7. Component Patterns
Panel Anatomy
<div class="void-panel">
<div class="panel-header">
<h3 class="font-semibold text-foreground">Title</h3>
</div>
<div class="panel-body">
</div>
</div>Stat Card
- Use
void-panelbase - Numeric values:
font-mono text-2xl font-bold - Icons: SVG, 24x24 (w-6 h-6), colored with void accent classes
- Color-specific glow via
badge-glow-*classes
Agent Node (ReactFlow)
- Base:
void-panelwith status-based border color - Active:
border-void-cyan glow-cyan - Idle:
border-void-amber/50 - Error:
border-void-crimson badge-glow-error - Badges:
font-mono text-xswith accent background/border
CORE Node
- Central orchestration hub in agent network
- Concentric pulsing rings (CSS keyframes, no framer-motion)
font-mono tracking-widestfor "CORE" label
8. Animation
Keyframe Inventory
| Name | Duration | Effect | Usage |
|---|---|---|---|
glowPulse |
3s | Opacity + brightness oscillation | Active agent indicators |
float |
6s | Vertical float (-6px) | Floating UI elements |
gridFlow |
20s | Background position shift | Background grid animation |
edgeGlow |
2s | Opacity oscillation | Border glow effects |
pulse-live |
2s | Opacity fade | Live status indicators |
pulse-dot |
2s | Scale + opacity | Connection status dots |
Guidelines
- Prefer CSS
@keyframesover JavaScript animation - Duration: 2-3s for ambient loops, 150-200ms for interactions
- Easing:
ease-in-outfor loops,ease-outfor entrances - Always respect
prefers-reduced-motion: reduce
9. Icon System
- ViewBox:
0 0 16 16 - Style: Stroke-based, not filled
- Stroke width:
1.5 - Line caps/joins:
round - Size in UI:
w-5 h-5(nav),w-4 h-4(inline),w-6 h-6(stat cards) - Color: Inherits via
stroke="currentColor"
Example:
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor"
strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"
className="w-5 h-5">
<circle cx="8" cy="8" r="6" />
</svg>10. Accessibility
Contrast
- Text on void background: minimum 4.5:1 ratio (WCAG AA)
--foreground(92% lightness) on--background(4% lightness) exceeds 15:1- Cyan accent on dark: 5.2:1 — passes AA for normal text
Focus Indicators
- Use
ringutility:focus-visible:ring-2 focus-visible:ring-ring - Ring color matches
--void-cyan
Reduced Motion
Global rule in globals.css:
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}Semantic HTML
- Nav uses
role="navigation"andaria-label - Active nav items use
aria-current="page" - Disabled items use
aria-disabled - Decorative elements use
aria-hidden="true"
Plans 2026 03 10 Onboarding Walkthrough Hardening (`docs/plans/2026-03-10-onboarding-walkthrough-hardening.md`)
Onboarding + Walkthrough hardening plan
Base branch: fix/refactor
Working branch: fix/refactor-onboarding-walkthrough
Goals
- Verify current onboarding and walkthrough flows are functional.
- Fix edge cases for first-run, skip, replay, and recovery states.
- Improve UX discoverability of walkthrough entry points.
- Add regression tests to keep flows stable.
Phase 1: audit and test map
- Identify current onboarding/walkthrough code paths.
- Document triggers, persistence flags, and routing.
- Add failing tests for first-run, skip, replay, and already-seen states.
Phase 2: implementation hardening
- Fix state transitions and persistence updates.
- Ensure walkthrough can be reopened from primary UI.
- Add visible hint/help entry to improve discoverability.
- Handle corrupted or partial onboarding state safely.
Phase 3: verification
- Run targeted tests for onboarding/walkthrough.
- Run full project checks.
- Validate end-to-end flow manually in local dev.
Deliverables
- Code changes in onboarding/walkthrough modules
- Automated tests covering key onboarding paths
- Updated docs/help text for walkthrough discoverability
Plans 2026 03 20 Mission Control Platform Cli Tui Prd (`docs/plans/2026-03-20-mission-control-platform-cli-tui-prd.md`)
Mission Control Platform Hardening + Full Agent CLI/TUI PRD
For Hermes: execute this plan in iterative vertical slices (contract parity -> CLI core -> TUI -> hardening), with tests at each slice.
Goal
Build a production-grade Mission Control operator surface for autonomous agents via a first-party CLI (and optional lightweight TUI), while fixing platform inconsistencies discovered in audit: API contract drift, uneven reliability controls, and incomplete automation ergonomics.
Architecture
Mission Control remains the source of truth with REST + SSE endpoints. A first-party CLI consumes those APIs with profile-based auth and machine-friendly output. TUI is layered on top of CLI API client primitives for shared behavior. API contract reliability is enforced through route-to-spec parity checks in CI.
Tech Stack
- Existing: Next.js app-router API, SQLite, Node runtime, SSE
- New: Node CLI runtime (no heavy deps required for v1), optional TUI in terminal ANSI mode
- Testing: existing Playwright/Vitest patterns + CLI smoke tests + OpenAPI parity checks
1) Problem statement
Current Mission Control backend has strong capabilities for agent orchestration, but external automation quality is constrained by:
- API surface drift between route handlers, openapi.json, and /api/index.
- No first-party comprehensive CLI for operators/agents.
- Uneven hardening around operational concerns (auth posture defaults, multi-instance rate limiting strategy, spawn history durability).
- Incomplete UX for non-interactive agent workflows (idempotent commands, stable JSON output, strict exit codes).
Result: agents can use Mission Control partially, but not yet with high confidence as a full control plane.
2) Product objectives
Primary objectives
- Deliver a first-party CLI with functional parity across core agent workflows.
- Add optional TUI for rapid situational awareness and interactive operations.
- Establish API contract parity as an enforceable quality gate.
- Improve reliability and security defaults for autonomous operation.
Success criteria
- 95%+ of documented operator workflows executable via CLI without web UI.
- Contract parity CI gate blocks drift between route handlers and OpenAPI.
- CLI supports machine mode: stable JSON schemas and deterministic exit codes.
- TUI can monitor and trigger core actions (agents/tasks/sessions/events).
Non-goals (v1)
- Replacing the web UI.
- Building an advanced ncurses framework dependency stack if not needed.
- Supporting all historical/legacy endpoint aliases immediately.
3) Personas and workflows
Personas
- Autonomous agent runtime (headless, non-interactive).
- Human operator (terminal-first incident response).
- Platform maintainer (release and contract governance).
Critical workflows
- Poll task queue and claim work.
- Manage agents (register/update/diagnose/wake).
- Manage sessions (list/control/continue/transcript).
- Observe events in real time.
- Track token usage and attribution.
- Manage skills, cron jobs, and direct CLI connections.
4) Functional requirements
A. API contract governance
- FR-A1: A parity checker must compare discovered route handlers and OpenAPI paths/methods.
- FR-A2: CI fails on non-ignored mismatches.
- FR-A3: Ignore list must be explicit and reviewable.
- FR-A4: /api/index should be validated or generated from same contract source.
B. CLI v1 requirements
- FR-B1: Profile-based configuration (URL + auth mode + key/cookie).
- FR-B2: Commands must support --json output and strict exit codes.
- FR-B3: Support key domains:
- auth
- agents
- tasks
- sessions
- connect
- tokens
- skills
- cron
- events watch
- raw request fallback
- FR-B4: Non-interactive defaults suitable for autonomous agents.
- FR-B5: Request timeout + retry controls for reliable automation.
C. TUI v1 requirements (optional but included)
- FR-C1: Dashboard with agents/tasks/sessions summary panels.
- FR-C2: Keyboard-driven refresh/navigation.
- FR-C3: Trigger key operations (wake agent, queue poll, session controls).
- FR-C4: Clear degraded mode messaging if endpoints unavailable.
D. Platform hardening requirements
- FR-D1: Document and enforce least-privilege auth guidance for agent keys.
- FR-D2: Expose explicit warning/controls for global admin API key usage.
- FR-D3: Add durable spawn history persistence (DB-backed) replacing log scraping fallback.
- FR-D4: Add scalable rate-limit strategy plan (in-memory now, pluggable backend next).
5) CLI command map (v1)
mc auth
- login --username --password
- logout
- whoami
mc agents
- list
- get --id
- create --name --role
- update --id ...fields
- delete --id
- wake --id
- diagnostics --id
- heartbeat --id
- memory get|set --id
- soul get|set --id
mc tasks
- list [filters]
- get --id
- create --title [--description --priority --assigned-to]
- update --id ...fields
- delete --id
- queue --agent [--max-capacity]
- comments list/add --id
- broadcast --id
mc sessions
- list
- control --id --action monitor|pause|terminate
- continue --kind claude-code|codex-cli --id --prompt
- transcript --id [--source]
mc connect
- register --tool-name --agent-name [...]
- list
- disconnect --connection-id
mc tokens
- list
- stats
- by-agent [--days]
- export --format json|csv
mc skills
- list
- content --source --name
- upsert --source --name --file
- delete --source --name
- check --source --name
mc cron
- list
- create/update/pause/resume/remove/run
mc events
- watch [--types]
mc raw
- raw --method GET --path /api/... [--body '{}']
6) UX and interface requirements
- Default output must be concise human-readable; --json returns machine-stable payload.
- All non-2xx responses include normalized error object and non-zero exit.
- Exit code taxonomy:
- 0 success
- 2 usage error
- 3 auth error
- 4 permission error
- 5 network/timeout
- 6 server error
- Pagination/filter flags normalized across list commands.
7) Security requirements
- Do not log raw API keys or cookies.
- Redact sensitive headers in verbose/debug output.
- Provide per-profile auth scope awareness (viewer/operator/admin implied risk labeling).
- Strong guidance: prefer agent-scoped keys over global admin key.
8) Reliability requirements
- Configurable timeout/retry/backoff.
- Safe JSON parsing and clear error surfaces.
- SSE reconnection strategy for watch mode.
- Graceful handling for partial endpoint availability.
9) Testing strategy
Unit
- CLI arg parsing and request mapping.
- Output modes and exit codes.
- API parity checker route extraction and mismatch detection.
Integration
- CLI against local Mission Control test server.
- Auth modes (API key, login session where enabled).
- Session control, queue polling, skills CRUD.
E2E
- Playwright/terminal-driven smoke for critical command paths.
- TUI render and keyboard navigation smoke tests.
Contract tests
- OpenAPI parity check in CI.
- Optional index parity check in CI.
10) Rollout plan
Phase 0: Contract stabilization
- Add parity checker and fail CI on drift.
- Resolve existing mismatches.
Phase 1: CLI core
- Ship profile/auth client + core command groups (auth/agents/tasks/sessions/connect).
Phase 2: CLI expansion
- tokens/skills/cron/events/raw + transcript ergonomics.
Phase 3: TUI
- Live dashboard + action shortcuts.
Phase 4: Hardening
- durable spawn history
- auth warnings and safeguards
- scalable rate-limit backend abstraction
11) Risks and mitigations
Risk: Large API surface causes long-tail parity gaps.
Mitigation: enforce parity checker + allowlist for temporary exceptions.
Risk: Auth complexity across cookie/key/proxy modes.
Mitigation: profile abstraction + explicit mode selection and diagnostics.
Risk: CLI churn if endpoint contracts continue changing.
Mitigation: typed response normalizers + compatibility layer + semver release notes.
12) Acceptance criteria
- PRD approved by maintainers.
- CLI provides end-to-end control for core workflows.
- Contract parity CI gate active and green.
- TUI displays operational state and triggers key actions.
- Security and reliability hardening changes documented and tested.
13) Immediate implementation tasks (next 1-2 PRs)
PR 1
- Add API parity checker script and CI command.
- Add first-party CLI scaffold with command routing and normalized request layer.
- Add docs for CLI profiles/auth/output contract.
PR 2
- Implement full command matrix.
- Add TUI dashboard shell.
- Add CLI integration tests.
- Introduce durable spawn history model and endpoint alignment.
Releases 2.0.0 (`docs/releases/2.0.0.md`)
Mission Control 2.0.0
Released: 2026-03-11
Mission Control 2.0.0 is the major release that lands the feat/refactor branch as the new baseline for the project. It rolls up 189 commits on top of main and shifts Mission Control from an early dashboard into a broader agent operations console for both local and gateway-driven setups.
Highlights
Dual-mode operation
- Mission Control now supports both OpenClaw gateway mode and local workstation mode cleanly.
- Onboarding, runtime detection, security checks, and panel behavior were reworked so the app can adapt to the active environment instead of assuming one deployment shape.
Broader agent observability
- Hermes observability was added across sessions, memory, tasks, cron, and transcripts.
- OpenClaw coverage was expanded across channels, chat, sessions, cron, devices, approvals, logs, usage, and config editing.
- Agent communication, session routing, and inline transcript visibility were strengthened throughout the app.
Memory system redesign
- The memory panel was redesigned into an Obsidian-style knowledge surface.
- Mission Control now ships with a filesystem memory browser, link/context endpoints, memory health signals, and an interactive graph view for linked knowledge.
- Loading and navigation performance in the memory panel were improved substantially, including lazy tree loading and graph prefetching.
Onboarding, security, and doctor workflows
- The onboarding experience was rebuilt into a guided walkthrough with stronger separation between per-user progress and per-session display behavior.
- The security scan now has clearer severity handling, improved autofix behavior, and better reporting of manual vs auto-fixable issues.
- OpenClaw doctor warnings, doctor fix, and state-integrity handling are now surfaced directly in the UI.
Deployment and runtime hardening
- Node support was standardized on
22.xacross local development, CI, Docker, and standalone deploys. - Build-time SQLite handling was isolated from runtime SQLite state to avoid noisy or fragile deploy behavior.
- Standalone deploys were hardened around asset inclusion, runtime data directories, backups, and restart detection.
- Dynamic host handling and safer env mutation behavior improved self-hosted reliability.
Agent lifecycle and operator UX
- Agent/workspace creation and deletion flows were hardened end to end, including OpenClaw config normalization and cleanup.
- The boot loader was redesigned with real progress phases and framework logos.
- Cost tracking, approvals, channels, chat, and session controls were all tightened during the refactor.
Everything Included In The v2 Update
Core platform and mode handling
- Local mode and OpenClaw gateway mode were hardened into first-class operating modes.
- Gateway discovery and connection handling improved across configured runtimes, systemd-managed gateways, Tailscale Serve, proxied websocket paths, forwarded-proto setups, and token-preserving websocket URLs.
- Mission Control can register itself as the dashboard for an OpenClaw runtime without the earlier device-auth and dashboard URL failure cases.
- Managed-gateway UX was tightened across health, status, mode badges, and startup auto-connect behavior.
Agents, sessions, chat, and comms
- Embedded chat became a shared workspace rather than a fragmented set of views.
- Session navigation was unified into Chat, with local Claude/Codex sessions included alongside gateway sessions.
- Hermes sessions, transcripts, memory, tasks, and cron surfaced throughout the app.
- Session transcript handling improved across local, Hermes, aggregated gateway, and disk-backed OpenClaw transcript sources.
- Agent comms, runtime tool visibility, coordinator inbox behavior, session-thread routing, and agent feed ergonomics were hardened.
- Agent registration, self-registration, rate limiting, attribution, wake/spawn actions, and agent detail editing all received follow-up fixes.
Tasks, quality flow, and automation
- Task dispatch now polls assigned tasks and runs agents through OpenClaw with session linkage.
- Aegis quality review became an automated scheduled workflow for review-stage tasks.
- Natural-language recurring tasks now parse into cron-backed template spawning.
- Spawn/task flows were consolidated, old spawn-only UI was removed, and task/session linking became more traceable.
- Cost tracking moved into a unified Cost Tracker panel.
Memory, knowledge, and browsing
- The memory experience was redesigned into a graph-first, Obsidian-style knowledge system.
- The memory browser now supports faster loading, lazy directory hydration, better overflow handling, and improved graph fitting behavior.
- Memory APIs expanded around graph, health, links, context, and processing actions.
- Boot-time prefetching and panel persistence reduced the need to re-fetch heavy memory state on every navigation.
Skills and local discovery
- Skills Hub support expanded across browsing, installation, bidirectional sync, registry search, security scanning, and local disk roots.
- Local agent discovery now covers
~/.agents,~/.codex/agents, and Claude agent roots more reliably. - Skill roots and E2E skill paths can now be overridden cleanly for isolated test and self-hosted environments.
Security, audit, and approvals
- Security audit posture scoring, secret detection, evals, optimization, and security events were substantially expanded.
- Security scan severity scoring, infrastructure checks, OpenClaw hardening checks, autofix behavior, and agent-side scan APIs improved.
- Global exec approval overlay and approval flows were added/refined.
- Auth hardening covered timing-safe behavior, CSRF, session revocation, host allowlists, and safer trusted-host resolution.
- Audit trail coverage expanded across grouped action types and more complete operator activity logging.
Onboarding and first-run experience
- The onboarding wizard went through several iterations and now combines runtime capability detection, gateway setup, security scan, credentials, and guided getting-started flow.
- Walkthrough visibility is session-aware while progress persists per user.
- The loading experience was redesigned with branded motion, framework logos, and real boot phases instead of generic spinner states.
UI, navigation, and operator polish
- Agent cards, the agent detail modal, the cron calendar, activity/history views, interface mode toggles, sidebar categories, and panel loading states were redesigned.
- Shared loader patterns replaced ad-hoc spinners across more panels.
- Navigation state, URL synchronization, and panel persistence were tightened to reduce remount churn and stale data flashes.
- Branding assets and logos for Mission Control, OpenClaw, Claude, Codex, and Hermes were refreshed across the interface.
Runtime, deployment, and template hardening
- Standalone deploys were hardened across static assets, runtime data directories, sqlite migration/backup flow, restart detection, and build/runtime separation.
- Build-time DB/token isolation removed noisy runtime coupling during
next build. - Node support was standardized on
22.x, with matching local, CI, Docker, and deploy expectations. - Proxy and host validation logic became more template-safe and more dynamic for self-hosted environments.
- OpenClaw doctor drift handling, doctor fix, config normalization, and workspace lifecycle cleanup were tightened to better support real self-hosted installs.
E2E, CI, and release readiness
- The E2E harness now uses isolated OpenClaw runtime state, isolated skill roots, deterministic scheduler behavior, and safer env handling.
- Several regressions that only showed up in CI were fixed around security autofix, workload signals, and agent deletion behavior.
- README, landing page assets, and release documentation were refreshed for the v2 release.
Notable Improvements
- Unified cost tracker replacing the split token/cost views
- Global exec approval overlay
- Better local agent discovery and skill sync behavior
- More reliable gateway config concurrency handling
- Better navigation responsiveness and less panel reload churn
- Stronger E2E runtime isolation for CI and local test harnesses
Detailed Functional Additions
- Framework adapters and normalized multi-agent registration flow
- Self-update banner and admin-triggered update flow
- Tenant-scoped workspaces and free-tier extraction cleanup
- Google Workspace integration
- Plugin capabilities system and Hyperbrowser integration
- Claude Code task bridge
- OpenClaw backup creation and restore-oriented backup directory handling
- Embedded
/chatpanel and provider-session-first chat workspace - Memory graph upgrades from Canvas to Reagraph WebGL
- Security audit panel, agent eval framework, and optimization endpoint
- OpenClaw update-now trigger from the UI
- Approvals overlay, channels parity, chat parity, usage parity, device parity, and logs parity with the newer OpenClaw surface
Detailed Fix Areas
- Login autofill, redirect race, CSP/theme flash, and auth/session regressions
- Channels auth and RPC fallback behavior
- Gateway websocket stability and device identity handshake behavior
- Memory graph blank states, overflow, sizing, auto-fit, and speed issues
- Agent detail/model-shape crashes and delete/provisioning edge cases
- Doctor warning misclassification and state-integrity surfacing
- Security scan autofix false positives and active-host preservation
- Standalone deploy asset/runtime drift and SQLite migration contention
- README and docs freshness so product marketing reflects the shipped interface
Upgrade Notes
- Mission Control 2.0.0 expects Node
22.x. - Self-hosted installs should verify env files, host allowlist configuration, and runtime data directory settings after upgrade.
- If you run OpenClaw, use the in-app doctor and security panels after upgrade to catch any stale config drift.
Links
- Changelog:
CHANGELOG.md - README:
README.md - Security hardening guide:
docs/SECURITY-HARDENING.md
Releases 2.0.1 (`docs/releases/2.0.1.md`)
Mission Control 2.0.1
Released: 2026-03-18
Mission Control 2.0.1 is the patch release that consolidates everything shipped after the v2.0.0 launch. It includes the operational fixes that stabilized HTTP/Tailscale deployments, a zero-config first-run path, full application internationalization, broader task-routing automation, and the latest OpenClaw compatibility updates needed for current self-hosted installs.
Highlights
HTTP, Tailscale, and gateway stability
- Login now works reliably on HTTP Docker installs and Tailscale-served deployments.
- CSP handling was tightened so SSR nonces, theme bootstrapping, and inline script policy stay aligned during login and chunk loading.
- Public websocket URL selection and Tailscale Serve detection were hardened for proxied gateway setups.
- Gateway startup and runtime checks now better tolerate read-only configs, missing
OPENCLAW_HOME, and container health-probe requirements.
Better first-run setup
- A first-time setup wizard now guides fresh installs through bootstrap and initial configuration.
- Zero-config startup paths reduce the amount of manual environment setup needed for local and Docker-based installs.
- Doctor and onboarding follow-ups are more resilient, including banner persistence and safer health-check behavior.
Stronger task and automation flow
- Task routing now preserves implementation metadata, targets the correct gateway session/agent identifiers, and can classify complexity for model-tier routing.
- GNAP sync landed for git-native task persistence.
awaiting_ownerstate detection and other dispatch/runtime fixes improve workflow accuracy after the v2 cut.
Broader self-hosted platform support
- Full app localization now ships across 10 languages.
- Windows setup improved with a PowerShell installer and stronger password-generation behavior.
- Workspace skill-root discovery and filtering are now surfaced throughout the app for operators running mixed local/gateway environments.
- The Docker/image pipeline now supports publishing the official image to Docker Hub when release secrets are configured.
Full Changelog
Added
- First-time setup wizard and zero-config startup flow
- Full i18n across the app with 10 language packs
- Trusted reverse proxy/header-auth support
- Gateway health history timeline
- Port-based Tailscale Serve proxy detection
- Task implementation-target persistence, session targeting, and complexity-based model-tier routing
- GNAP sync for git-native task persistence
- Hybrid gateway/local dashboard mode
- Workspace skill-root discovery and per-agent display
- Windows PowerShell installer
awaiting_ownertask status detection
Changed
- Node runtime support is now
>=22 - CSP/browser-security helpers were split into dedicated modules
- Release automation now supports Docker Hub publishing when configured
- Repository/release metadata now consistently points at
builderz-labs/mission-control
Fixed
- HTTP/Tailscale login and CSP nonce regressions
- Fresh HTTP Docker login failures caused by secure-cookie mismatch
- Gateway auth/token detection in mixed runtime setups
- Task dispatch using display names instead of gateway IDs
- Docker/runtime regressions around Compose, assets, probes,
OPENCLAW_HOME, and read-only configs - SQLite
SQLITE_BUSYcontention during build/runtime crossover - Doctor banner persistence, cron panel crash handling, and null-safe model config editing
- Public websocket URL preference and onboarding gateway health probe handling
- Notification refresh timing, agent empty-state UX, delete handling, and duplicate task-title behavior
- Memory diagnostics scoping, gateway notification delivery, session labels, and missing i18n namespaces
- Windows installer password generation via CSPRNG
- Reagraph CSP regression from
style-srcnonce handling - OpenClaw spawn compatibility when agents use configured default models
- Regression coverage for gateway dashboard registration preserving device-auth posture
Security
- Removed
unsafe-inlinein favor of nonce-based CSP - Added stronger SSRF/path-traversal detection in the skill registry
- Stopped forcing
dangerouslyDisableDeviceAuthwhen registering Mission Control as a dashboard
Tests
- Utility coverage improvements to satisfy the Vitest coverage threshold
- Gateway health history E2E coverage
- Docker-mode integration coverage for gateway connectivity regressions
- Regression tests for spawn compatibility and gateway registration behavior
Contributors
- @0xNyk
- @Brixyy
- @clintbaxley
- @dk-blackfuel
- @firefloc-nox
- @HonzysClawdbot
- @hectorse.88
- @jonathan-squaredlemons
- @jonboirama
- @joshua-mo-143
- @jrrcdev
- @lucascr
- @RazorFin
- @topshelfmedia
Releases 2.2.0 (`docs/releases/2.2.0.md`)
Mission Control 2.2.0
Mission Control 2.2.0 is a security and workspace-isolation release. It rolls the post-2.1 work into a reviewed baseline for self-hosted operators while keeping the existing trunk-based OSS workflow.
Highlights
- Native workspace brand and isolation fields, backed by migration
052 - Strict workspace boundaries across request, scheduler, event, audit, gateway, filesystem, and background-dispatch paths
- Safer host CLI dispatch with explicit tool, budget, and workspace-root constraints
- Hardened privileged mutations for gateway control, runtime setup, users, skills, backups, updates, approvals, and host maintenance
- Tailwind CSS v4 migration with visual verification across core surfaces and themes
- Stronger protected CI with immutable action-pin and standalone artifact-boundary checks
- Structured OSS issue and PR intake with clearer provenance, risk, and verification contracts
Security posture
The security work in this release concentrates on authority boundaries rather than UI-only controls. Ambiguous workspace ownership fails closed, sensitive mutations are throttled and strictly validated, command output is bounded or redacted, audit records avoid host paths and secrets, and privileged client calls reject failed API responses.
The release-preparation audit found no known high-severity dependency vulnerabilities. The protected quality gate covers API parity, lint, typecheck, unit tests, production build, standalone artifact boundaries, and the full Playwright suite.
Upgrade notes
- Back up the Mission Control database and runtime configuration.
- Upgrade from a protected
v2.2.0tag or corresponding immutable container digest. - Run migrations before enabling strict isolation on existing workspaces.
- Review
MC_WORKSPACE_ROOT, trusted proxies, gateway credentials, and host-runtime permissions. - Re-test downstream theme customizations against Tailwind CSS v4 CSS tokens.
Workspace classification and isolation metadata do not grant execution authority. The declarative approval-policy engine remains future roadmap work.
Compatibility
- Node.js 22 or newer remains required.
- Existing shared workspaces remain supported.
- The release does not intentionally remove public API routes.
- Custom Tailwind configuration is the primary downstream migration surface.
Verification
The release commit must pass the repository's protected quality-gate and screenshot-drift checks before tagging. Tags are created only from the merged main commit.
Releases 2.3.0 (`docs/releases/2.3.0.md`)
Mission Control 2.3.0
Mission Control 2.3.0 is a dependency-security and maintenance release. It patches 13 known vulnerabilities in the dependency tree (8 high severity), refreshes the test toolchain to current majors, and closes a locale-integrity gap — all behind the same protected quality gate as feature work.
Highlights
- 13 OSV advisories patched: next 16.2.11 (SSRF in Server Actions, middleware/proxy bypass, cache confusion, DoS), sharp 0.35.3, brace-expansion across three major lines, transitive postcss ≥8.5.18
- Supply-chain posture retained: fixes younger than the 7-day release-age gate are excluded explicitly and age out naturally; every workspace override carries an explicit major-line upper bound
MC_DISABLE_RUNTIME_SCANopt-out for local CLI probing during runtime detection- Locale parity restored across all 10 locales, now enforced by a guard test in the quality gate
- Test toolchain on current majors: vite 8, vitest 4, @vitejs/plugin-react 6 (production builds remain webpack)
Security posture
This release concentrates on the dependency boundary. The patched advisories include server-side request forgery in Server Actions and a middleware/proxy bypass in the framework the dashboard runs on — self-hosted operators exposing Mission Control beyond localhost should treat this as a priority upgrade. No Mission Control application code required security changes; the protected quality gate (API parity, lint, typecheck, unit tests, production build, standalone artifact boundaries, Playwright suite) passed on the patch series unchanged.
A note for downstream forks: pnpm overrides replace a dependent's declared version range entirely, so an unbounded override range can jump major API lines in transitive dependencies. Every override this release ships carries an explicit upper bound; keep that pattern if you extend them.
Upgrade notes
- Back up the Mission Control database and runtime configuration.
- Upgrade from the protected
v2.3.0tag or corresponding immutable container digest. - No migrations in this release; no configuration changes are required.
- Optionally set
MC_DISABLE_RUNTIME_SCAN=1on hosts where local CLI probing is unwanted. - Forks that patched dependencies independently should reconcile against the
pnpm-workspace.yamloverrides and release-age exclusions.
Compatibility
- Node.js 22 or newer remains required.
- No public API routes were added or removed.
- No database schema changes.
- The vite/vitest major migration affects the test toolchain only; downstream forks with custom tests should review the vitest 4 mock-constructor semantics (constructible implementations for mocks invoked with
new).
Verification
The release commit must pass the repository's protected quality-gate before tagging. Tags are created only from the merged main commit.
--- METRICS ---
- Files Extracted: 21
- Estimated Token Budget: ~33825 tokens
- Canonical Reference: https://codewiki.google/github.com/builderz-labs/mission-control