shotproof

Screenshot to code for Claude Code and Codex, with no API key

shotproof turns a screenshot into matching HTML + CSS (or React + Tailwind) using your agent's own model. It renders the page in Chromium at the screenshot's exact size, scores it against your image with SSIM, and fixes the worst-matching part until the score passes.

Install

Claude Code

/plugin marketplace add deserteaglemj/shotproof
/plugin install shotproof@shotproof

Codex

codex plugin marketplace add deserteaglemj/shotproof
codex plugin add shotproof@shotproof

One-time helper setup (Python 3):

python3 -m pip install playwright pillow numpy && python3 -m playwright install chromium

Then run /shotproof ./screenshot.png, add react for React + Tailwind, or just say "turn this screenshot into code".

How it works

  1. Read the screenshot like a builder: sections, exact text, colors sampled from real pixels, type sizes and spacing.
  2. Build one HTML file with inline CSS (no CDN, no web fonts), or React components with Tailwind in your project.
  3. Render it in Chromium at the screenshot's own viewport and device scale.
  4. Compare: SSIM overall and for 8 horizontal bands, band shift in pixels, a side-by-side image and a diff heatmap.
  5. Fix the worst band with targeted edits, keep the best round, and stop at the pass line or after 5 rounds. Console errors, failed requests, a blank page, a pasted screenshot or sideways scroll at 375px fail the check whatever the score.

Results

Each case was rebuilt by a fresh agent that saw only the screenshot, then re-scored by a separate script. Mean gain from the fix loop: +0.085 SSIM. Full results and per-round logs.

Orders dashboard: input screenshot on the left, rebuilt page on the right, SSIM 0.980
Dashboard: input (left) and rebuilt (right), SSIM 0.980.
Mobile login screen: input screenshot on the left, rebuilt page on the right, SSIM 0.983
Mobile login at 2x: input (left) and rebuilt (right), SSIM 0.983.
Eval scores (SSIM vs the input screenshot)
CaseFirst buildFinalPass lineResult
Landing page0.9480.9760.90Pass
Pricing (dark)0.8480.9510.90Pass
Dashboard0.9370.9800.90Pass
Mobile login, 2x0.8240.9830.90Pass
Serif article0.8330.9300.90Pass
Hacker News (real site)0.7800.8650.80Pass
GOV.UK, proof mode (real site)0.7240.8860.80Pass
Settings, React + Tailwind0.99910.99960.90Pass

FAQ

How do I convert a screenshot to HTML with Claude Code?

Install shotproof (/plugin marketplace add deserteaglemj/shotproof, then /plugin install shotproof@shotproof) and run /shotproof ./screenshot.png, or just say "turn this screenshot into code". Claude Code writes one index.html, renders it, scores it against your screenshot and fixes it until it passes.

Is there a screenshot-to-code tool that needs no OpenAI key?

Yes: shotproof runs on the model your Claude Code or Codex session already uses, so it needs no OpenAI, Anthropic or Gemini API key. The render and scoring run locally with Python, Playwright and Chromium.

How is this different from abi/screenshot-to-code?

abi/screenshot-to-code is a standalone web app that needs a provider API key and supports more stacks and video input. shotproof runs inside your agent with no key, and checks its own output with a measured SSIM score and a fixed pass line, fixing the worst band for up to 5 rounds.

Does it work in Codex?

Yes. Run codex plugin marketplace add deserteaglemj/shotproof and codex plugin add shotproof@shotproof; Codex picks up the same skill and helper script.

How do I check the generated page matches the design?

s2c.py verify renders the page at the screenshot's size and writes an SSIM score, a score for each of 8 horizontal bands, a side-by-side image and a red diff heatmap. It passes at 0.90 SSIM (0.80 for real sites) and fails on console errors, failed requests, a blank page, a pasted screenshot or sideways scroll at 375px.

Can it output React + Tailwind?

Yes. Ask for React, or use it in a project that already has React; it writes components into your project and verifies them against your local dev server. One eval case covers this mode (0.9996 SSIM, an easy case because its source also used Tailwind defaults).

Limitations

  • The score is grayscale SSIM: it measures visual match, not code quality or accessibility.
  • Static frame only: hover, focus, menus and motion are inferred.
  • No font identification or asset extraction; it uses a system font of the same style and crops images from the screenshot.
  • Small eval set (8 screens) with one React + Tailwind case.
  • Needs Python 3 with Playwright, Pillow and numpy, plus Chromium, on your machine.