PilotDeck runs as two cooperating Node.js processes in the container:
PILOTDECK_GATEWAY_PORT (default 18789)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.
Set the model provider variables in docker-compose.yml or an .env file:
PILOTDECK_MODEL=openai/gpt-4.1
PILOTDECK_API_KEY=sk-your-api-key
PILOTDECK_API_URL=https://api.openai.com/v1
Then start:
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.
Create the host config file first:
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:
volumes:
- pilotdeck-home:/root/.pilotdeck
- ${PILOTDECK_CONFIG:-${HOME}/.pilotdeck/pilotdeck.yaml}:/root/.pilotdeck/pilotdeck.yaml:ro
Start the service:
docker compose up -d --build
The UI is available at http://localhost:3001.
Agents run inside the container. To let them access a host project, mount it into /workspace by uncommenting the workspace bind mount:
volumes:
- pilotdeck-home:/root/.pilotdeck
- ${PILOTDECK_WORKSPACE:-${PWD}}:/workspace
You can set PILOTDECK_WORKSPACE=/path/to/project before running docker compose up.
docker build -t pilotdeck:latest .
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
docker run -d --name pilotdeck \
-p 3001:3001 \
-v pilotdeck-home:/root/.pilotdeck \
-v ~/.pilotdeck/pilotdeck.yaml:/root/.pilotdeck/pilotdeck.yaml:ro \
pilotdeck:latest
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
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
| 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 |
Browser (localhost:3001) ──► UI Server (port 3001) ──► Gateway (port 18789)
Both processes are managed by concurrently inside the Docker container.
npm install
npm run dev
This starts the Gateway and UI dev server with hot reload.