Docker
Run oversight as a Docker container for local development or production deployment. The multi-stage Dockerfile builds all three workspace packages (shared, server, web) into a single production image.
Single Container
The included Dockerfile uses a multi-stage build based on
node:20-slim. The first stage installs dependencies with
pnpm, builds all packages, and writes a build-hash.txt.
The production stage copies only the compiled output and production
dependencies.
docker build \
--build-arg VITE_SUPABASE_URL=https://<ref>.supabase.co \
--build-arg VITE_SUPABASE_ANON_KEY=<anon-key> \
-t oversight:latest .
The VITE_* build args are baked into the web frontend at build time.
Server-side variables are provided at runtime instead.
docker run -d \
--name oversight \
-p 3001:3001 \
-e SUPABASE_URL=https://<ref>.supabase.co \
-e SUPABASE_SERVICE_ROLE_KEY=<service-role-key> \
-e SUPABASE_ANON_KEY=<anon-key> \
-e NODE_ENV=production \
oversight:latest
Environment Variables
Build-time (ARG)
| Variable | Required | Description |
|---|---|---|
VITE_SUPABASE_URL |
Yes | Supabase project URL, baked into the web frontend |
VITE_SUPABASE_ANON_KEY |
Yes | Supabase anon/public JWT, baked into the web frontend |
RAILWAY_GIT_COMMIT_SHA |
No | Git SHA used for the build hash (defaults to dev) |
Runtime (ENV)
| Variable | Required | Description |
|---|---|---|
SUPABASE_URL |
Yes | Supabase project URL |
SUPABASE_SERVICE_ROLE_KEY |
Yes | Supabase service role JWT (Settings > API) |
SUPABASE_ANON_KEY |
Yes | Supabase anon/public JWT (Settings > API) |
PORT |
No | Server listen port (default: 3001) |
NODE_ENV |
No | Set to production for optimized logging |
Docker Compose
For a full local stack you can run the server, runner, and web dev server
together. The runner is a separate long-lived process that polls the
Supabase tasks table and executes work locally using the Claude
CLI.
version: "3.9"
services:
server:
build:
context: .
args:
VITE_SUPABASE_URL: ${VITE_SUPABASE_URL}
VITE_SUPABASE_ANON_KEY: ${VITE_SUPABASE_ANON_KEY}
ports:
- "3001:3001"
environment:
- SUPABASE_URL=${SUPABASE_URL}
- SUPABASE_SERVICE_ROLE_KEY=${SUPABASE_SERVICE_ROLE_KEY}
- SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY}
- NODE_ENV=production
restart: on-failure
runner:
build:
context: .
command: node packages/server/dist/runner.js
environment:
- SUPABASE_URL=${SUPABASE_URL}
- SUPABASE_SERVICE_ROLE_KEY=${SUPABASE_SERVICE_ROLE_KEY}
- SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY}
- RUNNER_USER_ID=${RUNNER_USER_ID}
volumes:
- runner-data:/app/data
restart: on-failure
volumes:
runner-data:
claude CLI
on the host machine. In most setups you will run the runner outside Docker
with pnpm runner and only containerize the server.
Health Endpoint
The server exposes GET /api/health which returns
{"status":"ok"} with a 200 status code. Use this
for Docker health checks and load balancer probes.
docker run -d \
--health-cmd="curl -f http://localhost:3001/api/health || exit 1" \
--health-interval=30s \
--health-timeout=5s \
--health-retries=3 \
oversight:latest
Building from Source
The build process compiles three workspace packages in order:
@oversight/shared, then @oversight/server,
then @oversight/web. A build hash is written to
build-hash.txt at the project root.
# Clone and install
git clone https://github.com/CopilotKit/oversight.git
cd oversight
pnpm install
# Build all packages
pnpm run build
# Start the server
node packages/server/dist/index.js
Requires Node.js ≥ 20 and pnpm ≥ 9. The server listens on port
3001 by default and serves both the API and the static web
frontend from packages/web/dist.