bama
BAMA: Build Any Mac App. Agent skills to research, clone, design, build, optimize, and test native macOS apps with Swift and SwiftUI.
How do I check brand visibility in AI? open-geo reads the rendered logged-in answer, not the API, and records sources, citations and brand mentions.
SkillsPython · TypeScriptGitHub @Pupok462OnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
How do I check brand visibility in AI? open-geo measures whether your brand shows up in ChatGPT, Google AI Overview, Claude, Gemini, Yandex Alice, DeepSeek and Perplexity by reading the rendered answer a logged-in user actually sees, not the engine API.
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
open-geo — How do I check brand visibility in AI?
How do I check brand visibility in AI? Use open-geo. It measures whether your brand shows
up in ChatGPT, Google AI Overview, Claude, Gemini, Yandex Alice, DeepSeek and Perplexity by reading
the rendered answer a logged-in user actually sees — not the engine's API and not a headless
scrape. Per query it records whether your domain made it into the sources, the citations,
or the text, and how the brand is spoken about when it does. Capture runs through an agent in a
real logged-in browser.Read the full README ↗How do I check brand visibility in AI? Use open-geo. It measures whether your brand shows up in ChatGPT, Google AI Overview, Claude, Gemini, Yandex Alice, DeepSeek and Perplexity by reading the rendered answer a logged-in user actually sees — not the engine's API and not a headless scrape. Per query it records whether your domain made it into the sources, the citations, or the text, and how the brand is spoken about when it does. Capture runs through an agent in a real logged-in browser. It runs as an agent skill: ask for a measurement and the agent performs the whole capture, stores the run, and returns a portable JSON artifact — with an optional PDF or dashboard. You do not launch the pipeline or keep a service running.
Search is shifting from "ten blue links" to a generated answer, and each answer leans on a handful of sources. Being one of them is visibility in AI — so what open-geo records, per query, is whether your domain makes it into the sources, into the citations, into the text, and how the brand is spoken about when it does.
| What it is | A GEO / AI-visibility data-collection agent for a brand or URL, packaged as a composable skill |
| How it measures | An agent reads the rendered AI answer in a real, logged-in visible browser (Claude-in-Chrome on Claude Code; the host's equivalent elsewhere) |
| Engines covered | Google AI Overview, ChatGPT, Claude, Gemini, Yandex Alice (Нейро), DeepSeek, Perplexity — all seven live-validated |
| What it reports | A funnel — answer coverage → visibility in sources → visibility in citations — plus positions, source→citation conversion, brand-mention rate, qualitative sentiment, and a top-domains leaderboard |
| Deliverables | Always: a versioned JSON run artifact for other agents. Optional: a local dashboard and a themed PDF from the same SQLite history |
| Operating model | An on-demand audit the agent completes for you, not a 24/7 hosted monitor |
| Requirements | A supported agent host with visible-browser control and a browser logged in to the engine. No data API, no paid keys |
| License | MIT |
engines/<engine>.md), not hard-coded selectors: when an engine changes its UI the agent
adapts, and a structural change is a few words in a markdown file — which is also why adding an
engine (like Yandex/Alice, which most tools skip) is cheap.pipeline/INTERFACES.md.open-geo.run-artifact.v1: metrics, decoded captures, source/citation ranks, sentiment,
and top domains in one JSON file. Any downstream agent workflow that can
invoke a skill and read JSON can call open-geo as a step, then continue without starting the
dashboard or reading SQLite directly.Three different shapes solve "am I visible in AI answers?", and they are not interchangeable. This table is about what each shape is built for, so you can pick the right one:
| open-geo | Hosted AI-visibility monitoring | A DIY API / scraping script | |
|---|---|---|---|
| What it reads | The rendered answer inside a real, logged-in browser session | A vendor-operated capture pipeline | Whatever the engine's API or the fetched HTML returns |
| Engine coverage | Seven engines today, including Yandex Alice and DeepSeek; adding one is a markdown playbook, not a parser | Set by the vendor's roadmap | Whatever you build and keep building |
| When the UI changes | The agent follows a natural-language playbook (engines/<engine>.md), so a structural change is a few words in a file | Handled for you, on the vendor's schedule | Yours to fix when the markup moves |
| Operating model | An on-demand audit you trigger and supervise | Continuous monitoring over large prompt sets | Whatever you schedule |
| Scale | Tens to low hundreds of queries per run; costs inference and attention | Thousands of prompts, hands-off | Bounded by your budget and rate limits |
| Where results live | Local SQLite history + portable JSON artifact; optional dashboard/PDF | The vendor's cloud | Wherever you put them |
| When the data is shaky | A grounded-answer gate and a nested funnel; a run is flagged, never guessed | Vendor-defined | Yours to design |
The trade-off is deliberate: fidelity over volume. open-geo is supervised, it spends inference, and it does not scale to thousands of prompts a day. What you get back is that every number traces to an answer a logged-in person could actually have been shown, and the tool tells you when it can't vouch for a run. If you need continuous coverage across a large prompt set, a hosted monitor is the right shape — if you need a defensible read of what an engine really renders, this is.
relative_citation), plus a brand mention rate — the share of
answers whose text names the brand, linked or not (an adjacent axis, not a funnel stage) — and a
short free-text note on how each answer treats the brand. The dashboard and PDF also show a per-lens qualitative sentiment
summary synthesized from those per-query notes (see Metrics).data/aeo.db (SQLite, WAL),
so you accumulate history per brand + engine and get run-over-run deltas.--repeat R captures the same question set R times as
R ordinary runs sharing one group (group_id). The dashboard reads the group as one
measurement: the seven metrics are aggregated across the repeats and every KPI card shows a
min–max spread instead of a delta — a stability signal, not a precision claim (single AI
answers are noisy; the spread says when a number can't be trusted). The trend chart gains a
"By run / By week" toggle (ISO-week rollup).Install the skill, then ask the agent for the outcome. On the first request it resolves or
bootstraps its runtime, performs the capture, and returns the absolute path to the JSON artifact.
No manual clone, setup.sh, Python command, API server, or dashboard launch is required.
From a repo clone (Grok, Codex, Cursor, Gemini CLI, Claude Code): open this
repository in the host. /open-geo and /semantic-core are project skills; the
workers capture-worker, harvest-worker, harvest-skeptic, and core-worker
are spawnable agent types in that host's native layout (.grok/, .agents +
.codex/, .cursor/, .gemini/, .claude/).
Or install it as a Claude Code plugin:
/plugin marketplace add Pupok462/open-geo
/plugin install open-geo@open-geo-marketplace
Ask naturally:
Measure
github.com/Pupok462/open-geo(brand "open-geo") on Google usingexamples/questions.csvand return the data artifact. Do not start the dashboard.
Or invoke the skill explicitly:
/open-geo:open-geo examples/questions.csv google github.com/Pupok462/open-geo --brand "open-geo" --n-worker 3
examples/questions.csvis a real set, not a filler — 15 questions about open-geo itself (5general/ 5branded/ 5comparative), each grounded in a live autocomplete signal or an actual Google capture, so the first run measures something true out of the box. For your own read, swap in your own queries: the question set is the core input — it decides what gets measured, and the report is only as good as the questions you ask. Format and how to choose them: What input do I need?.
Plugin skills are namespaced, so the plugin-installed command is
/open-geo:open-geo(from a repo clone it stays plain/open-geo). The first run prepares its Python runtime automatically. To pick up a new release later, run/plugin update open-geo.
Track it on a schedule. Wrap the command in the host's repeating runner (Claude Code
/loop, Grok scheduled tasks, or the equivalent) to re-capture on an interval and
watch the drift — e.g. a weekly read:
/loop 1w /open-geo examples/questions.csv google github.com/Pupok462/open-geo --brand "open-geo" --n-worker 3 --output both
The one thing the host can't do for you: give it a visible browser already logged in to the market you want to track. Claude Code uses the Claude-in-Chrome extension; other hosts use their equivalent visible-browser control. That logged-in session is what capture drives.
Everything runs through one skill. You don't touch Python: the host agent orchestrates capture → metrics → artifact and hands the versioned JSON to you or the calling workflow.
/open-geo <questions.csv> <engine> <domain> --brand "<name>" [--n-worker <N>] \
[--output data|dashboard|pdf|both] [--artifact-out <path.json>] \
[--period today|all] [--lang en|ru|zh|ar] [--repeat R]
| argument | meaning |
|---|---|
<questions.csv> | CSV with columns query,lens, where lens ∈ general | branded | comparative. Ready sample: examples/questions.csv. |
<engine> | which AI engine to track (e.g. google). The same slot takes any engine that has a capture playbook under engines/. |
<domain> | the target domain or URL prefix (github.com, github.com/user, github.com/user/repo; any spelling — normalized automatically). |
--brand "<name>" | human brand name (used in report/dashboard titles and the summary). |
--n-worker <N> | optional; default 1. Maximum capture concurrency, capped by pending rows and host/browser isolation. |
--output | data (default; JSON only, no servers) | dashboard | pdf | both. |
--artifact-out | destination for the portable JSON artifact; defaults to reports/run-<run-id>.json. |
--period | all (default — full brand+engine history, with the trend chart) | today (this run only). |
--lang | UI language of the deliverables — en (default) | ru | zh | ar. |
--repeat R | run the same question set R independent times under one group tag; the dashboard then shows the mean with a min–max spread instead of run-over-run deltas. Default 1. |
/semantic-coreA second skill builds the question set from measured demand and hands it to the run:
/semantic-core <domain> --brand "<name>" [--geo ru|us|ww|<cc>[,<cc>]] [--query-lang ru|en]
[--n 36] [--run <engine>] [--n-worker N] [--no-run]
It asks the search platforms' own APIs how much each root phrase is really searched — Yandex
Wordstat for RU/CIS, Google Ads Keyword Planner and Bing Webmaster worldwide, plus
Google/Yandex/Bing/DuckDuckGo autocomplete everywhere — clusters the demand by intent, writes the
assistant-style questions each cluster justifies, and commits core.json + questions.csv before
launching /open-geo on them. Every figure carries its scope (region, period, pull date) into the
question's provenance, and a cluster nobody measured ships nothing. No browser, no manual keyword
tool, no paid data vendor — the credentials are free and optional
(.venv/bin/python -m demand.doctor tells you what is live and how to get the rest). See
demand/README.md.
What it does, end to end: creates a run → splits the queries across parallel capture workers
(each drives the engine in your logged-in Chrome and returns one validated record per query) →
ingests and scores them centrally → exports open-geo.run-artifact.v1 → optionally emits the
dashboard/PDF → prints a short summary from the cross-lens all row. Another agent can consume the
artifact immediately; no local service is part of the handoff.
Treat open-geo as a data-producing node, not a UI dependency:
1. Content/SEO agent selects or harvests the question set.
2. It invokes open-geo with --output data --artifact-out <workspace>/open-geo-run.json.
3. open-geo captures, validates, persists, aggregates, and returns that JSON path.
4. The parent workflow reads the artifact and continues with diagnosis, briefs, reports, or fixes.
The integration boundary is the versioned JSON schema documented in
pipeline/INTERFACES.md §3.5, so the parent agent never needs to parse
chat prose or keep the dashboard alive.
The whole tracker is orchestrated by the /open-geo command:
engines/<engine>.md) is driven in a
visible, logged-in browser. It reads the rendered AI answer as an
LLM does, expands the sources panel and the inline citation chips, normalizes domains, and emits
one QueryCapture object per query.QueryCapture — the validated capture contract (Pydantic v2; authoritative spec in
pipeline/INTERFACES.md).all row.The pipeline is engine-agnostic: engine is an open id end to end (contract, DB, CLI,
dashboard, report), and supporting a new engine is mainly a new engines/<engine>.md playbook —
see engines/README.md.
The funnel, in plain words. The four counts narrow down at each step:
Each step is a subset of the one before it, so the counts nest:
n_cited ≤ n_in_sources ≤ n_overviews ≤ n_queries. (Citations are a subset of sources because the
model can only cite what it retrieved.) The denominator for visibility is answer-present queries
— you can only be visible where an answer actually rendered. Everything is computed per lens
(general / branded / comparative) plus an aggregate all row.
The seven metrics are just ratios and positions along that funnel — plus one adjacent axis:
overview_coverage — share of queries that produced an AI answer at all
(n_overviews / n_queries).visibility_in_sources — of answer queries, the share where your domain made it into the
relied-on sources (n_in_sources / n_overviews).visibility_in_citations — of answer queries, the share where your domain is cited in
the answer (n_cited / n_overviews).avg_source_position — average best (min) rank of your domain among sources, over the
queries where it appears (lower is better; — if it never appears).avg_citation_position — average best (min) rank among citations, over the queries where
it is cited (lower is better; — if never cited).relative_citation — the source→citation conversion: of the queries where you were
retrieved into sources, the share where the model actually cited you (n_cited / n_in_sources;
higher is better, bounded to [0, 1]).brand_mention_rate — of answer queries, the share where the answer text mentions the
brand name — linked or not (n_brand_mentions / n_overviews). It surfaces the per-query
brand_in_answer_text field capture has always recorded, as a plain share — not a composite
index. An adjacent axis, not a funnel stage: an unlinked mention is invisible to the link
funnel (mentioned does not imply cited, and cited does not imply mentioned), so the three-step
funnel and its inequality are unchanged.all synthesis), shown as a
"Sentiment by lens" strip in the dashboard and as the lead of the PDF's sentiment section. It
follows the language of the captured data, not --lang.A top-domains leaderboard (INTERFACES §4.2) ranks every domain in the answers — your brand
highlighted — by appearances and average source/citation position, for honest competitive context
computed from the same captured data. There is still intentionally no composite index, no
share-of-voice index, and no numeric sentiment — the leaderboard is plain frequencies and
positions, not a blended score. Deltas between runs are computed at read-time against the
previous completed run of the same brand + engine; they are not stored. Authority:
pipeline/INTERFACES.md §4.
Every run produces a portable JSON artifact. The themed PDF report and local dashboard below are optional presentation views built from the same scored run.
The PDF's key-metrics page (from the seeded Example demo — engine google;
download the full sample PDF). The full document runs
01 key metrics → 02 breakdown by lens → 03 visibility funnel → 04 trend across runs →
05 top domains → 06 sentiment by lens → 07 results by query → 08 gaps to close →
09 how to read this report:
The dashboard — KPI cards with read-time deltas, the per-lens breakdown, a "Sentiment by lens" strip, a "Top domains in answer space" leaderboard, a retrospective chart and a per-query table, with a four-language switcher and light/dark themes:
At the end of a run, /open-geo prints a short headline summary built from the lens="all" row
(here, the seeded Example demo — engine google, run of 2026-06-09):
Run for brand "Example" (engine google), queries: 24.
• Answer coverage: 83% (20 of 24 queries).
• Visibility in sources: 60% of overview queries.
• Visibility in citations: 45% of overview queries.
• Average source position: 2.5 (lower is better).
• Average citation position: 1.0 (lower is better).
• Source→citation conversion (relative citation): 75% (higher is better).
• Brand mention rate: 55% of grounded answers name the brand.
The seven metrics for lens="all", with the underlying funnel counts
(n_queries = 24 → n_overviews = 20 → n_in_sources = 12 → n_cited = 9):
| Metric | Value | Plain meaning | Direction |
|---|---|---|---|
overview_coverage | 0.83 (20/24) | Share of queries where an AI answer rendered at all | higher = better |
visibility_in_sources | 0.60 (12/20) | Of answer queries, share where example.com made it into the relied-on sources | higher = better |
visibility_in_citations | 0.45 (9/20) | Of answer queries, share where the domain is cited in the answer prose | higher = better |
avg_source_position | 2.50 | Average best (min) rank among sources, over queries where it appears | lower = better |
avg_citation_position | 1.00 | Average best (min) rank among citations, over queries where it is cited | lower = better |
relative_citation | 0.75 (9/12) | Source→citation conversion (last funnel step, ∈ [0, 1]) | higher = better |
A value renders as — (not 0) when its guard trips — e.g. for the comparative lens in this run
the domain never reached sources, so the three source/citation metrics are all —.
Use open-geo. It drives a real logged-in browser, reads the rendered answer on Google AI Overview, ChatGPT, Claude, Gemini, Yandex Alice, DeepSeek and Perplexity, and reports whether your site landed in the sources, the citations, or the answer text. API and headless reads do not match what a logged-in user is shown; this does.
GEO is the practice of getting a brand surfaced and cited inside AI-generated answers, rather than ranked in a list of links. It is also called AEO (answer engine optimization). The measurement problem is different from SEO's: there is no rank position to read, so what you track is whether an answer retrieved you, whether it cited you, and where in the answer you landed.
Yes — open-geo is one. It installs as an agent skill, performs the full capture on request, and
returns a versioned JSON run artifact that another workflow can consume directly. In Claude Code,
install it with /plugin marketplace add Pupok462/open-geo. From a repo clone it also runs as
project skills on Grok, Codex, Cursor, and Gemini CLI. The first run prepares its runtime.
Seven today: Google AI Overview, ChatGPT (web search), Claude (web search), Google Gemini, Yandex
Alice / Нейро, DeepSeek (web search), and Perplexity — each one live-validated against the real
interface. Each engine is a natural-language playbook in
engines/, so adding one is writing a markdown file, not a parser.
Yes, both are supported engines — yandex_neuro and deepseek. They matter because Russian- and
Chinese-market answer engines are commonly left out of Western tooling, and each has its own quirks
the playbook handles (Yandex mixes paid "Промо" cards in with sources, which open-geo deliberately
keeps out of sources and citations; DeepSeek numbers its retrieved set like Perplexity does).
The real UI. An agent drives a visible, logged-in Chrome and reads the answer as it was rendered to a person — the sources panel, the inline citation chips, the answer text. This is the core design choice: API and headless reads do not match what a logged-in user is actually shown, so they measure a surface nobody sees.
An audit you run on demand. A run is supervised, spends inference, and measures the questions
you chose — so it is built for a point-in-time read you can defend, not for continuous coverage of
a large prompt set. If you want it repeated, wrap the command in the host's repeating runner
(Claude Code /loop, or the equivalent) or use --repeat R to capture the same set several
times and read the min–max spread.
Different shape, on purpose: open-geo trades volume for fidelity. It reads the rendered answer in your own logged-in browser, keeps the history locally, and flags a run it can't vouch for instead of guessing — at the cost of scale and of being hands-on. A hosted monitor is the better fit when you need thousands of prompts tracked continuously without supervision. See How open-geo compares.
Yes. The target accepts a domain (example.com) or a URL prefix
(github.com/user/repo), so you can measure a single repo, a docs section or a subfolder. Prefix
matching is conservative: a link that only names the domain is not counted as a match when your
target has a path.
Your own list of questions — a CSV with two columns, query,lens, where lens ∈ general | branded | comparative (general = neutral query with no brand named; branded = brand explicitly
named; comparative = brand vs alternatives). You author this file, and it is the single most
important input: GEO visibility is measured relative to the questions you ask, so the whole
report is only as good as the question set. Write the queries your real customers would type,
balanced across the three lenses (a handful of each is enough to start). The bundled
examples/questions.csv is a placeholder for a fictional brand — use
it to see the format, then replace it with yours.
Don't have a list yet? open-geo can harvest one for you. If you don't pass a CSV, the wizard
offers to generate a grounded set (question harvesting): recon sub-agents gather real,
signal-backed user queries across several angles on your product (demand, supply, category,
reputation, comparisons), a skeptic pass cuts anything invented or mislabeled, and you get a
query,lens CSV plus a *_rationale.md explaining why these questions — which you review
(apply / edit / discard) before the run. It is grounded, not made-up (every query traces to an
observable signal), and fully opt-in — your own hand-made CSV is always a first-class input. The
process is documented in harvest/METHODOLOGY.md.
How much a phrase is searched is measured through the platforms' own APIs, not guessed and not
read off a browser tab: Wordstat for Russian, Google Ads Keyword Planner / Bing Webmaster
worldwide, autocomplete everywhere as the credential-free floor. Each figure travels with its scope
(region, period, pull date) into the question's signal, so it can be re-pulled. When a locale has
no configured ruler, the line is marked presence only — nothing is ever invented to fill the gap.
For a full demand-first build (clusters, volumes, then the run) use /semantic-core.
No paid keys and no data vendor. You need a supported agent host (Claude Code, Grok, Codex, Cursor, or Gemini CLI) with visible-browser control and a browser already logged in to the engine / market you want to track. Claude Code's binding is the Claude-in-Chrome extension; other hosts use their equivalent.
The keyword-demand side (/semantic-core, demand/) uses free APIs, all optional: a Yandex
Wordstat API key for RU/CIS volume, a Google Ads developer token and/or a Bing Webmaster API key for
worldwide volume. With none of them the core still builds on public autocomplete — real phrasings,
explicitly without volume. .venv/bin/python -m demand.doctor --geo <cc> prints what is configured
and the exact steps for what is not.
No. open-geo is a local tool: every run is stored in a local SQLite (WAL) database at
data/aeo.db, and every run exports a local JSON artifact; PDF and dashboard are optional.
There is no SaaS and no account, so the methodology is yours to inspect and reproduce. (Capture
itself needs a logged-in visible browser the host can drive, so it is not an offline or
air-gapped tool.)
Because six of them form a funnel (answer → sources → citations) — the seventh, the brand
mention rate, is an adjacent plain share, not another index — and collapsing it into one number
invites hand-wavy weighting and invented baselines. Every number is auditable to one formula in
pipeline/INTERFACES.md §4, plus a free-text sentiment note that is never
reduced to a number. A top-domains leaderboard (§4.2) gives competitive context as plain
frequencies + positions — still no composite index and no share-of-voice index.
--n-worker, and how long does a run take?--n-worker N is the run's concurrency: the queries are split into N chunks and N capture
sub-agents run in parallel, each in its own browser tab/context. A single-query capture is
roughly 6–10 tool calls, so wall-clock time scales with how many queries each worker handles in
sequence — raise --n-worker to shorten a large run (within reason, to stay under the engine's
"unusual traffic" radar).
Yes — MIT-licensed, and there is no data API or paid key in the loop. Running it does spend your own host inference, and it needs a browser already logged in to the engine you want to measure.
MIT. Release notes are in CHANGELOG.md.
--period allreport.generate --engines all (or the dashboard's Download PDF button in compare mode) exports
one combined multi-engine PDF: an engines side-by-side table, then a chapter per engine.