Run Alembic as a service: harness API, SSE events, and web cockpit behind Caddy.
This lab connects @alembic/harness, @alembic/web, and @alembic/infra. You will:
alembic serve --data-dir ~/.alembic on a droplet or local machine.alembic cockpit --data-dir ~/.alembic on the same host or a different one.curl -X POST http://host:port/api/runs ...Think of it like… turning a kitchen appliance into a restaurant: the engine stays the same, but now multiple people can order and watch their meal being cooked.
createHarnessServer exposes POST /api/runs, GET /api/runs, GET /api/runs/:id, and GET /api/runs/:id/events (SSE). createCockpitServer serves static assets and proxies SSE to the harness. The infra package provides a Caddyfile template and a Docker Compose example. Never expose the host plane directly; only the droplet plane should be public.
# start services alembic serve --data-dir ~/.alembic & alembic cockpit --data-dir ~/.alembic & # create a run curl -X POST http://localhost:8787/api/runs -H 'Content-Type: application/json' -d '{"goal":"Add a /health endpoint","plan":"./alembic.plan.ts","offline":true}' # stream events curl -N http://localhost:8787/api/runs/<id>/events
The harness server stores run state in the same append-only JSONL files as the CLI, so the cockpit and TUI can read them without a database. The Caddy template in packages/infra/caddy routes /api and /events to the harness and everything else to the cockpit, plus automatic HTTPS.
Start alembic serve and alembic cockpit locally, create a run with curl, and watch events in the browser and with curl -N.