Design Mode & UI annotation for AI coding agents — precise, element-pinned hand-offs between you and Claude Code / Cursor, in both directions.
Caliper is built on one idea: a clicked DOM element already carries a stable selector, its owning component, and computed styles matched to your design tokens — enough for an AI agent to act on without decoding a screenshot. Two products put that to work in opposite directions.
🐞 Human → agent — @caliper/qa-extension
A Chrome extension for manual QA. A reviewer marks broken UI on the live app; the export is a compact payload — selector, component, token-matched styles — an agent fixes straight from the file.
💬 Agent → human — @caliper/ask
An MCP server for the reverse flow. While a coding agent implements a UI and is unsure what a region should do, it asks you — questions pinned to the live elements, answered in place, sent straight back as structured data.
Both products share the same element-picking core and in-page overlay:
| Package | Description |
|---|---|
packages/core |
Element → annotation logic. No chrome.*, no UI framework, portable to any shell. |
packages/overlay |
In-page picker UI rendered in a Shadow DOM. |
apps/qa-extension |
Chrome MV3 extension for manual QA — README. |
apps/ask |
MCP server for live agent→developer UI review — README. |
The extension — install from the Chrome Web Store, or build it locally:
pnpm install
pnpm --filter @caliper/qa-extension buildThen load apps/qa-extension/.output/chrome-mv3 via chrome://extensions → Load unpacked.
pnpm --filter @caliper/qa-extension dev gives you hot reload, but writes a development build to the
same directory: it registers the content script at runtime through the dev server instead of
declaring it in the manifest, so the picker stops working the moment that server is gone. If the
shortcut list shows Alt+R — Reload the extension during development, you are running the dev build.
Click the toolbar icon to arm the picker, click an element, describe the defect, save. Open the side panel to review and export.
The MCP server — see apps/ask for setup, the proxy/snippet modes, and the
agent contract.
The extension turns each marked defect into a compact record — this is the JSON export (TOON and a screenshot zip are available too):
{
"schemaVersion": 1,
"annotations": [
{
"comment": "Padding is too small",
"severity": "minor",
"target": {
"selector": "soa-inform-block p.info",
"selectorConfidence": "medium",
"componentName": "soa-inform-block",
"componentSource": "tag-heuristic",
"styles": {
"padding-top": {"value": "4px", "token": "--spacing-1", "tokenMatch": "exact"},
"color": {"value": "rgb(51, 51, 51)", "token": "--color-text-primary", "tokenMatch": "exact"}
}
}
}
]
}Screenshots live in a separate assets map keyed by screenshotId, and are omitted from
Copy JSON by default.
Every tag matching v* builds, verifies, publishes to the Chrome Web Store and attaches the zip to
a GitHub release:
git tag v0.2.0
git push --follow-tagsThe workflow takes the version from the tag name, so package.json is never bumped by hand.
One-time setup. The Chrome Web Store API can only update an existing item, so the first version has to be uploaded manually — that upload is what mints the extension ID. After that:
- Google Cloud Console → new project → enable Chrome Web Store API → OAuth client of type Desktop app.
- Run
pnpm --filter @caliper/qa-extension exec wxt submit init— it walks through the OAuth flow and prints the refresh token. - Add four repository secrets:
CHROME_EXTENSION_ID,CHROME_CLIENT_ID,CHROME_CLIENT_SECRET,CHROME_REFRESH_TOKEN. - Verify without uploading anything:
wxt submit --dry-run --chrome-zip .output/caliper-<v>-chrome.zip.
Each upload goes through Google's review, so a published tag is not live immediately.
Everything stays in chrome.storage.local. No backend, no network requests, no telemetry — see
PRIVACY.md.
MIT

