> ## Documentation Index
> Fetch the complete documentation index at: https://panopticon-cli.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Architecture

> Technical architecture and design decisions

export const ThemedImage = ({light, dark, alt = ""}) => {
  const [darkMode, setDarkMode] = useState(null);
  useEffect(() => {
    const root = document.documentElement;
    const syncTheme = () => setDarkMode(root.classList.contains("dark"));
    const observer = new MutationObserver(syncTheme);
    syncTheme();
    observer.observe(root, {
      attributes: true,
      attributeFilter: ["class"]
    });
    return () => observer.disconnect();
  }, []);
  if (darkMode === null) return null;
  return <img src={darkMode ? dark ?? light : light} alt={alt} loading="lazy" />;
};

# Architecture

Deep dive into Overdeck's technical architecture and design decisions.

## System Overview

Overdeck consists of three main components:

```
┌─────────────────────────────────────────────────────────────────┐
│                         DASHBOARD                                │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐            │
│  │   React     │  │   Vite      │  │   Express   │            │
│  │   Frontend  │──│   Build     │──│   API       │            │
│  └─────────────┘  └─────────────┘  └─────────────┘            │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                           CLI                                    │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐            │
│  │   Commands  │  │   Skills    │  │   Hooks     │            │
│  └─────────────┘  └─────────────┘  └─────────────┘            │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                        CLOISTER                                  │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐            │
│  │  Heartbeat  │  │  Handoff    │  │ Specialists │            │
│  │  Monitor    │  │  Manager    │  │ (review,    │            │
│  └─────────────┘  └─────────────┘  │ test, inspect│           │
│                                    │ uat, merge) │            │
│                                    └─────────────┘            │
└─────────────────────────────────────────────────────────────────┘
```

The dashboard uses **React + Vite** for the frontend and **Express** for the API server. There is no SSR layer — the frontend is a standard SPA served by the Express API.

Because the `projects.yaml` registry (see [Directory Structure](#directory-structure)) lets one Overdeck instance manage many repositories at once, the dashboard's **God View** aggregates every project's agents and conversations into a single cross-project surface — one place to see what every agent is doing, regardless of which repo it belongs to.

<ThemedImage light="/images/dashboard/god-view-light.png" dark="/images/dashboard/god-view-dark.png" alt="God View: aggregate cross-project view of all agent activity across every registered project" />

### Conversation subagents

When a Claude Code or Codex conversation starts subagents, the conversation panel shows an **Agents** rail on the right. Each row shows the subagent type, description, live status, and nesting depth. Select a row—or choose **Open subagent transcript** from its expanded tool row—to read the subagent's full transcript without leaving the parent conversation.

The selected subagent is stored in the `?subagent=<id>` URL parameter, so a direct link reopens the same transcript. The rail stays hidden when a conversation has no subagents. Codex children use the same interaction, including live updates and reopening completed transcripts. The rail includes nested children. Pi conversations do not currently expose subagents in this view.

## Directory Structure

Overdeck stores all runtime state in `~/.overdeck/`:

```
~/.overdeck/
  config.yaml           # Main configuration
  projects.yaml         # Multi-project registry with issue routing
  project-mappings.json # Linear project → local path mappings (legacy)

  skills/               # Shared skills (SKILL.md format)
  commands/             # Slash commands
  agents/               # Subagent templates (.md files)
  bin/                  # Hook scripts (synced via pan sync)
    heartbeat-hook      # Real-time activity monitoring hook

  agents/               # Per-agent runtime state
    agent-min-123/
      state.json        # Agent state (model, phase, complexity)
      health.json       # Health status
      hook.json         # FPP work queue
      cv.json           # Work history
      mail/             # Incoming messages
      handoffs/         # Handoff prompts (for debugging)

  cloister/             # Cloister AI lifecycle manager
    config.json         # Cloister settings
    state.json          # Running state
    events.jsonl        # Handoff event log

  heartbeats/           # Real-time agent activity
    agent-min-123.json  # Last heartbeat from agent

  logs/                 # Log files
    handoffs.jsonl      # All handoff events (for analytics)

  costs/                # Raw cost logs (JSONL)
  backups/              # Sync backups
  traefik/              # Traefik reverse proxy config
    dynamic/            # Dynamic route configs
    certs/              # TLS certificates
```

## Agent State Management

Each agent's state is tracked in `~/.overdeck/agents/{agent-id}/state.json`:

```json theme={null}
{
  "id": "agent-min-123",
  "issueId": "MIN-123",
  "workspace": "/home/user/projects/myapp/workspaces/feature-min-123",
  "branch": "feature/min-123",
  "phase": "implementation",
  "model": "kimi-k2.5",
  "complexity": "medium",
  "handoffCount": 0,
  "sessionId": "abc123",
  "createdAt": "2024-01-22T10:00:00-08:00",
  "updatedAt": "2024-01-22T10:30:00-08:00"
}
```

| Field | Description |
| - | - |
| `phase` | Current work phase: `planning`, `implementation`, `testing`, `review`, `merging` |
| `model` | Current model: `haiku`, `sonnet`, `opus`, `kimi-k2.5`, or other provider models |
| `complexity` | Detected complexity: `trivial`, `simple`, `medium`, `complex`, `expert` |
| `handoffCount` | Number of times the agent has been handed off to a different model |
| `sessionId` | Claude Code session ID (for resuming after handoff) |

**State Cleanup:** When an agent is killed or aborted (`pan kill`), Overdeck automatically cleans up its state files to prevent stale data from affecting future runs.

## Remote Workspaces

Overdeck supports remote workspace execution via Fly.io Machines. Remote workspaces provide:

* **Cloud-hosted agent environments** — run agents on remote machines without local resource constraints
* **On-demand provisioning** — Fly.io Machines spin up per workspace and shut down after merge
* **Same workflow** — `pan admin remote` commands mirror local workspace operations

Remote workspace management:

```bash theme={null}
pan admin remote init        # Initialize the Fly.io app for workspace machines
pan admin remote setup       # Install flyctl and configure auth
pan admin remote status      # Check Fly.io connection and machine status
pan admin remote resources   # Show RAM/disk usage across VMs
```

## Deep Wipe

For issues that get into a stuck or inconsistent state, use `pan wipe` to completely reset:

```bash theme={null}
pan wipe MIN-123                # Asks for confirmation
pan wipe MIN-123 -y             # Skip confirmation
```

**Deep wipe cleans up:**

* Tmux sessions (`planning-min-123`, `agent-min-123`)
* Agent state directories (`~/.overdeck/agents/planning-*`, `agent-*`)
* Legacy planning directories (`project/.planning/min-123/`)
* Workspace files and the issue's branches
* Issue tracker status (reset to Backlog/Open)

**Dashboard UI:** When aborting planning, choose **Reset to Todo** from the issue's right-click menu for a complete reset. (`pan wipe` remains available from the CLI.)

## Health Monitoring (Deacon Pattern)

Overdeck implements the Deacon pattern for stuck agent detection:

* **Ping timeout**: 30 seconds
* **Consecutive failures**: 3 before recovery
* **Cooldown**: 5 minutes between force-kills

When an agent is stuck (no activity for 30+ minutes), Overdeck will:

1. Force kill the tmux session
2. Record the kill in health.json
3. Respawn with crash recovery context

The dashboard's **Metrics** page shows today's cost, agent health counts and the top spenders, served by `/api/metrics/summary` and `/api/metrics/costs` from Cloister's cost tracking.

<ThemedImage light="/images/dashboard/metrics-light.png" dark="/images/dashboard/metrics-dark.png" alt="Metrics page: runtime comparison and performance analytics across models" />

## FPP (Fixed Point Principle)

> "Any runnable action is a fixed point and must resolve before the system can rest."

*Inspired by Doctor Who: a fixed point in time must occur — it cannot be avoided.*

**Fixed Point Principle (FPP):** Any runnable bead, hook, or agent action represents a fixed point in execution and must be resolved immediately. Overdeck continues executing until no fixed points remain.

FPP ensures agents are self-propelling:

1. Work items are pushed to the agent's hook
2. On spawn/recovery, the hook is checked
3. Pending work is injected into the agent's prompt
4. Completed work is popped from the hook

## Development

### Dev vs Production Strategy

Overdeck uses a **shared config, switchable CLI** approach:

```
~/.overdeck/           # Shared by both dev and prod
├── config.yaml          # Settings
├── projects.yaml        # Registered projects
├── project-mappings.json # Linear → local path mappings
├── agents/              # Agent state
└── skills/              # Shared skills
```

Both dev and production versions read/write the same config, so you can switch between them freely.

### Running in Development Mode

```bash theme={null}
# Clone and setup
git clone https://github.com/eltmon/overdeck.git
cd overdeck
npm install

# Link dev version globally (makes 'pan' use your local code)
npm link

# Start the dashboard (with hot reload)
npm run dev
# → Frontend: http://localhost:3010
# → API: http://localhost:3011
```

### Switching Between Dev and Prod

```bash theme={null}
# Use dev version (from your local repo)
cd /path/to/overdeck && npm link

# Switch back to stable release
npm unlink @overdeck/core
npm install -g @overdeck/core
```

### Dashboard Modes

| Mode | Command | Use Case |
| - | - | - |
| **Production** | `pan up` | Daily usage, HTTPS at [https://overdeck.localhost](https://overdeck.localhost) |
| **Dev** | `npm run dev` | Only for active development on Overdeck itself |

**Note:** Use `pan up` for normal usage. Only use dev mode when actively working on Overdeck's codebase.

### Working on Overdeck While Using It

If you're both developing Overdeck AND using it for your own projects:

1. **Use `npm link`** so CLI changes take effect immediately
2. **Run dashboard from source** for hot reload on UI changes
3. **Config is shared** - workspaces/agents work the same either way
4. **Test in a real project** - your own usage is the best test

## PRD Architecture

### PRD Types

```
myproject/
├── docs/
│   └── PRD.md                   # Canonical PRD (always on main)
└── workspaces/
    └── feature-min-123/
        └── docs/
            └── MIN-123-plan.md   # Feature PRD (lives in feature branch)
```

| PRD Type | Location | Purpose |
| - | - | - |
| **Canonical PRD** | `docs/PRD.md` | Core product definition, always on main |
| **Feature PRD** | `workspaces/feature-{issue}/docs/{ISSUE}-plan.md` | Feature spec, lives in feature branch, merged with PR |

### Feature PRDs Live in Workspaces

When you start planning an issue, Overdeck creates:

1. A git worktree (workspace) for the feature branch
2. A planning session that generates a feature PRD

The feature PRD **lives in the workspace** (feature branch) because:

* It gets merged with the PR (documentation travels with code)
* If you abort planning and delete the workspace, you don't want orphaned PRDs
* Clean separation - each feature is self-contained

### PRD Naming Convention

| Document | Naming | Example |
| - | - | - |
| Canonical PRD | `PRD.md` | `docs/PRD.md` |
| Feature PRD | `{ISSUE}-plan.md` | `MIN-123-plan.md`, `PAN-4-plan.md` |
| Planning artifacts | In `.planning/{issue}/` | `.planning/min-123/STATE.md` |

## Developer Skills

Overdeck has two types of skills:

| Directory | Purpose | Synced When |
| - | - | - |
| `skills/` | User-facing skills for all Overdeck users | Always via `pan sync` |
| `dev-skills/` | Developer-only skills for Overdeck contributors | Only in dev mode |

**Dev mode is automatically detected** when running from the Overdeck source repo (npm link). Skills in `dev-skills/` are:

* Checked into the repo and version-controlled
* Only synced to developers' machines, not end users
* Shown with `[dev]` label in `pan sync --dry-run`

```bash theme={null}
# Check what will be synced (including dev-skills)
pan sync --dry-run

# Output shows:
# Developer mode detected - dev-skills will be synced
# ...
#   + skill/test-specialist-workflow [dev]
```

## Related Guides

* [Cloister](/features/cloister) - AI lifecycle management
* [Core Commands](/cli/core-commands) - CLI reference
* [Troubleshooting](/reference/troubleshooting) - Common issues


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.