npx getclaros in your project sets this up: it installs getclaros-browser with your package manager and, for Playwright Test, writes claros.fixture.ts (every test’s page guarded). Then change from "@playwright/test" to from "./claros.fixture" (the path init prints) in your specs. By hand: npm install getclaros-browser and the code below.
Works on any web app: nothing in it knows an app’s names, selectors or URLs.

What happens on a click

  1. A script in every frame holds commits before the app’s handlers run: a POST form submit, Enter in a form, or a click on a button, link or menu item whose name commits (submit, save, send, pay, approve, delete, deploy, merge, refund … in 7 languages). Reads, navigation and typing pass.
  2. It reads the record around the button from the DOM: labels and values, tables and ARIA grids as rows, review lists, open shadow roots.
  3. It asks POST /v1/check/page. No fields at all (canvas, cross-origin iframe)? A screenshot goes to the screen fallback.
  4. Allowed: the action is replayed once and reaches the app. Stopped (stop or ask): it’s dropped and your call throws ClarosStop. Nudged: replayed like an allow; the nudge (rule, the owner’s words, suggested fix) goes to onNudge, guard.nudges and console.warn.
A form.submit() from a script (no submit event) is checked at the network from its form data and aborted on a stop.

Options

ClarosStop has rule, quote, expert, whoToAsk, checkId, result, and message (the same text as the MCP guard). guard() returns {decisions, stops, nudges, drain()}: drain() waits for pending checks and returns the first stop. Stops caused by calls Playwright doesn’t wrap (for example page.evaluate) are still held and checked; they land in stops and onDecision.

New tabs

One guard(page) per page:
See Limits.