elmohq/elmo: self-hosted AI visibility tracking for ChatGPT, Claude and Perplexity
Open-source Answer Engine Optimization (AEO) and Generative Engine Optimization (GEO) platform. Track how ChatGPT, Claude, Perplexity, Gemini, Copilot, Grok, and Google AI Overviews mention and cite your brand in AI search. MIT-licensed, self-hostable, every metric auditable in code.
At a glance
- What is it?
- Elmo is an MIT-licensed TypeScript monorepo that runs your prompts against AI answer engines on a schedule and stores every raw answer in PostgreSQL. The pitch is auditability: the mention detection and scoring code sits in the same repository you deploy.
- Who is it for?
- Adopt Elmo if you have engineering capacity to run a pnpm and Turborepo monorepo on Node 24 with PostgreSQL, and you want AI visibility numbers you can re-derive from stored raw answers rather than trust. Do not adopt it if you need a managed service with no infrastructure, or if you cannot fund the scraping providers and model API keys that every scheduled run depends on.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem Elmo targets: brand mentions inside AI answers
Classic rank tracking assumes a list of blue links. AI answer engines do not produce one. A response from ChatGPT, Claude, Perplexity, Gemini or Google AI Overviews may mention a brand in prose, cite a URL, or do neither, and the same question can produce different answers on different days. Marketing teams that want to know whether they appear in those answers have had few options other than asking an assistant by hand and pasting the result into a spreadsheet.
Elmo is built for the team that wants that measurement to be repeatable. Prompts are defined per brand, either generated by an onboarding wizard that analyzes a website or written by hand. A background worker runs each prompt on a schedule, several times a day by default, against every engine you configure. The output is not a single score but a set of records: the answer text, the cited URLs, the web searches the engine ran while grounding its response, and the model version.
The intended user is a technical marketer or a small growth team with someone who can run Docker and read TypeScript. The README positions it as a free alternative to hosted tools such as Profound, Peec and Otterly, with the difference being that you run it on your own infrastructure and own the data. That framing is accurate as far as it goes, but it also means the operational burden lands on you, which is the trade the rest of this article examines.
How the measurement loop works, from prompt to stored answer
The methodology section of the README describes five steps, and they map cleanly onto the repository structure. Prompts are the unit of work. Each one is a question a potential customer might ask an assistant, and each is tagged and can be enabled or disabled individually.
A background worker executes those prompts against configured engines. Elmo splits collection into two approaches. Scraping providers capture what the README calls the real consumer surfaces: ChatGPT, Google AI Mode, Google AI Overviews, Gemini, Perplexity and Microsoft Copilot. Direct model APIs from OpenAI, Anthropic, Mistral and OpenRouter add coverage for Claude, Grok and other models with web search enabled. The project's providers guide compares the two approaches and their costs, which is the right place to look before assuming full engine coverage is free.
Every run is normalized into a common shape: answer text, cited URLs, the query fan-out (the searches the engine ran while grounding), and the model version. The text is then scanned for your brand's name, aliases and domains, and for each competitor's. All of it lands in PostgreSQL, including the raw engine output, so a metric can be re-derived later rather than taken on faith. Aggregation turns runs into trends: visibility is the share of runs that mention your brand, share of voice compares your mention rate against competitors, and citation counts roll up by URL, domain and category, filterable by prompt, tag, engine and time range.
The design decision worth noting is that Elmo stores raw answers rather than only computed scores. That is what makes the audit claim meaningful. If you disagree with a visibility number, you can go back to the answer that produced it. The cost is storage and a schema that has to accommodate whatever shape each provider returns.
Installing Elmo and running a first prompt
The repository is a pnpm workspace driven by Turborepo. The root package.json pins the package manager to pnpm@11.18.0 and declares Node 24.x under engines, so those two constraints come before anything else. The scripts you will use most are dev, build, test and lint, all routed through turbo.
The README does not include a copy-paste install sequence, so treat the repository scripts as the source of truth. A local development session starts with dependency installation and the dev task:
pnpm install
pnpm devThe turbo dev task fans out to the workspace packages, so you should expect the web app and the worker to come up together. Configuration for database connection and provider credentials is not spelled out in the README; check the docs site at elmohq.com/docs and the docker directory in the repository for the environment variables your deployment expects.
For container-based deployment, the repository carries a docker directory and a .dockerignore at the top level, which is where the self-hosting path lives. The repository also ships a CLI package, exposed through the root script elmo, which runs the CLI entry point directly with tsx:
pnpm elmoThere is also a global link workflow for developing the CLI locally, using cli:link and cli:unlink. Once the app is running, the first real task is creating a brand and adding prompts. The README describes an onboarding wizard that analyzes your website and suggests keywords, competitors, buyer personas and tracking prompts. After the worker has completed a few scheduled runs, the dashboard shows visibility per prompt and per model, and the citations view groups cited domains into categories such as your own domains, competitor domains, social media, Google properties and institutional sources.
Where Elmo is the wrong tool
The honest limitation is that Elmo measures a moving target with paid inputs. Every scheduled run consumes either a scraping provider request or a model API call, and the README points to a providers guide specifically because the costs differ. A team that configures six engines and runs prompts several times a day per prompt is signing up for a recurring bill that scales with both prompt count and run frequency. There is no free mode described in the README.
The second constraint is coverage. The README is explicit that scraping providers capture the consumer surfaces while direct APIs cover Claude, Grok and other models with web search enabled. That means the fidelity of your Claude or Grok numbers depends on an API with web search turned on, not on the consumer product. If your stakeholders expect Elmo's Claude figure to match what they see in claude.ai, that expectation needs correcting before you buy anything.
Third, this is infrastructure. A pnpm monorepo on Node 24 with PostgreSQL and a background worker is not a spreadsheet replacement for a solo marketer. If nobody on the team can read a Dockerfile or debug a failing worker, the hosted alternatives the README names will be cheaper in practice than a self-hosted deployment nobody maintains. Elmo also does not promise real-time numbers. Prompts run on a schedule, several times a day by default, so a mention that appears this afternoon may not show up until the next run.
How Elmo differs from hosted AEO platforms
The README names Profound, Peec and Otterly as the tools Elmo replaces and links to comparison pages for each. The architectural difference is not the feature list, which overlaps heavily: visibility scoring, competitor benchmarking, citation analysis and share of voice appear in all of them. The difference is where the data lives and who can inspect the calculation.
With a hosted tool you get a dashboard and a number. With Elmo you get the same categories of metric plus the raw engine output in your own PostgreSQL instance, and the mention detection, scoring and aggregation code in the repository you cloned. If a visibility score looks wrong, you can trace it to the specific answer that produced it. That is the entire argument for self-hosting here, and it is a real one for teams whose reporting gets challenged internally.
The trade is operational. A hosted platform absorbs provider outages, schema changes in scraped surfaces, and model version churn. Elmo's worker does not. When a scraping provider changes its response format or an engine changes its markup, the fix has to come from you or from an upstream release. The release history shows steady iteration, with v0.3.0 published on 2026-08-31, but you are still the one deploying it.
Maintenance, releases and the MIT licence
Elmo is MIT-licensed, and the root package.json carries the same identifier. In practical terms that is a permissive licence: you can run it commercially, modify it and redistribute it, provided the copyright notice and licence text travel with copies. This is not legal advice, and the repository includes a CLA.md and a CONTRIBUTING.md that matter if you intend to send patches upstream rather than fork.
The maintenance picture is active. The last push to the default branch was on 2026-09-13, and the repository is not archived. Releases arrive frequently rather than on a fixed cadence: v0.2.18 on 2026-08-06, v0.2.19 on 2026-08-10, and v0.3.0 on 2026-08-31. Versioning is handled with Changesets, and the version-packages script runs changeset version followed by a sync script that keeps the root version aligned. That matters if you fork, because it tells you how upstream intends to cut releases.
Upgrade cost is the part to budget for. The project is pre-1.0, so minor versions can carry breaking changes, and a self-hosted deployment means you own the migration. The repository ships an e2e workspace with separate tasks for cloud, whitelabel and demo targets, plus API spec validation, which suggests the maintainers test multiple deployment shapes. That helps upstream, not you. Pin your versions and read the changelog before moving between minor releases.
Editorial conclusion
Adopt Elmo if you have engineering capacity to run a pnpm and Turborepo monorepo on Node 24 with PostgreSQL, and you want AI visibility numbers you can re-derive from stored raw answers rather than trust. Do not adopt it if you need a managed service with no infrastructure, or if you cannot fund the scraping providers and model API keys that every scheduled run depends on. Before committing, verify which engines you can actually cover with the providers you are willing to pay for, and read the scoring and mention-detection code in the repository to confirm its definition of a mention matches the one your stakeholders expect.
Frequently asked questions
What does Elmo actually track?
It tracks how AI answer engines mention, cite and describe your brand across tracked prompts. For each run it stores the answer text, cited URLs, the web searches the engine ran while grounding its response, and the model version, then aggregates those into visibility scores, share of voice and citation breakdowns.
Which AI engines does Elmo cover?
The README lists ChatGPT, Google AI Mode, Google AI Overviews, Gemini, Perplexity and Microsoft Copilot through scraping providers, and Claude, Grok and other models through direct APIs from OpenAI, Anthropic, Mistral and OpenRouter with web search enabled. The providers guide compares the two approaches and their costs.
Can I self-host Elmo?
Yes. It is an MIT-licensed, self-hostable platform, and the repository includes a docker directory for container deployment. The root package.json pins pnpm@11.18.0 and Node 24.x, and the dev and build tasks run through Turborepo.
How does Elmo calculate visibility scores?
Visibility is the share of runs that mention your brand, and each answer is scanned for your brand name, aliases and domains so mentions are counted the same way across engines. Because the raw engine output is stored in PostgreSQL and the scoring code is in the repository, any metric can be re-derived and audited.
Is Elmo a free alternative to tools like Profound or Peec?
The software is free under the MIT licence and the README positions it as an alternative to Profound, Peec and Otterly. Running it is not free, since scheduled runs consume scraping provider requests or model API calls, and the README points to a providers guide that compares those costs.
What is query fan-out in Elmo?
When an answer engine grounds a response it often runs several web searches first, and Elmo records those searches. The query fan-out view shows how engines rewrite your wording, which words they add, drop or keep, and which searches your content wins or misses.
Community notes