Skip to content
▚ evestack docs

Local setup & troubleshooting

Docker, Postgres, and the Ollama path to a genuinely $0 stack.

Picking a provider

EVESTACK_PROVIDER selects the branch in agent/agent.ts. It is the only variable that does, and EVESTACK_MODEL on its own never changes providers — it just hands a different model name to whichever provider is already selected.

EVESTACK_PROVIDERKey it readsDefault EVESTACK_MODEL
unset, or openaiOPENAI_API_KEYgpt-5-mini
anthropicANTHROPIC_API_KEYclaude-sonnet-5
ollamanoneqwen3

create-evestack asks which one you want and writes both lines. Anything other than those three values is rejected at boot with the list above rather than silently treated as OpenAI — a misspelled provider is a mistake, not a preference.

One thing that table does not cover, and it decides whether long-term memory works: embeddings. openai has an embeddings endpoint on the same key. ollama has one, but it is a second pull (ollama pull nomic-embed-text). anthropic has none at all, so remember and recall on that path need either an OPENAI_API_KEY as well or EVESTACK_EMBED_PROVIDER=ollama to run embeddings locally. Nothing else about the Anthropic path is affected. The three EVESTACK_EMBED_* variables are in long-term memory.

Ollama

For zero cost, total:

ollama pull qwen3                # the chat model
ollama pull nomic-embed-text     # embeddings — a separate model, and `remember` needs it

Then set both of these in .env.local:

EVESTACK_PROVIDER=ollama
EVESTACK_MODEL=qwen3

EVESTACK_PROVIDER is the one that selects the local path. The model name on its own is handed to the OpenAI provider, and the agent then refuses to boot:

Cannot compile agent compaction because the primary compaction trigger model
"openai/qwen3" does not have known AI Gateway context window metadata.

create-evestack offers this as an option at scaffold time and writes both lines for you.

Two more, both optional:

OLLAMA_BASE_URL=http://127.0.0.1:11434   # bare host — no /api suffix
EVESTACK_CONTEXT_WINDOW=32768            # qwen3's native window

ai-sdk-ollama appends the API path itself, so a OLLAMA_BASE_URL ending in /api gives OllamaError: 404 page not found. EVESTACK_CONTEXT_WINDOW is what the template passes to eve's modelContextWindowTokens — the escape hatch that skips the catalog lookup entirely. Raise it for a model with a bigger window; set it too high and compaction fires too late to save the turn. Both are ignored on the hosted providers, whose models the catalog does know.

Check your free RAM first. qwen3 is 5.2 GB, and it loads on top of Docker, Postgres, the dashboard and the agent — plus the 274 MB embedding model once memory is used. On a machine without roughly both model sizes + 4 GB to spare, this does not degrade gracefully — it can take minutes to answer a one-word prompt and can take the host down. On a laptop already running the rest of the stack, a hosted key is the practical choice.

Local models generally have weaker tool-calling than gpt-5-mini or Claude. That's the honest tradeoff for $0 total cost — try it, and switch to a cloud key if tool use feels unreliable.

What it costs on disk

The RAM warning above is the one that bites first, but disk is the one nobody budgets for. Measured on macOS with Colima, one project, clean Docker:

With an API keyOn the $0 Ollama path
Docker images~2.0 GB~2.0 GB
Postgres volume~70 MB~70 MB
Project directory~300 MB~300 MB
qwen3 + nomic-embed-textnot pulled5.5 GB
Total≈ 2.4 GB≈ 7.9 GB

Budget 10 GB free on the local-model path, 4 GB with an API key. That leaves room to grow; the flat totals do not.

The image figure is pgvector/pgvector:pg17 at 646 MB, the dashboard at 1.05 GB unpacked from a 228 MB pull, and a 665 MB sandbox template image eve builds on first run, less the node:24-slim layers two of them share. The project directory is almost entirely node_modules (262 MB measured); .eve/ accounts for the rest and grows while eve dev is running.

Each additional project on the same machine costs about 0.5 GB. The big images are shared — its own sandbox template image (+157 MB), its own Postgres volume (~70 MB) and its own node_modules are not.

What grows, and the one thing nothing cleans up

Spans are about 1.55 KB each and self-prune on a 30-day window (EVESTACK_TRACE_RETENTION_DAYS). The workflow schema never prunes itself; npm run db:prune is the manual answer to both, and Operations covers it — including why space is not returned to the filesystem without a VACUUM FULL.

The exception is the per-project eve-sandbox-template:* image. eve builds one per project, tagged with a hash of the project id, and at 665 MB it is the third-largest single item on disk. Nothing removes it: no evestack command, no docker compose down -v, and not deleting the project directory either. It outlives the project that created it, and a cleanup on the development machine reclaimed several GB from seven stale ones that had accumulated this way.

# what is actually there
docker images --filter reference='eve-sandbox-template:*'

# remove them — `docker image prune` rejects a reference filter, so list and pipe
docker images --filter reference='eve-sandbox-template:*' -q | xargs docker rmi

Do that after you delete a project, not while one is running: the tag carries no hint of which project it belongs to, and a live project rebuilds its own on the next turn.

Docker sandbox

The default backend, docker(), keeps one long-lived container per durable session and persists /workspace across turns with no idle timeout — genuinely free to run 24/7 on your own machine, since it's just a container.

Swaps, one line in agent/sandbox/sandbox.ts:

  • microsandbox() — real VM isolation, domain-level network policies, credential brokering. macOS on Apple Silicon or Linux with KVM only.
  • justbash() — no daemon at all, but no real binaries either.

Common issues

eve dev seems to not be listening on port 2000. It is listening on EVESTACK_AGENT_PORT from .env.local, which the scaffolder set to the first free port at or above 2000 at the time you scaffolded — so on a machine that already had something on 2000, it is 2001 or higher. npm run dev passes that number to eve dev as --port, and eve only scans for a free port when it is given none, so nothing auto-increments at boot: if that port is busy now, you get EADDRINUSE and no server. Read .env.local for the number, and free the port rather than waiting for eve to move.

A follow-up request 404s or the agent seems to have forgotten everything. Check that WORKFLOW_POSTGRES_URL is actually set and Postgres is reachable — without it, eve silently falls back to its local on-disk world under .eve/.workflow-data, which does not survive a container rebuild the way Postgres does.

@workflow/world-postgres fails at boot with a protocol or spec version error. It is not pinned to an exact version somewhere. eve needs the 5.0.0-beta line, so npm's latest (the 4.x line) is wrong — and so is the beta dist-tag, which now resolves past the release eve 0.30.8 can talk to. Pin 5.0.0-beta.32 exactly; see Troubleshooting for the spec-version message.

The dashboard can't reach the database. It reads WORKFLOW_POSTGRES_URL directly — same variable, same database, as the agent. If the agent works but the dashboard doesn't, the two processes likely have different .env.local files with different values.

Reverse-proxying either the agent or the dashboard. Forward /eve/ and /.well-known/workflow/, unrewritten. Forwarding only /eve/ lets a session start, then stalls it forever — the workflow callback can't get back in.