Orchestration Board
The Board tab in the command center provides a visual task orchestration interface at optimal.miami. It merges kanban tasks from Supabase with live agent sessions from the StateHub into a unified view.
Layout
The board uses a three-column kanban layout:
| Column | Task statuses | Session states |
|---|---|---|
| Queued | backlog, ready | idle |
| Active | in_progress, claimed | running |
| Review | review, blocked | awaiting_review, completed, failed |
Epic Swimlanes
Tasks are organized into collapsible epic swimlanes. Each epic swimlane shows:
- Epic title
- Progress indicator (e.g., "3/7 done") counting completed children
- Collapsible section containing stories and direct tasks
Stories within an epic can themselves contain sub-tasks, forming a three-level hierarchy: epic > story > task.
Ungrouped tasks (those without a parent epic) appear in a separate "Ungrouped" section at the bottom.
Task Cards
Task cards display:
- Status dot (color-coded by state)
- Title
- Project or source repo
- Type badge (epic, story, task) with distinct colors (peach for epic, mauve for story, blue for task)
- Priority badge (P1--P4)
Clicking a task card opens a detail panel (slide-in on desktop, bottom sheet on mobile) showing the full description, children list, metadata, and a launch agent button.
Agent Session Cards
Agent session cards display:
- Status dot (color-coded by state)
- Label and agent type icon
- Agent type and tmux session name
- Last activity timestamp
- Truncated prompt (expandable)
- Quick action buttons
Quick Actions on Session Cards
| Action | When visible | What it does |
|---|---|---|
| Stop | running, awaiting_review | Sends SIGINT via /api/agents/stop |
| Restart | completed, failed | Re-launches the session |
| Resume | awaiting_review | Transitions back to running |
| Dismiss | completed, failed | Removes the session |
| Attach | always (if tmux session exists) | Opens a terminal tab attached to the tmux session |
Status Dots
Color-coded dots indicate the state of tasks and sessions:
| Color | States |
|---|---|
| Blue | running, in_progress, claimed |
| Green | completed, done |
| Yellow | awaiting_review, review |
| Red | failed, blocked |
| Dim (gray) | idle, backlog, ready, and other states |
Session State Machine
Every agent session follows a deterministic state machine with 5 states:
idle --> running --> awaiting_review --> completed
--> failed| State | Meaning |
|---|---|
idle | Session created, agent not yet started |
running | Agent is actively working |
awaiting_review | Agent finished or paused, waiting for human input |
completed | Work finished successfully |
failed | Agent errored or was cancelled |
Transitions
| From | Event | To |
|---|---|---|
| idle | start | running |
| running | hook.to_review, agent.prompt_ready | awaiting_review |
| running | process.exit | completed |
| running | process.exit_error, user.cancel | failed |
| awaiting_review | hook.to_running, user.resume, agent.tool_use | running |
| awaiting_review | process.exit | completed |
| awaiting_review | process.exit_error, user.cancel | failed |
| completed | start | running (restart) |
| completed | user.requeue | idle |
| failed | start | running (retry) |
| failed | user.requeue | idle |
State transitions happen automatically via lifecycle hooks (see Hook System) or can be triggered manually by dragging session cards between columns on the board.
Session Discovery
A background scanner runs every 30 seconds, listing all tmux sessions via tmux list-sessions. It:
- Auto-registers any tmux session with an
agent-prefix that is not already tracked - Checks non-prefixed sessions for the
OPTIMALOS_SESSION_TMUXenvironment variable - Infers agent type from session name (
claude-> claude-code,openclaw-> openclaw, otherwise shell) - Marks tracked sessions as ended if their tmux session has disappeared
Session Persistence
Sessions are stored in ~/.optimalos/sessions.json with debounced writes (500ms). On server restart, sessions are restored from disk. Completed and failed sessions older than 24 hours are pruned on load.
On shutdown (SIGINT/SIGTERM), sessions are flushed synchronously to prevent data loss.
Agent Launcher
The board includes a launch modal accessible from the toolbar or task detail panel.
Launch API
POST /api/agents/launch
Authorization: Bearer <token>
Content-Type: application/json{
"agent_type": "claude-code",
"prompt": "Fix the login timeout bug",
"task_id": "task-uuid",
"session_name": "agent-login-fix",
"depends_on": ["other-task-uuid"],
"working_dir": "/home/oracle/.openclaw/workspace/optimalOS",
"interactive": false
}| Field | Required | Description |
|---|---|---|
agent_type | Yes | claude-code, openclaw, or shell |
prompt | Yes (unless interactive) | The prompt or command to run |
task_id | No | Link to a kanban task |
session_name | No | Custom tmux session name (auto-generated if omitted) |
depends_on | No | Array of task IDs this session depends on |
working_dir | No | Working directory (defaults to $HOME) |
interactive | No | Launch Claude Code in interactive mode (claude-code only) |
Agent Types
Agent types are config-driven — the catalog is loaded from config.agents in ~/.optimalos/config.json rather than hardcoded. Common types shipped in the default catalog:
| Type | Command |
|---|---|
claude-code | claude --print '<prompt>' (or bare claude in interactive mode). |
openclaw | openclaw agent --message '<prompt>'. |
shell | Runs the prompt directly as a shell command. |
Custom agent types (Kimi, Codex, Aider, anything PTY-friendly) can be added by extending config.agents with a new entry that supplies a command template. See optimalOS/src/agents/catalog.ts.
The launcher injects OPTIMALOS_SESSION_TMUX and OPTIMALOS_HOOK_PORT environment variables into the tmux session. For Claude Code agents, it also installs hook scripts in ~/.claude/settings.json that curl lifecycle events back to /api/hooks/ingest.
Stop API
POST /api/agents/stop
Authorization: Bearer <token>
Content-Type: application/json{
"session_id": "session-1"
}Sends Ctrl+C to the tmux session and transitions the session state to failed.
Dependency Chains
Tasks can declare dependencies on other tasks via depends_on. When a session's linked task completes:
- The StateHub checks all idle sessions for unmet dependencies
- If all dependencies are satisfied, the session auto-starts (
idle -> running)
This allows multi-step workflows where each step triggers the next automatically.
Drag-and-Drop
Session cards support two drag mechanisms:
- Pointer Events drag (works on mobile and desktop) -- uses
pointerdown/pointermove/pointerupwith a 5px threshold to distinguish taps from drags - HTML5 drag-and-drop fallback for desktop
Dropping a session card on a different column triggers a state transition via PATCH /api/hooks/sessions/:id.
Filters
A filter bar at the top of the board provides:
- Type filter: Show all, or filter to epics, stories, or tasks only
- Priority filter: Show all, or filter to P1, P2, P3, or P4
Filters are client-side and applied immediately without server requests.
Real-Time Updates
The board connects to the WebSocket State Hub at /ws/state on load. When a state change arrives:
- Session cards are patched individually in the DOM (no full re-render)
- Cards move between columns as states change
- Status dots and activity timestamps update in place
Multiple browsers or devices viewing the board all stay in sync without polling.