Electron IPC Communication
Expert knowledge of Electron Inter-Process Communication patterns for SEPilot Desktop. Use this when adding IPC handlers, creating frontend-backend communication, implementing streaming responses, or debugging IPC issues. Ensures secure and efficient communication between renderer and main processes.
$ Instalar
git clone https://github.com/jhl-labs/sepilot_desktop /tmp/sepilot_desktop && cp -r /tmp/sepilot_desktop/.claude/skills/electron-ipc ~/.claude/skills/sepilot_desktop// tip: Run this command in your terminal to install the skill
SKILL.md
name: Electron IPC Communication description: > Expert knowledge of Electron Inter-Process Communication patterns for SEPilot Desktop. Use this when adding IPC handlers, creating frontend-backend communication, implementing streaming responses, or debugging IPC issues. Ensures secure and efficient communication between renderer and main processes.
Electron IPC Communication Skill
Architecture Pattern
SEPilot Desktop uses Electron IPC for all frontend-backend communication:
- Frontend → Backend:
window.electron.invoke('channel-name', data) - Backend → Frontend:
event.sender.send('channel-name', data) - Streaming: Use IPC events (never HTTP) for real-time data
Handler Location
All IPC handlers are in electron/ipc/handlers/:
langgraph.ts- LangGraph agent execution with streamingupdate.ts- Application auto-update functionality- Add new handlers here following the same pattern
Creating New Handlers
Backend Handler (electron/ipc/handlers/)
import { ipcMain, IpcMainInvokeEvent } from 'electron';
export function setupMyFeatureHandlers() {
// Request-response pattern
ipcMain.handle('myfeature:action', async (event: IpcMainInvokeEvent, data: InputType) => {
// 1. Validate input
if (!data || !data.requiredField) {
throw new Error('Invalid input');
}
// 2. Perform work
const result = await doWork(data);
// 3. Return results
return { success: true, data: result };
});
// Streaming pattern (for LLM responses, etc.)
ipcMain.handle('myfeature:stream', async (event: IpcMainInvokeEvent, data: InputType) => {
const stream = createStream(data);
stream.on('data', (chunk) => {
// Send incremental updates
event.sender.send('myfeature:stream:data', chunk);
});
stream.on('end', () => {
event.sender.send('myfeature:stream:end');
});
stream.on('error', (error) => {
event.sender.send('myfeature:stream:error', error.message);
});
return { success: true };
});
}
Frontend Usage (app/ or components/)
// Simple request-response
const result = await window.electron.invoke('myfeature:action', {
requiredField: 'value',
});
// Streaming
window.electron.on('myfeature:stream:data', (data) => {
setStreamData((prev) => [...prev, data]);
});
window.electron.on('myfeature:stream:end', () => {
setIsStreaming(false);
});
window.electron.on('myfeature:stream:error', (error) => {
console.error('Stream error:', error);
});
await window.electron.invoke('myfeature:stream', { prompt: 'Hello' });
Security Checklist
- Validate all incoming IPC data (type, shape, values)
- Use TypeScript strict mode for type safety
- Sanitize user input before using in bash/file operations
- Never expose sensitive file paths to frontend
- Use
app.getPath('userData')for persistent storage - Avoid command injection in
execFileorspawn
Type Definitions
Define IPC types in lib/types/ or inline:
interface MyFeatureRequest {
prompt: string;
options?: {
temperature?: number;
maxTokens?: number;
};
}
interface MyFeatureResponse {
success: boolean;
data?: ResultType;
error?: string;
}
Testing IPC
// In tests
const result = await window.electron.invoke('myfeature:action', testData);
expect(result.success).toBe(true);
Real-World Examples
See existing handlers:
electron/ipc/handlers/langgraph.ts- Streaming LangGraph responseselectron/ipc/handlers/update.ts- Update checks and installation
Common Patterns
File Operations
import { app } from 'electron';
import * as path from 'path';
import * as fs from 'fs/promises';
const userDataPath = app.getPath('userData');
const filePath = path.join(userDataPath, 'conversations', `${id}.json`);
await fs.writeFile(filePath, JSON.stringify(data));
Error Handling
ipcMain.handle('myfeature:action', async (event, data) => {
try {
const result = await doWork(data);
return { success: true, data: result };
} catch (error) {
console.error('Error in myfeature:action:', error);
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error',
};
}
});
Quick Reference
| Pattern | Use Case | Example |
|---|---|---|
handle + invoke | Request-response | ipcMain.handle() + window.electron.invoke() |
handle + sender.send | Streaming | Initiate with handle, stream with sender.send() |
on listener | Receive streams | window.electron.on('channel', callback) |
Repository

jhl-labs
Author
jhl-labs/sepilot_desktop/.claude/skills/electron-ipc
41
Stars
1
Forks
Updated5d ago
Added1w ago