mission-control Documentation

Self-hosted control plane for AI agents: dispatch tasks, review runs, track spend, and operate OpenClaw, Claude Code, Codex, and other runtimes.

RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy mission-control on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name mission-control --restart always builderz-labs/mission-control:latest
Configured Services & Ports
⚙️ mission-control
image: build locally
docker-compose.yml
yaml (docker-compose.yml)
# Production hardening overlay
# Usage: docker compose -f docker-compose.yml -f docker-compose.hardened.yml up -d
services:
  mission-control:
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"
    environment:
      - MC_ALLOWED_HOSTS=localhost,127.0.0.1
      - MC_COOKIE_SECURE=1
      - MC_COOKIE_SAMESITE=strict
      - MC_ENABLE_HSTS=1
    networks:
      mc-internal:

networks:
  mc-internal:
    driver: bridge
    internal: true

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.

bash
git clone https://github.com/builderz-labs/mission-control.git
cd mission-control
bash install.sh --local

Open 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:

bash
nvm use 22
pnpm install
pnpm dev

Windows users can run ./install.ps1 -Mode local in PowerShell.

Start with Docker

bash
docker compose up

Or run the published multi-architecture image:

bash
docker pull ghcr.io/builderz-labs/mission-control:latest
docker run --rm -p 3000:3000 ghcr.io/builderz-labs/mission-control:latest

Use the hardened Compose overlay for a network-accessible deployment:

bash
docker compose -f docker-compose.yml -f docker-compose.hardened.yml up -d

The 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:

bash
export MC_URL=http://localhost:3000
export MC_API_KEY=replace-with-your-api-key

Register an agent and create work:

bash
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:

bash
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

bash
pnpm mc agents list --json
pnpm mc tasks queue --agent scout --json
pnpm mc events watch --types agent,task

MCP server

bash
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.cjs

Use 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

text
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_HOSTS are 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

bash
pnpm install --frozen-lockfile
pnpm lint
pnpm typecheck
pnpm test
pnpm build
pnpm test:e2e

pnpm quality:gate runs the full repository gate. Useful diagnostics:

bash
bash scripts/station-doctor.sh
bash scripts/security-audit.sh
pnpm api:parity

Common 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.

License

MIT © 2026 Builderz Labs


Overview (`tests/README.md`)

E2E Tests

Playwright end-to-end specs for Mission Control API and UI.

Running

bash
# 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.ts

Test Environment

Tests require .env.local with:

  • API_KEY=test-api-key-e2e-12345
  • MC_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 auth
  • csrf-validation.spec.ts — CSRF origin header validation
  • legacy-cookie-removed.spec.ts — Old cookie format rejected
  • login-flow.spec.ts — Login, session, redirect lifecycle
  • rate-limiting.spec.ts — Login brute-force protection
  • timing-safe-auth.spec.ts — Constant-time API key comparison
  • workspace-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 gate
  • agents-crud.spec.ts — Agents CRUD, lookup by name/id, admin-only delete
  • task-comments.spec.ts — Threaded comments on tasks
  • workflows-crud.spec.ts — Workflow template CRUD
  • webhooks-crud.spec.ts — Webhooks with secret masking and regeneration
  • alerts-crud.spec.ts — Alert rule CRUD with full lifecycle
  • user-management.spec.ts — User admin CRUD

Features

  • notifications.spec.ts — Notification delivery and read tracking
  • quality-review.spec.ts — Quality reviews with batch lookup
  • search-and-export.spec.ts — Global search, data export, activity feed

Infrastructure

  • limit-caps.spec.ts — Endpoint limit caps enforced
  • delete-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

  1. Detects the target OS and available runtimes (Docker or Node.js 20+)
  2. Clones or updates the Mission Control repository
  3. Generates a secure .env with random credentials
  4. Starts the dashboard via Docker Compose or local Node.js
  5. Runs an OpenClaw fleet health check (cleans stale PIDs, old logs, validates gateway)
  6. Prints the access URL and admin credentials

Usage

Run the installer script:

bash
# 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-openclaw

Or as a one-liner:

bash
curl -fsSL https://raw.githubusercontent.com/builderz-labs/mission-control/main/install.sh | bash

Prerequisites

  • 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:

  1. Open http://localhost:3000 (or your configured port)
  2. Log in with the credentials printed by the installer (also in .env)
  3. Configure your OpenClaw gateway connection in Settings
  4. 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 password
  • API_KEY — 32-character hex API key
  • AUTH_SECRET — 32-character session secret

To regenerate credentials independently:

bash
bash scripts/generate-env.sh --force

Overview (`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

bash
# 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

bash
# Full system status (memory, disk, sessions, processes)
curl -H "x-api-key: $API_KEY" http://localhost:3000/api/status?action=overview

Diagnostics (Admin Only)

bash
# 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 policies

Check for Updates

bash
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

bash
# Apply available update (bare-metal only; Docker returns instructions)
curl -X POST -H "x-api-key: $API_KEY" http://localhost:3000/api/releases/update

Database Backup

bash
curl -X POST -H "x-api-key: $API_KEY" http://localhost:3000/api/backup

Agent Management

bash
# 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/agents

Station Doctor

For local diagnostics without API access:

bash
bash scripts/station-doctor.sh

Checks: Docker health, port availability, disk space, DB integrity, backup age.

Common Workflows

Automated Health Monitoring

bash
# 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"
fi

Pre-Upgrade Checklist

  1. Check for updates: GET /api/releases/check
  2. Create backup: POST /api/backup
  3. Run diagnostics: GET /api/diagnostics (verify no active tasks)
  4. Apply update: POST /api/releases/update (or docker pull + recreate for Docker)
  5. 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 dev or Docker)
  • An admin account (visit /setup on first run)
  • Your API key (auto-generated on first run, shown in Settings)

Step 1: Start Mission Control

bash
pnpm dev

Open 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:

bash
export MC_URL=http://localhost:3000
export MC_API_KEY=your-api-key

Step 2: Register an Agent

Agents can self-register via the API. This is how autonomous agents announce themselves to Mission Control:

bash
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"}' | jq

Expected response:

json
{
  "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

bash
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"
  }' | jq

Expected response:

json
{
  "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:

bash
curl -s "$MC_URL/api/tasks/queue?agent=scout" \
  -H "Authorization: Bearer $MC_API_KEY" | jq

Expected response:

json
{
  "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:

bash
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."
  }' | jq

Step 6: Send a Heartbeat

Heartbeats tell Mission Control your agent is alive. Without them, agents are marked offline after 10 minutes:

bash
curl -s -X POST "$MC_URL/api/agents/1/heartbeat" \
  -H "Authorization: Bearer $MC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}' | jq

Expected response:

json
{
  "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:

text
┌─────────────────────────────────┐
│  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:

bash
# 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,agent

See 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:

bash
claude mcp add mission-control -- node /path/to/mission-control/scripts/mc-mcp-server.cjs

Set 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?


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-drift label is applied to a PR (see automation)

How to Take New Screenshots

Prerequisites

  • Mission Control running against a new disposable database (pnpm dev or Docker)
  • Browser with at least 1440×900 viewport recommended

Steps

  1. Start a disposable demo instance. Never capture an operator or production database.

    bash
    pnpm dev
    # or
    docker compose up
  2. Seed 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.

  3. 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.

  4. 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.png
  5. Review the final pixels at full resolution. A second reviewer should inspect every
    visible label and value. Strip image metadata, then add the approved file under docs/.

    bash
    cp ~/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/, and public/
  • Adds a screenshot-drift label 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.png variant 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
bash scripts/security-audit.sh        # Check .env and configuration
bash scripts/station-doctor.sh         # Check runtime health

Or use the diagnostics API (admin only):

bash
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=day

The 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
bash scripts/generate-env.sh           # Generates .env with random secrets
chmod 600 .env                          # Lock down permissions

The installer (install.sh) does this automatically. If you set up manually, ensure:

  • AUTH_PASS is 12+ characters, not a dictionary word
  • API_KEY is 32+ hex characters
  • AUTH_SECRET is a unique random string
  • .env file permissions are 600

2. Network Access Control

Mission Control uses a host allowlist in production:

env
# 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=1

Deploy behind a reverse proxy with TLS (Caddy, nginx, Tailscale Funnel) for any network-accessible deployment.

3. HTTPS & Cookies

For HTTPS deployments:

env
MC_COOKIE_SECURE=1           # Cookies only sent over HTTPS
MC_COOKIE_SAMESITE=strict    # CSRF protection
MC_ENABLE_HSTS=1             # HTTP Strict Transport Security

4. 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:

bash
docker compose -f docker-compose.yml -f docker-compose.hardened.yml up -d

This enables:

  • Read-only filesystem with tmpfs for /tmp and /app/.next/cache
  • Capability dropping — all Linux capabilities dropped, only NET_BIND_SERVICE retained
  • 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

env
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 history

11. 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:

env
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) or
shasum -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" in openclaw.json.
  • Use SSH tunneling or Tailscale for remote access.
  • Docker users: Be aware that Docker can bypass UFW rules. Use DOCKER-USER chain rules.

2. Authentication

  • Always enable gateway auth with a strong random token.
  • Generate: openclaw doctor --generate-gateway-token
  • Store in OPENCLAW_GATEWAY_TOKEN env var (never in NEXT_PUBLIC_* variables).
  • Rotate regularly.

3. Hardened Gateway Configuration

json
{
  "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

bash
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:

text
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.

Create per-agent keys with limited scopes:

bash
# 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
}' --json

Scoped 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:

bash
pnpm mc raw --method GET --path '/api/security-audit?event_type=global_api_key_used&timeframe=day' --json

Goal: 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.

Agents register themselves at startup. This is the simplest path and requires no manual setup:

bash
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:

bash
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:

bash
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:

bash
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 .md files
  • ~/.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:

markdown
---
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

markdown
# 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 immediately

Example: Researcher Agent

markdown
# 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 insights

Example: Reviewer Agent

markdown
# 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:

bash
curl -s http://localhost:3000/api/agents/1/soul \
  -H "Authorization: Bearer $MC_API_KEY" | jq

Response:

json
{
  "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 workspace soul.md file on disk
  • database — Read from the MC database (no workspace file found)
  • none — No SOUL content set

Update a SOUL:

bash
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:

bash
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:

json
{
  "openclawId": "scout",
  "dispatchModel": "9router/cc/claude-sonnet-4-6",
  "capabilities": ["code-review", "testing", "documentation"],
  "framework": "claude-sdk"
}

Update via API:

bash
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

  1. Agent sends POST /api/agents/{id}/heartbeat every 30 seconds
  2. MC updates status to idle and refreshes last_seen
  3. If no heartbeat for 10 minutes (configurable), agent is marked offline
  4. Stale tasks (in_progress for 10+ min with offline agent) are requeued

Heartbeat Request

bash
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:

bash
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 access
  • reviewer — Read-only tools for code review and quality checks

What's Next


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

  1. Ensure Mission Control API is running.
  2. Set environment variables or use profile flags:
  1. Run commands:
bash
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 terminate

Command 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 --json mode, 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:

bash
node scripts/check-api-contract-parity.mjs \
  --root . \
  --openapi openapi.json \
  --ignore-file scripts/api-contract-parity.ignore

Machine output:

bash
node scripts/check-api-contract-parity.mjs --json

The 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.ignore currently 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

bash
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:

json
{
  "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_name doesn'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:

bash
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)

bash
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):

bash
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

bash
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

text
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/connect for the same agent deactivates the previous connection.
  • The sessionId format 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:

bash
sudo apt-get update
sudo apt-get install -y python3 make g++

macOS

Xcode command line tools are required:

bash
xcode-select --install

Quick Start (Development)

bash
cp .env.example .env.local
pnpm install
pnpm dev

Open http://localhost:3000. Login with AUTH_USER / AUTH_PASS from your .env.local.

Production (Direct)

bash
pnpm install --frozen-lockfile
pnpm build
pnpm start

The pnpm start script binds to 0.0.0.0:3005. Override with:

bash
PORT=3000 pnpm start

Important: 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.

bash
pnpm install --frozen-lockfile
pnpm build
pnpm start:standalone

For a full in-place update on the target host:

bash
BRANCH=fix/refactor PORT=3000 pnpm deploy:standalone

What 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):

bash
# 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 status

Mode-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.yml
  • MC_MODE=dev → docker-compose-dev.yml
  • OPENCLAW_ENABLED=1 → make <verb> all includes OpenClaw
  • OPENCLAW_ENABLED=0 → make <verb> all manages MC only

Command grammar:

text
make <verb> [all|mc|openclaw] [dev|prod]
  • all is default scope.
  • dev / prod override MC_MODE for one command invocation.
  • Why no --dev / --prod: GNU Make consumes unknown --xxx tokens as Make options before Makefile goals are parsed, so mode overrides use positional tokens for deterministic behavior.
  • make restart [scope] is deterministic and always executes make down [scope] followed by make up [scope].
  • With default all scope, OPENCLAW_ENABLED=1 includes OpenClaw in both the down and up phases; OPENCLAW_ENABLED=0 skips 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:

bash
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, if OPENCLAW_ENABLED=1, also refreshes OpenClaw source state.
    • For scope=openclaw, refreshes OpenClaw source state regardless of OPENCLAW_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 when OPENCLAW_ENABLED=1.

Minimum .env / .env.openclaw keys for this flow:

env
# .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.1
bash
docker compose up          # with gateway connectivity
docker compose --profile standalone up   # without gateway (standalone mode)

Or build and run manually:

bash
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-control

The Docker image:

  • Builds from node:22-slim with multi-stage build
  • Compiles better-sqlite3 natively 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:

  1. 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 via extra_hosts.

  2. Browser-side (user's browser → gateway WebSocket): When the gateway host is a
    Docker-internal name (like host.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, set NEXT_PUBLIC_GATEWAY_HOST to the public hostname.

If your gateway runs in another container, put both on the same Docker network and set
OPENCLAW_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_SECURE unset
  • Keep MC_ENABLE_HSTS unset
  • Use OPENCLAW_GATEWAY_HOST=host.docker.internal when 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:

bash
docker run -v /path/to/data:/app/.data ...

Automatic backups

  • Set MC_AUTO_BACKUP=1 (accepts 1/true/yes/on) in your .env to 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 authenticated
claude / codex / opencode CLIs in ~/.local/bin, the default
docker-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 claude and codex as a fallback — if the host doesn't
    have them in ~/.local/bin, the container's installed copies are used.
    The host's ~/.local/bin comes first in PATH, 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 /mnt are 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 node user,
    renamed nextjs) so bind-mounted host files (typical Linux uid 1000) are
    read/written without chown.

Ports. docker-compose.yml maps ${MC_PORT} on the host to ${PORT} in
the container. The bundled Makefile computes its readiness/status URL from
MC_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:

yaml
user: "$(id -u):$(id -g)"   # or hard-code your uid:gid

Otherwise 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

bash
docker compose -f docker-compose.yml -f docker-compose.hardened.yml up -d

This 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.local as needed)
  • /tmp noexec: add tmpfs /tmp tmpfs defaults,noexec,nosuid,nodev 0 0 to /etc/fstab, then sudo 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 install selinux-basics selinux-policy-default and 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=1 requires Docker access. Ensure the mc-openclaw-gateway service bind-mounts the host Docker socket (/var/run/docker.sock) as shown in docker-compose-openclaw.yml.

Note — OPENCLAW_HOME vs OPENCLAW_STATE_DIR

Mission Control supports two env vars for locating OpenClaw:

  • OPENCLAW_HOME — treated as the parent home directory; .openclaw is appended automatically.
    Setting OPENCLAW_HOME=/root/.openclaw will resolve to /root/.openclaw/.openclaw (double-nesting bug).
  • OPENCLAW_STATE_DIR — treated as the exact state directory path. Always prefer this.

Recommended .env for a standard install:

env
OPENCLAW_STATE_DIR=/root/.openclaw
MISSION_CONTROL_DATA_DIR=/absolute/path/to/.data

Using an absolute path for MISSION_CONTROL_DATA_DIR ensures your
database and data survive npm 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

text
┌──────────────── Pod ────────────────┐
│  ┌─────────┐     ┌───────────────┐  │
│  │   MC    │◄───►│   Gateway     │  │
│  │ :3000   │     │   :18789      │  │
│  └─────────┘     └───────────────┘  │
│       ▲                  ▲          │
│       │ localhost        │          │
│       └──────────────────┘          │
└─────────────────────────────────────┘

Required Configuration

Environment variables for the MC container:

bash
AUTH_USER=admin
AUTH_PASS=<secure-password>
API_KEY=<your-api-key>
OPENCLAW_GATEWAY_HOST=127.0.0.1
NEXT_PUBLIC_GATEWAY_PORT=18789

Agent Registration

The gateway must register its agents with MC on startup. Include the agents array in the gateway registration request:

bash
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:

bash
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:

bash
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.

bash
pnpm rebuild better-sqlite3

The health endpoint (/api/status?action=health) will report this error explicitly.

"Module not found: better-sqlite3"

Native compilation failed. On Ubuntu/Debian:

bash
sudo apt-get install -y python3 make g++
rm -rf node_modules
pnpm install

Docker: gateway unreachable / WebSocket not connecting

Checklist:

  1. Verify the gateway is reachable from inside the container:

    bash
    docker exec mission-control curl -s http://host.docker.internal:18789
  2. Check env vars are set:

    bash
    docker exec mission-control env | grep -i gateway

    You should see OPENCLAW_GATEWAY_HOST=host.docker.internal.

  3. If using a mounted ~/.openclaw directory, the openclaw.json inside may have
    gateway.host = "127.0.0.1" — this is the host's loopback, not reachable from the
    container. Environment variables take precedence over openclaw.json, so set
    OPENCLAW_GATEWAY_HOST=host.docker.internal in your .env or docker-compose.

  4. 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, set NEXT_PUBLIC_GATEWAY_HOST to a hostname your browser can reach.

  5. Linux-specific: host.docker.internal requires Docker 20.10+. The extra_hosts
    entry in docker-compose.yml handles this. If using docker run directly, 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 to
pnpm 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:

bash
rm -rf node_modules .next
pnpm install
pnpm build

Database 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:

json
{
  "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:

bash
NEXT_PUBLIC_GATEWAY_OPTIONAL=true

This runs Mission Control in standalone mode (core features available, live gateway streams unavailable).

Production option: reverse-proxy gateway WebSocket over 443.

nginx example:

nginx
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:

bash
NEXT_PUBLIC_GATEWAY_URL=wss://your-domain.com/gateway-ws

Mission 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:

json
{
  "id": "coder",
  "model": "anthropic/claude-sonnet-4-6",
  "fallbacks": []
}

Doctor output showed:

text
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:

  1. Remove fallbacks from each entry in agents.list inside ~/.openclaw/openclaw.json.
  2. Run openclaw doctor.
  3. Verify with openclaw gateway status.

Expected result:

  • openclaw doctor no longer reports Unrecognized key: "fallbacks".
  • openclaw gateway status shows Runtime: running and RPC 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:

text
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.

bash
# 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:

bash
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

  1. Create tasks in inbox status (no assigned_to):
bash
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"
  }'
  1. Agents poll the queue. MC atomically claims the best task:
bash
# 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:

  1. Priority: critical > high > medium > low
  2. Due date: Earliest due date first (null = last)
  3. Created at: Oldest first (FIFO within same priority)

Capacity Control

Each agent can set max_capacity to limit concurrent tasks:

bash
# 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

  1. Tasks are created with assigned_to set
  2. The scheduler's dispatchAssignedTasks job runs periodically
  3. 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 review status

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:

bash
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_attempts and revert to assigned
  • 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

text
in_progress ──► review ──► Aegis reviews ──► APPROVED ──► done
                                          └─► REJECTED ──► assigned (with feedback)

How Aegis Reviews

  1. Scheduler's runAegisReviews job picks up tasks in review status
  2. Builds a review prompt with the task description and agent's resolution
  3. Sends to the Aegis agent (configurable via MC_COORDINATOR_AGENT)
  4. Parses the verdict:
    • VERDICT: APPROVED → task moves to done
    • VERDICT: REJECTED → feedback is attached as a comment, task reverts to assigned
  5. 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 failed with accumulated feedback
  • All review results are stored in the quality_reviews table

Setting Up Aegis

Aegis is just a regular agent with a reviewer SOUL. Create it:

bash
# 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

bash
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

bash
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

bash
# 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:

bash
# 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:

bash
# 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:

  1. Finds tasks stuck in in_progress for 10+ minutes with an offline agent
  2. Reverts them to assigned with a comment explaining the stall
  3. 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:

  1. Cron creates recurring tasks (Pattern 5)
  2. Queue-based dispatch distributes tasks to available agents (Pattern 2)
  3. Model routing picks the right model per task (Pattern 3)
  4. Aegis reviews all completed work (Pattern 4)
  5. Stale recovery handles agent failures (Pattern 7)
text
Cron ──► inbox ──► Queue assigns ──► Agent works ──► Aegis reviews ──► done
                                          │                  │
                                          └── timeout ───────┘── requeue

Event Streaming

Monitor orchestration in real time with SSE:

bash
# Watch all task and agent events
node scripts/mc-cli.cjs events watch --types task,agent --json

Or via API:

bash
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


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

Quick Start (5 Minutes)

bash
git clone https://github.com/builderz-labs/mission-control.git
cd mission-control
pnpm install
cp .env.example .env
pnpm dev

Then 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.
  • Home (this page)
  • Getting-Started - install, auth, first login, and initial checks
  • Architecture - runtime model, data flow, and component map
  • Operations-Runbook - backups, upgrades, troubleshooting, incident steps
  • API-Guide - endpoint groups, auth patterns, and examples
  • Security-Model - auth, RBAC, API keys, host/network controls
  • Integrations - webhooks, GitHub sync, direct CLI, multi-gateway setup
  • FAQ - common operator/admin questions

Notes For Maintainers

  • Keep wiki pages aligned with shipped behavior in the same PR when features change.
  • Add a Last reviewed line 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):

html
<div class="bg-card text-foreground border-void-cyan">

Inline styles (ReactFlow, recharts):

ts
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 values
  • text-sm font-medium — labels, nav items
  • text-xs font-mono — metadata, timestamps, model names
  • text-[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

html
<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-panel base
  • 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-panel with 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-xs with accent background/border

CORE Node

  • Central orchestration hub in agent network
  • Concentric pulsing rings (CSS keyframes, no framer-motion)
  • font-mono tracking-widest for "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 @keyframes over JavaScript animation
  • Duration: 2-3s for ambient loops, 150-200ms for interactions
  • Easing: ease-in-out for loops, ease-out for 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:

tsx
<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 ring utility: focus-visible:ring-2 focus-visible:ring-ring
  • Ring color matches --void-cyan

Reduced Motion

Global rule in globals.css:

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" and aria-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

  1. Identify current onboarding/walkthrough code paths.
  2. Document triggers, persistence flags, and routing.
  3. Add failing tests for first-run, skip, replay, and already-seen states.

Phase 2: implementation hardening

  1. Fix state transitions and persistence updates.
  2. Ensure walkthrough can be reopened from primary UI.
  3. Add visible hint/help entry to improve discoverability.
  4. Handle corrupted or partial onboarding state safely.

Phase 3: verification

  1. Run targeted tests for onboarding/walkthrough.
  2. Run full project checks.
  3. 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:

  1. API surface drift between route handlers, openapi.json, and /api/index.
  2. No first-party comprehensive CLI for operators/agents.
  3. Uneven hardening around operational concerns (auth posture defaults, multi-instance rate limiting strategy, spawn history durability).
  4. 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

  1. Deliver a first-party CLI with functional parity across core agent workflows.
  2. Add optional TUI for rapid situational awareness and interactive operations.
  3. Establish API contract parity as an enforceable quality gate.
  4. 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

  1. Autonomous agent runtime (headless, non-interactive).
  2. Human operator (terminal-first incident response).
  3. 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

  1. Add API parity checker script and CI command.
  2. Add first-party CLI scaffold with command routing and normalized request layer.
  3. Add docs for CLI profiles/auth/output contract.

PR 2

  1. Implement full command matrix.
  2. Add TUI dashboard shell.
  3. Add CLI integration tests.
  4. 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.x across 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 /chat panel 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.

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_owner state 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_owner task 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_BUSY contention 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-src nonce handling
  • OpenClaw spawn compatibility when agents use configured default models
  • Regression coverage for gateway dashboard registration preserving device-auth posture

Security

  • Removed unsafe-inline in favor of nonce-based CSP
  • Added stronger SSRF/path-traversal detection in the skill registry
  • Stopped forcing dangerouslyDisableDeviceAuth when 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

  1. Back up the Mission Control database and runtime configuration.
  2. Upgrade from a protected v2.2.0 tag or corresponding immutable container digest.
  3. Run migrations before enabling strict isolation on existing workspaces.
  4. Review MC_WORKSPACE_ROOT, trusted proxies, gateway credentials, and host-runtime permissions.
  5. 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_SCAN opt-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

  1. Back up the Mission Control database and runtime configuration.
  2. Upgrade from the protected v2.3.0 tag or corresponding immutable container digest.
  3. No migrations in this release; no configuration changes are required.
  4. Optionally set MC_DISABLE_RUNTIME_SCAN=1 on hosts where local CLI probing is unwanted.
  5. Forks that patched dependencies independently should reconcile against the pnpm-workspace.yaml overrides 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 ---