Skip to content
▚ evestack docs

Quickstart

One command to a running, durable, dashboard-observed agent.

Requirements

  • Node 24+
  • Docker, running (for Postgres and the agent sandbox)
  • An OPENAI_API_KEY or an ANTHROPIC_API_KEY — or skip straight to Ollama for $0 total

Create the project

npx evestack create my-agent

npx create-evestack my-agent does the same thing. They are two published names for one implementation — evestack is the single command (create, status, tour, open, verify, attach, doctor — see the CLI reference), and create-evestack is the name npm's create-* convention leads people to. Same code, same prompts, same flags.

It asks four questions, all of them before any work starts, so the install and the image pull are a wait you can walk away from:

  1. Where — the project directory.
  2. Model — OpenAI, Anthropic or Ollama, and a key if you have one.
  3. Tools — Composio's one-click tool sign-in, on by default.
  4. Bring it up — whether it should start Postgres, create the schema and pull the dashboard for you.

Pass --yes to skip all four and fill in .env.local yourself afterward — the scaffolder never hangs waiting on input it isn't going to get.

Question 4 decides how much of this page you have to type. Answer yes and the scaffolder does Bring up the database and See it in the dashboard for you, then offers to run Run it as well — so there is nothing left to paste, and you can read those sections as a description of what already happened. Answer no — or run under --yes, or with Docker not running — and it prints those same four commands when it finishes, which are the ones below.

Whichever you pick, .env.local gets EVESTACK_PROVIDER and that provider's own key variable. Both matter: EVESTACK_PROVIDER is what agent/agent.ts branches on, and setting a model name without it leaves you on the previous provider. See the provider table if you're switching later by hand.

The provider you pick decides whether long-term memory works. remember and recall need an embeddings model, and the three providers differ: OpenAI has one on the same key; Ollama has one but it is a second pull (ollama pull nomic-embed-text); Anthropic has no embeddings endpoint at all, so on that path memory needs either an OPENAI_API_KEY as well or EVESTACK_EMBED_PROVIDER=ollama to run embeddings locally. Nothing else is affected — the agent, its sandbox, durable sessions and the dashboard all work either way, and the first remember call names the variable that fixes it. Full detail in long-term memory.

This generates a unique EVESTACK_AUTH_PASSWORD per project. eve fails closed by default, so there's no shipped default password sitting between a stranger and your agent.

Bring up the database

cd my-agent
docker compose up -d postgres
npm run db:bootstrap

Nothing creates the workflow schema for you: @workflow/world-postgres runs its migrations only from its own CLI, and eve never invokes it. Skip this and npm run dev starts against a database with no tables.

Run it through the script, not as npx --package=@workflow/world-postgres bootstrap. That CLI loads .env through dotenv and never looks at .env.local — which is the only env file create-evestack writes — so it silently falls back to postgres://world:world@localhost:5432/world and dies on ECONNREFUSED. The db:bootstrap script passes --env-file-if-exists=.env.local explicitly.

Pin @workflow/world-postgres to an exact version. npm's latest is the 4.x line and eve rejects it outright, but the beta dist-tag is not the fix — upstream moves the World spec version inside 5.0.0-beta.* with no semver signal, so beta resolving one release forward is enough to kill a boot. The scaffolded package.json pins 5.0.0-beta.32; leave it exact if you ever touch that dependency by hand.

Run it

npm run dev

The agent boots on the port the scaffolder wrote into .env.local as EVESTACK_AGENT_PORT — 2000 unless that was already taken when you scaffolded. npm run dev passes it to eve dev as --port, which means there is no auto-increment: eve only scans for a free port when no port is given at all, so if something else has grabbed that port since, the boot fails with a plain EADDRINUSE rather than moving. Free the port, or change EVESTACK_AGENT_PORT in .env.local — and if you do, change the EVESTACK_AGENT_URL default in docker-compose.yml to match, because the scaffolder wrote that number in at generation time.

Verify it's durable

The whole point is that restarting doesn't lose anything. Prove it to yourself:

curl -X POST http://127.0.0.1:2000/eve/v1/session \
  -H 'content-type: application/json' \
  -d '{"message":"Remember this exact phrase: quokka-orbit-9."}'

Kill the dev server (Ctrl-C), restart it (npm run dev), then send a follow-up using the continuationToken from the first response. The agent recalls it — durable state survives the process, because it never lived in the process to begin with.

See it in the dashboard

One command, in the project you just scaffolded:

docker compose --profile dashboard up -d

That is a pull. The generated docker-compose.yml points at ghcr.io/sammytourani/evestack-dashboard, pinned to the version tested with this template, and the service is already wired to this project's database and to the .env.local your agent reads — so there is no repository to clone, no image to build, and no credential to copy across.

That pull resolves a multi-arch manifest — linux/amd64 and linux/arm64, ~230 MB compressed each — so the same command works on an Apple Silicon laptop and on an x86 server without you choosing a platform. It unpacks to about 1 GB on disk.

To run an image of your own — a fork, a private registry, a local build under a different name — set EVESTACK_DASHBOARD_IMAGE in a .env beside the compose file, or export it in your shell. Nothing else in the generated compose file needs to change.

Open the dashboard — usually http://localhost:4000, but check what the scaffolder printed. It calls freePort(4000) and takes the first port at or above 4000 that is actually free, so a second project on the same machine, or anything already holding 4000, moves it. The same is true of the agent's 2000 and Postgres's 5433. The generated docker-compose.yml and .env.local both carry the numbers this project actually got.

Sign in with the EVESTACK_AUTH_USER and EVESTACK_AUTH_PASSWORD generated into .env.local — the scaffolder prints them when it finishes. Every route is behind that credential: the dashboard starts agent runs, approves gated shell commands and deletes memories, so it fails closed rather than serving a viewer to anyone who reaches the port. Scripts can use HTTP Basic instead:

curl -u "$EVESTACK_AUTH_USER:$EVESTACK_AUTH_PASSWORD" localhost:4000/api/fleet

Every session you just created is already there, read straight out of the same Postgres — no ingest step required for the session list itself.

If the container comes up, docker ps shows it unhealthy, and every page answers 503 except /signin — which renders an error and no sign-in form — the credential did not reach it. The compose service reads .env.local, so that is the file to check — both halves are required, and a blank password counts as unset.

To hack on the dashboard rather than run it, install and build from the repository root — not from packages/dashboard, where workspace:* cannot resolve and @evestack/schedules has no dist/ for Turbopack to find:

cd evestack
pnpm install
pnpm -r --if-present --filter '@evestack/dashboard^...' run build
EVESTACK_AUTH_USER=evestack EVESTACK_AUTH_PASSWORD=dev \
  WORKFLOW_POSTGRES_URL=postgres://evestack:evestack@localhost:5433/evestack \
  pnpm --filter @evestack/dashboard dev