Skip to content

Repository files navigation

Caveatly — Chrome extension

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

Install from a release

  1. Download caveatly.zip and unzip it.
  2. Open chrome://extensions, enable Developer mode, click Load unpacked, pick the unzipped caveatly/ folder.
  3. Add your Gemini API key in Caveatly → Settings (free from Google AI Studio).

Build from source

npm install
npm run build        # bundles into dist/
  1. Open chrome://extensions, enable Developer mode, click Load unpacked, pick dist/.
  2. Click the Caveatly toolbar icon → Settings → paste your Gemini API key (AIza… from aistudio.google.com). The key is stored in chrome.storage.local only — never synced.
  3. 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).

How a scan works

  1. extract-page.js is injected into the tab: finds Terms/Privacy links (or detects the page itself is a legal doc) and returns candidates.
  2. background.js fetches up to two policy documents, converts HTML → text.
  3. groq.js (OpenAI-compatible client) sends the text to Gemini which returns tiered flags with plain-English titles, explanations, clause refs, and verbatim quotes.
  4. report.js computes the grade/stats deterministically from the flags; the report is cached per-origin and the badge shows the concern count.

Privacy features (Settings)

  • Block non-essential cookies / dismiss consent banners — consent.js clicks "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.

Privacy & analytics

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

Tests

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/.

Layout

  • src/components/ — design-system primitives (ported verbatim from the DS project)
  • src/screens/ — PopupHome, ReportPanel, SettingsPanel
  • src/lib/ — extraction, HTML→text, AI client, report builder, settings
  • src/background.js / src/consent.js — service worker & consent content script
  • src/styles/ — DS tokens (colors, type, spacing, effects)
  • site/ — static landing page, deployed on Vercel (project root: site)

License

MIT. Found a security issue? See SECURITY.md.

About

Chrome extension that scans a site's Terms of Service and Privacy Policy with AI and flags what matters.

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages