Quickstart

Boot pond and run your first run end-to-end — no worker pool needed (we use an in-process stage). ~5 minutes.

Prerequisites

  • uv and Docker (for Postgres).

1. Start Postgres + configure

docker compose -f docker-compose.pond.yml up -d        # Postgres on :5433
cp .env.example .env

Edit .env and set at least:

POND_SOURCE_KEY=$(python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())")
POND_SERVICE_TOKEN=dev-secret-change-me   # the bearer you'll submit runs with
AUTH0_DOMAIN=placeholder                   # only the admin key routes use Auth0;
AUTH0_AUDIENCE=placeholder                 # any value is fine for local dev

See Configuration for the full list.

2. Migrate + run pond

uv sync
uv run alembic upgrade head
uv run uvicorn app.main:app --reload --port 8001

Check it’s up:

curl localhost:8001/health
# → {"status":"ok","env":"dev","build":"…"}

Prefer the CLI? Steps 3–4 below use raw curl so they’re dependency-free, but the pond CLI is friendlier — set a context once and use pond run submit -f run.json / pond run logs -f <id>:

uv tool install '.[cli]'
pond config set-context local --url http://localhost:8001 --token dev-secret-change-me
pond status

3. Submit a run

A run executes a workflow definition you pass inline. Here’s the smallest possible one — a single noop stage. projectId is just an opaque id pond attributes the run to (use any UUID).

TOKEN=dev-secret-change-me
curl -sX POST localhost:8001/v1/runs \
  -H "Authorization: Bearer $TOKEN" \
  -H 'content-type: application/json' \
  -d '{
    "projectId": "00000000-0000-0000-0000-000000000001",
    "definition": {
      "stages": [
        {"key": "hello", "name": "Hello", "executor": {"kind": "noop", "ticks": 1, "interval_sec": 0}}
      ]
    }
  }'

The response is the created run, including its id.

4. Watch it

RUN=<id from above>
curl -s localhost:8001/v1/runs/$RUN        -H "Authorization: Bearer $TOKEN"   # status + stages
curl -s localhost:8001/v1/runs/$RUN/logs   -H "Authorization: Bearer $TOKEN"   # log lines

The run goes queued → running → done within a second.

5. Do something real (still no pool)

Swap the noop stage for a builtin that inspects actual source. Builtins run in-process, so still no worker needed — you just need to give the run a source. Point POND_LOCAL_SOURCE_ROOT at a directory of repos in .env, then submit a folder source + a file_inventory builtin:

{
  "projectId": "00000000-0000-0000-0000-000000000001",
  "sources": [{"label": "app", "kind": "folder", "config": {"path": "myrepo"}}],
  "definition": {
    "stages": [
      {"key": "inventory", "name": "Inventory", "executor": {"kind": "builtin", "name": "file_inventory"}}
    ]
  }
}

Then read GET /v1/runs/$RUN/artifacts for what it produced.

Next