DEV Community

Cover image for ExtensionDash: tracking a browser extension from your agent
Anton Kopylov
Anton Kopylov

Posted on Originally published at kopylov.net

ExtensionDash: tracking a browser extension from your agent

After shipping two browser extensions this year — Reverse Image Search Anywhere and Stackpeek — I still could not answer the simplest question about a listing: is it working?

Both stores tell you how many people installed the thing. Neither tells you the number that decides whether anyone installs it at all: where you appear when someone searches the words they would actually type. The Chrome Web Store developer dashboard has no notion of search position. Firefox's is no better. So the honest answer to "did last week's title change help?" was to open an incognito window, type the keyword, and count down the results with my finger. In three languages.

So I built ExtensionDash. It scrapes both stores nightly and records installs, ratings, category rank, keyword positions, competitors and listing copy — and keeps the history.

The decision that mattered

Not the scraper. It was making the agent a first-class reader rather than an export button.

POST /mcp speaks the Model Context Protocol over stateless HTTP, authenticated with a per-user token. Fifteen tools; eleven read, and the four that write cannot delete recorded history. Everything the dashboard renders, an agent can read.

That part mostly just works. What took actual thought is that an agent needs absence to be legible, and a web page does not.

A human seeing a blank cell reads it from context: still loading, new row, or genuinely nothing. An agent gets a JSON document with a null in it, and a null is a wonderfully confident thing to summarize as a zero. "Your extension does not rank for this keyword" and "nobody has looked yet" are opposite facts, and a tool that returns the same shape for both will get one narrated as the other to a user who believes it.

So three states stay distinct: never scanned, scanned and found, scanned but absent. add_keyword reports whether a fetch was actually enqueued and names the tools to poll. list_scrape_runs surfaces a failed fetch as a failure rather than as a position that silently never arrives.

Same instinct behind the field I am most attached to: every position travels with the depth it was scanned to. #1 of 9 and #1 of 50 are different results. Reporting "you rank #12" while omitting that the scan stopped at 50 is how a tool lies by arithmetic rather than by mistake.

History you did not pay for

Every nightly keyword search already scans fifty results, so all fifty are recorded. add_competitor promotes one — which earns it a listing fetch, and therefore a description, installs and a rating — but the ranks are already there. A competitor you add today arrives with rank history going back to the day you started tracking the keyword. You get to ask "when did they pass me?" about someone you had not thought about until this morning.

Stack is unremarkable on purpose: Rails 8, Postgres, Solid Queue with browser work on its own single-threaded queue, Nokogiri and Ferrum for Chrome, the public AMO API for Firefox. Kamal from a laptop.

The beta

Open, free, no card, at extensiondash.com. Limits are three extensions per account and fifteen keywords per extension, because a keyword is a nightly browser session in perpetuity — not because there is a paid tier behind them.

What I would most like people to try is the part I cannot evaluate alone: connect it to your agent and ask it something real.

claude mcp add --transport http extensiondash https://extensiondash.com/mcp \
  --header "Authorization: Bearer <your token>"
Enter fullscreen mode Exit fullscreen mode

The token and a ready-to-paste command are on the Help page. Then ask your agent why an extension slipped last week, or what a competitor changed — and tell me where it stalls, what it guesses at, and what it reaches for that is not there. I designed those fifteen tools by reasoning about what an agent would need. Reasoning about it is not the same as watching it happen.

Anything else you find, I want too: anton@kopylov.net.

Top comments (0)