GitHub Issueの確認事項(最後のコメント・descriptionの両方)を、コードベース・ドキュメント・そこから参照されている外部リンク(仕様書・ライブラリ公式ドキュメント等)まで調査し、根拠に基づいた回答をコメントに追記するスキル。調査しても事実で決まらず人間の意思決定が必要な項目は、固定セクションで明示して後続のトリアージへ引き渡す。
edit-pencil-design
pen.dev CLI(`pencil` / `pen`コマンド)だけを使って.penファイル(pen.devで作成されたデザインファイル)をAIプロンプトまたは決定論的な編集操作で修正・更新・新規作成するスキル。.penファイルの編集、ボタン追加、レイアウト変更、UIデザインの調整、pen.devデザインの更新、新しい.penデザインの作成などの依頼で必ず使用する。AI任せの編集・新規作成はエージェントモード(`pencil --in --out --prompt`)で行い、既存ファイルは同一パスを指定して上書き、新規作成は`--in`を省略して`--out`に新しいパスを指定する。決定論的な編集はインタラクティブモード(`pencil interactive`)の`execute`(`Insert` / `Update` / `Delete` など)で行い、最後に`save()`する。編集・作成後は「**編集・作成したコンポーネントのNodeだけ**」を`execute`の`Export` / `TakeScreenshot`でPNG出力し、`.pen`と同階層の`snapshots/`ディレクトリに保存する。pen.dev MCPには依存せず`pencil`コマンドのみで完結する。.penファイルのgitコンフリクト解消・破損復旧は本スキルではなく`resolve-pencil-conflict`スキルの担当。
インストール方法を見る含まれるファイル(1)
- SKILL.md33.2 KB
SKILL.md(原文)
インストールする前に、エージェントに与えられる指示の中身を確認できます。
Edit Pencil Design
pen.dev CLI(pencil コマンド。pen も同じバイナリ)のみで .pen デザインファイルを編集・新規作成し、編集・作成Nodeだけのスクリーンショットを残すスキル。MCPサーバーには依存しない。公式ドキュメント: docs.pen.dev/for-developers/pen-cli
CLI 0.3.5 でシェル内ツールが5つに整理された。現在あるのは browser / execute / get_app_state / get_style / read_skill(+ save() / exit())のみ。Nodeの読み書きも画像出力も execute に一本化されている(Export / TakeScreenshot は execute の中の関数であってツールではない)。廃止済みツールは早見表の「廃止済み」を参照。パッケージ名は @pen.dev/cli で、pen / pencil の両方のbinを提供する。
設計思想
pen.dev CLI の2つの実行モードを使い分ける:
| モード | 起動方法 | できること |
|---|---|---|
| エージェントモード | pencil --in --out --prompt(新規作成時は --in 省略) | AIプロンプトで .pen を編集・新規作成(自然言語での編集・作成はこのモードのみ) |
| インタラクティブモード | pencil interactive -i -o | read_skill() / get_app_state() / get_style() / execute({ input }) / save() / exit()。決定論的な編集(Insert / Update / Delete 等)も画像出力(Export / TakeScreenshot)もこちらで完結する |
.pen は暗号化バイナリで Read / Grep では読めないため、Node構造の確認・Node ID取得・Node単位スクリーンショットはすべて pencil interactive 経由で行う。
重要な前提
- 既存ファイルの編集はその場で上書き更新する(別名出力は二重管理を生むため避ける)
- 新規作成は
--inを省略し、--outにまだ存在しないパスを指定する(既存パスを--outに指定すると意図せぬ上書きになるため、実行前に存在チェックを必ず行う) - gitコンフリクトのテキストマージは絶対禁止(
.penは暗号化バイナリのため、コンフリクトマーカーの手編集やgit mergetoolはファイルを破損させる。コンフリクト解消はresolve-pencil-conflictスキルの担当) - スクリーンショットはファイル全体ではなく編集・作成対象のNodeだけ(差分レビューが容易になる)
前提条件の確認
pencil version— 未インストールならnpm install -g @pen.dev/cliを案内(Node.js 18以上必要。0.3.5 未満はツール構成が違うため、その場合も更新する)pencil status— 未認証ならpencil login、またはPEN_CLI_KEY環境変数の設定を案内- 対象の
.penファイルの存在確認 — 編集なら先に存在している必要がある。新規作成なら存在していてはならない(既に存在する場合は、編集として扱うべきかユーザーに確認する)。新規作成では出力先ディレクトリをmkdir -pで用意する
実行ルール
ルール1: 操作種別(編集 / 新規作成)とモードの選択
まず依頼が既存ファイルの編集か新規ファイルの作成かを判定する。
既存ファイルの編集(エージェント / interactive どちらも可)
- エージェントモード
pencil --in path/to/design.pen --out path/to/design.pen --prompt "<修正内容>"(短縮形-i/-o/-p)— 自然言語で任せたい編集。大きめのリファイン、レイアウト調整、複数Nodeにまたがる修正向き - インタラクティブモードの
execute({ input: '...' })— 「このNodeの色を#123456に」「このフレームにテキストを1つ足す」のような決定論的な編集向き。結果が予測可能で差分も追いやすいが、heredoc/シェルの改行展開を誤るとサイレントに失敗するため、ルール2の安全規則を必ず守る
どちらのモードでも --in と --out には同じ .pen パスを指定する。
execute で編集する場合は、先に read_skill({ path: "pen-schema.md" }) と read_skill({ path: "execute.md" }) を1回ずつ呼んでスキーマと execute APIドキュメントを読む(get_app_state はスキーマもAPIドキュメントも返さない。0.3.5 でドキュメント取得は read_skill に移った)。プロパティ名を推測で書くと警告付きで無視され、無編集のまま save() が走る。
execute の主な関数(詳細は read_skill({ path: "execute.md" }) が返すドキュメントが正):
| 関数 | 用途 |
|---|---|
Insert(parent, nodeData) | 子Nodeを末尾に追加。戻り値は生成されたNode ID |
Update(path, updateData) | 既存Nodeのプロパティ更新 |
Copy(path, parent, copyNodeData) / Replace(path, nodeData) / Move(path, parent, index) / Delete(path) | 複製 / 置換 / 移動 / 削除 |
Get(path | visit, options) / Print(...) | 読み取り(inspect-pencil-node と同じ。編集前後の確認に使う) |
SetVariables(vars, replace) / GetVariables() | デザイン変数 |
Generate(nodeId, "ai" | "svg" | "stock", prompt) | 画像・SVGの生成(ロゴ・イラストは手描きせずこれを使う) |
FindEmptySpace({...}) | 空き領域の探索(新規フレームの配置先) |
TakeScreenshot(nodeIds) | Nodeを描画してレスポンスに画像を添付("document" 可。旧 get_screenshot) |
Export(nodeIds, format, outputPath, options) | Nodeをファイルへ書き出し(旧 export_nodes / export_html。ルール5参照) |
execute の重要な性質:
- エラー時はその
execute呼び出し内の変更と作成されたグローバルがすべて巻き戻る(部分適用にはならない) - 失敗したスニペットは丸ごと投げ直さず
editsで直す。失敗レスポンスにeditIdが出るので、次の呼び出しはexecute({ editId: "<id>", edits: [{ find: "...", replace: "..." }] })の形にする(パッチ後のスニペットが最初から再実行される) - 警告(warnings)はレスポンスに列挙される。無視せず次の
executeで必ず直す - 呼び出しごとにスコープが独立する。値を持ち越すなら
const/letを付けずにmyNode = Insert(...)と書く - 追加した全Nodeに人間可読な
nameを必ず付ける。executeは末尾に name → 生成ID のマッピングを返すので、これがそのまま「編集Nodeの特定」に使える idは指定しない(常にPencilが採番する)。コンポーネント作成は生成IDを受け取るために別のexecuteに分ける
新規ファイルの作成(エージェントモード、または空キャンバスからの execute)
pencil --out path/to/new-design.pen --prompt "<作成したいデザインの内容>"
--inを省略し、--outに新しい.penパスを指定する- 実行前に
--outのパスが未使用であることを確認する([ -e path ]チェック)。既に存在する場合は上書きせず、編集として扱うかユーザーに確認する - 決定論的に組み立てたい場合は
pencil interactive -o path/to/new-design.pen(-i省略=空キャンバス)でexecuteのInsertを重ね、最後にsave()する
ルール2: インタラクティブモードを heredoc で非対話的に呼び出す
pencil interactive は標準入力からコマンドを流せば非対話的に実行できる。
pencil interactive -i path/to/design.pen -o path/to/design.pen <<'EOF'
execute({ input: 'Update("title-01", { fill: "#123456" })' })
save()
exit()
EOF
-iと-oには編集対象と同じ.penパスを指定(ヘッドレスモードでは-oが必須)save()を呼ばなければファイルへの変更は永続化されない(読み取りのみならsave()不要。実測でもsave()無しのセッションは-oのパスにファイルを作らない)- 最後に必ず
exit()を呼ぶ
heredoc / シェルの改行展開を正しく扱う(重要)
execute({ input: '...' }) の中身はJS文字列リテラルなので、複数行のスニペットは \n の2文字で区切って渡す。シェルが文字列内の \n を実改行に展開するとJS文字列が閉じずパースエラーになり、Pencil側はその execute を失敗させたまま save() だけが走る。結果、小数点正規化(13.995000000000001 → 13.995)のような無害な差分だけがディスクに残る。失敗が表面上は成功に見える事故パターンなので必読。
| シェル / コマンド | "a\nb" の扱い |
|---|---|
zsh の組み込み echo | \n を実改行に展開(デフォルト挙動) |
bash の組み込み echo | デフォルトでは展開しない(-e で展開) |
printf '%s' "..." | 移植性ありで \n を2文字のまま出力 |
print -r -- "..." (zsh) | エスケープ解釈なし |
heredoc <<'EOF'(クォート付) | 本文をリテラルのまま渡す(\n は2文字のまま、変数展開も無し) |
heredoc <<EOF(クォート無) | 変数展開・コマンド置換は行うが、リテラル \n は2文字のまま |
原則は「JS/JSON文字列リテラル内の \n は2文字(バックスラッシュ + n)のままPencilに届けること」。execute のスニペットを複数文に分ける区切りにも同じ \n を使う('a=Insert(...)\nUpdate(...)')。
改行を確実に2文字のまま渡すための4原則
-
heredoc は最優先で
<<'EOF'(シングルクォート付き)を使う — 変数展開もエスケープ解釈も止まり、本文のJSがそのままPencilに届く。 -
動的な値は
jqでJSONエンコードしてから heredoc に差し込む。echo "{\"text\": \"$user_input\"}"のような自前組み立ては禁止(改行・ダブルクォート・バックスラッシュが含まれた瞬間に壊れる)。TEXT_JSON=$(jq -Rs 'rtrimstr("\n")' <<< "Hello World") # → "Hello\nWorld" という、正しくエスケープされたJSON文字列リテラルになる pencil interactive -i path/to/design.pen -o path/to/design.pen <<EOF execute({ input: 'Update("title-01", { content: ${TEXT_JSON} })' }) save() exit() EOFinputはシングルクォートで囲み、注入する値(前後にダブルクォート付き)はinput内のダブルクォート文字列として使う。inputをダブルクォートで囲むと注入値のダブルクォートと入れ子が壊れ、Invalid syntax. Expected: tool_name({ key: value })になる。 -
echoを使わない。printf '%s'またはprint -r --(zsh)を使う。# NG (zshで\nが実改行に化けてスニペットが壊れる) ARGS=$(echo 'Update("t1", { content: "Hello\nWorld" })') # OK ARGS=$(printf '%s' 'Update("t1", { content: "Hello\nWorld" })') -
JS値として改行が必要なら、リテラル
\nの2文字で書く(heredoc本文に実改行を含むテキストを直接書かない)。
失敗を早く検出するセルフチェック
Pencilに流す前に「シェルが解釈した最終文字列」を cat で目視する。
cat > "${WORK_DIR}/cmds.txt" <<'EOF'
execute({ input: 'Update("t1", { content: "line1\nline2" })' })
save()
exit()
EOF
cat "${WORK_DIR}/cmds.txt" # 文字列リテラル内の \n が2文字のまま残っていることを目視
pencil interactive -i path/to/design.pen -o path/to/design.pen < "${WORK_DIR}/cmds.txt"
\n が実改行に化けていたら即失敗。<<'EOF' に修正してやり直す。あわせて execute のレスポンスに Error / warnings が出ていないかも必ず確認する(出ていれば save() してはいけない)。
ルール3: 同時実行で競合しない一時ディレクトリを毎回確保する
中間ファイルの保存先を固定パスにすると、同じ .pen の同時編集で上書き衝突が起きる。開始時に mktemp -d で実行ごとに一意なディレクトリを確保する(trap で途中失敗時も自動後始末される)。
WORK_DIR="$(mktemp -d -t pencil-edit-XXXXXX)"
trap 'rm -rf "$WORK_DIR"' EXIT
before.json / after.json などの中間ファイルは必ず ${WORK_DIR} 配下に置く(/tmp/before.json のような固定パスは使わない)。
ルール4: 編集の前後でNodeツリーを取得し、対象Nodeを特定する
新規作成の場合は手順1をスキップし「空のツリー」として扱う(= 作成後の after.json に含まれる全Nodeが新規Node)。手順5の代わりに、--out のファイルが実際に生成されたこと・after.json にNodeが含まれることを確認し、どちらかを満たさなければ作成失敗として ${WORK_DIR}/edit.log を確認のうえ再実行する。
get_editor_state() は廃止されたので、ツリーのスナップショットは execute の Get visitor で1行のコンパクトJSONとして吐き出す(そのまま jq で比較できる)。
- 編集前のスナップショット取得(編集のみ)
pencil interactive -i path/to/design.pen -o path/to/design.pen <<'EOF' 2>/dev/null | sed -n 's/^TREE //p' > "${WORK_DIR}/before.json"
execute({ input: 'Print("TREE", JSON.stringify(Get((n,c)=>({d:c.depth,id:n.id,name:n.name,type:n.type,x:n.x,y:n.y,w:c.bounds.width,h:c.bounds.height,fill:n.fill,content:n.content}))))' }) exit() EOF
出力は `[{"d":0,"id":"F9RVcy","name":"Hero",...}, ...]` の1行JSON。**行頭マーカー `TREE ` を付けて `sed` で抜く**(`[INFO] Starting pen.dev (headless)...` のような起動ログも `[` で始まるため、`grep '^\['` では拾い分けられない)。属性を増やしたいときは visitor の返すオブジェクトに足す(重くなるので必要な分だけ)。
heredoc本文と終端の `EOF` は**行頭から**書く(インデントすると終端が認識されない)。同じコマンドを `after.json` にも使うので、`.pen` パスと出力先だけ差し替える。
2. **編集(エージェントモード)** — 標準出力・標準エラーも `${WORK_DIR}` に流し、同時実行時のログ取り違えを防ぐ
```bash
pencil --in path/to/design.pen --out path/to/design.pen --prompt "<具体的な指示>" \
> "${WORK_DIR}/edit.log" 2>&1
execute で編集する場合はルール2のheredocで実行し、その出力も ${WORK_DIR}/edit.log に残す。
-
編集後のスナップショット取得 — 同様に
${WORK_DIR}/after.jsonへ保存 -
編集Nodeの特定
executeで編集した場合は、レスポンス末尾の## Created nodes by nameのマッピング(Hero=cGySg形式)と、Update/Deleteに渡した既知のIDがそのまま対象- エージェントモードの場合は before/after のJSON差分から判定:
afterにあってbeforeに無いid→ 新規追加Node、双方にあるが属性差分のあるid→ 変更Node - 判定が難しい場合(idの再採番、大規模な再構成など)は推定できる範囲で抽出し、残りはユーザーに確認。フォールバックとして影響を受けた最上位フレーム/コンポーネントのNode IDを1つ選んでスクリーンショットを取る
-
「実質的な編集が無い」ケースの検出 → 編集失敗扱いにする(編集のみ。新規作成では前述のファイル生成チェックで代替)
差分が「Node IDの追加・削除なし、type / name / 構造の変化なし、数値フォーマットの正規化のみ(例:
13.995000000000001→13.995、100.0→100)」なら、executeのスニペットが壊れて適用されずsave()だけ走った可能性が極めて高い(ルール2のトラブルの典型的な観測像)。編集失敗として報告し、再実行する。チェックはjqで数値表現を正規化してから diff:jq -S 'walk(if type == "number" then tonumber|tostring|tonumber else . end)' \ "${WORK_DIR}/before.json" > "${WORK_DIR}/before.norm.json" jq -S 'walk(if type == "number" then tonumber|tostring|tonumber else . end)' \ "${WORK_DIR}/after.json" > "${WORK_DIR}/after.norm.json" if diff -q "${WORK_DIR}/before.norm.json" "${WORK_DIR}/after.norm.json" >/dev/null; then echo "編集失敗の疑い: 構造に有意な差分なし。heredocのJS引数が壊れていないかルール2を再確認してください" >&2 exit 1 fiこの検証は編集Node特定の直前に必ず通す。
ルール5: 編集・作成したNodeだけをスクリーンショットし snapshots/ に保存する
CLI 0.3.5 では画像出力も execute の関数(Export / TakeScreenshot)に一本化された。Export の出力先は画像フォーマットではディレクトリ指定で、ファイル名はNode IDに固定される(<outputPath>/<nodeId>.png)。したがって命名規則は「一次出力 → mv でリネーム」で満たす。
新規作成の場合は全Nodeが新規のため、after.json のトップレベルフレーム(画面・ページ単位のNode)を対象にする。多数ある場合は主要なフレームに絞る。
DESIGN="designs/login.pen"
SNAP_DIR="$(dirname "$DESIGN")/snapshots"
STEM="$(basename "$DESIGN" .pen)"
TS="$(date +%Y%m%d-%H%M%S)"
mkdir -p "$SNAP_DIR"
pencil interactive -i "$DESIGN" -o "$DESIGN" <<EOF
execute({ input: 'Export(["<編集Node1 ID>", "<編集Node2 ID>"], "png", "${WORK_DIR}/img")' })
exit()
EOF
for f in "${WORK_DIR}"/img/*.png; do
mv "$f" "${SNAP_DIR}/${STEM}-$(basename "$f" .png)-${TS}.png"
done
Export(nodeIds, format, outputPath, options?) の仕様: nodeIds(必須・配列)/ format(png | jpeg | webp | pdf | html-tailwind | html-css)/ outputPath(画像はディレクトリ、HTMLは出力ファイルのパス。相対パスは pencil interactive を起動したcwd基準)/ options(scale 既定 2 / quality / HTML用の includeHtmlScaffold など)。書き出したファイルの絶対パスがレスポンスに列挙される。pdf は全Nodeが1つの export.pdf にまとまる。nodeIds に "document" は渡せない(Failed to find a node with id document)。
画像を自分の目で確認したいだけなら TakeScreenshot(["<Node ID>"])("document" はこちらでのみ有効)。レスポンスに { nodeId, image: "<base64>", mimeType } の配列が返るので、ファイルとして残すなら base64 を自分でデコードする。
pencil interactive -i "$DESIGN" -o "$DESIGN" <<'EOF' > "${WORK_DIR}/shot.txt"
execute({ input: 'TakeScreenshot(["<Node ID>"])' })
exit()
EOF
grep -o '"image": "[^"]*"' "${WORK_DIR}/shot.txt" | sed 's/.*: "//; s/"$//' | base64 -d > "${SNAP_DIR}/${STEM}-<node>-${TS}.png"
- ファイル命名規則:
<.penファイル名のステム>-<Node名 or Node ID>-<YYYYMMDD-HHMMSS>.png(例:login.penのheaderNode →snapshots/login-header-20260627-153045.png)。タイムスタンプ込みによりsnapshots/内も同時実行で衝突しない - 新規Nodeが親コンテナ内に追加された場合、親Node IDも対象に加えると配置確認しやすい
- ファイル全体のエクスポート(エージェントモードの
--export)は原則使わない。ユーザーが明示的に全体画像を要求した場合のみpencil --in <path> --export <全体画像のpath> --export-scale 2を補助的に使う - スクリーンショットはコスト高。サイズ・配置の確認だけなら
executeのGetvisitor でctx.bounds/ctx.problems("partially clipped"/"fully clipped")をPrintする方が安く確実 Export/TakeScreenshotは編集と同じexecute呼び出しの末尾に置いてよい(同一呼び出し内の変更が反映される)。ただし失敗したexecuteの画像は返らない
ルール6: 実行結果をユーザーに伝える
.pen の中身は直接確認できないため、最終報告に必ず含める:
- 実行したコマンド(エージェントモードのCLIと、インタラクティブモードのheredoc)
- 編集・作成したと判定したNode(IDと、可能なら名前・type)
- 更新または新規作成した
.penファイルの絶対パス - 出力したNode単位スクリーンショット画像の絶対パス(対象Nodeごと)
標準ワークフロー
- 前提確認:
pencil version(0.3.5 以上であること)、pencil status - 操作種別の判定と対象ファイル確認: 編集なら
.penが存在すること、新規作成なら--outのパスが未使用であること(ルール1) - 作業ディレクトリ確保(ルール3)
snapshots/準備:mkdir -p <.penと同じディレクトリ>/snapshots- 編集前スナップショット(編集のみ): ルール4のツリーダンプ(
Print("TREE", ...))→${WORK_DIR}/before.json - 編集/作成実行(ルール1。
executeを使うなら先にread_skill({ path: "pen-schema.md" })/read_skill({ path: "execute.md" })でスキーマとAPIを確認。ログは${WORK_DIR}/edit.logへ) - 編集/作成後スナップショット: 同じツリーダンプ →
${WORK_DIR}/after.json - 失敗検出: 編集はルール4-5 の
jq正規化 diff で「実質的編集が無い」ケースを検出(該当すればルール2に戻る)。新規作成は--outファイルの存在とafter.jsonにNodeが含まれることを確認 - 対象Node特定:
executeなら生成IDマッピング、エージェントモードは before/after の差分、新規作成はafter.jsonのトップレベルフレーム - Node単位スクリーンショット(ルール5。タイムスタンプ込み)
- 報告(ルール6。
${WORK_DIR}は trap で自動削除)
使用例
編集A(自然言語): ログインページに「Forgot password?」リンクを追加
標準ワークフローどおり before.json 取得 → pencil --in designs/login.pen --out designs/login.pen --prompt "Add a 'Forgot password?' link below the password input, aligned to the right" > "${WORK_DIR}/edit.log" 2>&1 → after.json 取得。差分から新規Node forgot-link-01 を特定したら:
TS="$(date +%Y%m%d-%H%M%S)"
mkdir -p designs/snapshots
pencil interactive -i designs/login.pen -o designs/login.pen <<EOF
execute({ input: 'Export(["forgot-link-01"], "png", "${WORK_DIR}/img")' })
exit()
EOF
mv "${WORK_DIR}/img/forgot-link-01.png" "designs/snapshots/login-forgot-link-${TS}.png"
編集B(決定論的): 同じリンクを execute で正確に追加する
pencil interactive -i designs/login.pen -o designs/login.pen <<'EOF' > "${WORK_DIR}/edit.log" 2>&1
read_skill({ path: "pen-schema.md" })
read_skill({ path: "execute.md" })
execute({ input: 'Insert("password-field-01", { type: "text", name: "Forgot Password Link", content: "パスワードをお忘れですか?", fontSize: 13, fill: "#2563EB" })' })
save()
exit()
EOF
## Created nodes by name に出る Forgot Password Link=<id> がそのまま対象Node ID。Error や warnings が出ていたら save() の結果を信用せず、警告内容を直して再実行する。
新規作成: 404エラーページ
# 出力先が未使用であることを確認(既存なら上書きせず、編集として扱うか確認する)
[ -e designs/error-404.pen ] && { echo "designs/error-404.pen は既に存在します" >&2; exit 1; }
# 作成(--in は省略、--out に新しいパス)
pencil --out designs/error-404.pen \
--prompt "Create a 404 error page with a large '404' heading, a 'ページが見つかりません' message, and a primary button linking back to home" \
> "${WORK_DIR}/edit.log" 2>&1
# 作成結果の確認(before は無いので after のみ)
[ -f designs/error-404.pen ] || { echo "作成失敗: edit.log を確認してください" >&2; exit 1; }
その後 after.json を取得し、トップレベルフレーム(例: error-404-page)を同様に execute の Export で snapshots/ へ出力する。
主要オプション/コマンド早見表
エージェントモード(編集・新規作成用)
--in/-i <path>(入力。新規作成時は省略)、--out/-o <path>(出力。編集時は --in と同じパス、新規作成時は未使用の新しいパス)、--prompt/-p <text>(編集・作成指示)、--prompt-file/-f <path>(画像・テキストファイルの添付。参照デザインを渡すときに使う。繰り返し指定可)、--agent <claude|codex|gemini>(既定 claude)、--model/-m <id>(claude-opus-5(既定) / claude-fable-5 / claude-sonnet-5 / claude-haiku-4-5 など。--list-models で一覧)、--effort <level>、--repo/-C <path>(エージェントの作業ディレクトリ)、--max-failed-calls <n>、--verbose/-v、--export/-e <path> / --export-scale <n> / --export-type <png|jpeg|webp|pdf>(ファイル全体の画像出力。本スキルでは原則使わない)
インタラクティブモード(読み書き・スクショ用)
起動オプション: --in / -i <path>(省略で空キャンバス)、--out / -o <path>(ヘッドレス時必須)、--app / -a <name>(起動中アプリへ接続)、--help / -h
シェル内ツール(CLI 0.3.5 はこの5つのみ):
read_skill({ path })— pen.dev 公式スキルの取得。引数なしでSKILL.md、{ path: "pen-schema.md" }で.penスキーマ、{ path: "execute.md" }でexecuteAPIドキュメント(guide/web-app.mdなど SKILL.md から参照されるファイルも読める)get_app_state()— 引数なし。トップレベルNode・再利用可能コンポーネント・選択状態・統合ブラウザの状態のみ(スキーマとAPIドキュメントは返さないのでread_skillを使う)execute({ input })/execute({ editId, edits })— 読み書き・画像出力の中核。Insert/Update/Copy/Replace/Move/Delete/SetVariables/Generate/Get/Print/GetVariables/FindEmptySpace/TakeScreenshot/Export。失敗時はeditId+editsでパッチして再実行するget_style({ name, params })— 視覚スタイルのアーキタイプ(フォント・配色・イメージ)。引数なしで一覧、{ name }で必要paramsの確認、{ name, params }で読み込み。ブランド指定が無い新規作成で作風を揃えたいときに使うbrowser({ action, target, querySelector, url })— 統合ブラウザで実サイトを読み込み、キャンバスへ取り込み/スクショ/DOM取得save()— 編集結果を.penに書き出す(読み取り目的なら省略)/exit()— シェル終了
廃止済み: get_screenshot / export_nodes / export_html / get_guidelines / spawn_agents(0.3.5 で削除。呼ぶと Unknown tool: ...)、および 0.2.x の batch_design / batch_get / get_editor_state / snapshot_layout / get_variables。読み替えは順に execute の TakeScreenshot / Export / Export(html-tailwind / html-css)/ read_skill + get_style / 代替なし、execute の変更系関数 / Get / get_app_state(+ Get のツリーダンプ)/ ctx.bounds の Print / GetVariables()。
トラブルシューティング
pencil: command not found/ 認証エラー: 前提条件の確認どおりnpm install -g @pen.dev/cli(Node.js 18以上)/pencil loginまたはPEN_CLI_KEYを案内Unknown tool: get_screenshot/export_nodes/export_html/get_guidelines/spawn_agents/batch_design/batch_get/get_editor_state: 廃止済み。早見表の「廃止済み」の読み替え表に従う(多くはexecuteの中の関数へ移動している)。pencil versionが 0.3.5 未満なら入れ直すget_app_state({ include_schema: true, ... })が効かない / スキーマが返らない: 0.3.5 のget_app_stateは引数を取らず、スキーマとexecuteAPIドキュメントはread_skill({ path: "pen-schema.md" })/read_skill({ path: "execute.md" })から取るInvalid syntax. Expected: tool_name({ key: value }):executeのinputをダブルクォートで囲んだ中にダブルクォート文字列を注入して入れ子が壊れている。ルール2の原則2(inputはシングルクォート囲み)を適用する-oが必須エラー: ヘッドレス実行では-o必須。ルール2のとおり-iと同じパスを指定する(save()を呼ばなければ変更は永続化されない)TakeScreenshotで画像ファイルができない:TakeScreenshotはレスポンスに base64 を添付するだけ。ファイルとして残すならルール5のデコード手順を使うかExportを使うExportでFailed to find a node with id document:Exportは"document"を受け付けない。トップレベルのフレームIDを列挙するかTakeScreenshot(["document"])を使うexecuteが warnings を返した: プロパティ名・値がスキーマと合っていない。read_skill({ path: "pen-schema.md" })でスキーマを確認し、次のexecuteで直してからsave()する- 編集Nodeが特定できない(idが再採番される/大規模変更): 影響を受けた最上位フレーム/コンポーネントを代表として1つエクスポートし、ユーザーに確認を求める
.penファイルが見つからない: パスを再確認。新規作成の依頼であれば--inを省略して--outに新しいパスを指定する(ルール1の新規作成手順)- 新規作成したはずなのに
--outにファイルが無い /after.jsonのNodeが空:${WORK_DIR}/edit.logを確認し、--promptを具体化して再実行。認証エラーやプロンプト拒否がログに残っていることが多い。executeで作成した場合はsave()の呼び忘れも疑う - 新規作成の
--outに指定したパスが既に存在する: 上書きせず中断し、既存ファイルの編集として扱うか別パスに作成するかをユーザーに確認する .penがgitコンフリクト状態(git statusでUU/AAなど)、またはコンフリクトマーカー混入で破損して開けない: 本スキルの対象外。テキストマージは絶対にせず、resolve-pencil-conflictスキルで解消・復旧する- 想定と違う編集結果:
--promptをより具体的に書き直して再実行するか、決定論的に決めたい部分をexecuteへ移す。.penは上書きされるため、重要な編集前にはユーザーに git コミット等のバックアップを促す - 編集したはずなのに小数点正規化(例:
13.995000000000001→13.995)だけが残っている: heredoc経由のexecuteでJS引数が壊れ、save()だけ走った典型的な事故。ルール2の4原則(<<'EOF'/jq -Rs .・printf '%s'/ リテラル\n)とセルフチェックのcat目視を順に確認して再実行し、ルール4-5 の正規化 diff で「数値正規化だけ」でないことを確認してから報告する
レビュー
まだレビューはありません。使ってみた感想をお寄せください。
同じリポジトリのスキル
概要と使いどころ
Write the merged Pencil design reference back into a UI implementation Issue's description. Takes the Issue number as argument, resolves the merged design PR on the `cc-ui-design-<Issue number>` branch, collects the `.pen` and snapshot paths it added, and appends (or replaces) the `## UIデザイン` section at the end of the Issue body using a lost-update-safe edit.
依頼された内容(自然言語の説明、または既存のIssue番号)を要件とTODOに分解し、タスクごとにGitHub Issueを作成するスキル。タスクの整理・分解、複数Issueの一括作成、依存関係の明示が必要な場合に使用する。「この機能をIssueに分けて」「タスクを洗い出してIssueにして」「PRDのIssue #123 を分解して」といったリクエストで発動する。
claude-task-worker のカスタムワーカー(`workerFiles` に登録する TS 定義)を、`AskUserQuestion` で要件を全項目確定させてから生成し、`claude-task-worker list-workers` でロード検証までするスキル。「カスタムワーカーを作って」「独自のワーカーを追加したい」「新しいラベルで動くワーカーを定義したい」といったリクエストで使用する。
claude-task-workerプラグインのバージョンをインクリメントし、commit-pushでコミット・プッシュしたうえでPRを作成する。引数で `major` / `minor` / `patch` を受け取り、対応する部分をインクリメントする(省略時は `patch`)。「バージョンを上げて」「バージョンアップ」「bump version」「メジャーバージョンを上げて」などのリクエストで使用する。
指定されたPR番号のDependabot PRを確認し、依存ライブラリのバージョンアップ内容をCHANGELOGとcontext7から取得して、コード修正が必要かを判定します。修正が必要な場合は修正を行い、pushまで実施します。