Convert a UI screenshot into a Pencil (.pen) prototype file. Use when you have a screenshot or mockup image and need to create a machine-readable design prototype. Analyzes layout, components, colors, typography, spacing, and icons to produce a structured .pen JSON file.
Analyze a UI screenshot and generate a Pencil (.pen) prototype file that faithfully represents the visual design.
Identify the screenshot: The user must provide a screenshot — either as a file path, clipboard image, or inline image in the conversation. If no image is provided, ask the user for one.
Identify target .pen file: Determine where to write the output:
$ARGUMENTS specifies a path, use it.pen file already exists in the project's docs/design/ directory, ask whether to append a new frame to it or create a new filedocs/design/screens.penLoad existing .pen (if appending): Read the existing file to:
variables)"reusable": true)Load references:
references/pencil-format-spec.md for the .pen format specificationreferences/tech-stack.md for design token mappings and component conventionsAnalyze the screenshot systematically:
Map observed colors to design tokens:
$bg, $bg-sidebar, $bg-card, $bg-input, $bg-muted$text-primary, $text-secondary, $text-muted$accent, $destructive, $green, $blue, $red$border, $border-lightBuild the .pen JSON:
Generate unique IDs: 5-character alphanumeric (e.g., aE3Ug). Use Python:
import random, string
''.join(random.choices(string.ascii_letters + string.digits, k=5))
Build node tree top-down:
frame with screen name, 1440×900 (desktop) or 390×844 (mobile)text, icon_font, ellipse nodesApply layout rules:
layout: "vertical" or "horizontal" for flexbox-like flowsgap based on observed spacingpadding based on observed internal spacingalignItems for cross-axis alignment"fill_container" for stretching elements, "fit_content" for auto-sizedMap icons: Match visual icons to Lucide names:
menuarrow-leftsearchsettingsplusxchevron-down, chevron-rightuser or ellipse with initialsIdentify reusable components: If a visual pattern repeats across screens (e.g., sidebar, header), mark it with "reusable": true and reference it with "type": "ref" in other frames.
version, children, variableschildren array, merge any new tokens into variables{
"version": "2.10",
"children": [
{
"type": "frame",
"id": "xxxxx",
"name": "1. Screen Name",
"width": 1440,
"height": 900,
"fill": "$bg",
"layout": "horizontal",
"children": [
/* sidebar, content, etc. */
]
}
],
"variables": {
"$bg": { "type": "color", "value": "#09090B" },
/* ... */
}
}
$variable references (no hardcoded hex except in variables)layout + gap + padding (not absolute positioning, unless needed for overlays)iconFontFamily: "lucide"fontSize, fontWeight, fill"fill_container" / "fit_content" where appropriateopenspec-to-codepencil-to-openspec