A browser extension that helps you judge text on a web page: what kind of writing it is, who published it, what other sources say about them, and whether its links actually go anywhere.
Its organising commitment is not accuracy but honesty about evidence. Every claim Crabe makes says how strong its own footing is, and it refuses to make claims it cannot support.
Crabe supports critical judgement; it does not replace it. Keep reading critically — the page, and the assessment too. Any model can be confidently wrong, and comparing two of them on the same page is the cheapest way to see it. Like the scope limit below, this is carried on every result rather than written here alone.
Crabe assesses text only. It does not evaluate images, video or audio — including whether they are authentic, current, or shown in their original context. This limit is deliberate and documented; it is stated on every result.
Why Crabe. The name is the acronym: Content Reliability Assessment Browser Extension. The scope has since narrowed to text alone, which would make it Trabe — so the crab stays.
There is a second justification, found afterwards and kept: the move at the centre of this tool is lateral reading, leaving the page to see how it is regarded elsewhere. Crabs go sideways.
Text Reliability Assessment is the name in the Chrome Web Store and on addons.mozilla.org, because that one says what it does to someone who has never heard of it. Same extension.
Not a single number. Crabe emits a vector of axes, each with its own findings and its own evidence tier.
| Axis | What it answers | Kind |
|---|---|---|
| What the text does | Factual, Opinion or Fiction, scored against the matching rubric | contribution |
| Who published it | Byline and date from the page; the model’s knowledge of author and publisher | contribution |
| What other sources say | Lateral reading (SIFT) — independent sources on this publisher and claim | contribution |
| Whether its links work | Each outbound link in the article fetched and its real outcome reported | gate — can only lower |
An axis that could not run says why — it never reports zero. “We could not look” and “we looked and it was bad” are different statements and stay different all the way to the screen. A gate that concluded nothing publishes no score at all, because a neutral 5 and a perfect 5 are the same pixels.
And an absence the page chose is said out loud. An article that names Der Bund, swissinfo, RSI, AFP and Keystone in its prose and links to none of them is not a page Crabe failed to measure — it is a page that offers its reader no way to check it, and Crabe states that. Stated, never scored: marking an absence negative is the one thing the tiers exist to prevent.
The load-bearing idea. Every finding carries one:
| Tier | Meaning |
|---|---|
| Verified | A real artifact was fetched and checked — an HTTP status, a field in the page’s own markup. |
| Retrieved | External sources were fetched and are cited with URLs you can open. |
| Assessed | A judgement about text you can read yourself. Checkable by looking. |
| Recalled | The model’s own knowledge. Not verifiable from inside the extension. |
| Absent | The thing that would have carried evidence is not there. Common, and not a mark against the page. |
The tier is rendered three ways — a written label, a border style, and a colour — so the distinction survives any one channel being unavailable to a reader. An axis summary carries the weakest tier beneath it, so a paragraph cannot claim more than the findings it generalises over.
Why it exists: earlier versions presented what the model remembered about a publisher with exactly the same visual weight as something measured. A tool whose purpose is to make epistemic status visible must not do that.
The rubrics ship inside the extension, rendered from the same data that builds the prompt — not a description of them, the thing itself. Below them, the complete instruction sent to the model, verbatim, one block per axis, plus what travels with it as the user message.
This exists because of a question that could not be answered from inside the tool. A Gemini analysis returned the sentence “International outlets independently corroborate the central claims” above four findings that were all marked as model recall, because the search had returned nothing. The obvious first question — is that sentence the model’s or ours? — required reading the source. It was the model’s. Now it can be checked in the extension, offline, in the version you actually installed.
storage.sync replicates to Mozilla’s or Google’s servers, which would make a key something you had handed to a third party without being asked. The exclusion is declared in constants.ts and asserted by invariants, not left to whoever writes the next storage call.With a local model (Ollama), the page’s text never leaves your machine. Lateral reading is then unavailable, because a local model has no web search tool — Crabe says so rather than quietly reaching for a cloud provider you did not choose. Citation checking is the exception and only when switched on: verifying a link resolves means requesting it, so those requests reach the linked sites under any provider.
npm install
npm run build:chrome # → dist-chrome/
npm run build:firefox # → dist-firefox/
Load dist-chrome/ as an unpacked extension (Chrome/Edge, Developer mode), or dist-firefox/ as a temporary add-on in Firefox.
Crabe runs in a persistent side panel — Chrome’s side panel, Firefox’s sidebar — rather than a popup. A grounded analysis takes tens of seconds and several requests, and a popup is destroyed the moment the window loses focus. Click the toolbar icon to open it.
Then open Settings and choose a provider:
| Provider | Key from | Notes |
|---|---|---|
| Anthropic Claude | Anthropic Console | Web search returns real, durable source URLs |
| Google Gemini | Google AI Studio | Free tier. Its search citations are redirect links that expire and cannot be checked automatically — Crabe labels them as such |
| Local (Ollama) | none | ollama pull mistral, set OLLAMA_ORIGINS. See docs/OLLAMA_SETUP_WINDOWS.md |
npm run type-check
npm test # invariants — assert only what must hold, never a desired outcome
npm run observe # runs a corpus and reports; no thresholds, judges nothing
The two harnesses are kept apart on purpose. A test that asserts a desired result becomes a target, and the system gets shaped to satisfy it. test/invariants.test.ts asserts spec-fidelity only — consent fails closed, tiers never rise, a not-run axis carries no score, agents fail independently. test/observe.ts reports what actually happened and leaves the interpreting to you.
Built, type-clean, the invariant suite passing. The value model, the three providers, all four axes, the consent-gated network boundary, the panel, the settings page and the bundled reference page.
Run live against real pages (August 2026) on Anthropic — Haiku 4.5, Sonnet 5 and Opus 5 — and on Google Gemini. All four axes complete end to end; the consent boundary held; every outbound request carried its purpose. Pages used include news reports, an academic paper, a satirical article, an opinion essay and a GNU manifesto.
Not proven, and worth knowing before trusting a number:
content across three runs with the same model and configuration. Two news pages were stable to the decimal. Sampling variance concentrated on the hardest classification is a fact about what a score can carry, not a bug to tune away — and it is an argument against composing the axes into one figure.npm run observe runs in Node, where cross-origin rules do not exist; it reported the citations axis working perfectly for weeks while the axis failed on every external link in the actual extension. Anything browser-only has to be proven in the browser. The harness and the product are two sides too.localhost:11434 and nowhere else, and the lateral axis degrades with its reason stated rather than throwing. But mistral fails the provenance schema on every page tried; qwen2.5:7b holds it. A local model that cannot keep to the shape makes an axis fail, and Crabe reports that rather than guessing.Documentation: docs/ARCHITECTURE-v3.md is the canonical spec, including decision records for what was dropped and why. docs/privacy_policy.md describes what leaves your browser. docs/store-listing.md holds the store copy.
Phase 1 — text analysis. Done. Classification plus rubric scoring.
Phase 2 — provenance & lateral reading. Done. Real web search with cited sources, and deterministic citation checking.
Phase 3 — media forensics. Dropped, on evidence. The short version:
next/image. No traditional camera manufacturer is in the conformance programme. Security analysis (UMBC/NSA, 2026) finds the specifications “do not achieve any of their claimed security goals”.Building it would have meant promoting a paid service while presenting dateless alternatives as fallbacks for a question they cannot answer. That is the same unearned claim the evidence tiers exist to refuse, so the axis was dropped rather than shipped weak. Full reasoning in the spec, §7.
Phase 4 — orchestration and synthesis. Deferred by design. Merging axes into one figure binds Crabe’s output contract to how downstream consumers gate on it, so it is to be co-designed rather than settled here.
GNU Affero General Public License v3.0. Deliberate: the network-copyleft clause forecloses turning this into a closed hosted service. See LICENSE.