# PilotDeck Docker

PilotDeck runs as two cooperating Node.js processes in the container:

- **Gateway**: agent runtime on `PILOTDECK_GATEWAY_PORT` (default `18789`)
- **UI Server**: web frontend + REST/WebSocket adapter on `SERVER_PORT` (default `3001`)

The Docker Compose setup persists the full `PILOT_HOME` directory, including generated config, auth DB, permissions, sessions/projects, memory, skills/plugins, and router stats.

## Quick Start with Docker Compose

### Prerequisites

- [Docker](https://docs.docker.com/get-docker/) v20+
- [Docker Compose](https://docs.docker.com/compose/) v2+

### Option A: Configure via environment variables

Set the model provider variables in `docker-compose.yml` or an `.env` file:

```env
PILOTDECK_MODEL=openai/gpt-4.1
PILOTDECK_API_KEY=sk-your-api-key
PILOTDECK_API_URL=https://api.openai.com/v1
```

Then start:

```bash
docker compose up -d --build
```

If `/root/.pilotdeck/pilotdeck.yaml` does not exist in the `pilotdeck-home` volume, the entrypoint generates it from the `PILOTDECK_*` environment variables on first start.

### Option B: Configure via YAML file

Create the host config file first:

```bash
mkdir -p ~/.pilotdeck
cat > ~/.pilotdeck/pilotdeck.yaml <<'YAML'
schemaVersion: 1
agent:
  model: openai/gpt-4.1
model:
  providers:
    openai:
      protocol: openai
      url: https://api.openai.com/v1
      apiKey: sk-your-api-key
      models:
        gpt-4.1: {}
YAML
```

Then uncomment the config bind mount in `docker-compose.yml`:

```yaml
volumes:
  - pilotdeck-home:/root/.pilotdeck
  - ${PILOTDECK_CONFIG:-${HOME}/.pilotdeck/pilotdeck.yaml}:/root/.pilotdeck/pilotdeck.yaml:ro
```

Start the service:

```bash
docker compose up -d --build
```

The UI is available at **http://localhost:3001**.

## Workspace Mounts

Agents run inside the container. To let them access a host project, mount it into `/workspace` by uncommenting the workspace bind mount:

```yaml
volumes:
  - pilotdeck-home:/root/.pilotdeck
  - ${PILOTDECK_WORKSPACE:-${PWD}}:/workspace
```

You can set `PILOTDECK_WORKSPACE=/path/to/project` before running `docker compose up`.

## Manual Docker Build & Run

### Build the image

```bash
docker build -t pilotdeck:latest .
```

### Run with environment variables

```bash
docker run -d --name pilotdeck \
  -p 3001:3001 \
  -v pilotdeck-home:/root/.pilotdeck \
  -e PILOTDECK_MODEL=openai/gpt-4.1 \
  -e PILOTDECK_API_KEY=sk-your-api-key \
  -e PILOTDECK_API_URL=https://api.openai.com/v1 \
  pilotdeck:latest
```

### Run with a config file

```bash
docker run -d --name pilotdeck \
  -p 3001:3001 \
  -v pilotdeck-home:/root/.pilotdeck \
  -v ~/.pilotdeck/pilotdeck.yaml:/root/.pilotdeck/pilotdeck.yaml:ro \
  pilotdeck:latest
```

### Run with a workspace mount

```bash
docker run -d --name pilotdeck \
  -p 3001:3001 \
  -v pilotdeck-home:/root/.pilotdeck \
  -v "$PWD":/workspace \
  -e PILOTDECK_MODEL=openai/gpt-4.1 \
  -e PILOTDECK_API_KEY=sk-your-api-key \
  -e PILOTDECK_API_URL=https://api.openai.com/v1 \
  pilotdeck:latest
```

### Run with a proxy

```bash
docker run -d --name pilotdeck \
  -p 3001:3001 \
  -v pilotdeck-home:/root/.pilotdeck \
  -e PILOTDECK_MODEL=openai/gpt-4.1 \
  -e PILOTDECK_API_KEY=sk-your-api-key \
  -e PILOTDECK_API_URL=https://api.openai.com/v1 \
  -e PILOTDECK_PROXY=http://host.docker.internal:7890 \
  pilotdeck:latest
```

## Environment Variables

| Variable | Description | Default |
|---|---|---|
| `PILOT_HOME` | PilotDeck state directory inside the container | `/root/.pilotdeck` |
| `PILOTDECK_MODEL` | Main model identifier, formatted as `provider/model` | `openrouter/deepseek/deepseek-v4-flash` |
| `PILOTDECK_LIGHT_MODEL` | Lightweight routing/judge model identifier | `openrouter/qwen/qwen3-8b` |
| `PILOTDECK_API_KEY` | API key for the main model provider | `PLACEHOLDER_RUN_ONBOARDING_TO_REPLACE` |
| `PILOTDECK_API_URL` | Base URL for the main model provider API | `https://openrouter.ai/api/v1` |
| `PILOTDECK_LIGHT_API_KEY` | API key for a different light-model provider | Falls back to `PILOTDECK_API_KEY` |
| `PILOTDECK_LIGHT_API_URL` | Base URL for a different light-model provider | Falls back to `PILOTDECK_API_URL` |
| `PILOTDECK_PROXY` | HTTP/HTTPS proxy URL | — |
| `SERVER_PORT` | UI server port | `3001` |
| `PILOTDECK_GATEWAY_PORT` | Gateway port used by the UI bridge | `18789` |

## Architecture

```text
Browser (localhost:3001) ──► UI Server (port 3001) ──► Gateway (port 18789)
```

Both processes are managed by `concurrently` inside the Docker container.

## Development

```bash
npm install
npm run dev
```

This starts the Gateway and UI dev server with hot reload.
