Run a local trial server
Bring up a Werft server on your local machine and get an API key
A Werft server consists of an API server, a scheduler, a reconciler, a worker container started for each session, PostgreSQL, S3 (SeaweedFS), a read-only Git server for the example repository, and an egress proxy. This page brings all of them up on one machine with Docker Compose. It uses a fake model that runs without a key, so you do not need an Anthropic account.
Once it is up, the server address is http://127.0.0.1:3000. The SDK and curl examples connect to the server with this address and the API key you get here.
Prerequisites
| Item | Version |
|---|---|
| Docker Engine | 28 or later |
| Docker Compose | 2.24.6 or later |
| curl, jq, uuidgen, git | Any version |
The stack opens ports on 127.0.0.1 only. Ports 3000 (API and web console), 5432 (PostgreSQL), 4566 (S3) and 4567 (LocalStack Secrets Manager), and 3001 (read-only Git server) must be free.
docker version --format 'Docker Engine {{.Server.Version}}'
docker compose version
for p in 3000 5432 4566 4567 3001; do
lsof -nP -iTCP:$p -sTCP:LISTEN >/dev/null 2>&1 && echo "사용 중: $p"
doneIf no line starting with 사용 중: ("in use") appears, you can continue.
Get the code
git clone https://github.com/JeongJaeSoon/werft.git
cd werftStart the stack
scripts/local.sh up --fake-modelThe first run builds the images from this checkout, so it takes a few minutes to about 10 minutes. When it is ready, the last line shows the following.
{"status":"ready","checks":{"database":"ok","schema":"ok","config":"ok"}}With --fake-model, model calls are received by a fake Messages API inside compose. A real Claude Code runs inside the worker, and the fake answers according to the script written in the message (Create your first session). If you start without the option, with scripts/local.sh up, it calls the real Claude and costs money. The default way to give it the model key is the console, under Settings > Agent connections > Model connections > Add connection; passing the shell's ANTHROPIC_API_KEY is the alternative. Started without a key, the stack does not switch to the fake: it comes up with no model connection.
Check the status
scripts/local.sh statusYou are good when api, scheduler, and reconciler are running and /readyz responds at the end. Worker containers do not stay resident. The scheduler starts and removes one for each session.
Get an API key
API=http://127.0.0.1:3000
KEY=$(scripts/local.sh key quickstart \
--scopes sessions:read,sessions:write,sessions:approve,sessions:control,sessions:recover)
echo "${KEY:0:4}…"key_id …
csp_…key_id is the id of the key, printed to stderr. The key itself is printed to stdout only once. You cannot see it again, so keep it only in a variable. quickstart is the key's owner name, and sessions created with this key belong to that owner. Scopes are described in API key.
Pass the server address (API) to the SDK as baseUrl and this key as apiKey (Install the SDK). An environment variable such as WERFT_API_KEY="$KEY" works too. The HTTP API examples keep using API and KEY in the same terminal.
Stop the stack
scripts/local.sh downscripts/local.sh down deletes the stack and all data (sessions, checkpoints, API keys). To start over from scratch, use scripts/local.sh reset --fake-model.
To stop while preserving data and removing worker containers and networks, use scripts/local.sh down --keep-volumes. Start again with scripts/local.sh up --fake-model. PostgreSQL and S3 keep their data in named volumes. S3 objects and their encryption key live together in local-s3-data, so checkpoints survive Docker/OrbStack restarts.
When migrating an older LocalStack installation, back up from the old checkout before pulling, then restore into a new, unused project after pulling. Missing checkpoint objects cannot be recovered without a backup; explicitly decide whether to give up their references. Follow the migration and backup guide.
When you are stuck
| Symptom | Action |
|---|---|
Docker Engine … is too old | Upgrade Docker Engine to 28 or later |
127.0.0.1 port(s) … already in use | Use the lsof loop above to find the process using that port |
up prints no ANTHROPIC_API_KEY … no model connection and sessions are refused as no connection (connection_missing) | up without options uses the real Claude and starts without a key. Enter the key under Settings > Agent connections > Model connections > Add connection. To run without a model account, add --fake-model |
| The API does not come up after restarting Docker | Check the S3 volume, encryption key, and logs. For lost objects from an older LocalStack installation, follow the migration and backup guide |
After a pull, up ends with has neither an image nor a build context specified or port is already allocated | The Git server's service is now named fake-git. Fix the key in your port override file, run scripts/local.sh down --keep-volumes, then up again. Older sessions stop with CATALOG_MISMATCH, so open a new session |
Next steps
- Install the SDK: Connect to this server with the SDK and create your first session
- Self-hosting: Run a server that several people use