Skip to content

Getting started

Paddock is a single process per data root + port. The fastest way to try it is npx — nothing to install, nothing to clone. For an always-on instance on a server, use the published Docker image; to hack on Paddock itself, run it from source.

If you have Node 22+, you can run Paddock against your existing Claude Code history in one command. cd into a directory where you’ve been using Claude Code recently:

Terminal window
cd ~/code/some-project
npx @edspencer/paddock --here

Paddock opens that directory as its workspace, finds the Claude Code sessions you already have for it, and offers them for import. Open http://127.0.0.1:4000 (or add -o to have it opened for you) — and instead of an empty instance, you’re looking at your own conversations, resumable.

Later runs in the same directory resume it, with no flag needed.

Without --here, Paddock never touches the directory you ran it from — it starts a normal instance in ~/.paddock and you create projects from the UI.

First run downloads ~250 MB. Paddock drives Claude Code, and the Claude Agent SDK ships a per-platform binary of that size. Later runs reuse the npm cache and start immediately. If you expect to use it often, npm i -g @edspencer/paddock is friendlier than bare npx.

Useful flags:

-p, --port <port> HTTP/WS port (default 4000)
--host <host> Bind address (default 127.0.0.1)
-d, --data-dir <path> Projects + state (default ~/.paddock)
--here Open the CURRENT directory as the workspace
-o, --open Open the app in your browser once it is listening
--verbose Show the server's own logs (quiet by default)

Credentials work the same as everywhere else — see Claude authentication below.

An npx run binds loopback with authentication disabled, which is the right default for a laptop, and it fails closed: bind a routable address without configuring auth and it refuses to start. See Binding & network exposure.

For an always-on instance on a server, the published image is the simplest route. 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.

Or provide neither. If this machine already has a Claude Code login, Paddock uses it: the macOS Keychain entry on a Mac, your ~/.claude/.credentials.json elsewhere. That is claude.credentials: host, the default, and it is the one thing Paddock shares by default — because reading a login writes nothing. Set claude: { credentials: own } in the config file to turn it off.

You need Node 22+. Chats resolve the Claude Agent SDK’s own bundled binary and never consult PATH, so they work without anything else installed; the claude CLI on your PATH is needed only for the post-turn sweeper and for triggers.

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.