Skip to content

Getting started

Paddock is a single process per data root + port. The fastest way to try it is the published Docker image; you can also run it from source for development.

Run the published image, point it at a data volume, and give it a Claude token:

Terminal window
docker run -d --name paddock -p 127.0.0.1:4000:4000 \
-e CLAUDE_CODE_OAUTH_TOKEN=… `# Max plan auth (or ANTHROPIC_API_KEY)` \
-e PADDOCK_DATA_DIR=/data \
-e PADDOCK_DANGEROUSLY_ALLOW_OPEN=1 `# required in a container — see below` \
-v paddock-data:/data \
ghcr.io/edspencer/paddock:latest

Then open http://localhost:4000 and click New Project.

Paddock publishes two official images from the same source — pick the tag that matches what your agents do:

  • ghcr.io/edspencer/paddock:latest — the base image (used above). The lean runtime: the Paddock app plus git, openssh-client, gh, and the claude CLI. Everything a stock instance needs to read, write, and reason over code.
  • ghcr.io/edspencer/paddock:devbox — the devbox image. Base plus the coding-agent toolbox: pm/PM2 preview servers, ffmpeg, a headless Playwright MCP browser, the Docker CLI (with the buildx and compose plugins), kubectl, and a scripting kit (python3, uv, jq, rsync). Reach for it when Claude needs to build and run apps, not just edit them.

The devbox only adds tools — same app, same /data layout — so you can swap tags against the same volume. It’s a much bigger image (the Chromium layer alone is ~1 GB), so stay on base unless you need those tools. The Dev Box flavor is the canonical breakdown of what each image carries, and why each tool is in the image it’s in.

services:
paddock:
image: ghcr.io/edspencer/paddock:latest
ports:
# Loopback only. Do NOT use "4000:4000" without an auth mode in front.
- "127.0.0.1:4000:4000"
environment:
CLAUDE_CODE_OAUTH_TOKEN: ${CLAUDE_CODE_OAUTH_TOKEN} # or ANTHROPIC_API_KEY for API pricing
PADDOCK_DATA_DIR: /data
# Required in a container — see the caution above.
PADDOCK_DANGEROUSLY_ALLOW_OPEN: "1"
volumes:
- paddock-data:/data
volumes:
paddock-data:

Paddock passes your Claude credentials through to the agents. Provide one:

  • CLAUDE_CODE_OAUTH_TOKEN — Claude Max plan auth.
  • ANTHROPIC_API_KEYAPI-pricing auth.

Either works on either runtime — the choice of credential is independent of how a turn is driven.

The token is passed through the process environment; it is never written to disk by Paddock.

You need Node 22+ and the claude CLI on your PATH.

Terminal window
git clone https://github.com/edspencer/paddock.git
cd paddock
npm install

Production-like (one process serves API + WS + SPA)

Section titled “Production-like (one process serves API + WS + SPA)”

This is how the deployed service runs — the server serves the built SPA and exposes /api + /ws on the same origin.

Terminal window
# Load your Claude token into the environment (never echo it).
export CLAUDE_CODE_OAUTH_TOKEN=
npm run build # build web dist + server dist
export PADDOCK_DATA_DIR="$(mktemp -d /tmp/paddock-dev.XXXXXX)" # optional throwaway data dir
npm run start # node packages/server/dist/index.js

Open http://localhost:4000/. Quick checks:

Terminal window
curl -s http://localhost:4000/api/health # {"ok":true}
curl -s http://localhost:4000/api/projects # {"projects":[...]}

For frontend iteration — Vite serves the SPA on :5173 and proxies /api + /ws to the backend on :4000:

Terminal window
npm run dev # terminal 1 — backend (watched) on :4000
npm run dev:web # terminal 2 — Vite SPA on :5173

See the repo’s DEV.md for the full local-development guide.