◂ Topic Center Compiled on 2026-07-28 Official English Version ↗ Verified 2026-08-17
⚡ Unofficial English Guide · Covers all pages of official docs

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.

Source: docs.pencil.devOfficial Update: 2026-07-27English Translation: 2026-07-28
Overview

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)

Quick Start 01

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

  1. Open VS Code, go to Extensions panel (Cmd/Ctrl + Shift + X)
  2. Search "pen.dev" and click Install
  3. Verify: Create a new .pen file (e.g., test.pen) and open it; the pen.dev icon should appear in the top-right corner.
Can't see the icon? Open the Command Palette (Cmd/Ctrl + Shift + P), search for "pen.dev" to see available commands, and ensure the extension is enabled.

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 .dmg from 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
Known Issues Wayland / Hyprland environments may experience UI glitches. X11 is more stable.

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
Editor's Note The above reflects the original official documentation. The current npm package for Claude Code is @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 /mcp in Codex; pen.dev should appear in the MCP list.

After Installation

  1. Complete Activation — Use your email to activate pen.dev
  2. Log into Claude Code — Required for AI features
  3. Open Welcome File — Right-click on canvas → Open Welcome File
  4. 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 claude to complete authentication. Ensure there are no conflicting auth configs (like environment variable keys or custom Providers).
Quick Start 02

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

  1. On first launch, follow the prompt to enter your email
  2. Check your email to get the activation code
  3. 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

MethodDescriptionRecommendation
Claude CLI (Recommended)Run claude in terminal, browser login, all features automatically availableSimplest and most reliable
API KeySet ANTHROPIC_API_KEY environment variableMay conflict with CLI auth, generally not recommended

A Complete Viable Workflow

  1. Install pen.dev (extension or desktop app)
  2. Complete pen.dev activation (email verification code)
  3. Install Claude Code CLI
  4. Authenticate Claude Code (claude command)
  5. Create a .pen file in your project
  6. 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
Quick Start 03

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.

  1. pen.dev MCP server runs locally — Design operations don't rely on the cloud
  2. AI assistants connect via MCP — They can connect as soon as pen.dev is running
  3. AI calls tools — To read, modify, and generate designs
  4. 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

  1. Press Cmd/Ctrl + K to open the AI prompt panel
  2. Describe your request in natural language, for example: "Create a login form with email and password" or "Add a navbar to this page"
  3. AI uses MCP tools to modify your .pen file
  4. Changes reflect instantly on the canvas

Prompt Examples

ScenarioExample 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

  1. Install the pen.dev extension in Cursor and complete activation
  2. Authenticate Claude Code
  3. 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 .pen file.
  • 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

  1. Run pen.dev first (desktop app or IDE extension)
  2. Open Codex in the terminal, execute /mcp to verify connection
  3. 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.

Known Issue pen.dev might modify or repeatedly write to Codex's 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.

CategoryToolCapability
DesignexecuteCreate/modify/manipulate design elements: Insert/Copy/Update/Replace/Move/Delete operations; manage variables and themes via GetVariables/SetVariables sub-operations; generate and place images
Analysisget_screenshotRender design previews, verify visual output, before/after comparisons
Analysisget_app_stateCurrent 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 claude to 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"
Core Concepts 01

.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
ActionMethod
CreateIDE: create a file with a .pen extension; Desktop: File → New or Cmd/Ctrl + N
OpenDouble-click a .pen file, or open it in the IDE like a normal file; pen.dev activates automatically
SaveCmd/Ctrl + S; Note: no auto-save yet, save frequently! Commit via Git to keep history
Best Practices Save often (no auto-save yet); commit to Git regularly; keep .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).

Core Concepts 02

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 — .pen and 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".
Best Practices Commit frequently, write clear commit messages; put designs in feature branches so "what changed in design" and "what changed in code" are reviewed together in the same PR.
How this philosophy becomes a workflow "Design as Code" is more than a storage format; it unlocks a set of two-way design-code sync strategies (shared variables, single-prompt design-to-code, reverse-engineering existing components into designs). For full workflows and real cases, see pen.dev × Claude Code Best Practices · Four Core Workflows in this repo.
Core Concepts 03

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.

ShortcutAction
Space + DragPan canvas
Shift + ScrollHorizontal pan
0Zoom to 100%
1Zoom 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
ShortcutAction
ClickSelect element
Cmd/Ctrl + ClickDirect select (deepest element)
Shift + ClickAdd to selection
Cmd/Ctrl + ASelect 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.

Best Practices Press Cmd/Ctrl + S frequently to save; commit to Git before major changes; use Git history to rollback if needed.
Core Concepts 04

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.

Core Concepts 05

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:

  1. Select an element
  2. Press Cmd/Ctrl + Option/Alt + K, or click "Create component" at the top of the properties panel
  3. 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.

Core Concepts 06

Slots

Original: Core Concepts / Slots

Slots are designated drop zones inside components, used to define flexible, customizable content areas within a component.

Creating Slots

  1. Create a Frame and turn it into a component (Cmd/Ctrl + Option/Alt + K or "Create component" in the properties panel)
  2. Style it as needed
  3. Click the "Make a slot" button at the top of the properties panel
Rule Only an empty Frame inside a component origin can become a slot; slots on the canvas are indicated by a diagonal slash texture marking it as a drop zone.

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".

  1. Select a layer with a slot inside a component origin
  2. Click the + button on the "Slots" row at the top of the properties panel
  3. 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.

Core Concepts 07

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

  1. 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)
  2. Link a .js file: Enter the path in the script field in the properties panel; paths are resolved relative to the .pen file, so just write chart.js for a file in the same folder
  3. Tweak parameters on canvas: Drag handles to resize, and the script reruns and reflows in real-time; every @input generates 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 .js file is independent of the .pen file; 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 @input comments 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

TypeExampleDescription
number@input size: number(min=0, max=100) = 10Optional 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 = trueRenders as a checkbox
color@input fill: color = #3B82F6HEX literal or quoted string
enum@input layout: enum("grid", "stack") = "grid"Renders as a dropdown menu
ref@input target: refReference to a reusable component, pickable from a thumbnail grid

pencil Global Object

FieldTypeDescription
pencil.widthnumberCurrent width of the Script node
pencil.heightnumberCurrent height of the Script node
pencil.input.<name>Matches @input typeCurrent value of the input (clamped and validated)
Limits Can return at most 1000 nodes per run, and must complete within 2 seconds. If you bind an input to a variable (e.g., $primary), the script will automatically respond to theme switches.
Core Concepts 08

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

  1. Create a new .pen file and fill it with components
  2. Click the "Libraries" icon in the left layers panel
  3. Click "Turn this file into a library" at the bottom
Note Design library files use the .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.

Core Concepts 09

Import & Export

Original: Core Concepts / Import & Export

Import

SourceMethod
Full Figma FileToolbar: click the arrow below the Rectangle icon → Import Figma; Desktop app: File → Import Image/SVG/Figma...
Single Figma LayerCopy 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)
ImagesDrag & drop / Copy-paste / Toolbar Import Image or SVG... / File menu in Desktop app; supports PNG, JPEG, SVG
IconsBuilt-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.
Core Concepts 10

Keyboard Shortcuts

Original: Core Concepts / Keyboard Shortcuts

AI Chat

ShortcutAction
Cmd/Ctrl + KToggle AI chat
Cmd/Ctrl + TNew Agent tab
Ctrl + Tab / Ctrl + Shift + TabNext / Previous chat tab
↑ / ↓Prompt history

Tools

ShortcutTool
VMove
HHand
RRectangle
OEllipse
A / FFrame
TText
NNote

Editing

ShortcutAction
Cmd/Ctrl + C / V / XCopy / Paste / Cut
Cmd/Ctrl + DDuplicate
Delete/BackspaceDelete selection
Arrow keys / Shift + ArrowsMove 1px / 10px; swap order in Flex layout
Cmd/Ctrl + G / Cmd/Ctrl + Shift + GGroup / Ungroup
Cmd/Ctrl + Option/Alt + GApply Flex layout to selection
Cmd/Ctrl + [ / ]Send backward / Bring forward
[ / ]Send to back / Bring to front
Cmd/Ctrl + Z / Cmd/Ctrl + Shift + ZUndo / Redo

Selection

ShortcutAction
Cmd/Ctrl + ASelect all
Cmd/Ctrl + ClickDirect select (deepest element under cursor)
Shift + ClickAdd to selection
Shift + EnterSelect parent of current element
EnterSelect children of current element
EscDeselect

Components

ShortcutAction
Cmd/Ctrl + Option/Alt + KElement → Component, or Component → Detach to regular elements
Cmd/Ctrl + Option/Alt + XDetach instance from component

Canvas Navigation

ShortcutAction
Cmd/Ctrl + ScrollZoom
Space + Drag / Middle ClickPan canvas
Shift + ScrollHorizontal pan
= / -Zoom in / Zoom out
0 / 1 / 2100% / Zoom to fit all / Zoom to fit selection

Canvas Settings & File Ops

ShortcutAction
Cmd/Ctrl + 'Toggle pixel grid
Cmd/Ctrl + Shift + 'Toggle snap to pixel grid
Cmd/Ctrl + S / N / OSave / New / Open file
Tip Click the keyboard icon in the app toolbar to pull up the shortcuts list anytime.
Design & Code

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

  1. Design screens, layouts, or individual UI components on the pen.dev canvas
  2. Save the .pen file in your project workspace
  3. Press Cmd/Ctrl + K to open AI chat
  4. Ask pen.dev to generate the code
ScenarioExample 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:

  1. Start from Code — Import existing components into pen.dev
  2. Make visual improvements in pen.dev
  3. Ask AI to write changes back to the code
  4. 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

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 .pen file; 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.pen in 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:

  1. Review docs: Installation, Authentication, AI Integration
  2. Update all components to the latest version: pen.dev, Claude Code CLI, IDE
  3. Try a clean reinstall: uninstall extension → clear extension data → reinstall
  4. 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 .pen file to reproduce the issue

Common Errors Cheat Sheet

ErrorPossible CauseSolution
"Claude Code not connected"Not logged inRun claude
"Invalid API key"Auth conflictClear env vars and re-authenticate
"Process exited with code 1"Export/auth issueCheck Claude Code config
"Need Cursor Pro"Plan limitCheck Cursor subscription
"Invite not found"Activation issueReinstall extension
"Can't access folder"PermissionsUpdate folder permissions

Prevention Checklist

  1. Save often (no auto-save yet)
  2. Keep Claude Code authentication valid
  3. Keep .pen files inside your project workspace
  4. Commit to Git regularly
  5. Keep pen.dev and Claude Code updated
  6. Accept permission prompts
  7. Use supported workflows (do not manually edit .pen files)
Summary in one sentence Most issues can be fixed by "making sure Claude Code auth is valid + keeping pen.dev updated"; when in doubt, restart your IDE and re-authenticate.
For Developers 01

The .pen Format

Original: For Developers / The .pen Format

Living Document This section is a bird's-eye view of the .pen format; for an authoritative and comprehensive reference, please consult the TypeScript Schema at the end of the original document. The official team reserves the right to introduce breaking changes to the 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 a type (such as rectangle, 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, and effect.
  • 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.

For Developers 02

pen.dev CLI

Original: For Developers / pen.dev CLI

Editor's Note (2026-07-28): Rebranding The official documentation has been completely rebranded from "Pencil" to pen.dev: the CLI binary is now 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

MethodDescription
pen loginInteractive login (email+password or email+OTP); session token is stored in ~/.pencil/session-cli.json
PEN_CLI_KEYCLI 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 statusShows 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

OptionDescription
--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, -cUse 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 / --helpList models / output full MCP errors / help

Available Models

Model IDFeaturesDefault
claude-opus-4-6Most capable, higher cost✓
claude-sonnet-4-6Fast, balanced performance
claude-haiku-4-5Fastest, 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.

ParameterDescription
--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, -hShow 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; use save() 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()
Operation Names Unverified The 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

Toolset Major Overhaul (as of 2026-07-27) The official docs have consolidated the original 5-6 granular tools into 5 tools (not 3 as written in earlier versions; verified line-by-line against the original HTML of the official page): names like 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.
CategoryTool (New Version)DescriptionCorresponding Old Tool (If not updated)
Design OperationsexecuteInsert/Update/Delete/Move/Copy/Replace nodes; read nodes and computed bounds; read/write variables via GetVariables/SetVariables sub-operationsConsolidates old batch_design / batch_get / get_variables
get_app_stateGet document metadata and structureCorresponds to old get_editor_state / snapshot_layout
Visual Operationsget_screenshotRender a node as a PNG imageName unchanged
export_nodesExport nodes as PNG/JPEG/WEBP/PDFName unchanged, officially kept separate
Image GenerationG() operation in executeG(nodeId, "ai", prompt) for AI-generated images; G(nodeId, "stock", keywords) for Unsplash stock imagesNot a standalone tool, hangs under execute
Style & Guidelinesget_guidelinesLoad .pen working guidelines and stylesName 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"
VariableDescription
PEN_CLI_KEYCLI Key for CI/CD (takes precedence over stored session)
ANTHROPIC_API_KEYAnthropic API Key
PEN_API_BASEBackend API URL (default https://api.pen.dev)
DEBUGEnable 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.

Unverified Operation NamesThe 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

Major Toolset Overhaul since 2026-07-27The official docs have consolidated the original 5-6 granular tools into 5 tools (not 3 as written in earlier versions, verified line-by-line against the original HTML of the official page): names like 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.
CategoryTool (New Version)DescriptionCorresponding Old Tool (If not upgraded)
Design OperationsexecuteInsert/Update/Delete/Move/Copy/Replace nodes; read nodes and computed boundaries; read/write variables via GetVariables/SetVariables sub-operationsCorresponds to the merger of the old batch_design / batch_get / get_variables
get_app_stateGet document metadata and structureCorresponds to the old get_editor_state / snapshot_layout
Visual Operationsget_screenshotRender nodes as PNG imagesName unchanged
export_nodesExport nodes as PNG/JPEG/WEBP/PDFName unchanged, officially still kept separate
Image GenerationG() operation in executeG(nodeId, "ai", prompt) AI generated image; G(nodeId, "stock", keywords) Unsplash stock imageNot a separate tool, nested under execute
Style & Guidelinesget_guidelinesLoad .pen working guidelines and stylesName 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"
VariableDescription
PEN_CLI_KEYCLI Key for CI/CD (takes precedence over existing session)
ANTHROPIC_API_KEYAnthropic API Key
PEN_API_BASEBackend API address (default https://api.pen.dev)
DEBUGEnable 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.