> ## 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 = ""}) => <>
    <img src={light} alt={alt} className="block dark:hidden" />
    <img src={dark ?? light} alt={alt} className="hidden dark:block" />
  </>;

# 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 conversation starts subagents through the `Agent` tool, the conversation panel opens a **Subagents** 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. Pi and Codex conversations are unchanged because they do not use Claude Code's subagent file layout.

## 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)
  session-map.json      # Claude sessions → issue linking
  runtime-metrics.json  # Runtime performance metrics

  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 work 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 remote` commands mirror local workspace operations

Remote workspace management:

```bash theme={null}
pan remote init        # Initialize Fly.io provider
pan remote setup       # Configure remote environment
pan remote status      # Check remote workspace status
pan remote resources   # View resource allocation
```

## Deep Wipe

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

```bash theme={null}
pan work wipe MIN-123           # Basic cleanup
pan work wipe MIN-123 -w        # Also delete workspace
pan work wipe MIN-123 -y -w     # 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 (if `-w` flag is used)
* Issue tracker status (reset to Backlog/Open)

**Dashboard UI:** When aborting planning, click "Deep Wipe" for a complete reset.

## 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 runtime data captured here — persisted to `runtime-metrics.json` in the state directory — feeds the dashboard's **Metrics** page, where per-model runtime comparisons and performance analytics let you see how different models perform across your workflow.

<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
