EasyEDA Pro を外部から自動操作する — 拡張機能を書かずに CDP で叩く

設計ツール自動化 2026年8月4日

GUI しか入口がない設計ツールを、どう自動化するか

基板設計を繰り返していると、同じ操作を何度もやることになります。 製造データを出す、部品表を吐く、回路図の変更を基板に反映する。 どれも決まった手順なのに、毎回マウスで同じ場所をクリックしています。

EasyEDA Pro には拡張機能の仕組みがあり、eda.* という API が公開されています。 ドキュメント上はこれで自動化できます。

しかし拡張機能として書くと、面倒がついて回ります。

やりたいのは「アプリの外から1コマンドで叩く」ことでした。

結論から言うと、拡張機能を1つも書かずに、同じ API をすべて外部から呼べます。

この記事が向いていない人

仕組み:Electron のレンダラに拡張APIが露出している

EasyEDA Pro のデスクトップ版は Electron アプリです。 つまり中身は Chromium で、**Chrome DevTools Protocol(CDP)**が使えます。

ここからが本題です。

エディタのレンダラプロセスには window._EXTAPI_ROOT_ というオブジェクトがあります。 そしてこれが、拡張機能の中で eda として参照するオブジェクトそのものです。

拡張機能の中:  eda.pcb_ManufactureData.getGerberFile(...)
レンダラの中:  window._EXTAPI_ROOT_.pcb_ManufactureData.getGerberFile(...)

同じものです。

つまり CDP でレンダラに接続して JavaScript を評価できれば、 拡張をインストールすることも、署名を通すことも不要で、API 全体に手が届きます。

筆者の環境では 94 名前空間 / 703 メソッドが見えています。

手順

1. CDP を有効にして起動する

easyeda-pro.exe --remote-debugging-port=9222

素で起動したプロセスには後から CDP を生やせません。 すでに起動している場合は、一度終了してから起動し直す必要があります。 未保存の作業があると失われるので、ここは自動で kill せず、 手動で保存・終了してもらう運用にしています。

2. レンダラのターゲットを探す

http://127.0.0.1:9222/json

これでターゲットの一覧が JSON で返ります。 複数のウィンドウやワーカーが並ぶので、エディタのレンダラを選ぶ必要があります。 webSocketDebuggerUrl が接続先です。

3. WebSocket で繋いで評価する

Runtime.evaluate に式を渡します。非同期 API が多いので awaitPromise: true を付けるのがポイントです。

{
  "id": 1,
  "method": "Runtime.evaluate",
  "params": {
    "expression": "window._EXTAPI_ROOT_.sys_Environment.getEditorCurrentVersion()",
    "awaitPromise": true,
    "returnByValue": true
  }
}

これだけです。あとは呼びたいメソッドを差し替えるだけになります。

筆者は PowerShell のラッパーを書いて、こう叩けるようにしています。

.\eda-cdp.ps1 -Expression 'await eda.sys_Environment.getEditorCurrentVersion()'
.\eda-cdp.ps1 -File .\scripts\pcb-summary.js

Claude Code から自動化する場合、この1行が実行単位になります。 API の名前さえ分かれば、あとは自然言語で指示して実行させられます。

API の名前をどう調べるか

推測は当たりません。引数の順序も enum の値も、想像とは違います。

幸い、クライアントに api-types.d.ts が同梱されています。 型定義とコメント(中国語)が入っているので、これを検索するのが確実です。

クラス名から名前空間への変換は、先頭だけ小文字という規則です。

PCB_Document  →  eda.pcb_Document
SYS_Message   →  eda.sys_Message

ハマった点

ここからが本題かもしれません。素直に動かない API がそれなりにあります。

ヘッドレスでない API がある

pcb_Document.importChanges()(回路図→基板の反映)は、 確認ダイアログを開くだけで true を返します。 「Apply Changes」を押すまで、実際には何も変わりません。

返り値が true なので、成功したと勘違いします。

対処は単純で、ダイアログのボタンを自分で押す関数を用意しました。

await eda.pcb_Document.importChanges();
await clickDialogButton('apply changes');

アプリ自身のボタンを押すのは安全ですが、DOM 要素を消してはいけません。 トースト通知を消そうとして要素を削除したら、UI 全体が消えました (レンダラをリロードして復帰しました)。 showToastMessage の表示時間に 0(無期限)を渡すと閉じる API が無いので、 必ず有限値を渡す、というのも同じ話です。

ファイルを外に出せない

sys_FileSystem.saveFile()ネイティブの保存ダイアログが出ます。自動化になりません。 saveFileToFileSystem() は拡張の権限が無いため Failed to fetch で落ちます。

そこで、生成したデータを base64 にして CDP の戻り値として吸い出し、 呼び出し側で書き出す方式にしました。ガーバー、BOM、ピック&プレース、 DXF、PDF、IPC-2581、ODB++、3D — 製造データ系は pcb_ManufactureData に揃っているので、これで全部持ち出せます。

壊れている API

呼んでも意図通りに動かないものがあります。

呼び出し挙動
dmt_Project.createProject()必須の path を送らないため常に undefined
dmt_Project.deleteProject()@internal で無効
dmt_Project.getAllProjectsUuid()ローカル工程では常に []
sys_FileSystem.getProjectsPaths()応答しない(await するとハングする)
sch_Netlist.getNetlist()同上。sch_ManufactureData.getNetlistFile() を使う
sys_FileSystem.saveFileToFileSystem()拡張権限が無く Failed to fetch

工程(プロジェクト)の作成・削除は拡張 API ではできません。 内部の HTTP API を直接叩く別スクリプトで回避しています。

なお、開いたままの工程を削除するとフロントエンドの状態が壊れます。 以降 openProject() が黙って false を返し続けるようになるので、 削除処理の後は自動でリロードするようにしました。

危険な API に注意

これが一番重要です。

pcb_ManufactureData.place*Order()
sch_ManufactureData.place*Order()

これらは 実際に JLCPCB へ発注します。

API 一覧を眺めながら「何が呼べるか試す」という進め方をしていると、 うっかり呼ぶ可能性があります。名前で判断せず、必ず事前に確認してください。

同様に、openProject()closeDocument()未保存の変更を無確認で破棄します。 先に sch_Document.save() / pcb_Document.save() を呼ぶ必要がありますが、 save はディスク上を上書きするので、これも安易に呼べません。

自動化スクリプトを書くときは、破壊的な操作の前に必ず人間の確認を挟む設計にしています。

この方法の位置づけ

利点は明確です。

欠点も明確です。

個人の作業を自動化する用途には十分に実用的で、 実際に基板の製造データ出力まで一通り自動化できています。 業務の本番フローに載せるなら、壊れたときに自分で直せることが前提になります。

まとめ

GUI しか入口がないと思っていたツールでも、 Electron 製なら中身に手が届くことがあります。 同じ発想は他の Electron アプリにも使えるはずです。


実装の詳細(依存なしの Node.js コード、ターゲットの特定方法、ヘルパーの実装)は Zenn に書きました → EasyEDA Pro を拡張機能なしで外部から自動操作する