mcpField
D
desktop-framework-electron

desktop-framework-electron

github.com/agents-inc開発2656 回インストール2 日前に更新
リポジトリ

desktop-framework-electron について

Electron デスクトップアプリの開発ガイドです。プロセス構成、安全な IPC、ネイティブ API、パッケージ化や更新を扱い、特に安全な既定値とプロセス間通信の検証に重点を置いています。

主な機能

  1. 01メイン・レンダラープロセス構成
  2. 02安全な BrowserWindow 設定
  3. 03contextBridge による IPC ラップ
  4. 04要求応答とプッシュ通知
  5. 05ネイティブ API とディープリンク
  6. 06パッケージ化と自動更新

活用シーン

  1. 01クロスプラットフォーム Electron アプリの構築
  2. 02プロセス間通信の設計と確認
  3. 03メニュー、トレイ、ファイルダイアログの追加
  4. 04配布とアプリ更新の設定

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/agents-inc/skills --skill desktop-framework-electron

インストール後、Claude Code で/desktop-framework-electronを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

metadata.yaml
reference.md
examples/
core.md
ipc.md
native-apis.md
packaging.md
security.md

詳細

Electron デスクトップアプリケーション

クイックガイド: Electron アプリは、2 種類のプロセスで動作します。ウィンドウとシステム API を管理する メインプロセス(Node.js)と、ウィンドウごとに 1 つ起動する レンダラープロセス(Chromium)です。両者の通信はすべて、contextBridge を使って最小限の型付き API を公開するプリロードスクリプト経由で IPC を利用します。contextIsolation は絶対に無効にしないでください。レンダラーで nodeIntegration を絶対に有効にしないでください。Electron Forge または Electron Builder でパッケージ化してください。自動更新には、autoUpdater(macOS/Windows では Squirrel)またはすべてのプラットフォームに対応する electron-updater を使用してください。


<critical_requirements>

重要:このスキルを使用する前に

(contextIsolation: true(デフォルト)を必ず維持してください。有効範囲を無効にすると、信頼できないレンダラーコードにプリロードの全スコープが公開されます)

(プリロードスクリプトでは必ず contextBridge.exposeInMainWorld() を使用してください。ipcRenderer を直接公開してはいけません)

(どの BrowserWindow でも nodeIntegration: true を有効にしてはいけません。レンダラーに Node.js への完全なアクセス権が付与されるため、重大なセキュリティ脆弱性となります)

(メインプロセスで IPC 経由で受信するすべてのデータを必ず検証し、サニタイズしてください。レンダラーからのメッセージは信頼できない入力として扱ってください)

(リクエストとレスポンスを伴う IPC には、必ず ipcMain.handle() / ipcRenderer.invoke() を使用してください。レンダラーをブロックする sendSync は避けてください)

(nodeIntegration が有効、または contextIsolation が無効な状態でリモート URL を読み込んではいけません。これはリモートサイトにシステムへの完全なアクセス権を与えるのと同じです)

</critical_requirements>


自動検出: Electron、electron、BrowserWindow、ipcMain、ipcRenderer、contextBridge、preload、webPreferences、electron-builder、electron-forge、app.whenReady、electronAPI、mainWindow、autoUpdater、nativeTheme、safeStorage、Tray、Menu、dialog、protocol、shell

使用する場面:

  • クロスプラットフォームのデスクトップアプリケーションを構築する
  • メインプロセス/レンダラープロセスのアーキテクチャを設定する
  • セキュアな IPC 通信パターンを構築する
  • ネイティブ OS の機能(トレイ、メニュー、ダイアログ、通知、ファイルシステム)を統合する
  • デスクトップアプリケーションをパッケージ化して配布する
  • 自動更新機能を実装する
  • カスタムプロトコルハンドラー/ディープリンクを登録する

使用しない場面:

  • レンダラー用の UI フレームワークを選ぶ(適切なウェブフレームワークのスキルを使用してください)
  • レンダラー UI のスタイルを設定する(適切なスタイリングスキルを使用してください)
  • メインプロセスに関係しないサーバー側またはバックエンドのロジック
  • モバイルアプリケーション(Electron はデスクトップ専用です)
  • GUI を必要としない CLI ツール

主なパターン

パターン 1:セキュアな BrowserWindow の作成

すべての BrowserWindow でプリロードスクリプトを使用し、セキュアなデフォルト設定(contextIsolation: true、sandbox: true、nodeIntegration: false)を維持する必要があります。

const mainWindow = new BrowserWindow({
  width: 1200,
  height: 800,
  webPreferences: {
    preload: path.join(__dirname, "preload.js"),
    // contextIsolation: true  -- default since Electron 12
    // sandbox: true           -- default since Electron 20
    // nodeIntegration: false  -- default since Electron 5
  },
});

重要な点: セキュリティのデフォルト設定を絶対に上書きしないでください。メインプロセスとレンダラーの間をつなぐ唯一のブリッジがプリロードスクリプトです。詳しくは examples/core.md を参照してください。


パターン 2:contextBridge を使ったプリロード

プリロードスクリプトは、明示的に型を指定した限定的な API をレンダラーに公開します。ipcRenderer を直接公開してはいけません。

// preload.js
const { contextBridge, ipcRenderer } = require("electron");

contextBridge.exposeInMainWorld("electronAPI", {
  readFile: (filePath) => ipcRenderer.invoke("read-file", filePath),
  onUpdateAvailable: (callback) => {
    ipcRenderer.on("update-available", (_event, data) => callback(data));
  },
});

重要な点: 公開する各メソッドは、単一の IPC チャネルをラップします。レンダラーは IPC の内部実装を知らなくても、window.electronAPI.readFile(path) を呼び出せます。詳しくは examples/core.md を参照してください。


パターン 3:IPC のリクエストとレスポンス(invoke/handle)

非同期の双方向通信には、メインプロセスで ipcMain.handle() を、プリロードで ipcRenderer.invoke() を使用します。

// main process
ipcMain.handle("read-file", async (_event, filePath) => {
  const content = await fs.readFile(filePath, "utf-8");
  return { success: true, content };
});

重要な点: handle/invoke は Promise を返します。ハンドラー内で必ず filePath を検証してください。レンダラーからの入力を信頼してはいけません。すべての IPC パターンについては examples/ipc.md を参照してください。


パターン 4:メインプロセスからレンダラーへのメッセージ

メインプロセスから webContents.send() を使用し、プリロードではコールバックパターンでリッスンします。

// main: send to specific window
mainWindow.webContents.send("update-progress", { percent: 45 });

// preload: expose listener
onUpdateProgress: (callback) => {
  ipcRenderer.on("update-progress", (_event, data) => callback(data));
},

重要な点: レンダラーからメインプロセスのデータを取得することはできません。メインプロセスから送信する必要があります。リスナーは必ず特定のチャネルに限定してください。詳しくは examples/ipc.md を参照してください。


パターン 5:アプリのライフサイクル

メインプロセスは、プラットフォーム固有の規約に従ってアプリのライフサイクルを管理します。

app.whenReady().then(() => {
  createWindow();
  app.on("activate", () => {
    if (BrowserWindow.getAllWindows().length === 0) createWindow();
  });
});

app.on("window-all-closed", () => {
  if (process.platform !== "darwin") app.quit();
});

重要なポイント: macOS アプリはすべてのウィンドウを閉じても終了しません(window-all-closed で終了させてはいけません)。Dock アイコンがクリックされると、activate イベントによってウィンドウが再作成されます。examples/core.md を参照してください。


パターン 6:OS ネイティブとの統合

Electron は、ダイアログ、メニュー、トレイアイコン、通知などのネイティブ API をメインプロセスから利用できるようにします。

const { dialog } = require("electron");

const result = await dialog.showOpenDialog(mainWindow, {
  properties: ["openFile", "multiSelections"],
  filters: [{ name: "Documents", extensions: ["txt", "md", "json"] }],
});

重要なポイント: mainWindow を第 1 引数として渡すと、ネイティブダイアログはそのウィンドウに対してモーダルになります。examples/native-apis.md を参照してください。


パターン 7:カスタムプロトコル/ディープリンク

ブラウザーやほかのアプリからのディープリンクに対応するため、アプリを myapp:// URL のハンドラーとして登録します。

if (process.defaultApp) {
  app.setAsDefaultProtocolClient("myapp", process.execPath, [
    path.resolve(process.argv[1]),
  ]);
} else {
  app.setAsDefaultProtocolClient("myapp");
}

重要なポイント: 開発時(process.defaultApp が true の場合)は、引数としてスクリプトのパスを渡す必要があります。macOS では、app オブジェクトの open-url イベントを処理します。Windows/Linux では、second-instance イベントで処理します。examples/native-apis.md を参照してください。


<decision_framework>

判断フレームワーク

IPC パターンの選択
Which IPC pattern?
+-- Renderer needs a response from main?
|   +-- YES --> ipcMain.handle() + ipcRenderer.invoke()
+-- Renderer sends data, no response needed?
|   +-- YES --> ipcMain.on() + ipcRenderer.send()
+-- Main needs to push data to renderer?
|   +-- YES --> webContents.send() + ipcRenderer.on() (in preload)
+-- Two renderers need to communicate?
|   +-- YES --> Route through main process (never direct renderer-to-renderer)
+-- High-frequency data transfer (streaming)?
    +-- YES --> MessageChannelMain / MessagePort pair
ウィンドウのアーキテクチャ
How many windows?
+-- Single window app?
|   +-- One BrowserWindow, one preload script
+-- Multi-window (e.g., preferences, about)?
|   +-- Separate BrowserWindow per view, each with its own preload
+-- Frameless / custom title bar?
|   +-- frame: false + custom drag regions via CSS (-webkit-app-region: drag)
+-- Persistent background work?
    +-- Use a hidden BrowserWindow or utilityProcess (Electron 22+)

</decision_framework>


詳細なリソース:

  • examples/core.md - アプリのライフサイクル、BrowserWindow、preload、contextBridge の基礎
  • examples/ipc.md - すべての IPC パターン:invoke/handle、send/on、メインプロセスからレンダラープロセスへの通信、MessagePort
  • examples/security.md - セキュリティの強化、CSP、権限ハンドラー、安全なデフォルト設定
  • examples/native-apis.md - ダイアログ、メニュー、トレイ、通知、プロトコルハンドラー、自動アップデーター
  • examples/packaging.md - Electron Forge、Electron Builder、コード署名、配布
  • reference.md - API クイックリファレンステーブル、バージョン履歴、セキュリティチェックリスト

<red_flags>

危険なパターン

重大なセキュリティ上の問題:

  • contextIsolation を無効にする(contextIsolation: false)――preload のグローバルをレンダラープロセスに公開します
  • nodeIntegration: true を有効にする――レンダラープロセスに Node.js への完全なアクセス権を与えます(fs、child_process など)
  • 個々のチャネルをラップせずに、ipcRenderer を contextBridge 経由で直接公開する
  • sandbox: true を設定せずに、リモート URL や信頼できない URL を読み込む
  • 本番環境で webSecurity を無効にする(webSecurity: false は同一オリジンポリシーを無効にします)
  • メインプロセスのハンドラーで IPC 引数を検証しない(パストラバーサル、インジェクション攻撃)
  • 検証されていない URL に対して shell.openExternal() を使用する(任意のコマンドが実行される可能性があります)

アーキテクチャ上の問題:

  • ipcRenderer.sendSync() を使用する――レンダラープロセスをブロックし、UI のフリーズを引き起こします
  • メインプロセスではなく、レンダラープロセスにビジネスロジックを置く
  • レンダラープロセス間で直接通信する(メインプロセスを介さない)
  • remote モジュールを使用する(Electron 14 以降で削除済み。セキュリティとパフォーマンスのリスクがありました)
  • レンダラープロセスから BrowserWindows を作成する
  • プラットフォームごとに window-all-closed を適切に処理しない(macOS アプリは終了させてはいけません)

パッケージング上の問題:

  • 本番ビルドに devDependencies を含めて配布する(アプリのサイズが肥大化します)
  • アプリケーションにコード署名しない(macOS で OS の警告が表示され、自動アップデートが失敗します)
  • node_modules を整理せずにバンドルする、または ASAR アーカイブを使用しない
  • 開発環境とパッケージ化環境で異なる絶対パスをハードコードする
  • レンダラープロセスのコードで __dirname を使用する(サンドボックス化されたレンダラープロセスでは使用できません)

よくある間違い:

  • app.whenReady() を呼び出し忘れる――ready イベントより前は API を利用できません
  • activate イベントでウィンドウを再作成しない(macOS では Dock をクリックしても何も起こりません)
  • <script> タグで読み込まれるレンダラースクリプト内で require() を使用する(サンドボックス化されたレンダラープロセスでは使用できません)
  • 外部コンテンツを読み込む iframe に対して nodeIntegrationInSubFrames: true を設定する
  • レンダラー HTML に適切な Content-Security-Policy ヘッダーを設定しない

</red_flags>


<critical_reminders>

重大な注意事項

(contextIsolation: true(デフォルト)を必ず維持してください。これを無効にすると、信頼されていないレンダラーコードにプリロードのスコープ全体が公開されます)

(プリロードスクリプトでは必ず contextBridge.exposeInMainWorld() を使用してください。ipcRenderer を直接公開してはいけません)

(いずれの BrowserWindow でも nodeIntegration: true を有効にしてはいけません。レンダラーに Node.js への完全なアクセス権が与えられ、重大なセキュリティ上の脆弱性につながります)

(IPC 経由で受信するすべてのデータを、メインプロセスで必ず検証してサニタイズしてください。レンダラーからのメッセージは信頼できない入力として扱ってください)

(リクエストとレスポンスを伴う IPC には、必ず ipcMain.handle() / ipcRenderer.invoke() を使用してください。レンダラーをブロックする sendSync は避けてください)

これらのルールに従わないと、深刻なセキュリティ上の脆弱性や、正常に動作しないデスクトップアプリが発生します。

</critical_reminders>

コメント