Pencil.dev に SVG エクスポートがなかったので、アイコンを SVG 化する agent skill を作った

Pencil.dev に SVG エクスポートがなかったので、アイコンを SVG 化する agent skill を作った

Pencil.dev を触っていて、かなり気に入っています。

しかし最近、アイコンまわりで少し困ったことがありました。

Pencil 上で作ったアイコンを、そのままアプリの public/assets/*.svg として使いたかったのですが、現時点では SVG として直接書き出す手段が見当たりませんでした。

Pencil から PNG や PDF は出せます。 なので、直接 SVG を書き出す代わりに、次のような流れで SVG を作る agent skill を用意しました。

  • Pencil MCP で対象ノードを読む
  • Pencil MCP で PNG を書き出して見た目の基準にする
  • 必要なら PDF も書き出す
  • PDF 内のアウトラインを SVG path に変換する
  • 最終 SVG を PNG 化して Pencil PNG と比較する

やりたいことはシンプルで、Pencil 上の見た目と、アプリで使う SVG の見た目をできるだけ合わせることです。

特にアイコンのような小さい UI 要素では、少しのズレでも見た目に影響します。 なので、SVG を「それっぽく書く」のではなく、Pencil から書き出した PNG を基準にして確認するようにしました。

以下が作った SKILL.md です。

# Pencil SVG Icon Skill

## Purpose

Use this skill when implementing an SVG icon from a Pencil design node.

This is useful when Pencil does not provide a direct SVG export for the desired icon, but the product needs an SVG asset such as:

- `public/assets/*.svg`
- an inline SVG component
- a reusable UI icon asset

The goal is to create an SVG whose rendered appearance matches the Pencil design as closely as practical.

---

## Core Idea

Do not treat the SVG as a rough recreation.

Use Pencil as the source of truth.

The basic workflow is:

1. Read the target node through Pencil MCP.
2. Export a PNG from Pencil and use it as the visual reference.
3. Create the SVG implementation.
4. Render the SVG back to PNG at the same size.
5. Compare the rendered SVG PNG with the Pencil PNG.
6. Adjust until the result is visually aligned.

When the icon contains font glyphs, strokes, or geometry that is difficult to reproduce directly, export PDF from Pencil and use the PDF outlines as the basis for the SVG paths.

---

## Important Rules

Never parse `.pen` files directly.

Always use Pencil MCP to inspect Pencil content.

Reasons:

- Pencil MCP gives the resolved node structure.
- Styles, variables, instances, and geometry should be read through the supported interface.
- The `.pen` file format should not be treated as the public API for this task.

Do not assume a third-party SVG icon with the same name will visually match Pencil.

For example, if Pencil displays an icon font, an official SVG from the same icon set may still render slightly differently.

The reference is the Pencil-rendered PNG, not the external icon library.

---

## Inputs

Required inputs:

- Pencil file path
- Target node ID
- Output SVG path

Typical values:

```txt
Pencil file: design/project.pen
Node ID: TARGET_NODE_ID
Output: public/assets/example.svg
````

Optional inputs:

* Expected icon size
* Asset naming convention
* Whether PDF outline extraction should be attempted

---

## Step 1: Inspect the Pencil Node

Use Pencil MCP to read the target node.

Read enough depth to include the icon and its children.

Example request:

```json
{
  "filePath": "design/project.pen",
  "nodeIds": ["TARGET_NODE_ID"],
  "readDepth": 4,
  "includePathGeometry": true,
  "resolveVariables": true,
  "resolveInstances": true
}
```

Check:

* width
* height
* fills
* strokes
* corner radius
* child nodes
* icon font information, if present
* path geometry, if present
* child positions and sizes

Avoid exposing private or product-specific node names in public writeups.

---

## Step 2: Export a Pencil PNG

Export the target node as PNG through Pencil MCP.

```json
{
  "filePath": "design/project.pen",
  "nodeIds": ["TARGET_NODE_ID"],
  "outputDir": "/tmp/pencil-svg-export",
  "format": "png",
  "scale": 1
}
```

Use `scale: 1` by default.

The PNG is the visual reference for the SVG.

---

## Step 3: Try a Direct SVG Implementation

For simple shapes, create SVG directly from the Pencil node structure.

This can work well for:

* simple filled shapes
* basic paths
* simple rectangles
* simple ellipses
* icons whose geometry is already available

Make sure the SVG has the correct:

* `width`
* `height`
* `viewBox`
* fills
* strokes
* path geometry

Then render the SVG to PNG and compare it with the Pencil PNG.

---

## Step 4: Use PDF Outlines When Needed

If the direct SVG does not match the Pencil PNG closely enough, export PDF from Pencil.

```json
{
  "filePath": "design/project.pen",
  "nodeIds": ["TARGET_NODE_ID"],
  "outputDir": "/tmp/pencil-svg-export",
  "format": "pdf",
  "scale": 1
}
```

Use PDF outlines when the icon involves:

* icon fonts
* text or glyph outlines
* strokes that render differently in the browser
* complex paths
* rounded shapes that need precise visual matching

The PDF may contain outlines that better represent what Pencil actually rendered.

Convert those outlines into SVG paths where appropriate.

---

## Step 5: Convert PDF Paths to SVG Paths

When extracting paths from PDF content streams, map common PDF path commands to SVG path commands.

| PDF  | SVG            |
| ---- | -------------- |
| `m`  | `M`            |
| `l`  | `L`            |
| `c`  | `C`            |
| `h`  | `Z`            |
| `re` | rectangle path |

If the PDF uses even-odd filling, use:

```svg
fill-rule="evenodd"
```

Preserve transforms and decimals.

Avoid unnecessary rounding.

---

## Step 6: Render the SVG Back to PNG

Render the final SVG at the same size as the Pencil PNG.

For example, for a 40x40 asset:

```html
<html>
  <body style="margin:0;background:white">
    <img src="file:///absolute/path/to/icon.svg" style="display:block;width:40px;height:40px">
  </body>
</html>
```

Use a stable rendering method, such as headless Chrome.

---

## Step 7: Compare the Images

Compare the Pencil PNG and the SVG-rendered PNG.

At minimum, check:

* overall size
* visible bounding box
* icon bounding box
* obvious pixel drift
* antialiasing differences

For small icons, check subpixel alignment carefully.

A practical target is to keep outline drift within about:

```txt
0.2px
```

Do not rely only on visual inspection if the asset is precision-sensitive.

---

## Completion Criteria

The task is complete when:

* The Pencil node was inspected through Pencil MCP.
* A Pencil PNG reference was exported.
* The SVG asset was created.
* The SVG was rendered back to PNG.
* The SVG PNG was compared with the Pencil PNG.
* Any visible drift was corrected or judged acceptable.
* The final SVG was saved to the requested output path.

---

## Output Summary

When finished, report:

```txt
Implemented: public/assets/example.svg

Source:
- Pencil file: design/project.pen
- Node ID: TARGET_NODE_ID

Verification:
- Pencil PNG exported
- SVG rendered to PNG
- PNG comparison completed
- Result accepted
```

Keep the summary generic when publishing publicly.
Do not include private node names, product-specific icon names, or unreleased design details.

まとめ

Pencil.dev で作ったアイコンをそのまま SVG asset として使いたかったので、Pencil MCP と PNG/PDF エクスポートを組み合わせる skill を作りました。

やっていることは地味ですが、AI agent に任せるにはちょうどよい作業です。

Pencil の情報を MCP で読み、PNG を基準にし、必要なら PDF のアウトラインを使って SVG を作る。
最後に SVG を PNG 化して比較する。

これで、Pencil 上の見た目に近い SVG アイコンを public/assets に置けるようになりました。