ドキュメント&知識ベース · daymade/claude-code-skills

excalidraw-use

既存の画像を Excalidraw ホワイトボードに配置し、スライドデッキを事前にスライドごとのクリーンな画像に変換し、.excalidraw ファイルの内部を検査します。ユーザーが Excalidraw、ホワイトボードやキャンバス、.excalidraw ファイル、「白板」や「画板」について言及したとき、特に「これらのスクリーンショットをボードに配置して」「過去のワークショップ画像をキャンバスに追加して」「手動で間隔を調整しなくていいように間隔を空けて配置して」「これらのスライドを描き込み可能な画像に変換して」「このシーンファイルには何が入っている?」といった場合に使用してください。また、共有キャンバス上でスクリーンショットの上に手描きしながら行う講演やワークショップ、選択用の画像トレイが必要な場合にも適しています。テキストの説明から図を生成する用途には対応していません(それは別のツールの役割です)。

L4 高権限 · 段階的認可と監査V1 コミット固定コマンド実行ネットワーク通信ファイル書き込みDual-pass Audit
Author daymadeGitHub daymade/claude-code-skills ↗Stars 1385License MIT(仓库根 LICENSE 文件;GitHub API spdx MIT;Copyright (c) 2025 daymade)Commit d5c4678cb5
管理レベルは Skill の能力と推奨統制措置を示すものであり、品質や安全性の認証、利用可否の判定ではありません。使用の可否はユーザーおよび管理者が決定します。Agent 環境によって制約が異なるため、自動保護を仮定しないでください。第三者製 Skill の著作権は原著作者に帰属し、利用リスクは利用者が負います。

1仕組みと動作原理

最大の特徴は、「大量の画像をホワイトボードに並べる」処理を、ユーザーが作業中のボードを直接編集するのではなく、独立した scene ファイル(ピックトレイ)として構築することです。Job 1 全体で、N 枚の画像を等比率で縮小し、グリッドの中央に配置して files マップに base64 形式で埋め込みます。

excalidraw-use/scripts/build_scene.py
The scene is a *pick tray*: open it in a second Excalidraw tab, select what you want, and copy-paste it onto your real board. It is never written into the board file itself — see references/paste_workflow.md for why that matters.
ここで行っていること:「成果物」と「ユーザーの実作業ファイル」を物理的に分離することで、マージのコンフリクトによる事故を根本から防ぎます。SKILL.md では「Never write into their live board file」というセクションを設け、この原則を徹底しています。

外部ライブラリに頼らず、ファイルヘッダーから直接画像サイズを解析します。PNG は IHDR の 8 バイトの幅・高さを読み取り、JPEG はセグメントをスキャンして SOF マーカーから幅・高さを取得します。

excalidraw-use/scripts/build_scene.py
"""(width, height) in pixels for PNG or JPEG, read from the file's own header."""
実装の詳細:PNG は struct.unpack(">II", data[16:24]) を使用し、JPEG は 0xFF マーカーをスキップして 0xC0〜0xCF 系列を検出します。読み取れない場合は ValueError を発生させ、build() が SystemExit に変換してファイル書き込みを拒否します。「破損したファイルを出力するくらいなら処理を失敗させる」という方針がスクリプト全体で一貫しています。

書き込み後はディスクから再読み込み(リードバック)して自己検証を強制します。要素数、fileId と base64 コンテンツの sha1 の一致、元画像とのアスペクト比の一致、バウンディングボックスの重複有無を検証し、1 つでも不一致があれば SystemExit で終了します。

excalidraw-use/scripts/build_scene.py
Deliberately re-reads from disk rather than checking the in-memory objects: the failure this catches is a bad write, and an in-memory assert cannot see one.
verify() の docstring にその理由が明記されています。SKILL.md ではこの出力行を使用可能かどうかのシグナルとして扱っています:「Expected output — if you do not see the `verified:` line, the file is not usable」。

重複除外および既存要素の判定はファイル名ではなくコンテンツハッシュ(sha256)で行うため、リネームされた複製ファイルも正確に識別されます。

excalidraw-use/scripts/build_scene.py
skip = {hashlib.sha256(p.read_bytes()).hexdigest() for p in exclude if p.exists()}
同一関数内で seen 辞書を用いたバッチ内重複排除も行われます(digest in seen の場合はスキップして「skipped (identical content)」を記録)。SKILL.md の該当項目:「The check is by image content, not filename, so a renamed copy is still caught.」

--template-from は「公式 JSON スキーマに image element 自身のフィールド定義が記載されていない」という欠落を解消します。ユーザー自身のボードから実際の image element をディープコピーしてフィールド構成を取得します。

excalidraw-use/scripts/build_scene.py
for el in scene.get("elements", []): if el.get("type") == "image" and not el.get("isDeleted"): return copy.deepcopy(el)
references/scene_file_format.md の「Image elements — NOT documented」セクションで解説されています:「The published schema describes the `files` map but does not enumerate the image element's own fields.」。また、「未記載のドキュメントから推測するのではなく、配置先から実例をコピーする」というアプローチがまとめられています。

受け渡し手順として「ファイルを開く(Open)」やドラッグ&ドロップではなく、意図的にクリップボードを採用しています。前者の 2 つはユーザーの現在のシーン全体を上書きしてしまうためです。

excalidraw-use/references/paste_workflow.md
The clipboard carries elements *and* their embedded image payloads, so copy-paste merges instead of replacing:
SKILL.md での表現:「at excalidraw.com, both *Open* and drag-and-drop **replace the entire current scene**」。paste_workflow.md でも、ディスク上のファイルと作業中のボードが一致しない理由として、ブラウザタブがファイル変更を検知しないこと、エクスポートされたファイルはブラウザの状態より古いことが多いことの 2 点を挙げています。

Job 2 のスクリーンショットでコンテンツの欠落を防げる理由は、ソースコードから正規表現で slide id と fragmentCount を抽出すること、ハッシュ変更ではなくページごとの完全な page.goto を行うこと、そして innerText ではなく computed opacity でフラグメントが実際に表示されたかを判定することの 3 点にあります。

excalidraw-use/scripts/shoot_deck.mjs
// Fragments that never revealed stay in the DOM at opacity 0, so any check // based on text content reports them as present while the picture is blank. // Measure what actually renders.
実際の判定基準は parseFloat(getComputedStyle(e).opacity) < 0.9 です。未表示の要素は unrevealed に記録され WARNING が出力されます(--strict 指定時は非ゼロで終了)。references/deck_screenshot_pitfalls.md の第 2 節では、「document.body.innerText は 4 年分すべて表示されていて正常に見えるのに、スクリーンショットには 1 年分しか写らない」という直感に反する挙動を指摘しています。

2 つのフラグメント進行モードは排他的とみなされ、スクリプト側で同時使用が禁止されています。--advance には pdf または keys のいずれかのみを指定できます。

excalidraw-use/scripts/shoot_deck.mjs
console.error(`--advance must be "pdf" or "keys", got ${ADVANCE}`)
理由はファイルヘッダーのコメントと SKILL.md に記載されています:「Never both — under `?pdf=1` the fragment index is already at maximum, so extra key presses move to the *next* slide and you silently capture the wrong content.」

Job 3 の inspect_scene.py は読み取り専用のヘルスチェックを行います。要素タイプごとのカウント、埋め込みペイロードサイズ、fileId とコンテンツ sha1 の整合性、占有範囲(ユーザーがどこまでスクロールしてから貼り付けるべきか)を出力します。

excalidraw-use/scripts/inspect_scene.py
# Excalidraw keys files by a content hash; when it holds, a # mismatch means the payload was swapped without rekeying.
レポートでは逆方向の問題(「file {fid} is embedded but no live element uses it」)やアスペクト比の歪み(abs(el['width']/el['height'] - px/py) > 1e-3)も検出します。ファイル全体を読み取り専用で扱い、例外は except Exception でキャッチしてレポート出力の中断を防ぎます。

split_scene.py は要素を均等分割した上で実際のチャンク数に基づいて命名し(「4-of-4 が存在しないのに 1-of-4 になる」状態を防止)、各チャンクが参照している files のみを保持します。そうしなければ分割による容量削減効果が得られないためです。

excalidraw-use/scripts/split_scene.py
"files": {e["fileId"]: files[e["fileId"]] for e in part},
コンテキストコメントには「Carry only the files this part actually references, or every chunk would be as large as the original and the split would buy nothing.」と記載されています。分割後もリードバック検証(要素数、fileId の一致、アスペクト比、重複なし)を実行し、total != len(elements) で要素の脱落を検出します。

2コア機能

01大量の既存画像をホワイトボード上の整列されたグリッドトレイに配置(列数、セルサイズ、間隔を指定可能)
02コンテンツハッシュを用いてボード上に既に存在する画像を除外(名前が変更された複製も検出)
03実際のボードファイルから image element のフィールド構造を抽出(公式スキーマの未記載部分を補完)
04Vite/React スライドデッキからクリーンなスライド単位の PNG 画像を撮影(発表者用 UI の非表示、ステップアニメーションの展開)
05.excalidraw ファイルの読み取り専用ヘルスチェック(要素の内訳、埋め込み容量、無効な参照、ハッシュの一致、占有範囲)
06大規模シーンのファイル分割(数十 MB に及ぶペイロードによるクリップボードのフリーズや無言の失敗を防止)
07「構造は検証済み・描画は未検証」という正確な注意点とクリップボード貼り付け手順の案内

3外部依存関係

KindDependency / Endpoint
packagepuppeteer(Job 2 无头浏览器,第三方 npm 包,需可被解析,skill 不负责安装)
clinode(执行 shoot_deck.mjs)
clinpx vite build(把 deck 从源码构建到 /tmp/deck-dist)
clipython3 / python3 -m http.server(本地静态服务器)
networkhttp://127.0.0.1:8080(无头浏览器取页地址;注意 http.server 默认监听 0.0.0.0)
networkhttps://excalidraw.com(不是调用点:只作为生成 scene 的 source 字段字符串,以及文档里指向站点的手工操作说明)
networkhttps://docs.excalidraw.com/docs/codebase/json-schema(参考文献里引用的官方文档链接,非运行时代码)

4推奨統制措置と判定根拠

安全運用のための推奨統制措置
Agent 向け
段階的・都度認可、サンドボックス推奨
管理者向け
承認フロー、ロールバック可能、全履歴監査
判定根拠(ファイルパスと抜粋)
  • scripts/: ローカルスクリプトまたはコマンドの実行: excalidraw-use/scripts/build_scene.py (python3、標準ライブラリのみ)
  • 网络端点: 外部ネットワークアクセスの宣言: http://127.0.0.1:8080 (ヘッドレスブラウザが /tmp/deck-dist を読み込むためのローカル静的サーバー、python3 -m http.server)
  • 本地工作目录: ファイルの読み書きと成果物出力: <out>.excalidraw (build_scene.py により生成、base64 埋め込み画像を含む。親ディレクトリは自動作成)
監査ノート: 標準基準に基づく判定:① 3 つの主要スクリプト(build/split/inspect)は標準ライブラリのみの Python で構成され、ローカル画像と .excalidraw の読み取り、およびユーザー指定の出力先ファイルへの書き込みのみを行い、ネットワーク通信や認証情報の扱いは皆無です(ワークスペース全体のトークンスキャンにおいて subprocess/os.environ/API_KEY/TOKEN/SECRET/.env/cookie/keychain の該当なし)。② 唯一の外部コード実行は Job 2 の Puppeteer ヘッドレスブラウザですが、ユーザー自身のローカルデッキを対象としており Node へのフォールバックもないため、任意コード実行のリスクはありません。③ 認証情報の取得、シークレット、トラッキング、外部ミラーへのアクセスはなく、ドメインレベルで登場するのは excalidraw.com(シーンの source 文字列として埋め込まれるのみ)と docs.excalidraw.com(ドキュメントリンク)のみです。グリーン判定とならない理由は、Job 2 がサードパーティ npm パッケージである puppeteer に依存している点(スキルには同梱されておらず環境依存)、および SKILL.md で指定された python3 -m http.server 8080 がデフォルトで 0.0.0.0 にバインドされ、/tmp/deck-dist のファイル一覧とコンテンツが同一ネットワーク内に公開される可能性がある点です(スクリプト自体の動作ではなくドキュメントの指示事項ですが注意が必要です)。

5二重目の独立検証

  • [ok] external_deps 每条的调用点是否真实存在 — puppeteer(shoot_deck.mjs 第 1 行 import)、node(shebang)、npx vite build 与 python3 -m http.server(SKILL.md Job 2 命令行)、127.0.0.1:8080(--url 实参)全部实读命中,非推测。
  • [discrepancy] excalidraw.com 是否被当作网络端点误报 — 〔第二遍标注:第一遍易误报,已修正〕build_scene.py 与 split_scene.py 里的 https://excalidraw.com 只是写入 scene 的 "source" 字段值,脚本从不请求该域名;README/文档里的链接同理。已在 external_deps 中显式标注『不是调用点』,避免把字符串常量当成外发。
  • [discrepancy] exec( 命中是否意味着命令执行 — 〔第二遍标注:扫描器误报,已澄清〕shoot_deck.mjs 的 const frag = /fragmentCount:\s*(\d+)/.exec(m[2]) 是 JavaScript RegExp.prototype.exec,属正则匹配,不执行进程。全目录无 child_process / spawn / execSync / subprocess。
  • [ok] 『不写用户现场板子』是否只是口号 — 代码层:build_scene.py 只写 --out 指定路径,从不读入并回写用户的板子文件;文档层:SKILL.md 有独立小节『## Never write into their live board file』并给出两条独立理由(标签页不监听文件、磁盘文件通常旧于浏览器状态)。
  • [ok] 写入后校验是否真做(不是文档承诺) — build_scene.py 的 verify() 在 build() 末尾被调用且从磁盘重读;split_scene.py 对每个分片做同样校验。两道都是可执行代码,失败即 SystemExit。
  • [unlocatable] python3 -m http.server 绑定范围 — 〔第二遍标注:文档未声明,属解释器默认行为〕SKILL.md 只写 python3 -m http.server 8080,未写 --bind 127.0.0.1;http.server 的默认绑定是 0.0.0.0。这是 CPython 的既定行为而非本 skill 的代码,故标注为「文档未声明」并在 security.reason 中提示,不写成 skill 缺陷。
  • [ok] Job 2 的 --advance 互斥是否代码强制 — shoot_deck.mjs 中 if (!['pdf','keys'].includes(ADVANCE)) 报错退出,且 query 只在 ADVANCE === 'pdf' 时拼 ?pdf=1;SKILL.md 有对应警告段,代码与文档一致。
  • [ok] 元数据(license/stars/last_push) — 取自同 repo 同 commit 的池内既有值(MIT、1385★、2026-09-09T12:33:29Z);本次未联网复核 gh。

6結論

  • Python 外部依存ゼロかつ書き込み後の即時自動検証により、出力成果物が気付かないうちに壊れるリスクを排除。
  • 「成果物の受け渡し」自体を重大なリスク要因として設計(Open ではなくクリップボード経由)。ユーザーの作業中データの安全性をプロセスに組み込んだ数少ないスキル。
  • 公式スキーマの不備を的確に把握し、フィールドを当て推量するのではなく再現可能な代替策(--template-from)を提供。
  • スクリーンショット処理において「一見正しそうだが実は破綻している」失敗パターンを網羅的に防止(opacity 判定、完全 goto、advance の排他制御、キーストロークバッジの待機、2 系統の装飾非表示)。
  • 機能の限界を誠実に明示:データ構造は検証可能だが実際の描画結果までは検証できないことを明記し、ユーザーへの説明を義務化。
  • 最適な用途: 手元にある大量のスクリーンショットや写真を既存のホワイトボードへ一括配置したい場合(手動ドラッグの手間を解消)、Vite/React スライドデッキを事前に綺麗な単一画像へ変換してキャンバス素材として利用したい場合、あるいはブラウザを開かずに .excalidraw の中身や壊れた参照の有無を確認したい場合に適しています。また、「Excalidraw ファイルフォーマットの実践的な仕様メモ」としても有用であり、references/scene_file_format.md にまとめられた公式未記載仕様の一覧は、独自ツールの開発に直接役立ちます。
    不向きな用途: 1 つの指示文からアーキテクチャ図やフローチャートなどの作図を行う用途には不向きです(SKILL.md で明示的に他ツールへの委譲が指定されており、本スキルは生成を行いません)。ユーザーによる手動貼り付けを行わず、エージェントが単独で完結させる必要があるワークフローには適していません。Vite/React 以外のスライドや、スライド登録形式が異なるデッキには対応していません(shoot_deck.mjs の正規表現は { id: '...', fragmentCount: n } 形式のみを前提としており、一致しない場合は終了します)。エージェントが excalidraw.com をブラウザで開いて描画結果を確認するような運用には適していません(作業中のボードが上書きされてしまうため)。
    Install Agent-Ready
    ① Verified Mirror 2026-09-15
    Option A · Direct DownloadDownload excalidraw-use.tar.gz
    sha256: 0c4ae44eb4c051d3…
    Option B · Copy Guide for Agent
    install.json
    Agent はこの JSON ガイドから自動的にダウンロードして検証します。
    ② Upstream GitHub
    GitHub Repo ↗
    Pinned to commit d5c4678cb5.