Two ways people approach generative engine optimization: rewrite pages by hand and hope ChatGPT cites you, or deploy a measurement stack first so every rewrite is checked against real engine answers. The second path wins. Without baseline mention rates, you’re guessing.
This guide installs Elmo v0.4.1 – open-source AEO/GEO tracking for how ChatGPT, Claude, Perplexity, Gemini, Copilot, Grok, and Google AI Overviews mention and cite your brand. Self-host is MIT-free. Managed cloud starts at $29/mo as of the product pages on GitHub/README.
System requirements before you touch npm
Pin the docs version in your head: getting started currently walks v0.4.1. From Elmo’s getting started table:
| Requirement | Minimum | Notes |
|---|---|---|
| Docker | Engine 24+ with Compose v2 | Daemon must be running; elmo init checks this since v0.4.0 |
| Node.js | 18.x or later | CLI only – the app runs in containers |
| AI keys | ≥1 of OpenAI / Anthropic / OpenRouter | Direct model APIs |
| Scrapers | Strongly useful in practice | Cloro, BrightData, Oxylabs, SearchApi, Olostep, DataForSEO for live ChatGPT / Google AI Mode surfaces |
| External Postgres (optional) | PostgreSQL 15+ | New bundled deploys use Postgres 18 |
No official RAM/CPU floor in those docs. On a laptop stack (web + worker + Postgres), budget something like 4 GB RAM free and ~10 GB disk for images/volumes – operator estimates only, not a vendor SLA. Anything that runs Docker Engine/Desktop is fine (Linux, macOS, Windows).
Official download source
Skip random forks. The published path is boring on purpose:
- CLI:
@elmohq/clion npm - Source/releases: github.com/elmohq/elmo – latest tag v0.4.1 (15 Sep 2026)
- Docs: elmohq.com/docs/getting-started
v0.4.0 added the external REST API + MCP server and made elmo init fail fast when Docker is missing. v0.4.1 fixed MCP sign-in for clients that use a client ID metadata document. If your install notes still say “clone and hope,” you’re on the wrong instructions.
Install Elmo v0.4.1 step by step
CLI + Docker Compose is the path this guide cares about. Building the monorepo from source is a contributor move – skip it unless you’re patching Elmo itself.
- Confirm Docker is up:
docker infoshould print server details, not a daemon error. - Install the CLI globally:
npm install -g @elmohq/cli
elmo --help
- Run the wizard (config dir is usually
./elmoor~/.elmo):
elmo init
You’ll pick config directory, bundled Postgres vs an existing DATABASE_URL, scraper and/or model API keys, and whether to start immediately. Init writes elmo.yaml (Compose) and .env (secrets).
- If you didn’t start during init:
elmo compose up -d
elmo compose ps
Wait until services report healthy, then open http://localhost:1515 and create the first account. On self-hosted builds from the v0.3.0 line onward, sign-up closes after that first user – plan who owns the admin login before you share the URL.
Pro tip: Drop real scraper credentials in during init if you care what people see inside ChatGPT/AI Mode. Direct OpenAI/Anthropic keys are cheaper and fine for Claude/Grok-style coverage. They will not match the consumer UI bit-for-bit.
First-time configuration that actually matters
Enough to start: one brand domain, a handful of buyer prompts, at least one working provider in .env. After init, edit secrets like this:
# example paths - use the config dir you chose
nano ~/.elmo/.env
elmo compose down
elmo compose up -d
The catch is ELMO_ENCRYPTION_KEY. Since v0.2.18, provider credentials are encrypted in Postgres with that key. Fresh wizards should set it. Hand-rolled older .env files? Add a long random value before you store keys, or credential handling fails closed.
Web = UI + REST/MCP. Worker = scheduled prompt runs. Postgres = answers + the pg-boss queue. If postgres is sick, nothing else matters.
Think of content tactics as the engine rebuild and Elmo as the dyno sheet. The KDD 2024 GEO paper (arXiv:2311.09735) reported up to ~40% visibility lift in controlled tests – only meaningful if you can read mention rate before and after. Elmo is the meter, not the rewrite bot.
Verify the install works
elmo compose ps
elmo compose logs -f web
# browser
open http://localhost:1515
You’re good when Compose shows healthy services, the login/signup page loads, and you can create a brand plus enqueue a prompt without the worker falling over. Tail elmo compose logs -f worker while the first job runs – that’s where silent provider failures show up. Logged in? Click through API/MCP settings once (v0.4.0+) just to prove the control plane is alive.
Common install errors and fixes
Cannot connect to the Docker daemon. Start Docker Desktop/Engine, then re-run elmo init or elmo compose up -d. v0.4.0+ surfaces this earlier in the wizard.
Port 1515 already allocated. Something else grabbed the port. Kill that process or change the published port in generated elmo.yaml, then bring the stack up again.
Provider runs fail or burn cash fast. After v0.2.18, DataForSEO SCRAPE_TARGETS moved off cheap model APIs (~$0.0006) onto real ChatGPT/Gemini UI scrapes (~$0.004). Pin legacy model strings only if you deliberately want the old API behavior – citation metrics can drift either way. Oxylabs Realtime API users needed the async jobs switch; the documented cutoff called out was 31 Aug 2026 for that provider path.
Onboarding crash on plain HTTP. Older builds choked when crypto.randomUUID needed a secure context. Stay on ≥ v0.3.0. Following this guide puts you on 0.4.1.
Weird scraper rows polluting citation views. If metrics look like provider errors got stored as answers, move to current 0.4.x images and re-run a known-bad prompt. Don’t tune content off contaminated rows.
Upgrade and uninstall
Upgrade:
npm install -g @elmohq/cli@latest
elmo upgrade
elmo upgrade (0.2.x line onward) runs registered DB migrations, re-pins app image tags to what the CLI supports, and restarts the stack if it was running. It warns when the CLI lags the newest release. It does not bump the Postgres major. New installs land on Postgres 18; older data dirs keep whatever major you started with. Jumping majors needs dump/restore – retagging the Postgres image alone can leave an unreadable data directory.
# sketch of a major move (adapt user/db names from your .env)
elmo compose up -d postgres
docker compose -f ~/.elmo/elmo.yaml exec -T postgres
pg_dump -U postgres -d elmo > elmo-backup.sql
# verify dump ends with "PostgreSQL database dump complete"
elmo compose down
# then follow current config docs for the 18.x volume layout before restore
Stop / uninstall / cleanup:
elmo compose down
# optional: remove containers + volumes (destroys tracking data)
elmo compose down -v
npm uninstall -g @elmohq/cli
rm -rf ~/.elmo # or ./elmo - your config dir
# optional image prune
docker image prune -a
FAQ
Is Elmo the same thing as “doing GEO” on my blog posts?
No. Elmo measures answer-engine visibility. Your CMS still owns the copy changes.
Can I skip scrapers and only use OpenAI or Anthropic keys?
Yes for a minimum install – model-API answers with web search where the provider supports it. You will not fully mirror logged-in ChatGPT or Google AI Mode. Shipping a product-launch prompt set next week? Add one scraper when budget allows; that’s the gap between “API proxy” and “what buyers actually see.”
Self-host vs Elmo Cloud – which should I deploy tonight?
Self-host when the data must sit on your Postgres, prompt volume shouldn’t hit a SaaS ceiling, and you want MIT-auditable scoring code. Cloud from $29/mo (as of vendor pricing) fits when nobody on the team wants Docker upgrades, seats, or paging. Agencies that need custom domains/SSO look at white-label. Same codebase either way. The real question: who runs elmo upgrade at 2 a.m. after a breaking provider change?
Next action: npm install -g @elmohq/cli && elmo init, start the stack, open http://localhost:1515, and log 20 buyer prompts against your brand before you rewrite a single landing page.