Verbatim is the design layer your AI does not have. A Chrome extension that pulls the real design out of any website, and an MCP server that hands your coding agent the same thing: exact values, verified against the page they came from.
The whole toolbar, one keystroke away on any page.
get_design_context({ url: "stripe.com", selector: ".pricing-card" })
34 rules across 12 elements 8 tokens, 3 states, 2 breakpoints contrast 8.4:1, passes AAA
// before trusting any of it verify_extraction({ url: "stripe.com", selector: ".pricing-card" })
22 of 22 properties match rendered in isolation, diffed against the live page
It can read your code and query your data. Ask it what colour the button is on a site you admire and it is back to guessing from a picture.
Verbatim is that third row. One call and the design stops being a picture and becomes something your agent can read: the rules that actually applied, in the order they applied, with the values it would otherwise invent.
Show it a screenshot and there are no values in it. Paste the stylesheet and there are five thousand rules in it. Either way it guesses, and you find out in review.
.mt-1 { margin-top: .25rem } .mt-2 { margin-top: .5rem } .mt-3 { margin-top: .75rem } .flex { display: flex } /* 5,768 more rules, 4 of which touch your element */
/* only what applies, in order */ .pricing-card { padding: var(--space-6); background: #0b69ff; } .pricing-card:hover { … } @media (min-width: 768px) { … }
Pin Verbatim, open any website, and hit Alt+Shift+P. A toolbar drops onto the page and stays there while you click around. A popup would close the moment you touched the thing you came for.
The icon or the shortcut, on any page including your own localhost. The toolbar lives in a shadow root, so the site's CSS cannot reach into it and it cannot leak into the site. Drag it out of the way by the grip.
Hover and the element is outlined, with its selector and its exact size in the toolbar's readout. Click to lock it. It reads through shadow roots and iframes on the same origin, so web components are pickable too.
The panel opens with the CSS, the same thing in Tailwind, a component in your framework, a written brief for a chat, and the raw inspection. Copy any of it, or press G to send it straight to your coding agent.
Press Esc and it leaves. Anything you hid comes back, anything you moved goes back where it was, and the page is as you found it. Chrome, Edge, Brave and Arc. No account, and no page you visit is sent anywhere.
Grouped by what each one does to your page rather than alphabetically, in the order you tend to reach for them. The bar carries a readout of whatever is under the cursor, so it behaves like an instrument with a display instead of a row of buttons.
Hover to outline, click to lock. It takes the whole component by default, the element and everything inside it, not one lonely tag. That is why what you paste actually renders.
The box model shaded in place, margin, border and padding separately, with rulers running out to the edges of the viewport. Width and height to the pixel in the readout.
The whole page at once. Palette ordered by how much of the screen each colour actually covers, with background, surface, text, accent and border named. Type scale with the weights and use counts. Spacing, radii, shadows, breakpoints, the site's own custom properties, and a contrast check on the text.
Chrome's own eyedropper, so it reads any pixel on the screen including inside images, canvas and video, which no amount of CSS reading can do. Copied as hex, rgb or oklch, whichever you set.
Every family on the page, webfont or system, each size with the weights it appears in and how many times it is used, plus the file each webfont was loaded from.
Every image, inline SVG, CSS background and video poster on the page, largest first, filterable by format and by rendered size.
Click any text and type over it. Real copy in a real layout, before anyone builds it.
Click to remove a cookie banner, a sticky header, a chat bubble, an ad. Z brings them back one at a time.
Drag anything anywhere. It moves by transform rather than by changing layout, so nothing around it reflows and putting it back is exact.
Our own toolbar hides itself and waits for the page to repaint before the shutter, so it never lands in your capture. Cropped to the selection if you have one, otherwise the viewport, named after the element.
The whole page as it stands right now, cookie banner dismissed and menu open, as one downloadable file next to its styles and a live preview.
Posts the full design context to the Verbatim server running on your machine. Your agent picks it up with get_handoff, no copy and paste in between.
Box model shading and distance rulers on or off, colour format, whether picking means the component or the element alone, whether reset rules are dropped, whether design tokens come along, Tailwind v3 or v4 and whether to generate a theme, TypeScript, and your bridge token.
Puts everything back and gets out of the way.
Pick an element and the panel opens beside it. Every tab is the same selection seen differently, and every one of them copies with a single button.
Every rule that applies, in cascade order, with @layer, @media and @supports kept intact, hover and focus states included, and the custom properties the rules read declared alongside. Authored rules, not a dump of computed style.
The same selection as utility classes, v3 or v4, with an optional theme so the classes point at named tokens instead of repeating raw values.
React, Vue, Svelte, Astro, Angular or plain HTML, in JavaScript or TypeScript, with a depth control that runs from the element alone to the entire subtree.
A written brief for a chat: what the thing is, its values, its states, its breakpoints, the tokens it depends on, its contrast. Rendered as formatted markdown so it is readable before you paste it.
The raw reading. Tag, classes, id, box model to a tenth of a pixel, how many rules matched, which states and breakpoints exist, pseudo-elements, web fonts, animations, then the matched selectors sorted by specificity with their layer and at-rule context.
Three of the heavier jobs get their own window, because a side panel is the wrong shape for code you actually need to read. Each one drags, resizes, and reopens where you left it.
The markup and styles on one side. On the other, the extraction rendered in a sandboxed iframe with the live element's computed values diffed against it, and anything that disagrees listed by name. Switch to Prompt for the brief.
The captured markup and the page's stylesheets in their own panes, with a preview rendered without scripts, and a button that downloads the file.
A grid of every asset with its format and rendered size, filterable, click to select. Copy the URLs, or download the selection as one zip packed in the browser with nothing sent to a server.
Exact values, never rounded to a nearby palette entry. The button below is rendered by the code beneath it, and that code is read from the same stylesheet as the page loads, so the two cannot drift apart.
Export as a Tailwind theme, CSS custom properties, or W3C design tokens. Contrast is measured while it reads, so your agent does not faithfully reproduce someone else's accessibility bug.
Your agent drives a browser with no session and no hands. It cannot log in to your dashboard, and it cannot see a dropdown that only exists while you hold it open. So pick it yourself, in the state you want it, and press G. The extension posts it to the server on your machine and the agent reads it from there.
Nothing is uploaded on the way. The bridge listens on loopback only and refuses anything without the token in your settings, so no page you happen to have open can read your captures or plant one.
get_handoff()# Component: .invoice-row from app.yourcompany.com markup, CSS, states, tokens
Everything the toolbar does by hand, your agent can ask for on its own. Same engine, so what it gets back is exactly what you would see picking that element yourself, and any client that speaks MCP works.
Make our pricing card match the one on stripe.com.
the call
get_design_context({ url: "stripe.com", selector: ".pricing-card", task: "rebuild it in our stack" })
what comes back
# Component: .pricing-card # from stripe.com, captured at 1440x900 ## Every rule that applies, in order .pricing-card { padding: var(--space-6); ... } .pricing-card:hover { ... } @media (min-width: 768px) { ... } ## What a stylesheet cannot say hover is triggered by the card, not the button contrast 7.1:1, passes AA and AAA
Buildable markup, every rule that styles it in cascade order with layers preserved, the tokens it reads, its states, its behaviour per breakpoint, its contrast.
Give me their testimonial block as a React component.
the call
get_component({ url: "linear.app", selector: ".testimonial", framework: "react", styling: "tailwind" })
what comes back
export function Testimonial() { return ( <figure className="flex gap-4 rounded-xl p-6"> <blockquote className="text-[17px] leading-6"> ... ) }
One part of a page as HTML and CSS, or as a React, Vue, Svelte, Astro or Angular component. Optionally converted to Tailwind.
Use their palette and type scale for this dashboard.
the call
get_design_system({ url: "linear.app", format: "tailwind" })
what comes back
@theme { --color-background: #08090A; /* 41% of screen */ --color-accent: #5E6AD2; /* 4% */ --text-base: 15px; /* 212 uses */ --radius-lg: 12px; }
Palette ordered by how much of the screen each colour covers, type scale, spacing, radii, shadows, breakpoints, and the site’s own custom properties. As prose, Tailwind, CSS variables or W3C tokens.
Your agent runs this on its own, before it trusts anything.
the call
verify_extraction({ url: "stripe.com", selector: ".pricing-card" })
what comes back
22 of 22 properties match rendered in isolation, diffed against the live page when something is off, it says which: box-shadow expected 0 1px 2px rgba(0,0,0,.08) got none
Renders the extraction in isolation and reports every computed style that differs from the live page. A model that can check its inputs need not trust them.
Pull their icon set and tell me what is oversized.
the call
get_assets({ url: "vercel.com" })
what comes back
hero-dark.avif 1920x1080 84 KB logo.svg inline 2 KB og-card.png 2400x1260 1.8 MB rendered at 600x315, 4x oversized
Every image, SVG, CSS background and video poster, largest first, with oversized sources flagged.
Show me what it looks like, not just the numbers.
the call
screenshot({ url: "stripe.com", selector: ".pricing-card" })
what comes back
image/png, 345x376, cropped to the element the values tell it what, the picture tells it why. useful alongside the context, not instead of it.
A page or one element as a PNG. Useful alongside the context rather than in place of it.
What did I send you from the browser?
the call
list_handoffs()what comes back
2 .invoice-row app.yourcompany.com 4m ago 1 .nav-dropdown app.yourcompany.com 11m ago open state, captured while the menu was held
Captures sent from the browser extension, for the pages a headless browser cannot reach.
Use the invoice row I just sent.
the call
get_handoff({ id: "2" }) // omit id for the newest
what comes back
# Component: .invoice-row # from app.yourcompany.com, behind your login markup, CSS, states, tokens, contrast everything get_design_context returns, for a page no browser of its own could have reached.
Whatever you picked by hand, in whatever state you picked it, waiting for the agent to read.
Responses are shortened here. The real ones are longer and duller, which is the point.
Verbatim renders what it copied and compares it against the live page, property by property. If anything is off it says so, before your agent writes a line.
| Property | Live page | Extracted | Result |
|---|---|---|---|
| color | rgb(255, 255, 255) | rgb(255, 255, 255) | match |
| background-color | rgb(11, 105, 255) | rgb(11, 105, 255) | match |
| padding-left | 26px | 26px | match |
| border-radius | 8px | 8px | match |
| letter-spacing | -0.16px | -0.16px | match |
This is not a marketing claim. The same check runs in the test suite on every build, and it has caught real bugs: cascade layers being flattened, and inherited styles outranking the rules they were meant to lose to.
The server speaks MCP over stdio, so anything that speaks MCP can use it. It runs on your machine: nothing is uploaded, and no page you copy from is sent anywhere.
Two routes. From source means npm install && npm run build once, then an absolute path to the built server: run pwd in the folder and use that in place of /path/to/verbatim. From npm needs no path at all, and lights up when the package is published.
One command in your terminal, from any directory.
Check it took with claude mcp list. Verbatim's eight tools then show up in /mcp.
Edit ~/Library/Application Support/Claude/claude_desktop_config.json macOS. On Windows, %APPDATA%\Claude\claude_desktop_config.json
Restart Claude Desktop afterwards. It only reads that file at launch.
Edit ~/.cursor/mcp.json for every project, or .cursor/mcp.json for one.
Then Settings, MCP, and check Verbatim is green.
Edit ~/.codex/config.toml
This is OpenAI's coding agent. ChatGPT itself connects only to MCP servers reachable over HTTP, so a server on your own machine is out of its reach: use Codex for local work.
Edit ~/.codeium/windsurf/mcp_config.json
Then Cascade, the plugins panel, refresh.
Edit .vscode/mcp.json in your project.
For Copilot in agent mode. VS Code names the key servers rather than mcpServers, and wants the transport spelled out.
Any client that speaks MCP over stdio. Give it this command.
No transport to configure, no port to pick, no key to paste. The client starts the process, talks to it over stdin and stdout, and stops it when it is done.
Then just ask for it. Match the hero on linear.app. Take the palette from our marketing site and apply it to this dashboard.
Paste a URL, get an answer. No install.
Every tool in this category gets the same complaint: too expensive for what it does. So the extension itself is free forever, with no account. Picking, measuring, inspecting, colours, fonts, assets and screenshots, as much as you like. You pay only when you want your agent doing it for you.