Mission Control is a standalone command center for autonomous coding agents.
It gives you a single place to:
- track tasks and task state
- orchestrate agent work across repos
- monitor running agents in tmux
- review artifacts and activity logs
- manage reusable project knowledge with Context Fabrica
- plug in external systems like Linear, GitHub, or OpenClaw without making them part of the core runtime
Mission Control is designed to be the system of record for internal agent lifecycle, while trackers, chat systems, and PR sync stay as optional integrations.
Mission Control runs a practical agent workflow:
task intake → triage → plan → execute → verify → review → complete
It is built for teams running real coding agents, not just prompt demos.
- Task lifecycle management
- tasks, workspaces, priorities, task types, deliverables, and activity history
- Agent orchestration
- spawn agents in isolated git worktrees
- track active sessions and retries
- re-launch work on human feedback
- choose agent profiles and models at runtime
- Operational visibility
- dashboard for tasks, swarm status, health, and system stats
- CLI for task operations and swarm session monitoring
- Knowledge system
- Context Fabrica-backed storage for notes, facts, and procedural skills
- repo exploration and distilled learnings from completed work
- Review loop support
- GSD Core planning and verification artifacts
- PR-aware orchestration for local swarm runtime
- Standalone-first architecture
- external ticketing, PR sync, and gateway/chat systems live under
integrations/
- external ticketing, PR sync, and gateway/chat systems live under
Mission Control treats the internal agent state machine as core:
- task status
- agent assignment
- retries
- review transitions
- deliverables
- session tracking
- human escalation state
External tools like Linear or GitHub are useful, but they should not own the lifecycle. They are adapters around the core, not the core itself.
Mission Control runs as a standalone service on port 18900 by default.
┌─────────────────────────────────────────────────────────────┐
│ Mission Control │
│ ├── HTTP API (/api/*) │
│ ├── Dashboard (/, /dashboard, /space) │
│ ├── CLI (./mc) │
│ ├── SQLite task state │
│ └── Local swarm runtime orchestration │
├─────────────────────────────────────────────────────────────┤
│ Context Fabrica │
│ ├── knowledge records │
│ ├── embeddings │
│ └── graph-aware retrieval │
├─────────────────────────────────────────────────────────────┤
│ Local swarm runtime │
│ ├── planner / bridge │
│ ├── GSD Core backend adapter │
│ ├── tmux agent sessions │
│ ├── repo watcher │
│ └── worktrees, prompts, progress, review loops │
└─────────────────────────────────────────────────────────────┘
By default, local runtime files live under:
~/.mission-control/
Task intake
↓
Bridge triage
↓
Planner creates structured execution plan
↓
Agent runtime executes in isolated worktree
↓
GSD Core verification + review loop
↓
Artifacts stored as deliverables
↓
Task moves to review / done
Human feedback can re-enter the system through Mission Control itself, and the swarm can be re-launched from internal state without relying on an external ticketing system.
Mission Control ships with a built-in dashboard:
/or/dashboard— main command center/space— operational space view
The dashboard gives you:
- task grid with status and priority
- task drawer with full activity and deliverables
- swarm/agent heartbeat visibility
- system stats
- knowledge browsing and review views
Mission Control also ships with a local CLI.
# list tasks
./mc tasks list --status inbox
# create a task interactively
./mc tasks create --interactive
# create a task with GSD-oriented prompts for acceptance criteria and verification
./mc tasks gsd --interactive
# inspect a task
./mc tasks get <task-id>
./mc tasks activities <task-id>
# work with knowledge
./mc knowledge list --project myorg --repo backend-api
./mc knowledge add --interactive
./mc knowledge doctor
./mc knowledge recall --query "deploy worktree failure" --project myorg --repo backend-api
./mc knowledge reembed --schema mission_control
./mc knowledge share <record-id>
# watch the swarm
./mc swarm sessions
./mc swarm attach <task-id>
./mc swarm monitor
# operational views
./mc services health
./mc board --json
# approve/resolve checkpoints an agent is waiting on
./mc checkpoints
./mc checkpoints resolve <checkpoint-id> --decision approveThe CLI talks to the same standalone API as the dashboard.
Environment:
MISSION_CONTROL_URL=http://127.0.0.1:18900The bridge claims inbox work through a durable task lease so multiple bridge processes do not dispatch the same task. The default lease is 15 minutes and can be tuned with:
MISSION_CONTROL_BRIDGE_OWNER=bridge-host-a
MISSION_CONTROL_BRIDGE_LEASE_SECONDS=900./mc services health reports service liveness plus local runtime readiness
for tools such as tmux, git, gh, Node/npm, model keys, PostgreSQL, and
context-fabrica knowledge diagnostics.
Mission Control is not limited to one hosted model or one agent runtime. It supports:
- planner models by provider (
anthropic,gemini,ollama) - agent profiles for the swarm runtime
- per-profile model selection
- per-profile env injection for local or OpenAI-compatible backends
The key idea is:
- the planner chooses a profile name for a step
- the swarm runtime launches the matching profile
- relaunches, retries, and review cycles keep using the same profile and model metadata
{
"agents": {
"defaultProfile": "pi",
"profiles": {
"pi": {
"launcher": "pi",
"provider": "google",
"model": "google/gemini-2.5-pro",
"thinking": "high",
"maxAgents": 5,
"fallbackProfile": "codex",
"env": {}
},
"claude": {
"launcher": "claude",
"model": "claude-opus-4-6",
"maxAgents": 10,
"fallbackProfile": "codex",
"env": {}
},
"codex": {
"launcher": "codex",
"model": "gpt-5.4",
"effort": "medium",
"maxAgents": 3,
"env": {}
},
"ollama-local": {
"launcher": "codex",
"model": "qwen2.5-coder:14b",
"maxAgents": 2,
"env": {
"OPENAI_BASE_URL": "http://127.0.0.1:11434/v1",
"OPENAI_API_KEY": "ollama"
}
}
}
}
}Mission Control now supports Pi as a built-in agent profile and also supports configuring local-model agent profiles, including Ollama-compatible setups, by passing profile-specific environment variables through spawn and relaunch flows.
That means Mission Control itself is agent/model agnostic at the orchestration layer.
Whether a given runtime can actually use a local model depends on the launcher you choose:
launcher: "pi"→ Pi CLI runtimelauncher: "claude"→ Claude CLI runtimelauncher: "codex"→ Codex CLI runtime
If your CLI runtime supports OpenAI-compatible endpoints, you can point it at Ollama with profile env values like:
{
"OPENAI_BASE_URL": "http://127.0.0.1:11434/v1",
"OPENAI_API_KEY": "ollama"
}So Mission Control is now profile-driven, even if the final capability still depends on the launcher runtime you attach.
If you already have pi installed, Mission Control can use it out of the box as the default agent profile.
Mission Control currently targets GSD Core through a small backend adapter in swarm/gsd_backend.py.
Supported backend:
MISSION_CONTROL_GSD_BACKEND=coreIn core mode, Mission Control prompts agents to use the maintained @opengsd/gsd-core command surface:
/gsd:plan-phase --prd/gsd:execute-phase/gsd:verify-work/gsd:plan-phase --gaps/gsd:new-project --autofor greenfield work
The monitor and knowledge distiller expect GSD Core artifacts under .planning/, especially:
.planning/phases/*/*-PLAN.md.planning/phases/*/*-VERIFICATION.md.planning/SUMMARY.md
If MISSION_CONTROL_GSD_BACKEND is set to anything other than core, the monitor fails closed instead of pretending the artifacts are valid. This leaves a clean path for a future gsd-pi adapter, which will need to read .gsd state and use Pi's command/runtime model rather than GSD Core's .planning files.
Mission Control uses Context Fabrica for durable operational memory.
Mission Control uses the installed context-fabrica package directly, but it defaults to a separate Postgres schema:
CONTEXT_FABRICA_SCHEMA=mission_control
EMBEDDING_PROVIDER=fastembed # fastembed | openai | ollama | gemini
CONTEXT_FABRICA_EMBEDDING_DIMENSIONS=384
CONTEXT_FABRICA_INCLUDE_EXISTING=true
CONTEXT_FABRICA_EXISTING_SCHEMA=context_fabrica
CONTEXT_FABRICA_EXISTING_EMBEDDER=fastembed
CONTEXT_FABRICA_EXISTING_EMBEDDING_DIMENSIONS=384Embeddings run through one pluggable module (swarm/embeddings.py). The default
is FastEmbed — local, free, no API key (BAAI/bge-small-en-v1.5, 384
dims) — so knowledge inject / recall / reembed work with zero credentials.
Switch providers with EMBEDDING_PROVIDER (set CONTEXT_FABRICA_EMBEDDING_DIMENSIONS
to match the model):
| Provider | Key? | Model (default) | Dims |
|---|---|---|---|
fastembed |
none | BAAI/bge-small-en-v1.5 (set EMBEDDING_MODEL for bge-base, 768) |
384 |
openai |
OPENAI_API_KEY |
text-embedding-3-small |
1536 |
ollama |
none (local Ollama) | nomic-embed-text |
768 |
gemini |
GOOGLE_GENERATIVE_AI_API_KEY |
gemini-embedding-001 |
1536 |
Changing provider changes vector dimensions, so re-embed (./mc knowledge reembed --force) or recreate the mission_control schema. The default writes to
mission_control (FastEmbed/384) and also reads the existing context_fabrica
schema read-only — using FastEmbed for both keeps them consistent.
Note: embeddings need no key, but text generation (triage, planner, autopilot scope/synthesis) still uses an LLM — configure a provider key or a local Ollama model for that.
For existing-schema read-through, install the same local embedder dependency used to create that schema's vectors. The default assumes Context Fabrica's local FastEmbed/MiniLM path.
Canonical Mission Control knowledge can also be explicitly copied into the shared Context Fabrica schema so agents using the Context Fabrica MCP directly can recall it:
./mc knowledge share <record-id>The dashboard exposes the same action as SHARE on canonical knowledge entries. Sharing re-embeds the record with the shared schema's configured embedder and writes it to CONTEXT_FABRICA_EXISTING_SCHEMA.
- codebase exploration
- linked docs / contextual references
- task completion artifacts
- research findings
- manual injection from CLI or API
- cross-repo architecture scans
- Developer Notes — human-authored guidance
- Procedural Skills — workflows distilled from complex tasks
- Atomic Facts — compact reusable findings
mc-explore myorg/backend-api
mc-explore myorg/backend-api --focus "API endpoints"
mc-explore myorg/platform --package api
mc-explore myorg/backend-api --dry-run
mc-explore myorg/backend-api --trustMission Control includes operational checks for the memory layer:
# Check configured vs actual pgvector dimensions for write/read schemas
./mc knowledge doctor
# Inspect what would be recalled, including source schema and score
./mc knowledge recall --query "auth middleware retry loop" --project myorg --repo backend-api
# Rebuild Mission Control vectors after changing embedding model or dimensions
./mc knowledge reembed --schema mission_control
# Copy reviewed Mission Control knowledge into shared Context Fabrica MCP memory
./mc knowledge share <record-id>The dashboard also exposes recall diagnostics in the Knowledge Base panel and
shows a SHARED badge for canonical records copied into shared Context Fabrica.
All standalone endpoints are served under:
/api/
tasksactivitiesdeliverablesworkspacesagentsagent-statusboardsystem-statsservices/healthknowledgereposcheckpointsstream(server-sent events)
Mission Control’s core API is standalone and tracker-agnostic.
Beyond the task lifecycle, Mission Control surfaces what agents are doing in real time and lets them coordinate:
- Structured progress — agents/bridge report
state,phase, current step, and ablocked_reasonviaPUT /api/tasks/:id/progress. The board shows this per task (and ablockedAgentscount) instead of only a heartbeat. - Agent-to-agent delegation — a blocked or specializing agent can spin up a
focused subtask with
POST /api/tasks/:id/delegate({ "wait": true }pauses the parent until children finish, then auto-resumes it).GET /api/tasks/:id/childrenlists subtasks with their progress. - Reactive event stream —
GET /api/streamis a server-sent-events feed of progress, delegation, completion, and agent-liveness events, so the dashboard updates without polling. - Liveness detection — a built-in reaper flags dead (tmux gone) or stalled
(no heartbeat) agents within seconds, marking the task blocked and emitting an
event, rather than waiting for the monitor cron. Tunable via
MISSION_CONTROL_REAPER_INTERVAL_MS/MISSION_CONTROL_STALE_HEARTBEAT_MS, or disable withMISSION_CONTROL_DISABLE_REAPER=1. - Approval checkpoints — before a risky or ambiguous action an agent can
raise a checkpoint (
POST /api/tasks/:id/checkpoints). The task pauses, the human is notified, and it resumes automatically once resolved. Resolve from the CLI (./mc checkpoints,./mc checkpoints resolve <id> --decision approve|reject|answer) orPOST /api/checkpoints/:id/resolve. The board reportsawaitingApprovaland per-task pending counts. - Push notifications — escalations (
needs_human), approval requests, and dead/stalled agents are pushed to a local~/.mission-control/swarm/notify.shhook (if present) and/or a webhook (MISSION_CONTROL_NOTIFY_WEBHOOK), so you don't have to watch the board. Rate-limited per event/task.
Mission Control starts with zero configuration — npm install && npm start
gives you the dashboard, tasks, board, checkpoints, agent coordination, and the
autopilot/objectives flow on a local SQLite database, no keys or services
required. Optional features are enabled from the dashboard Settings panel
(⚙) or ./mc setup when you want them:
| Feature | Needs | How to enable |
|---|---|---|
| Core (tasks, board, objectives, checkpoints) | nothing | works out of the box |
| Embeddings | nothing (FastEmbed, local) | default; pip install fastembed |
| Autopilot / triage generation | one LLM key (or local Ollama) | paste a key in Settings |
| Knowledge memory (cross-session recall) | Python 3.10+ · PostgreSQL + pgvector · context-fabrica | add the DSN in Settings |
| Agent runtimes (Claude/Codex/Pi) | the CLI installed + logged in | ./mc setup |
If an optional dependency is missing, the related endpoints return a friendly "set this up" response (HTTP 503) instead of failing — the rest keeps working.
npm install
npm start
# open http://localhost:18900 → click ⚙ SETTINGS to add a model key when ready- Node.js 22+
- PostgreSQL 17 + pgvector
- Python 3.12+
- Context Fabrica installed
git clone https://github.com/jimmdd/mission-control.git
cd mission-control
npm install
brew install postgresql@17 pgvector
brew services start postgresql@17
createdb context_fabrica
psql -d context_fabrica -c "CREATE EXTENSION IF NOT EXISTS vector;"
pip install context-fabrica fastembed
mkdir -p ~/.mission-control
cat >> ~/.mission-control/.env << 'EOF'
CONTEXT_FABRICA_DSN=postgresql://$(whoami)@localhost/context_fabrica
CONTEXT_FABRICA_SCHEMA=mission_control
# Embeddings: FastEmbed is local and needs no API key (384 dims).
EMBEDDING_PROVIDER=fastembed
CONTEXT_FABRICA_EMBEDDING_DIMENSIONS=384
CONTEXT_FABRICA_INCLUDE_EXISTING=true
CONTEXT_FABRICA_EXISTING_SCHEMA=context_fabrica
CONTEXT_FABRICA_EXISTING_EMBEDDER=fastembed
CONTEXT_FABRICA_EXISTING_EMBEDDING_DIMENSIONS=384
MISSION_CONTROL_GSD_BACKEND=core
# Text generation (triage/planner/autopilot) still uses an LLM — set a key for
# whichever provider you use, or point the planner at a local Ollama model.
# ANTHROPIC_API_KEY=your-anthropic-key
# GOOGLE_GENERATIVE_AI_API_KEY=your-gemini-key
MISSION_CONTROL_URL=http://127.0.0.1:18900
EOFThe knowledge and health endpoints shell out to the Python scripts under
swarm/ and health/. By default the server runs the copies shipped in this
repo using python3 on your PATH, so a plain pip install context-fabrica
into that interpreter is enough — no separate copy into ~/.mission-control is
required. If you prefer an isolated interpreter, set MC_PYTHON_BIN (or place a
venv at ~/.mission-control/venv-3.12, which is auto-detected). Set MC_HOME
only if you keep runtime scripts outside the checkout.
Mission Control uses the installed context-fabrica package, but defaults to a
separate Postgres schema (mission_control) so its Gemini embeddings do not
alter or conflict with an existing context-fabrica schema. It also reads from
the existing context_fabrica schema by default, without bootstrapping or
writing to that schema. Set CONTEXT_FABRICA_SCHEMA explicitly if you want to
use a different write schema.
Set CONTEXT_FABRICA_EMBEDDING_DIMENSIONS to change the vector size, but do
that before indexing records; an existing schema should be re-embedded after a
dimension change.
Mission Control currently uses the maintained @opengsd/gsd-core package for
agent planning and verification. The core backend expects agents to produce
GSD Core .planning/ artifacts and run commands such as /gsd:plan-phase,
/gsd:execute-phase, and /gsd:verify-work. MISSION_CONTROL_GSD_BACKEND
defaults to core; gsd-pi will need a separate adapter because it uses .gsd
state and a different command/runtime model.
npm start
# verify
curl http://localhost:18900/health
open http://localhost:18900/On start, Mission Control probes your agent runtimes and sources and logs a one-line readiness summary — you don't configure anything to see what's ready:
[mc] readiness: runtimes 2/3 (claude ✓, codex ✓, pi ✗) · sources 2/5 connected
[mc] not connected: Google Drive, Linear — run `mc connections` for details
It detects:
- Runtimes — whether
claude,codex, andpiare installed and authenticated (via each CLI's own login state, e.g.claude auth status/~/.claude.json,~/.codex/auth.json). - Sources — connected MCP servers (Notion, Google Drive, etc.) read straight
from
claude mcp list, plus API-key/CLI integrations (Linear, GitHub).
See the full picture any time with ./mc connections or GET /api/connections.
Run ./mc setup for an interactive walkthrough that fills the gaps: it
probes readiness, then offers to log in each runtime (claude auth login, etc.),
paste missing API keys (written to ~/.mission-control/.env), and points you at
MCP sources to connect. Set MISSION_CONTROL_SKIP_READINESS=1 to skip the
startup probe.
Mission Control binds to 127.0.0.1 by default. For normal local use, no token
is required. If you expose it beyond localhost, set one shared token:
export MISSION_CONTROL_ACCESS_TOKEN="use-a-long-random-value"Clients can pass it as Authorization: Bearer ... or ?token=.... The older
MISSION_CONTROL_READ_ACCESS_TOKEN name still works for compatibility.
Even with no token, the default localhost deployment is hardened against the common ways a browser can be tricked into reaching a local service:
- DNS-rebinding protection — requests are only served when the
Hostheader is an allowlisted name (127.0.0.1,localhost,::1, plusMC_HOST). A malicious site that rebinds its DNS to127.0.0.1still sends its own hostname and is rejected. - CSRF protection — state-changing requests (
POST/PATCH/PUT/DELETE) from a cross-site browser context are blocked viaSec-Fetch-Site/Originchecks. Same-origin dashboard calls and non-browser clients (CLI, bridge, curl) are unaffected. - SSRF protection — the knowledge
fetch-urlendpoint resolves the target host and refuses loopback/private/link-local addresses, including integer-encoded IP literals and redirects that point back inside the network.
If you expose Mission Control under a custom hostname (e.g. behind a reverse proxy), add it to the Host allowlist:
export MISSION_CONTROL_ALLOWED_HOSTS="mc.internal.example.com"Team installs can opt into scoped tokens only when needed:
export MISSION_CONTROL_AUTH_MODE=scoped
export MISSION_CONTROL_READ_TOKEN="read"
export MISSION_CONTROL_WRITE_TOKEN="write"
export MISSION_CONTROL_ADMIN_TOKEN="admin"
export MISSION_CONTROL_WEBHOOK_SECRET="webhook"Unset scoped tokens fall back to the shared token, so simple one-token installs stay simple.
npm install # first time (rebuilds the native better-sqlite3 binding)
npm run build # typecheck (tsc --noEmit)
npm test # behavioral test suite (node --test)If npm test fails to load better-sqlite3 with a NODE_MODULE_VERSION
mismatch after switching Node versions, run npm rebuild better-sqlite3.
GitHub Actions runs build + tests on every push and pull request.
mission-control/
├── server.ts
├── package.json
├── public/
├── src/
│ ├── cli.ts
│ ├── db.ts
│ ├── routes.ts
│ ├── events.ts # in-process event bus (SSE)
│ └── reaper.ts # agent liveness detection
├── tests/
├── health/
├── swarm/
│ ├── gsd_backend.py
│ ├── context_fabrica_config.py
│ ├── bridge.py
│ ├── planner.py
│ └── check-agents.sh
└── integrations/
├── github/
├── linear/
└── openclaw/
Core
- task state
- dashboard
- CLI
- local swarm orchestration
- structured agent progress, delegation, and a reactive event stream
- Context Fabrica integration
- GSD Core backend adapter
- task artifact harvesting and knowledge distillation
Integrations
- issue trackers
- PR review sync
- gateways/chat systems
- optional OpenClaw adapter
Mission Control is intentionally standalone-first.
Optional adapters live under:
integrations/
Current integration areas:
integrations/linear/integrations/github/integrations/openclaw/
These can create tasks, sync comments, or react to review events, but the internal Mission Control lifecycle remains authoritative.
- context-fabrica — knowledge storage and retrieval
- @opengsd/gsd-core — current GSD planning and verification backend
- better-sqlite3 — local task database
- FastEmbed — local embeddings, no API key (default; pluggable)
- Anthropic / Gemini / Ollama — text generation for planning, triage, and autopilot (configurable; pick one)
MIT