Privacy policy

Local-first. Nothing leaves your machine.

Last updated: 2026-06-09.

peek is a local-first developer tool. The Chrome extension captures your real browser session and ships it through a native-messaging stdio bridge to a local MCP server (peek-mcp). No remote endpoints, no telemetry, no analytics, no third-party SDKs.

This page is the canonical privacy policy used for the Chrome Web Store listing. The source markdown lives at docs/peek/PRIVACY_POLICY.md.

What peek processes

peek does not record:

Where the data goes

  1. Browser extension — masks events in the page (ISOLATED-world content script) before passing them to the service worker.
  2. Service worker — forwards events to the local native host via chrome.runtime.connectNative('com.peekdev.host'). stdio pipe; no sockets, no localhost HTTP, no DNS.
  3. peek-mcp native host — persists events to a local SQLite database at ~/.peek/sessions.db (POSIX) or %APPDATA%\\peek\\sessions.db (Windows). Large event chunks are gzipped to ~/.peek/rrweb-events/.
  4. AI coding agents — when you point Claude Code / Cursor / Cline / Windsurf at the peek-mcp MCP server, the agent reads sessions from the local SQLite database. Reads are gated by the permission model below.

No cloud sync. No telemetry endpoint. No third-party data sharing.

Permission model

Per-origin, 5 levels. Default is Level 1 — Observe only.

Live page snapshot (get_page_view) — at Level 1+, an agent may request an on-demand snapshot of the current page: a compact, ref-tagged list of interactive elements (so it can act on a stable reference instead of guessing a CSS selector). It is non-mutating and audit-logged. Password/email/tel and PII-autofill values (card, address, birthday, name, etc.) are masked in-page to •••. Any region marked .rr-mask / data-private / data-dd-privacy / data-peek-mask is masked to ••• in-page across its element names, values, and text (not only input values); structured PII in the remaining text is masked before it leaves the device. As with the recorder, free-text values of non-annotated fields may be included — mark sensitive free-text regions with a mask class to exclude them. Refs are identity-stable across snapshots (an element keeps its ref) via a MAIN-world WeakMap — a JS global, never a DOM attribute, so it is invisible to recordings.

Element detail (get_element_detail) — also at Level 1+, an agent may drill into a single element by its ref: role, full accessible name, every aria-* attribute, state, value, type, href, position, nearby heading/landmark, and interactive descendants. It is non-mutating, audit-logged, and applies the same masking as get_page_view (sensitive values become •••; structured PII is scrubbed). A region marked .rr-mask / data-private / data-dd-privacy / data-peek-mask is masked to ••• across the element's name, value, own/descendant text, every aria-* value, and every child name. It never reads raw outerHTML / innerHTML. The same free-text caveat applies.

Post-action delta (observe) — when an agent passes observe: true on a mutating execute_action, peek returns a masked delta of what changed after the action (added / removed / changed refs), so it can verify the result without a second snapshot. The delta carries the same masked fields as get_page_view (same caveats); a navigating action returns only a “refs expired” marker, no element content.

Destructive-action blocklist override — even at Level 4 (Auto), targets matching “delete”, “remove”, “drop”, “uninstall”, “transfer”, “send”, “pay”, etc. require explicit confirmation.

Deep capture — separately gated. Requires (a) the optional debugger Chrome permission, requested at user-gesture time, and (b) per-origin opt-in via the “Deep capture” toggle. Disabling Deep capture for an origin detaches the debugger from every tab on that origin immediately.

User controls

Open source

peek is Apache 2.0. The privacy posture above can be verified by reading the source — particularly the masking in packages/peek-extension/src/relay/mask.ts, the native port in packages/peek-extension/entrypoints/background.ts, and the stdin/stdout handler in packages/peek-mcp/src/native-host/.

No build phase, no installer, and no runtime path makes network calls to any host outside chrome.runtime.connectNative('com.peekdev.host').

Contact & changes

For questions, open an issue on the repository. For a privacy or security vulnerability, use GitHub's private vulnerability reporting per the SECURITY.md policy — coordinated disclosure with a 3-business-day acknowledgement target. Material changes to this policy bump the date at the top and are noted in the repository's CHANGELOG.