pen.dev Documentation
Complete English Guide
pen.dev is a powerful vector design tool embedded directly in your IDE: design on the canvas, implement in code. This guide is based on the official docs.pencil.dev (updated Verified August 17, 2026, including the rebrand to pen.dev and CLI/MCP terminology updates), translated section by section with original links for reference.
What is pen.dev?
Original: pen.dev Documentation (Home)
pen.dev is a powerful vector design tool integrated directly into your development environment. Unlike traditional design tools that run in a separate app or browser tab, pen.dev lives inside your IDE and works alongside your code.
Why choose pen.dev? It bridges the gap between design and development by placing both in the same environment: design components on the canvas, keep them synced with code, and let AI assistants help you maintain consistency between design and implementation, fundamentally accelerating engineering velocity.
▶ Official Intro Video (from docs home)
Installation
Original: Getting Started / Installation
pen.dev provides both an IDE extension and a standalone desktop app. Choose according to your workflow.
VS Code Extension
- Open VS Code, go to Extensions panel (Cmd/Ctrl + Shift + X)
- Search "pen.dev" and click Install
- Verify: Create a new
.penfile (e.g.,test.pen) and open it; the pen.dev icon should appear in the top-right corner.
Cursor Extension
Installation is the same as VS Code: search "pen.dev" in the Extensions panel, install, then create a .pen file to verify.
Common Issues
- Extension fails to connect: Ensure Claude Code is logged in (run
claude), activation is complete, and the pen.dev MCP server is connected. - Can't see the prompt input box: Check activation/login status, restart Cursor, or reinstall the extension if it persists.
- Prompt says "You need Cursor Pro": This may relate to Cursor's subscription/tool limits. Check your subscription status.
Desktop App
macOS
- Download the latest
.dmgfrom the official site or release page, drag it into Applications, and launch it. - If you encounter a security prompt on first launch, right-click → Open. Complete activation, and log in to Claude Code to use AI features.
Linux
# Example for .deb package
sudo dpkg -i pencil-*.deb
# Example for .AppImage
chmod +x pencil-*.AppImage
./pencil-*.AppImage
Windows
pen.dev runs on Windows. Windows users can also use the VS Code or Cursor extension directly. Installation steps are identical to macOS/Linux.
Claude Code CLI
pen.dev's AI features rely on an installed and authenticated Claude Code:
# Install Claude Code CLI
npm install -g @anthropic-ai/claude-code-cli
# Or use the official install script
curl https://claude.ai/cli/install.sh | sh
# Login (follow the browser authentication flow)
claude
# Verify login status
claude --version
@anthropic-ai/claude-code, and the install script is curl -fsSL https://claude.ai/install.sh | bash. Refer to the official Claude Code docs. For more details, see the Installation section of the "Claude Code Guide" in this repo.MCP Server
The pen.dev MCP (Model Context Protocol) server will automatically start and run locally when you use pen.dev, providing AI assistants with tools to read and write .pen files. No extra configuration is needed for basic use.
- Verify in Cursor: Go to Settings → Tools & MCP, confirm pen.dev appears in the list.
- Verify in Codex CLI: Run pen.dev first, then execute
/mcpin Codex; pen.dev should appear in the MCP list.
After Installation
- Complete Activation — Use your email to activate pen.dev
- Log into Claude Code — Required for AI features
- Open Welcome File — Right-click on canvas → Open Welcome File
- Create your first design — See .pen Files
Updating pen.dev
- VS Code / Cursor Extension: Updates automatically by default. To update manually, find pen.dev in the Extensions panel and click Update.
- Desktop App: Prompts when a new version is available. Download and install the latest version from the official site.
Installation Troubleshooting
- Extension installed but not connecting: Ensure Claude Code is logged in → Complete activation → Restart IDE.
- Not receiving activation email: Check spam folder; try a different email; reinstall the extension.
- "Invalid API key" or "Please run /login": Run
claudeto complete authentication. Ensure there are no conflicting auth configs (like environment variable keys or custom Providers).
Authentication
Original: Getting Started / Authentication
pen.dev requires two layers of identity verification: Activation (using pen.dev itself) + Claude Code Authentication (to use AI features).
pen.dev Activation
- On first launch, follow the prompt to enter your email
- Check your email to get the activation code
- Enter the activation code in pen.dev to complete activation
Activation Common Issues
- Not receiving activation email: Check your spam folder; try another email; wait a few minutes (emails can be delayed).
- "Invite for your email address was not found. Please join the waitlist.": Try reinstalling the Cursor/VS Code extension, contact support if it persists.
- Repeatedly asked to activate: Known issue in some versions—restart your IDE, reinstall the extension if it persists.
- Activation stuck during migration: Reinstall the extension, clear extension data, and try again.
Claude Code Authentication
Logging in via CLI is recommended:
# Launch Claude Code, follow browser auth flow
claude
This flow opens the browser → log in with Anthropic account → save credentials locally. Verification: run claude --version, or confirm there's no "Claude Code not connected" warning in pen.dev and the AI panel (Cmd/Ctrl + K) works normally.
Common Authentication Issues
"Claude Code isn't connected / not logged in"
Open the terminal in your project directory → run claude to complete auth → return to pen.dev and try again.
"Invalid API key" or "Please run /login"
Cause: Authentication incomplete; conflicting auth methods (Console login + env var key + custom Provider); expired credentials.
Solution: Run claude to complete auth; if using CLI auth, remove the ANTHROPIC_API_KEY environment variable, clear unneeded custom Provider configurations; do a clean fresh login if necessary.
"Claude CLI works, but pen.dev still shows not logged in"
Usually caused by auth conflicts from third-party/custom Providers or the extension failing to detect the CLI auth: keep a clean Claude Code login session (no custom Provider), restart the IDE after auth, and check for conflicting environment variables.
Authentication Methods Comparison
| Method | Description | Recommendation |
|---|---|---|
| Claude CLI (Recommended) | Run claude in terminal, browser login, all features automatically available | Simplest and most reliable |
| API Key | Set ANTHROPIC_API_KEY environment variable | May conflict with CLI auth, generally not recommended |
A Complete Viable Workflow
- Install pen.dev (extension or desktop app)
- Complete pen.dev activation (email verification code)
- Install Claude Code CLI
- Authenticate Claude Code (
claudecommand) - Create a
.penfile in your project - Start working — pen.dev and AI features should both be ready
Permissions and Access
- "pen.dev / Claude cannot access other folders": Mostly due to folder permissions or system security settings—accept the authorization prompt when it appears; update folder permissions in system settings; run the IDE/pen.dev with appropriate permissions.
- "Never saw the permission prompt": Try executing the action in a standalone Claude Code session outside pen.dev; check system notification settings and IDE permissions.
Security and Privacy
- The pen.dev MCP server runs locally on your machine; aside from using AI features (prompts sent to Claude), design data is not sent to remote servers. The repository is currently private.
- You can view MCP tool definitions in your IDE: Settings → Tools & MCP in Cursor; check MCP configuration in VS Code. Tool definitions show what the AI can do to your designs.
Still Have Issues?
If authentication issues remain unresolved:
- Consult the Troubleshooting doc
- Confirm you are using the latest versions of pen.dev and Claude Code
- Try completely reinstalling both pen.dev and Claude Code CLI
AI Integration
Original: Getting Started / AI Integration
pen.dev deeply integrates with AI assistants via MCP (Model Context Protocol) to enable powerful design automation workflows.
Supported AI Assistants
Claude Code (CLI and IDE), Claude Desktop, Cursor, Windsurf IDE (Codeium), Codex CLI (OpenAI), Antigravity IDE, OpenCode CLI.
What is MCP and How it Works
MCP is a protocol that gives AI assistants "tools to operate your design files"—think of it as an API that lets AI read and write .pen files programmatically.
- pen.dev MCP server runs locally — Design operations don't rely on the cloud
- AI assistants connect via MCP — They can connect as soon as pen.dev is running
- AI calls tools — To read, modify, and generate designs
- You stay in control — AI proposes, you approve
Using in Claude Code
Prerequisites: Install Claude Code CLI → run claude to authenticate → keep pen.dev running → open a .pen file.
▶ Official Demo: Using pen.dev in Antigravity / VS Code with the Claude Code panel
Basic Workflow
- Press Cmd/Ctrl + K to open the AI prompt panel
- Describe your request in natural language, for example: "Create a login form with email and password" or "Add a navbar to this page"
- AI uses MCP tools to modify your
.penfile - Changes reflect instantly on the canvas
Prompt Examples
| Scenario | Example Prompt |
|---|---|
| Create Design | "Design a dashboard with a sidebar and main content area" / "Create a three-tier pricing table" / "Add a Hero section with title and CTA button" |
| Modify Design | "Change all primary buttons to blue" / "Make the sidebar narrower" / "Add spacing between these elements" |
| Design System | "Create a button component with variants" / "Generate a color palette based on #3b82f6" / "Build a typography scale" |
| Code Sync | "Generate React code for this component" / "Import Header from my codebase" / "Generate Tailwind config from these variables" |
Using in Cursor
- Install the pen.dev extension in Cursor and complete activation
- Authenticate Claude Code
- Verify MCP connection: Settings → Tools & MCP
▶ Official Demo: Using pen.dev Extension in Cursor
- Inline Editing: Select elements in pen.dev, modify using Cursor's AI chat, and changes are written directly to the
.penfile. - Codebase Awareness: Cursor can see both code and design simultaneously; you can ask it to sync components between the two and keep them automatically consistent.
Using in Codex CLI
- Run pen.dev first (desktop app or IDE extension)
- Open Codex in the terminal, execute
/mcpto verify connection - pen.dev should appear in the MCP server list
You can give design commands directly in the terminal, offering the benefits of a command-line workflow, scriptable design generation, and integration with build tools.
config.toml. Officially confirmed and under investigation—please back up your config before first use.Available MCP Tools
As of 2026-07-27, the official documentation consolidated the toolset from 5-6 fine-grained tools into 5 (execute / get state / screenshot / export / load guidelines). For a complete old-vs-new comparison and a warning about your local environment potentially not being updated yet, see "pen.dev CLI" Chapter · Supported MCP Tools.
| Category | Tool | Capability |
|---|---|---|
| Design | execute | Create/modify/manipulate design elements: Insert/Copy/Update/Replace/Move/Delete operations; manage variables and themes via GetVariables/SetVariables sub-operations; generate and place images |
| Analysis | get_screenshot | Render design previews, verify visual output, before/after comparisons |
| Analysis | get_app_state | Current editor context, selection info, active file |
Advanced Workflows
- Automated Design Generation: Specify style ("Create a dashboard following Material Design principles"); batch operations ("Generate 5 variants for this button component", "Design a full landing page with Hero, features, pricing, and footer").
- Design System Management: Consistency constraints ("Ensure all buttons use the primary color variable", "Apply an 8px spacing grid to all elements"); component libraries ("Create a button component with all variants", "Generate text/dropdown/checkbox/radio form input components").
- Code-Design Linkage: Import existing app ("Recreate all components under src/components in pen.dev", "Import design system from Tailwind config"); sync changes ("Keep all React components consistent with pen.dev design", "Sync font variables between CSS and pen.dev").
Official Best Practices
- Be Specific: ❌ "Make it look better" → ✅ "Increase button padding to 16px and change color to blue"
- Give Context: ❌ "Add a form" → ✅ "Add a login form: email, password, remember me checkbox, and submit button"
- Reference Design System: "Use our existing button component", "Follow the spacing scale in variables", "Match the style of the Header component"
- Iterative Design: Scaffold first ("Create dashboard layout") → Refine ("Add sidebar with nav items") → Polish ("Add hover states to nav items") → Finalize ("Align spacing to 8px grid")
- Verification: Visually check the canvas after AI modifications → verify structure in layers panel → ask AI for screenshots to verify complex layouts if necessary
AI Integration Troubleshooting
- Connection Issues: "Claude Code not connected" → run
claudeto log in, restart pen.dev; MCP server not appearing → confirm pen.dev is running, check IDE's MCP settings, restart both pen.dev and the AI assistant. - Permissions Issues: Accept permission prompts; check system folder permissions; if prompts don't appear, try executing in a standalone Claude Code session.
- Output Issues: "Invalid API key" → Re-authenticate, clear conflicting env vars; AI makes unexpected changes → make prompts more specific, ask for explanation before execution, use version control to rollback if needed.
Example Session
# 1. Launch pen.dev and Claude Code
claude
# 2. Open design.pen in IDE; press Cmd+K to start designing
User: "Create a modern landing page Hero section"
AI: [Generates Hero with main title, subtitle, CTA button]
User: "Add a three-column features section below it"
AI: [Adds features section below Hero]
User: "Use our primary color variable for the CTA button"
AI: [Changes button to reference color variable]
User: "Generate React code for the entire page"
AI: [Exports as React + Tailwind components]
# 3. Review, tweak, and commit to Git
git add design.pen src/pages/landing.tsx
git commit -m "Add landing page design and implementation"
.pen Files
Original: Core Concepts / .pen Files
.pen is pen.dev's design file format, featuring three key characteristics:
- JSON-based — Structured, human-readable data format
- Version-control friendly — Manage with Git just like code files
- Portable — Shareable across teams and platforms
| Action | Method |
|---|---|
| Create | IDE: create a file with a .pen extension; Desktop: File → New or Cmd/Ctrl + N |
| Open | Double-click a .pen file, or open it in the IDE like a normal file; pen.dev activates automatically |
| Save | Cmd/Ctrl + S; Note: no auto-save yet, save frequently! Commit via Git to keep history |
.pen files and code in the same project workspace; use semantic names like dashboard.pen, components.pen.Want to read/write .pen files programmatically? See The .pen Format (Developers).
Design as Code
Original: Core Concepts / Design as Code
Because .pen is a text format, design files can be collaborated on and version-controlled exactly like code—this is the fundamental philosophy separating pen.dev from cloud design tools like Figma.
- Same Repository —
.penand code live in the same Git repo, sharing one version history; - Diffable — Design changes appear as text diffs in PRs, so you review design changes just like code;
- Branchable & Mergeable — Design follows feature branches, merging and rolling back together so design and code never drift apart;
- Single Source of Truth — No more "one version in Figma, another in code".
pen.dev Interface
Original: Core Concepts / pen.dev Interface
Infinite Canvas
The canvas provides a borderless workspace with interaction habits identical to professional design tools. Hold space and drag to pan; use your trackpad or hold Cmd/Ctrl and scroll to zoom.
| Shortcut | Action |
|---|---|
| Space + Drag | Pan canvas |
| Shift + Scroll | Horizontal pan |
| 0 | Zoom to 100% |
| 1 | Zoom to fit all |
Frames
Frames are containers for your design: they group related elements and define screen boundaries. Use Cmd/Ctrl + Option/Alt + G to apply Flex layout to a selection.
Selection & Highlights
Click or box-select canvas elements. The bounding box color indicates the element type:
- Blue — Regular elements: Frames, shapes, text
- Magenta — Component origin: The single source of truth; edits here apply to all instances automatically
- Violet — Component instance
| Shortcut | Action |
|---|---|
| Click | Select element |
| Cmd/Ctrl + Click | Direct select (deepest element) |
| Shift + Click | Add to selection |
| Cmd/Ctrl + A | Select all |
Layers Panel
Located on the left, it lists all elements on the canvas, letting you clearly browse, edit, and organize the design hierarchy in complex nested structures. Double-click a layer to rename it; click the "Layers" icon to toggle the panel.
Properties Panel
Appears on the right when one or more elements are selected. You can view and edit alignment, layout, appearance, fill, stroke, effects, etc. Supports exporting the selection as PNG / JPEG / WEBP / PDF; click the top-right icon to minimize.
AI Chat
pen.dev's AI chat is the gateway to "vibe-designing": you can have it design from scratch, or edit existing designs on the canvas. The chat panel is built into the desktop app; when using IDE extensions, you collaborate via the IDE's native AI chat.
- Selections on the canvas are automatically added to context.
- Click "New Agent" to start a new session and clear the context window.
Undo / Redo
Cmd/Ctrl + Z to undo, Cmd/Ctrl + Shift + Z to redo. Note: undo/redo capabilities might be more limited than typical design editors.
Variables
Original: Core Concepts / Variables
pen.dev variables are like CSS custom properties or design tokens: HEX colors, spacing/radius/size values, font family strings—define once, reference anywhere. Modify a variable in the variables panel, and all references update instantly.
Three Ways to Create Variables
- Manual Creation — Click the variables icon in the toolbar to open the panel, define variables, and set values for different themes.
- Import from CSS — Have an AI agent create variables based on your
globals.css, automatically extracting colors, spacing, and fonts. - Import from Figma — Paste a screenshot of your variables table and ask AI to recreate it in pen.dev; or simply copy single token values from Figma.
Using Variables
- Apply to Elements — Use variable references instead of hardcoded values; change a variable once, and all elements referencing it update automatically.
- Theming — Add a new column in the variables panel to create light/dark or other themes; switch themes in the properties panel to preview your design instantly.
Code Synchronization
Variables can be kept in sync between pen.dev and your codebase: ask AI to update CSS variables based on a pen.dev file, or import CSS changes back into pen.dev—this is the foundation of a two-way design-to-code workflow.
Components
Original: Core Concepts / Components
Why Use Components
Components ensure design consistency: edit the main component once, and all instances update automatically. Components are the building blocks of a design system.
Creating Components
Any standard design element (Frame, shape, text) can be converted into a reusable component:
- Select an element
- Press Cmd/Ctrl + Option/Alt + K, or click "Create component" at the top of the properties panel
- The element becomes the component origin, showing a magenta bounding box when selected
More complex structures can be turned into nested components.
Using Components
Simply copy the component origin on the canvas to create instances; instances show a violet bounding box when selected. Click the "Go to component" button in the properties panel to quickly jump back to the origin.
Slots
Original: Core Concepts / Slots
Slots are designated drop zones inside components, used to define flexible, customizable content areas within a component.
Creating Slots
- Create a Frame and turn it into a component (Cmd/Ctrl + Option/Alt + K or "Create component" in the properties panel)
- Style it as needed
- Click the "Make a slot" button at the top of the properties panel
Suggested Slot Components
Other components within the same .pen file can be marked as "suggested components" for a slot. For example, a table component's slot could suggest a table-row as its expected content—this provides guidance to both human and AI designers on "what should go in this slot".
- Select a layer with a slot inside a component origin
- Click the
+button on the "Slots" row at the top of the properties panel - Select the component(s) to set as suggested
Dropping Elements into Slots
After creating a component instance, drag or copy-paste elements into the slot to populate the content.
Code on Canvas
Original: Core Concepts / Code on Canvas
pen.dev brings code directly to the canvas via Script nodes: place a node, point it to a .js file, and the script's output renders as nested layers—pie charts, grids, decorative patterns, anything that can be described with code. It's perfect for structures that are tedious to build manually: data-driven designs, repeated elements with variations, or scenarios where you want to tweak parameters interactively with a few "knobs".
Quick Start
- Create a Script node: Open the shapes dropdown in the toolbar → select Script (
</>icon) → click on the canvas to place a 200×200 node (shows a green "No script file selected" placeholder until linked) - Link a .js file: Enter the path in the script field in the properties panel; paths are resolved relative to the
.penfile, so just writechart.jsfor a file in the same folder - Tweak parameters on canvas: Drag handles to resize, and the script reruns and reflows in real-time; every
@inputgenerates a control in the properties panel; save the .js file and the canvas updates instantly
You don't have to write scripts manually. Two shortcuts: grab ready-made examples (charts, grids, patterns, etc.) maintained by the official team at highagency/pencil-scripts; or open the AI panel, describe your needs, and AI will create the .js file and link it to the selected Script node.
Minimal Example
/**
* @schema 2.11
*
* @input columns: number(min=1) = 3
* @input color: color = #3B82F6
*/
const cols = Math.floor(pencil.input.columns);
const cellW = pencil.width / cols;
const nodes = [];
for (let c = 0; c < cols; c++) {
nodes.push({
type: "rectangle",
x: c * cellW,
y: 0,
width: cellW - 4,
height: pencil.height,
fill: pencil.input.color,
});
}
return nodes;
Official Docs Code on Canvas
Key Mechanisms
- The
.jsfile is independent of the.penfile; the node only stores the path. Multiple nodes can point to the same file, each maintaining its own size and input values. - Inputs are declared with
@inputcomments at the top of the file; the properties panel updates automatically if you rename or remove them. - The script must return an array of nodes. Each object follows the .pen format and is inserted as a child of the Script node.
- The output is derived state: it reruns and re-renders every time, and doesn't enter the undo history. To manually edit the generated content, click "Convert to layers" at the bottom of the properties panel to turn it into a snapshot of regular layers.
- Scripts run in a sandbox: no DOM, network, or filesystem access. They must execute synchronously (no async / setTimeout).
Math.random()is deterministic (re-seeded on every run): identical inputs guarantee identical outputs.- Errors and missing files are displayed directly on the node with the error line highlighted, no need to open a console.
API Reference
File Header
/**
* @schema <version> // Required, current schema version is 2.14
* @input <name>: <type>[(<args>)] [= <default>] // 0 or more
*/
Input Types
| Type | Example | Description |
|---|---|---|
number | @input size: number(min=0, max=100) = 10 | Optional min/max constraints, clamps value before running |
string | @input label: string = "Hello" | Renders as a multi-line text input in the panel |
boolean | @input filled: boolean = true | Renders as a checkbox |
color | @input fill: color = #3B82F6 | HEX literal or quoted string |
enum | @input layout: enum("grid", "stack") = "grid" | Renders as a dropdown menu |
ref | @input target: ref | Reference to a reusable component, pickable from a thumbnail grid |
pencil Global Object
| Field | Type | Description |
|---|---|---|
pencil.width | number | Current width of the Script node |
pencil.height | number | Current height of the Script node |
pencil.input.<name> | Matches @input type | Current value of the input (clamped and validated) |
$primary), the script will automatically respond to theme switches.Design Libraries
Original: Core Concepts / Design Libraries
Design libraries are collections of components that can be imported by other .pen files. Modifying components in a library file syncs the changes to everywhere they are used.
Creating a Design Library
- Create a new .pen file and fill it with components
- Click the "Libraries" icon in the left layers panel
- Click "Turn this file into a library" at the bottom
.lib.pen extension. Once a file is marked as a design library, it cannot be undone.Importing a Library
Layers Panel → "Libraries" icon → Select the library to import (you can also pick from default libraries).
Using Library Assets
Layers Panel → "Assets" icon → Scroll through the grid or search by name → Drag or click to place them on the canvas.
Import & Export
Original: Core Concepts / Import & Export
Import
| Source | Method |
|---|---|
| Full Figma File | Toolbar: click the arrow below the Rectangle icon → Import Figma; Desktop app: File → Import Image/SVG/Figma... |
| Single Figma Layer | Copy the element in Figma, paste directly onto pen.dev canvas (⚠️ Image elements aren't supported via copy/paste—import the full file or add images manually) |
| Images | Drag & drop / Copy-paste / Toolbar Import Image or SVG... / File menu in Desktop app; supports PNG, JPEG, SVG |
| Icons | Built-in libraries: Material Symbols (Outlined/Rounded/Sharp), Lucide, Feather, Phosphor; you can also import custom SVG icons just like images |
Export
- Design to Code: Press Cmd/Ctrl + K to open AI chat and ask it to generate code based on your design.
- Export Single Element: Select element → Choose size and format at the bottom of the properties panel (PNG / JPEG / WEBP / PDF) → Click Export layer and choose where to save.
Keyboard Shortcuts
Original: Core Concepts / Keyboard Shortcuts
AI Chat
| Shortcut | Action |
|---|---|
| Cmd/Ctrl + K | Toggle AI chat |
| Cmd/Ctrl + T | New Agent tab |
| Ctrl + Tab / Ctrl + Shift + Tab | Next / Previous chat tab |
| ↑ / ↓ | Prompt history |
Tools
| Shortcut | Tool |
|---|---|
| V | Move |
| H | Hand |
| R | Rectangle |
| O | Ellipse |
| A / F | Frame |
| T | Text |
| N | Note |
Editing
| Shortcut | Action |
|---|---|
| Cmd/Ctrl + C / V / X | Copy / Paste / Cut |
| Cmd/Ctrl + D | Duplicate |
| Delete/Backspace | Delete selection |
| Arrow keys / Shift + Arrows | Move 1px / 10px; swap order in Flex layout |
| Cmd/Ctrl + G / Cmd/Ctrl + Shift + G | Group / Ungroup |
| Cmd/Ctrl + Option/Alt + G | Apply Flex layout to selection |
| Cmd/Ctrl + [ / ] | Send backward / Bring forward |
| [ / ] | Send to back / Bring to front |
| Cmd/Ctrl + Z / Cmd/Ctrl + Shift + Z | Undo / Redo |
Selection
| Shortcut | Action |
|---|---|
| Cmd/Ctrl + A | Select all |
| Cmd/Ctrl + Click | Direct select (deepest element under cursor) |
| Shift + Click | Add to selection |
| Shift + Enter | Select parent of current element |
| Enter | Select children of current element |
| Esc | Deselect |
Components
| Shortcut | Action |
|---|---|
| Cmd/Ctrl + Option/Alt + K | Element → Component, or Component → Detach to regular elements |
| Cmd/Ctrl + Option/Alt + X | Detach instance from component |
Canvas Navigation
| Shortcut | Action |
|---|---|
| Cmd/Ctrl + Scroll | Zoom |
| Space + Drag / Middle Click | Pan canvas |
| Shift + Scroll | Horizontal pan |
| = / - | Zoom in / Zoom out |
| 0 / 1 / 2 | 100% / Zoom to fit all / Zoom to fit selection |
Canvas Settings & File Ops
| Shortcut | Action |
|---|---|
| Cmd/Ctrl + ' | Toggle pixel grid |
| Cmd/Ctrl + Shift + ' | Toggle snap to pixel grid |
| Cmd/Ctrl + S / N / O | Save / New / Open file |
Design ↔ Code
Original: Design and Code / Design ↔ Code
pen.dev supports a bidirectional workflow between design and code: Design → Code (generate components from pen.dev design), Code → Design (import existing code into pen.dev).
Design → Code
- Design screens, layouts, or individual UI components on the pen.dev canvas
- Save the
.penfile in your project workspace - Press Cmd/Ctrl + K to open AI chat
- Ask pen.dev to generate the code
| Scenario | Example Prompt |
|---|---|
| Component Generation | "Create a React component for this button" / "Generate TypeScript types for this form" / "Export this card as a reusable component" |
| Full Page Generation | "Generate a Next.js page from this design" / "Create a landing page component with Tailwind CSS" / "Export this dashboard as a React component" |
| Specific Libraries | "Generate code using shadcn/ui components" / "Implement this form with React Hook Form" / "Use Lucide icons instead of Material Icons" |
Code → Design
Existing components in your codebase can be visually reconstructed on the pen.dev canvas. Prerequisite: The .pen file and code must be in the same workspace, so the AI agent can access both.
Recreate the Button component from src/components/Button.tsx
Import the LoginForm from my codebase into this design
Add the Header component from src/layouts/Header.tsx
What gets imported: Component structure and hierarchy, layout and positioning, styles (colors, typography, spacing).
Bidirectional Sync
The most powerful workflow combines both directions:
- Start from Code — Import existing components into pen.dev
- Make visual improvements in pen.dev
- Ask AI to write changes back to the code
- Iterate
Syncing Variables & Design Tokens
- CSS → pen.dev: "Create pen.dev variables from my globals.css" / "Import design tokens from src/styles/tokens.css"
- pen.dev → CSS: "Update globals.css with these pen.dev variables" / "Sync these design tokens to my CSS"
Best Practices
File Organization: Put .pen in the repo
my-project/
├── src/
│ ├── components/
│ └── styles/
├── design.pen ← Design file
└── package.json
Benefits: AI agents can see both design and code at the same time; version control tracks both together; synchronized maintenance is easier.
Workflow Suggestions
- New Features: Design in pen.dev first → Generate initial code → Refine implementation → Write back to design when needed.
- Modifying Existing Features: Import component to pen.dev → Modify design → Sync back to code.
- Design System Maintenance: Define variables in pen.dev → Sync to CSS → Design and code share variables → Update in one place, effective everywhere.
Common Tech Stacks
pen.dev is framework-agnostic, you can ask AI to generate code for any tech stack. Common choices: Frameworks (React / Next.js / Vue / Svelte / Vanilla HTML+CSS), Styling (Tailwind CSS / CSS Modules / Styled Components / Vanilla CSS), Component Libraries (shadcn/ui / Radix UI / Chakra UI / Material UI / Custom components). Specify your tech stack in the prompt, e.g., "Generate Next.js 14 code with Tailwind CSS".
Icon Libraries
pen.dev has built-in support for Material Symbols (Outlined/Rounded/Sharp), Lucide, Feather, Phosphor; custom SVG icons can be imported as images. Specify your preferred library in the prompt when generating code (Lucide, Heroicons, FontAwesome, React Icons, etc.), e.g., "Generate this design using Lucide icons".
Troubleshooting
Original: Troubleshooting
Installation & Setup
- Extension installed but not working (no icon / can't open .pen): Confirm Claude Code is logged in (
claude) → Complete email activation → Check MCP is connected (Settings → MCP) → Create a new .pen file and try to open it → Restart IDE → Reinstall if it still fails. - Can't see pen.dev icon: Create and open a
.penfile; Check extension version; Search "pen.dev" in Command Palette; Ensure extension is enabled.
Authentication & Activation
- Not receiving activation email: Check spam folder → Wait a few minutes → Try another email → Reinstall extension if stuck.
- "Invite not found": Reinstall extension and reactivate; contact support if it persists.
- Repeatedly asked to activate: Restart IDE, reactivate once, reinstall if necessary.
- Claude Code connection issues: See the full troubleshooting steps in the Authentication section.
IDE Related
- Cursor: Prompt box doesn't appear → Check activation/login, restart, verify MCP, reinstall; "You need Cursor Pro" → Check subscription, or use basic features first.
- VS Code: Extension doesn't activate → Make sure a .pen file is open, check extension enabled status, check developer tools console for errors, reinstall.
Welcome File & New Projects
- Didn't get the welcome file: Right-click anywhere on the canvas → Open Welcome File (might open in a separate window).
- Recommended setup for new projects with pen.dev: Create
design.penin the workspace → Open in IDE → Activate pen.dev → Keep .pen in the same repo as code, so AI can see both.
Canvas and Interface
- Nested elements hard to select: Cmd/Ctrl + Click to direct select deepest layer; Shift + Enter to select parent; or just use the layers panel.
- Bounding box colors: Blue = regular element; Magenta/Violet = reusable component and its instances.
- No magenta box after converting to component: Deselect and reselect to make it appear.
Import & Export
- macOS image import fails: The File menu method might fail—use drag and drop instead, it's stable across platforms.
- Figma images won't paste over: Known limitation, copy-paste doesn't support images—use SVG or re-import separately.
- Export to Claude Code fails ("Process exited with code 1"): Check Claude Code auth and permissions; try exporting in an independent Claude Code session; check env vars.
- Export result differs from canvas: Known issue—take a screenshot for record, try re-exporting or tweaking the design, and report the specific case to the official team.
MCP & AI
- Is MCP local or remote? Runs locally, no cloud dependency for design operations. To verify: in Cursor check Settings → Tools & MCP; in Codex run
/mcp. - Codex config.toml got modified: Back it up before first use; officially under investigation.
- AI can't access folder / permission prompt missing: Accept permission prompts, check system permissions, or try a separate session.
Saving & Version Control
- No auto-save (planned): Press Cmd/Ctrl + S frequently, use Git commits for version history.
- Limited undo/redo: Save/commit before major changes; make small iterative edits; use Git rollback when needed.
- No real-time collaboration: Currently collaborate via Git—branch, pull → edit → commit → push → PR, and review designs via PRs.
Platform Specifics
- Linux: Desktop app available; Wayland/Hyprland might have UI issues, X11 is more stable, fallback to IDE extension if necessary.
- Windows: If desktop app is unavailable, use VS Code / Cursor extensions, functionality is identical.
Getting More Help
If your issue persists, follow these steps in order:
- Review docs: Installation, Authentication, AI Integration
- Update all components to the latest version: pen.dev, Claude Code CLI, IDE
- Try a clean reinstall: uninstall extension → clear extension data → reinstall
- When contacting support, include: your platform (macOS/Windows/Linux), pen.dev version, IDE and version, exact error message, and repro steps
Reporting Bugs
When reporting issues, please provide:
- Environment: OS & version, IDE (VS Code/Cursor/Desktop) & version, pen.dev version, Claude Code CLI version
- Details: What you tried to do, what actually happened, exact error message, repro steps
- Helpful attachments: Screenshots, console logs (if any), minimal
.penfile to reproduce the issue
Common Errors Cheat Sheet
| Error | Possible Cause | Solution |
|---|---|---|
| "Claude Code not connected" | Not logged in | Run claude |
| "Invalid API key" | Auth conflict | Clear env vars and re-authenticate |
| "Process exited with code 1" | Export/auth issue | Check Claude Code config |
| "Need Cursor Pro" | Plan limit | Check Cursor subscription |
| "Invite not found" | Activation issue | Reinstall extension |
| "Can't access folder" | Permissions | Update folder permissions |
Prevention Checklist
- Save often (no auto-save yet)
- Keep Claude Code authentication valid
- Keep .pen files inside your project workspace
- Commit to Git regularly
- Keep pen.dev and Claude Code updated
- Accept permission prompts
- Use supported workflows (do not manually edit .pen files)
The .pen Format
Original: For Developers / The .pen Format
Overview
- A .pen file is a JSON structure describing an object tree (similar to HTML or SVG).
- Each object is a graphical entity on an infinite 2D canvas.
- Objects must have a document-unique
id, and atype(such asrectangle,frame,text,script, etc.).
Layout
- Top-level objects are placed on the infinite canvas, with their top-left corner described by
x,y; nested objects are positioned relative to their parent's top-left corner. - Parent objects can take over the sizing and positioning of children in a Flexbox style via properties like
layout,justifyContent,alignItems. - Child objects can choose to fill the parent (
fill_container) or have fixed dimensions; parent objects can choose to fit content (fit_content) or have fixed dimensions.
Graphical Appearance
- Controlled by
fill,stroke, andeffect. - Fills can be solid colors, gradients (linear/radial/angular), images, mesh gradients, or even WebGL shaders; an object can stack multiple fills, drawn in document order.
- There is only one stroke, but the stroke can have multiple fills; effects (blur, background blur, inner/drop shadow) can be stacked and applied in order.
Components & Instances
The key difference between .pen and HTML/SVG: Fragments of the object tree in the document can be reused elsewhere—this is the component system.
Defining a Component: reusable: true
{
"id": "foo",
"type": "rectangle",
"reusable": true, // ← This object is now a reusable component
"x": 0, "y": 0, "width": 100, "height": 100,
"fill": "#FF0000"
}
Creating an Instance: type: "ref"
{
"id": "bar",
"type": "ref",
"ref": "foo", // ← An instance of foo (also a 100×100 red square)
"x": 120, "y": 0
}
Property Overrides
Instances can override properties defined in the component—in the example below, baz is still an instance of foo, but overwrites the inherited fill to blue:
{
"id": "baz",
"type": "ref",
"ref": "foo",
"x": 240, "y": 0,
"fill": "#0000FF" // ← A 100×100 blue square
}
Nested Customization: descendants
Instances copy everything under the component root; via the descendants mapping you can customize any descendant node inside (the key is the descendant id, for descendants inside nested instances use the instanceId/descendantId path):
{
"id": "red-round-button",
"type": "ref",
"ref": "round-button",
"fill": "#FF0000",
"descendants": {
"label": { // ← Customize the node with id 'label' inside the component
"text": "Cancel",
"fill": "#FFFFFF"
}
}
}
Rules: An entry in descendants without a type indicates a property override; with a type indicates full node replacement. You can also keep the node itself and only replace its children (suitable for container components like panels, cards, sidebars). Components can be composed of instances of other components.
Slots (Format Level)
When a Frame inside a component exists solely to "have its children replaced", use the slot property, where the array value is a list of suggested component ids to drop in:
{
"id": "content",
"type": "frame",
"slot": ["round-button", "icon-button"] // ← Suggested components to drop in
}
Variables & Themes
Common colors and values (padding, radius, opacity, etc.) can be extracted into document-level variables, referenced with a $ prefix:
{
"variables": {
"color.background": { "type": "color", "value": "#FFFFFF" },
"text.title": { "type": "number", "value": 72 }
},
"children": [
{ "id": "page", "type": "frame", "fill": "$color.background",
"children": [
{ "id": "title", "type": "text", "fontSize": "$text.title", "content": "Welcome!" }
]
}
]
}
Theming System: Variables can have multiple values, each bound to a set of theme conditions; when evaluating, the value of the last matching condition is used.
Beyond top-level properties (version, theme, variables), all other entities are Nodes, including frame, group, text, path, and vector. Nodes encapsulate basic geometry (x, y, width, height), styling (fills, strokes, effects, opacity), layout attributes, custom properties (props supporting color, boolean, number, string), and children. For the complete TypeScript Schema (all properties, fills, effects, and layout values), refer to the official documentation.
pen.dev CLI
Original: For Developers / pen.dev CLI
pen (was pencil), the npm package is @pen.dev/cli (was @pencil.dev/cli), and environment variables are PEN_CLI_KEY/PEN_API_BASE (were PENCIL_CLI_KEY/PENCIL_API_BASE). The following section has been updated to reflect the new version; the session file path ~/.pencil/session-cli.json was not changed by the official team and remains as is.The pen.dev CLI is a standalone command-line tool that allows you to create and edit .pen files in the terminal. It runs the exact same editor engine as the desktop app / IDE extensions, fully headless with no GUI required. It can be used to run AI agents with prompts, invoke MCP tools directly in an interactive shell, batch process multiple designs, or export PNG/JPEG/WEBP/PDF files.
Installation
npm install -g @pen.dev/cli
# Verify installation (requires Node.js 18+)
pen version
Authentication
| Method | Description |
|---|---|
pen login | Interactive login (email+password or email+OTP); session token is stored in ~/.pencil/session-cli.json |
PEN_CLI_KEY | CLI Key for CI/CD, created in the Developer Keys section of your organization settings in the pen.dev web app; always takes precedence over the stored session token |
pen status | Shows current auth method, validates the session with the backend, and displays account info |
Quick Start
# Login
pen login
# Create a design from scratch
pen --out design.pen --prompt "Create a login page with email and password fields"
# Modify an existing design
pen --in existing.pen --out modified.pen --prompt "Add a blue submit button"
# Export to PNG
pen --in design.pen --export design.png
# Interactive shell
pen interactive -o design.pen
# List available models
pen --list-models
Agent Mode Options
| Option | Description |
|---|---|
--in, -i <path> | Input .pen file (optional, starts with an empty canvas if omitted) |
--out, -o <path> | Output .pen file path (required unless using --export) |
--prompt, -p <text> | Prompt for the AI agent |
--model, -m <id> | Model to use (defaults to claude-opus-4-6) |
--custom, -c | Use a custom Claude model config (e.g., AWS Bedrock, Vertex AI) |
--tasks, -t <path> | Batch tasks JSON file |
--workspace, -w <path> | Workspace directory for the agent |
--export, -e <path> / --export-scale <n> / --export-type <type> | Export the final result image; scale multiplier (default 1); format png/jpeg/webp/pdf (default png) |
--list-models / --verbose-mcp / --help | List models / output full MCP errors / help |
Available Models
| Model ID | Features | Default |
|---|---|---|
claude-opus-4-6 | Most capable, higher cost | ✓ |
claude-sonnet-4-6 | Fast, balanced performance | |
claude-haiku-4-5 | Fastest, lowest cost |
Interactive Mode
pen interactive starts a shell where you can invoke MCP tools directly against a .pen file—ideal for scripting, debugging, and agentic workflows requiring fine-grained control over design operations.
| Parameter | Description |
|---|---|
--app, -a <name> | Connect to a running pen.dev app (e.g., desktop, vscode) |
--in, -i <path> | Input .pen file (optional—starts with an empty canvas if omitted) |
--out, -o <path> | Output .pen file (required in headless mode) |
--help, -h | Show detailed tool reference documentation |
- App Mode:
pen interactive -a desktop -i my-design.pen— connects via WebSocket to a running desktop app or extension, changes apply in real-time. - Headless Mode:
pen interactive -i input.pen -o output.pen— spins up a GUI-less local editor; usesave()to write to disk.
# Commands available in shell
tool_name({ key: value }) // Invoke MCP tool with arguments
tool_name() // Invoke with no arguments
save() // Save document to disk
exit() // Exit
# Example session (As of 2026-07-27, the toolset has been changed to execute / get_app_state / get_screenshot / export_nodes / get_guidelines, see "Supported MCP Tools" below)
pen > get_app_state({ include_schema: true })
pen > get_guidelines()
pen > execute({ operations: 'hero=Insert(document,{type:"frame",name:"Hero",x:0,y:0,width:1440,height:900,fill:"#0A0A0A"})' })
pen > get_screenshot({ nodeId: "hero" })
pen > save()
pen > exit()
Insert(...) syntax used inside execute above is an inferred illustrative example based on the official documentation's "Insert / Copy / Update / Replace / Move / Delete" operation family—the official docs do not provide a complete JSON example for execute parameters. Please test it yourself with pen interactive to verify the real signature before copying this snippet into production scripts.Batch Processing
pen --tasks batch.json executes multiple tasks in sequential order as defined in a JSON file, with each task running in a separate editor instance. Task fields: out (required), prompt (required), in, model.
{
"tasks": [
{ "out": "landing-page.pen",
"prompt": "Create a SaaS landing page with hero, features, and pricing sections" },
{ "in": "existing-app.pen", "out": "existing-app-v2.pen",
"prompt": "Add a dark mode toggle to the header" },
{ "out": "mobile-menu.pen", "model": "claude-haiku-4-5",
"prompt": "Create a mobile hamburger menu component" }
]
}
Supported MCP Tools
batch_design, batch_get, get_editor_state, get_variables, and snapshot_layout can no longer be found in the official documentation. However, as of this review, the pen.dev MCP server actually connected to by the author of this knowledge base still exposes the entire old set of tool names—meaning while the docs talk about the new version, many people locally/online might still have the old version installed. Before using them, run pen interactive or check your MCP client to list the tools and rely on the names you actually get in your environment.| Category | Tool (New Version) | Description | Corresponding Old Tool (If not updated) |
|---|---|---|---|
| Design Operations | execute | Insert/Update/Delete/Move/Copy/Replace nodes; read nodes and computed bounds; read/write variables via GetVariables/SetVariables sub-operations | Consolidates old batch_design / batch_get / get_variables |
get_app_state | Get document metadata and structure | Corresponds to old get_editor_state / snapshot_layout | |
| Visual Operations | get_screenshot | Render a node as a PNG image | Name unchanged |
export_nodes | Export nodes as PNG/JPEG/WEBP/PDF | Name unchanged, officially kept separate | |
| Image Generation | G() operation in execute | G(nodeId, "ai", prompt) for AI-generated images; G(nodeId, "stock", keywords) for Unsplash stock images | Not a standalone tool, hangs under execute |
| Style & Guidelines | get_guidelines | Load .pen working guidelines and styles | Name unchanged, officially kept separate |
Source: Official pen.dev CLI · Supported MCP Tools (Verification method: manual side-by-side comparison with the raw HTML of the page, as WebFetch summaries returned inconsistent results and shouldn't be the sole basis). The official documentation does not provide full JSON examples for execute parameters; the operation names in the example session are transcribed from text descriptions and are not guaranteed to match the actual invocation signature verbatim.
CI/CD & Environment Variables
export PEN_CLI_KEY=pen_cli_...
export ANTHROPIC_API_KEY=sk-ant-...
pen --out onboarding.pen --prompt "Create a 3-step onboarding flow"
| Variable | Description |
|---|---|
PEN_CLI_KEY | CLI Key for CI/CD (takes precedence over stored session) |
ANTHROPIC_API_KEY | Anthropic API Key |
PEN_API_BASE | Backend API URL (default https://api.pen.dev) |
DEBUG | Enable debug logging |
The CLI uses a different session file (~/.pencil/session-cli.json, this path was not adjusted by official rebranding) than the desktop app, making it easier for the backend to distinguish client types.
Insert(...) syntax inside execute above is an inferred illustrative example based on the official documentation's "Insert / Copy / Update / Replace / Move / Delete" operation family—the official docs themselves do not provide a complete JSON example of execute parameters. Please run pen interactive to verify the actual signature yourself before copying this snippet directly into production scripts.Batch Processing
pen --tasks batch.json executes multiple tasks sequentially according to the JSON file, with a separate editor instance for each task. Task fields: out (required), prompt (required), in, model.
{
"tasks": [
{ "out": "landing-page.pen",
"prompt": "Create a SaaS landing page with hero, features, and pricing sections" },
{ "in": "existing-app.pen", "out": "existing-app-v2.pen",
"prompt": "Add a dark mode toggle to the header" },
{ "out": "mobile-menu.pen", "model": "claude-haiku-4-5",
"prompt": "Create a mobile hamburger menu component" }
]
}
Supported MCP Tools
batch_design/batch_get/get_editor_state/get_variables/snapshot_layout can no longer be found in the official documentation. However, as of this review, the pen.dev MCP server actually connected by the author of this knowledge base still exposes this entire set of old tool names—meaning that while the documentation mentions the new version, many may still have the old version installed locally/online. Before using them, please use pen interactive or your MCP client to list the tools to confirm the actual names available in your environment.| Category | Tool (New Version) | Description | Corresponding Old Tool (If not upgraded) |
|---|---|---|---|
| Design Operations | execute | Insert/Update/Delete/Move/Copy/Replace nodes; read nodes and computed boundaries; read/write variables via GetVariables/SetVariables sub-operations | Corresponds to the merger of the old batch_design / batch_get / get_variables |
get_app_state | Get document metadata and structure | Corresponds to the old get_editor_state / snapshot_layout | |
| Visual Operations | get_screenshot | Render nodes as PNG images | Name unchanged |
export_nodes | Export nodes as PNG/JPEG/WEBP/PDF | Name unchanged, officially still kept separate | |
| Image Generation | G() operation in execute | G(nodeId, "ai", prompt) AI generated image; G(nodeId, "stock", keywords) Unsplash stock image | Not a separate tool, nested under execute |
| Style & Guidelines | get_guidelines | Load .pen working guidelines and styles | Name unchanged, officially still kept separate |
Source: Official pen.dev CLI · Supported MCP Tools (Verification method: directly fetch the raw HTML of the page and compare line by line, WebFetch summaries gave inconsistent results on this page and should not be used as the sole basis). The official docs do not provide full JSON examples of execute parameters; the operation names in the example session are transcribed based on the text description in the docs and are not guaranteed to match the actual invocation signature verbatim.
CI/CD & Environment Variables
export PEN_CLI_KEY=pen_cli_...
export ANTHROPIC_API_KEY=sk-ant-...
pen --out onboarding.pen --prompt "Create a 3-step onboarding flow"
| Variable | Description |
|---|---|
PEN_CLI_KEY | CLI Key for CI/CD (takes precedence over existing session) |
ANTHROPIC_API_KEY | Anthropic API Key |
PEN_API_BASE | Backend API address (default https://api.pen.dev) |
DEBUG | Enable debug logging |
The CLI and desktop app use different session files (~/.pencil/session-cli.json, this path was not adjusted along with the official brand name change), making it easier for the backend to distinguish client types.