Reads the fine print for you: scans the current site's Terms of Service and
Privacy Policy with Gemini and flags what matters in three tiers
(safe / caution / concern), graded A–F. UI implemented from the Caveatly
design-system project (ui_kits/extension).
Website: https://caveatly.n3el.dev · Download: caveatly.zip · License: MIT
- Download
caveatly.zipand unzip it. - Open
chrome://extensions, enable Developer mode, click Load unpacked, pick the unzippedcaveatly/folder. - Add your Gemini API key in Caveatly → Settings (free from Google AI Studio).
npm install
npm run build # bundles into dist/- Open
chrome://extensions, enable Developer mode, click Load unpacked, pickdist/. - Click the Caveatly toolbar icon → Settings → paste your Gemini API key (
AIza…from aistudio.google.com). The key is stored inchrome.storage.localonly — never synced. - Visit any site, open the popup, and hit Scan this page. Optional: in Settings set Auto-scan so Caveatly scans when it finds terms/privacy on a domain you have not scanned yet (never when you only open the toolbar).
extract-page.jsis injected into the tab: finds Terms/Privacy links (or detects the page itself is a legal doc) and returns candidates.background.jsfetches up to two policy documents, converts HTML → text.groq.js(OpenAI-compatible client) sends the text to Gemini which returns tiered flags with plain-English titles, explanations, clause refs, and verbatim quotes.report.jscomputes the grade/stats deterministically from the flags; the report is cached per-origin and the badge shows the concern count.
- Block non-essential cookies / dismiss consent banners —
consent.jsclicks "necessary only" / "reject all" in common consent dialogs (best effort). - Send Global Privacy Control — declarativeNetRequest rule adds
Sec-GPC: 1. - Strip tracking parameters — DNR rule removes
utm_*,gclid,fbclid, etc.
Scanned policy text goes only to Gemini, with your key. Separately, lib/heartbeat.js
sends one anonymous ping per UTC day to analytics.n3el.dev (run by the developer):
a random install ID, the extension version, Chrome major version, CPU arch, and
whether it's a Web Store or unpacked install. No URLs, page content, keys or
personal data, and no cookies; only the country is kept, not the IP address. Uninstalls are counted
via chrome.runtime.setUninstallURL. Turn it off with Settings → Share anonymous
usage stats: nothing is sent and the uninstall URL is cleared. The website counts
page views with a cookieless script. Full details: https://caveatly.n3el.dev/privacy
npm run test:e2e # loads the extension into Chromium, scans real sites
npm run test:heartbeat # unit test: daily usage ping + opt-out (no network)Visits github.com, stripe.com, and en.wikipedia.org; verifies extraction finds real
policy text (>2K chars), the LLM request is made, and all screens render. Uses a
local OpenAI-shaped mock by default; set GEMINI_API_KEY to run against real Gemini.
Screenshots land in screenshots/.
src/components/— design-system primitives (ported verbatim from the DS project)src/screens/— PopupHome, ReportPanel, SettingsPanelsrc/lib/— extraction, HTML→text, AI client, report builder, settingssrc/background.js/src/consent.js— service worker & consent content scriptsrc/styles/— DS tokens (colors, type, spacing, effects)site/— static landing page, deployed on Vercel (project root:site)
MIT. Found a security issue? See SECURITY.md.