/desktop-framework-electron
Electron process architecture, IPC patterns, preload security, native APIs, packaging and distribution
$ npx -y skills add agents-inc/skills --skill desktop-framework-electron --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.
- You can call itInvoke it directly when you want it.
- Slash command
/desktop-framework-electron
Context preview
The summary Claude sees to decide when to auto-load this skill.
Electron process architecture, IPC patterns, preload security, native APIs, packaging and distribution
SKILL.md
desktop-framework-electron.SKILL.mdname: desktop-framework-electron
description: Electron process architecture, IPC patterns, preload security, native APIs, packaging and distribution
Electron Desktop Applications
> **Quick Guide:** Electron apps run two process types: a **main process** (Node.js, manages windows and system APIs) and **renderer processes** (Chromium, one per window). All communication between them flows through IPC via a preload script that uses `contextBridge` to expose a minimal, typed API surface. Never disable `contextIsolation`. Never enable `nodeIntegration` in renderers. Package with Electron Forge or Electron Builder. Auto-update via `autoUpdater` (Squirrel on macOS/Windows) or `electron-updater` for all platforms.
---
<critical_requirements>
CRITICAL: Before Using This Skill
> **All code must follow project conventions in CLAUDE.md** (kebab-case, named exports, import ordering, `import type`, named constants)
**(You MUST keep `contextIsolation: true` (the default) -- disabling it exposes the entire preload scope to untrusted renderer code)**
**(You MUST use `contextBridge.exposeInMainWorld()` in preload scripts -- never expose `ipcRenderer` directly)**
**(You MUST NOT enable `nodeIntegration: true` in any BrowserWindow -- it gives renderers full Node.js access, which is a critical security vulnerability)**
**(You MUST validate and sanitize ALL data received via IPC in the main process -- treat renderer messages as untrusted input)**
**(You MUST use `ipcMain.handle()` / `ipcRenderer.invoke()` for request-response IPC -- avoid `sendSync` which blocks the renderer)**
**(You MUST NOT load remote URLs with `nodeIntegration` or disabled `contextIsolation` -- this is equivalent to giving the remote site full system access)**
</critical_requirements>
---
**Auto-detection:** Electron, electron, BrowserWindow, ipcMain, ipcRenderer, contextBridge, preload, webPreferences, electron-builder, electron-forge, app.whenReady, electronAPI, mainWindow, autoUpdater, nativeTheme, safeStorage, Tray, Menu, dialog, protocol, shell
**When to use:**
- Building cross-platform desktop applications
- Configuring main process / renderer process architecture
- Setting up secure IPC communication patterns
- Integrating with native OS features (tray, menus, dialogs, notifications, file system)
- Packaging and distributing desktop applications
- Implementing auto-update functionality
- Registering custom protocol handlers / deep links
**When NOT to use:**
- Choosing a UI framework for the renderer (use the appropriate web framework skill)
- Styling the renderer UI (use the appropriate styling skill)
- Server-side or backend logic not related to the main process
- Mobile applications (Electron is desktop-only)
- CLI tools that do not need a GUI
---
<patterns>
Key Patterns
Pattern 1: Secure BrowserWindow Creation
Every BrowserWindow must use a preload script and rely on the secure defaults: `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
},
});**Key point:** Never override the security defaults. The preload script is the ONLY bridge between main and renderer. See [examples/core.md](examples/core.md).
---
Pattern 2: Preload with contextBridge
The preload script exposes a narrow, explicitly typed API to the renderer. Never expose `ipcRenderer` directly.
// 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));
},
});**Key point:** Each exposed method wraps a single IPC channel. The renderer calls `window.electronAPI.readFile(path)` with no knowledge of IPC internals. See [examples/core.md](examples/core.md).
---
Pattern 3: IPC Request-Response (invoke/handle)
Use `ipcMain.handle()` in main and `ipcRenderer.invoke()` in preload for async two-way communication.
// main process
ipcMain.handle("read-file", async (_event, filePath) => {
const content = await fs.readFile(filePath, "utf-8");
return { success: true, content };
});**Key point:** `handle`/`invoke` returns a Promise. Always validate `filePath` in the handler -- never trust renderer input. See [examples/ipc.md](examples/ipc.md) for all IPC patterns.
---
Pattern 4: Main-to-Renderer Messages
Use `webContents.send()` from main and listen in the preload with a callback pattern.
// 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));
},**Key point:** The renderer cannot pull from main -- main must push. Always scope listeners to specific channels. See [examples/ipc.md](examples/ipc.md).
---
Pattern 5: App Lifecycle
The main process manages the app lifecycle with platform-specific conventions.
app.whenReady().then(() => {
createWindow();
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
});
app.on("window-all-closed", () => {
if (process.platform !== "darwin") app.quit();
});**Key point:** macOS apps stay alive when all windows close (`window-all-closed` should not quit). The `activate` event recreates a window when the dock icon is clicked. See [examples/core.md](examples/core.md).
---
Pattern 6: Native OS Integration
Electron exposes native APIs for dialogs, menus, tray icons, notifications,
Read more
name: desktop-framework-electron description: Electron process architecture, IPC patterns, preload security, native APIs, packaging and distribution
Electron Desktop Applications
> **Quick Guide:** Electron apps run two process types: a **main process** (Node.js, manages windows and system APIs) and **renderer processes** (Chromium, one per window). All communication between them flows through IPC via a preload script that uses `contextBridge` to expose a minimal, typed API surface. Never disable `contextIsolation`. Never enable `nodeIntegration` in renderers. Package with Electron Forge or Electron Builder. Auto-update via `autoUpdater` (Squirrel on macOS/Windows) or `electron-updater` for all platforms.
---
<critical_requirements>
CRITICAL: Before Using This Skill
> **All code must follow project conventions in CLAUDE.md** (kebab-case, named exports, import ordering, `import type`, named constants)
**(You MUST keep `contextIsolation: true` (the default) -- disabling it exposes the entire preload scope to untrusted renderer code)**
**(You MUST use `contextBridge.exposeInMainWorld()` in preload scripts -- never expose `ipcRenderer` directly)**
**(You MUST NOT enable `nodeIntegration: true` in any BrowserWindow -- it gives renderers full Node.js access, which is a critical security vulnerability)**
**(You MUST validate and sanitize ALL data received via IPC in the main process -- treat renderer messages as untrusted input)**
**(You MUST use `ipcMain.handle()` / `ipcRenderer.invoke()` for request-response IPC -- avoid `sendSync` which blocks the renderer)**
**(You MUST NOT load remote URLs with `nodeIntegration` or disabled `contextIsolation` -- this is equivalent to giving the remote site full system access)**
</critical_requirements>
---
**Auto-detection:** Electron, electron, BrowserWindow, ipcMain, ipcRenderer, contextBridge, preload, webPreferences, electron-builder, electron-forge, app.whenReady, electronAPI, mainWindow, autoUpdater, nativeTheme, safeStorage, Tray, Menu, dialog, protocol, shell
**When to use:**
- Building cross-platform desktop applications
- Configuring main process / renderer process architecture
- Setting up secure IPC communication patterns
- Integrating with native OS features (tray, menus, dialogs, notifications, file system)
- Packaging and distributing desktop applications
- Implementing auto-update functionality
- Registering custom protocol handlers / deep links
**When NOT to use:**
- Choosing a UI framework for the renderer (use the appropriate web framework skill)
- Styling the renderer UI (use the appropriate styling skill)
- Server-side or backend logic not related to the main process
- Mobile applications (Electron is desktop-only)
- CLI tools that do not need a GUI
---
<patterns>
Key Patterns
Pattern 1: Secure BrowserWindow Creation
Every BrowserWindow must use a preload script and rely on the secure defaults: `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
},
});**Key point:** Never override the security defaults. The preload script is the ONLY bridge between main and renderer. See [examples/core.md](examples/core.md).
---
Pattern 2: Preload with contextBridge
The preload script exposes a narrow, explicitly typed API to the renderer. Never expose `ipcRenderer` directly.
// 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));
},
});**Key point:** Each exposed method wraps a single IPC channel. The renderer calls `window.electronAPI.readFile(path)` with no knowledge of IPC internals. See [examples/core.md](examples/core.md).
---
Pattern 3: IPC Request-Response (invoke/handle)
Use `ipcMain.handle()` in main and `ipcRenderer.invoke()` in preload for async two-way communication.
// main process
ipcMain.handle("read-file", async (_event, filePath) => {
const content = await fs.readFile(filePath, "utf-8");
return { success: true, content };
});**Key point:** `handle`/`invoke` returns a Promise. Always validate `filePath` in the handler -- never trust renderer input. See [examples/ipc.md](examples/ipc.md) for all IPC patterns.
---
Pattern 4: Main-to-Renderer Messages
Use `webContents.send()` from main and listen in the preload with a callback pattern.
// 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));
},**Key point:** The renderer cannot pull from main -- main must push. Always scope listeners to specific channels. See [examples/ipc.md](examples/ipc.md).
---
Pattern 5: App Lifecycle
The main process manages the app lifecycle with platform-specific conventions.
app.whenReady().then(() => {
createWindow();
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
});
app.on("window-all-closed", () => {
if (process.platform !== "darwin") app.quit();
});**Key point:** macOS apps stay alive when all windows close (`window-all-closed` should not quit). The `activate` event recreates a window when the dock icon is clicked. See [examples/core.md](examples/core.md).
---
Pattern 6: Native OS Integration
Electron exposes native APIs for dialogs, menus, tray icons, notifications,
Showing the first part of this file.
The official skills marketplace for Agents Inc. 150+ skills covering everything from React and Prisma to Redis, ElevenLabs, and infrastructure tooling. Pick the skills that match your stack and install them via Claude Code. Need more control?
Repo: agents-inc/skills
Other skills on agents-inc-skills.
- /ai-infrastructure-huggingface-inference
Hugging Face Inference SDK patterns for TypeScript/Node.js — InferenceClient setup, chat completion, text generation, streaming, embeddings, image generation, audio transcription, translation, summarization, and Inference Endpoints
Open skill - /ai-infrastructure-litellm
LiteLLM proxy server setup, TypeScript client patterns via OpenAI SDK, model routing, fallbacks, load balancing, spend tracking, virtual keys, and production deployment
Open skill - /ai-infrastructure-modal
Serverless GPU compute platform for AI model deployment — web endpoints, GPU functions, model serving, and TypeScript client patterns
Open skill - /ai-infrastructure-ollama
Local LLM inference with the Ollama JavaScript client -- chat, streaming, tool calling, vision, embeddings, structured output, model management, and OpenAI-compatible endpoint
Open skill - /ai-infrastructure-replicate
Replicate SDK patterns for TypeScript/Node.js -- client setup, predictions, streaming, webhooks, file handling, model versioning, deployments, and training
Open skill - /ai-infrastructure-together-ai
Together AI SDK patterns for TypeScript — client setup, chat completions, streaming, structured output, function calling, embeddings, image generation, fine-tuning, and OpenAI-compatible endpoints
Open skill

