Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Agent-first screenshots — an agent drives the real app via CDP and produces clean, defect-free product screenshots (newsletters, landing pages, social, decks, PR). Dual-channel verification (DOM + pixels + vision) in a capture loop. Use for any "take/redo screenshots of the app" task.
.claude/skills/devin-axis-agent-first-screenshots/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-19 | ✗→✓ | ▲ Improved | 51% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 11% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 40% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 12% | 0% |
| case-12 | ✗→✓ | ▲ Improved | -32% | 0% |
An agent-first screenshot is produced by an agent driving the real app via CDP, gated by structural + pixel + vision verification before it ships. It turns screenshots from hand-crafted artifacts into a regenerable pipeline.
Use this for "take/redo screenshots / make marketing images" tasks. It is NOT e2e evidence — for pass/fail proof use the fraimz skill.
A shippable screenshot has ZERO obvious visual defects — the bar is not "the content is present", it is: would a human glancing at it immediately spot something broken? Overlapping or clipped text, misaligned/collapsed layout, garbled or mid-transition content, blank regions, stray modals/tooltips — any of these disqualifies the frame. Full stop.
Operate the app like a power user preparing a demo, not like a developer hacking the DOM. The app already looks great: get it into a real, settled state through the UI and capture it cleanly. Never rebuild or fake it.
"Sign in" footer link, status text) via display:none is safe. Never inject fake HTML, override flex/height/width on structural containers, add fixed-position overlays, or mutate the DOM tree — the layout engine will collapse (scroll areas shrink to 0, content disappears).
settings UI like a real user, or skip the shot and say so.
location.reload(), wait forfull render, navigate through the UI, minimal leaf cleanup, verify, capture. Never carry CSS hacks across shots.
via their close buttons (not CSS); run real multi-turn tasks so content is impressive — no toy data, no mid-stream captures.
at deviceScaleFactor: 2), then wait ~1s and re-verify — the override can trigger re-layout.
innerText existing does not mean visible; a healthy DOM rect does not mean it rendered. Every frame must pass all three before it ships:
collapsed), hero text inside the viewport rect, no unexpected modal/overlay. If it fails: reload and redo — never fix with more CSS.
DOM-derived hero rects. Calibration: for text-on-white UI, background ratio is a bad signal (85–92% background is normal). Variance is the reliable signal: content-filled region variance > ~200 (often 1000+); blank/flat region < 50. Whole-image bgRatio > 0.97 → blank frame.
defects that matter most — overlap, clipping, misalignment, double-rendering. Hand the PNG to a vision-capable model with a zero-defect rubric returning JSON:
{ any_obvious_defect: bool, // the gate — if true, REJECT overlapping_text_or_elements: bool, clipped_or_cutoff: bool, misaligned_or_broken_layout: bool, blank_or_empty_regions: bool, stray_modal_tooltip_or_panel: bool, legible: bool, polish_score: 1-5, defects: ["..."] }
If any_obvious_defect is true the frame is rejected regardless of layers 1–2. Diagnose, fix the root cause (settle the state, close the picker, reload), recapture.
Reusable scripts in this skill's directory: screenshot-verify.mjs (verify an existing PNG) and capture-verify.mjs (capture at 2x + verify regions + save only on pass); both use sharp.
| Symptom | Fix | |---------|-----| | Overlapping/clipped text (layers 1–2 pass) | Unsettled/edit-mode/wrong-width state — settle, use preview mode, gate on vision | | Blank screenshot / 32px scroll area | Structural element was CSS-hidden — reload, close panels via UI | | Overlay (picker/modal) on every shot | It was opened and never closed — Escape before capturing | | In DOM but not in pixels | Clipped/blank render — trust variance + vision, not innerText |
Injecting fake components; overriding flex properties; fixed-position overlays; carrying state across shots; verifying via innerText only; proof-frame mindset (the goal is "I want that", not "it didn't crash").
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 26,906 | 16,207 | -40% | 1 | 1 | 0% | 2,474 | 1,682 | -32% | 0 | 0 | — |
case-02 | fail→fail | 21,886 | 15,196 | -31% | 1 | 1 | 0% | 3,099 | 1,464 | -53% | 0 | 0 | — |
case-03 | fail→fail | 19,124 | 14,391 | -25% | 1 | 1 | 0% | 2,448 | 1,426 | -42% | 0 | 0 | — |
case-19 | fail→pass | 9,667 | 5,909 | -39% | 1 | 1 | 0% | 1,441 | 2,182 | +51% | 0 | 0 | — |
case-04 | pass→pass | 67,511 | 19,092 | -72% | 1 | 1 | 0% | 3,923 | 3,584 | -9% | 0 | 0 | — |
case-05 | pass→pass | 20,381 | 18,140 | -11% | 1 | 1 | 0% | 2,418 | 3,242 | +34% | 0 | 0 | — |
case-06 | pass→pass | 16,907 | 14,173 | -16% | 1 | 1 | 0% | 2,169 | 2,852 | +31% | 0 | 0 | — |
case-07 | fail→fail | 14,570 | 16,272 | +12% | 1 | 1 | 0% | 1,561 | 3,285 | +110% | 0 | 0 | — |
case-08 | fail→pass | 17,070 | 11,217 | -34% | 1 | 1 | 0% | 1,947 | 2,160 | +11% | 0 | 0 | — |
case-09 | fail→pass | 16,413 | 12,844 | -22% | 1 | 1 | 0% | 1,710 | 2,386 | +40% | 0 | 0 | — |
case-10 | fail→fail | 15,461 | 11,828 | -23% | 1 | 1 | 0% | 2,609 | 3,013 | +15% | 0 | 0 | — |
case-11 | fail→pass | 19,075 | 12,764 | -33% | 1 | 1 | 0% | 2,223 | 2,483 | +12% | 0 | 0 | — |
case-12 | fail→pass | 19,210 | 7,305 | -62% | 1 | 1 | 0% | 2,389 | 1,617 | -32% | 0 | 0 | — |
case-13 | fail→pass | 13,552 | 4,912 | -64% | 1 | 1 | 0% | 2,933 | 2,131 | -27% | 0 | 0 | — |
case-14 | pass→pass | 12,408 | 5,977 | -52% | 1 | 1 | 0% | 1,835 | 2,159 | +18% | 0 | 0 | — |
case-15 | fail→pass | 17,061 | 9,775 | -43% | 1 | 1 | 0% | 1,939 | 2,643 | +36% | 0 | 0 | — |
case-16 | fail→fail | 12,819 | 5,231 | -59% | 1 | 1 | 0% | 2,449 | 2,144 | -12% | 0 | 0 | — |
case-17 | fail→pass | 14,382 | 7,128 | -50% | 1 | 1 | 0% | 2,181 | 2,298 | +5% | 0 | 0 | — |
case-18 | fail→pass | 13,369 | 9,844 | -26% | 1 | 1 | 0% | 2,095 | 2,491 | +19% | 0 | 0 | — |
case-20 | fail→fail | 8,958 | 9,162 | +2% | 1 | 1 | 0% | 1,577 | 2,440 | +55% | 0 | 0 | — |
case-21 | fail→pass | 11,866 | 7,238 | -39% | 1 | 1 | 0% | 1,907 | 2,363 | +24% | 0 | 0 | — |
case-22 | fail→pass | 10,973 | 9,681 | -12% | 1 | 1 | 0% | 1,846 | 2,673 | +45% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 19 counted toward the lift figure. The other 3 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +50 percentage points is the difference between those two pass rates over the 19 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.