npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@pen.dev/cli

v0.3.9

Published

CLI tool for running the pen.dev AI agent manipulating .pen design files

Readme

pen.dev CLI (formerly Pencil CLI)

Command-line interface for pen.dev — create and edit .pen design files from the terminal. Run the AI agent with a prompt, call MCP tools directly in an interactive shell, batch-process multiple designs, or export to PNG/JPEG/WEBP/PDF. Built on the same editor engine as the desktop app and IDE extension, with full headless rendering, AI image generation, and stock photo support.

Installation

npm install -g @pen.dev/cli
# or
pnpm add -g @pen.dev/cli
# or
yarn global add @pen.dev/cli

Authentication

The CLI requires authentication before running agent operations. There are two methods:

Sign Up

pen signup --email [email protected] --username johndoe --name "John Doe"

Creates a new account. You'll receive a verification email — click the link, then log in.

Interactive Login

pen login

This starts an interactive session where you choose your login method (browser on pen.dev, email + password, or email + OTP). Browser sign-in opens pen.dev for consent, then asks you to paste a one-time code into the CLI. On success the session token is stored in ~/.pencil/session-cli.json.

Non-Interactive Login

# Step 1: Request an OTP code
pen login --email [email protected]

# Step 2: Log in with the code from your email
pen login --email [email protected] --code 123456

When flags are provided the interactive prompts are skipped, useful for scripting and CI.

CLI Key (for CI/CD)

Set the PEN_CLI_KEY environment variable. CLI keys are scoped to an organization and can be created/revoked in the Developer Keys section of your organization settings on the pen.dev web app.

PEN_CLI_KEY=pencil_cli_... pen --out design.pen --prompt "Create a form" --agent claude

The CLI key always takes precedence over a stored session token.

Checking Status

pen status

Displays the current authentication method, verifies the session with the backend, and shows account details (email, name, organization for CLI keys).

Codex (ChatGPT) Login

pen codex-login

Signs in to OpenAI Codex with your ChatGPT Plus/Pro account so the codex agent (--agent codex or any gpt-* model) can run. Choose browser login, or device-code login for headless machines. The credential is stored in ~/.pencil/agent-auth. Alternatively set PEN_AGENT_API_KEY to use an API key instead.

pen codex-logout

Removes the stored OpenAI Codex credential.

Quick Start

# Log in first
pen login

# Create a new design from scratch
pen --out design.pen --prompt "Create a login page with email and password fields" --agent claude

# Modify an existing design
pen --in existing.pen --out modified.pen --prompt "Add a blue submit button" --agent claude

# Start an interactive shell (in headless mode)
pen interactive -o design.pen

# Start an interactive shell (connect to a running pen.dev app)
pen interactive -a desktop -i design.pen

# List available models
pen --list-models --agent claude

Usage

pen [command] [options]

Commands:
  signup                 Create a new account (flags required, see below)
  login                  Log in interactively (browser, email + password, or OTP)
  status                 Check authentication status
  version                Show CLI version
  interactive            Start an interactive tool shell (see below)

Options:
  --in, -i <path>        Input .pen file (optional, starts with empty canvas if omitted)
  --out, -o <path>       Output .pen file path (required unless --export is used)
  --prompt, -p <text>    Prompt for the AI agent (required)
  --prompt-file, -f <path>  Attach a file to send with the prompt (repeatable). Images (png, jpeg, gif, webp) or text files; paths are not the prompt text itself.
  --agent <type>         Agent to use when --model is omitted: claude, codex, gemini (default: claude)
  --model, -m <id>       Model to use; agent is inferred from the model id
  --custom, -c           Use custom Claude model config (e.g. AWS Bedrock, Vertex AI)
  --list-models          List available models and exit
  --tasks, -t <path>     JSON tasks file for batch operations
  --workspace, -w <path> Workspace folder path to run the agent in
  --export, -e <path>    Export an image of the final result
  --export-scale <n>     Export scale factor (default: 1)
  --export-type <type>   Export format: png, jpeg, webp, pdf (default: png)
  --verbose-mcp          Log full MCP tool error details to the console
  --help, -h             Show help message

Interactive Mode

The interactive shell lets you call MCP tools directly on .pen files — useful for scripting, debugging, and agentic workflows that need fine-grained control over design operations.

pen interactive [options]

Options:
  --app, -a <name>   Connect to a running pen.dev app (e.g. desktop, vscode)
  --in, -i <path>    Input .pen file (optional, empty canvas if omitted)
  --out, -o <path>   Output .pen file (required in headless mode)
  --help, -h         Show detailed tool reference. Important for agentic workflows, so agents can learn the tool.

Modes

App mode — connects to a running pen.dev desktop or extension. Changes are applied live.

pen interactive -a desktop -i my-design.pen

Headless mode — spins up a local editor without a GUI. Use save() to write to --out.

# New empty canvas saved to the output file
pen interactive -o output.pen

# Edit an existing file
pen interactive -i input.pen -o output.pen

Shell commands

tool_name({ key: value })   Call an MCP tool
save()                      Save the document to disk (headless) or app
exit()                      Exit the shell

Getting started

Begin with read_skill to load the .pen schema and execute instructions, then get_app_state to understand the document:

pen > read_skill()
pen > read_skill({ path: "pen-schema.md" })
pen > read_skill({ path: "execute.md" })
pen > get_app_state()
pen > execute({ input: 'Get((n,c)=>{c.skipChildren();Print(n.id,n.name)})' }) # list top-level nodes
pen > execute({ input: 'Get(n=>n.reusable&&Print(n.id,n.name))' })            # find components

Example

pen > read_skill()
pen > read_skill({ path: "pen-schema.md" })
pen > read_skill({ path: "execute.md" })
pen > get_app_state()
pen > get_style()
pen > get_style({ name: "Aerial Gravitas" })
pen > execute({ input: 'rect=Insert(document,{type:"rectangle",name:"Foo",x:10,y:10,width:300,height:200,fill:"#E5484D"})' })
pen > execute({ input: 'TakeScreenshot([rect])' })
pen > save()
pen > exit()

Run pen interactive --help for the full tool reference with parameter types and descriptions.

Available Models

pen --list-models --agent claude|gemini|codex

Environment Variables

| Variable | Description | |----------|-------------| | PEN_CLI_KEY | CLI API key for CI/CD (takes precedence over stored session) | | PEN_AGENT_API_KEY | API key for the selected agent. | | ANTHROPIC_API_KEY | Anthropic API key for Claude agents. Ignored for Codex and Gemini. | | PEN_API_BASE | Backend API base URL (default: https://api.pen.dev) | | DEBUG | Enable debug logging |

Further environment variables and agent config can be set in settings.json as well.

Supported Operations

The CLI supports the following MCP tools with full feature parity to the desktop app:

Design Operations

| Tool | Description | |------|-------------| | execute | Insert, Update, Delete, Move, Copy, Replace, SetVariables, GetVariables, Get, Print, Generate, FindEmptySpace, TakeScreenshot, Export | | get_app_state | Get document metadata and structure |

Visual Operations (headless rendering via CanvasKit)

Screenshots are taken with the execute TakeScreenshot() operation. Files are exported with the execute Export() operation, which supports PNG/JPEG/WEBP/PDF images and HTML output.

Image Generation

The execute Generate() operation brings images and vector artwork into the document, either from a prompt or by transforming an image the document already has. Generated images are saved to an images/ directory alongside the output .pen file.

| Type | Description | |------|-------------| | Generate("ai", nodeId, prompt) | AI-generated image from a text prompt | | Generate("stock", nodeId, keywords) | Stock photo from Unsplash | | Generate("svg", frameId, prompt) | Vector artwork drawn into the frame | | Generate("vectorize-image", frameId, imageUrl) | Traces an existing image into vector paths inside the frame | | Generate("remove-background", imageUrl) | Returns the url of a transparent cutout of the subject | | Generate("replace-background", imageUrl, prompt) | Returns the url of the subject composed onto a described background |

The two *-background types write nothing themselves - apply the url they return with Update(nodeId, {fill: {type: "image", url}}).

Guidelines

| Tool | Description | |------|-------------| | read_skill | Read the pen-dev skill (SKILL.md, pen-schema.md, execute.md, guides) | | get_style | Load styles for working with .pen files |

Examples

Create a Login Page

pen --out login.pen --agent claude --prompt "Create a modern login page with:
- Email input field
- Password input field
- 'Sign In' button
- 'Forgot password?' link
- Social login options (Google, GitHub)"

Add Components to Existing Design

pen --in dashboard.pen --out dashboard-v2.pen --agent gemini --prompt "Add a sidebar navigation with:
- Dashboard link (active)
- Users link
- Settings link
- Logout button at bottom"

Create a Component Library

pen --out components.pen --agent codex --prompt "Create a component library with:
- Primary, secondary, and ghost button variants
- Text input with label and error state
- Card component with header and content
- Badge component in success, warning, error colors"

Using a Specific Model

Use --model to select a different Claude model:

# Use Claude Opus for complex tasks requiring highest capability
pen --out complex-app.pen \
  --model claude-opus-4-6 \
  --prompt "Create a complete e-commerce product page with image gallery,
reviews section, related products, and add-to-cart functionality"

# Use Claude Haiku for simple, fast tasks
pen --out simple.pen \
  --model claude-haiku-4-5 \
  --prompt "Create a simple 404 error page"

CI/CD Usage

# Authenticate with a CLI key
export PEN_CLI_KEY=pencil_cli_...
export PEN_AGENT_API_KEY=sk-...

# Generate designs in a pipeline
pen --out onboarding.pen --prompt "Create a 3-step onboarding flow" --agent claude

Verbose MCP Error Logging

Use --verbose-mcp to show full MCP tool error details (including stack traces where available) in the CLI output when a tool fails:

pen --out debug.pen \
  --agent claude \
  --prompt "Create a simple layout" \
  --verbose-mcp

Batch Processing with Tasks File

Use --tasks to process multiple designs from a JSON tasks file:

pen --tasks batch-tasks.json --agent claude

Example batch-tasks.json:

{
  "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"
    },
    {
      "out": "from-reference.pen",
      "prompt": "Match the layout and palette of the attached reference",
      "promptFiles": ["./assets/reference.png"]
    }
  ]
}

Each task in the array supports the same options as CLI arguments:

  • in - Input file (optional)
  • out - Output file (required)
  • prompt - AI prompt (required)
  • model - Model override (optional)
  • promptFiles - Array of attachment paths (optional). Relative paths are resolved from the directory that contains the tasks JSON file.

Limitations

The CLI is designed for headless operation and has some limitations compared to the desktop app:

  • No real-time preview - Changes are saved to file, not displayed interactively
  • No interactive UI features - No selection, zoom, or pan controls
  • No library browsing - Cannot browse or import from .pen libraries

Token Storage

| File | Purpose | |------|---------| | ~/.pencil/session-cli.json | Stored session token from pen login |

The CLI uses a separate session file from the desktop app (~/.pencil/session-desktop.json) so the backend can distinguish which client is in use.

License

Proprietary — see LICENSE file. © High Agency, Inc.