electron-ipc
π―Skillfrom seanchiuai/multishot
electron-ipc skill from seanchiuai/multishot
Installation
npx tsc --initnpx tailwindcss init -pnpm run devSkill Details
Electron IPC communication patterns between main and renderer processes. Use when implementing IPC handlers, sending events between processes, or working with the preload script.
Overview
# Electron IPC & UI (MVP)
Files
src/main/index.ts- Main process, BrowserWindow configsrc/main/ipc.ts- IPC handlerssrc/preload/index.ts- Context bridge APIsrc/renderer/styles.css- Global styles (Tailwind + custom)src/renderer/components/- React UI components
---
Preload API (window.api)
```typescript
interface API {
// Invoke handlers (renderer β main)
startRun(prompt: string, credentials: Credentials): Promise
selectWinner(agentId: string): Promise
cancelRun(): Promise
previewAll(): Promise
// Event listeners (main β renderer)
onAgentOutput(cb: (data: { agentId: string; chunk: string }) => void): () => void
onAgentStatus(cb: (data: { agentId: string; status: AgentStatus }) => void): () => void
onError(cb: (error: string) => void): () => void
}
interface Credentials {
daytonaApiKey: string
claudeOAuthToken?: string
anthropicApiKey?: string
}
interface PreviewResult {
agentId: string
url: string | null
error?: string
}
type AgentStatus = 'idle' | 'running' | 'completed' | 'failed'
```
---
IPC Communication
Main β Renderer Events
```typescript
sendToRenderer('agent-output', { agentId, chunk }) // Terminal data
sendToRenderer('agent-status', { agentId, status }) // Status change
sendToRenderer('error', errorMessage) // Error string
```
Renderer β Main Handlers
```typescript
ipcMain.handle('start-run', async (_event, { prompt, credentials }) => { ... })
ipcMain.handle('select-winner', async (_event, { agentId }) => { ... })
ipcMain.handle('cancel-run', async () => { ... })
ipcMain.handle('preview-all', async () => { ... })
```
Output Buffering
```typescript
const buffer = new OutputBuffer((agentId, data) => {
sendToRenderer('agent-output', { agentId, chunk: data })
})
buffer.append(agentId, chunk) // Add to buffer
buffer.flush(agentId) // Force flush
buffer.flushAll() // Flush all agents
```
---
BrowserWindow Configuration
Current config in src/main/index.ts:
```typescript
const mainWindow = new BrowserWindow({
width: 1400,
height: 900,
minWidth: 1000,
minHeight: 700,
show: false,
autoHideMenuBar: true,
backgroundColor: '#171717',
webPreferences: {
preload: join(__dirname, '../preload/index.js'),
sandbox: false,
contextIsolation: true,
nodeIntegration: false
}
})
```
---
UI Beautification Options
Custom Title Bar (Frameless Window)
```typescript
// Hidden title bar with traffic lights (macOS)
const win = new BrowserWindow({
titleBarStyle: 'hidden',
trafficLightPosition: { x: 15, y: 15 }
})
// Hidden with custom overlay (cross-platform)
const win = new BrowserWindow({
titleBarStyle: 'hidden',
titleBarOverlay: {
color: '#171717',
symbolColor: '#ffffff',
height: 40
}
})
// Custom traffic light behavior (macOS)
const win = new BrowserWindow({
titleBarStyle: 'hiddenInset' // Inset traffic lights
})
const win = new BrowserWindow({
titleBarStyle: 'customButtonsOnHover' // Show on hover only
})
```
Platform Vibrancy Effects
```typescript
// macOS Vibrancy
win.setVibrancy('sidebar') // Options: titlebar, sidebar, window, hud, etc.
win.setVibrancy('under-window') // Translucent background
// Windows 11 Mica/Acrylic (22H2+)
const win = new BrowserWindow({
backgroundColor: '#00000000', // Transparent for effects
// ...
})
win.setBackgroundMaterial('mica') // Long-lived windows
win.setBackgroundMaterial('acrylic') // Transient/popup windows
```
Transparent Window
```typescript
const win = new BrowserWindow({
frame: false,
transparent: true,
resizable: false, // Required when transparent
backgroundColor: '#00000000'
})
```
Window Controls Overlay API
Exposes native controls area to web content:
```typescript
const win = new BrowserWindow({
titleBarStyle: 'hidden',
titleBarOverlay: true // Enable CSS env() variables
})
```
In CSS, use safe area insets:
```css
.titlebar {
padding-top: env(titlebar-area-y, 0);
padding-left: env(titlebar-area-x, 0);
height: env(titlebar-area-height, 40px);
}
/ Draggable region /
.drag-region {
-webkit-app-region: drag;
}
.no-drag {
-webkit-app-region: no-drag;
}
```
---
Tailwind CSS Patterns
Current setup uses Tailwind with dark theme. Key patterns:
Color Palette (neutral-based)
```css
bg-neutral-900 / Main background #171717 /
bg-neutral-800 / Cards, inputs /
bg-neutral-700 / Borders, dividers /
text-neutral-100 / Primary text /
text-neutral-400 / Secondary text /
text-neutral-500 / Muted text, placeholders /
```
Status Colors
```css
/ Running /
bg-yellow-500/20 text-yellow-400 animate-pulse
/ Completed /
bg-green-500/20 text-green-400
/ Failed /
bg-red-500/20 text-red-400
/ Winner highlight /
border-green-500 bg-green-500/5
```
Interactive Elements
```css
/ Buttons - Primary /
bg-blue-600 hover:bg-blue-500 disabled:bg-neutral-700
/ Buttons - Danger /
bg-red-600/20 text-red-400 hover:bg-red-600/30
/ Inputs /
bg-neutral-800 border-neutral-700 focus:ring-2 focus:ring-blue-500
/ Cards /
rounded-lg border border-neutral-700 bg-neutral-800
```
Useful Effects for Beautification
```css
/ Glassmorphism /
backdrop-blur-md bg-white/10
/ Subtle gradients /
bg-gradient-to-br from-neutral-800 to-neutral-900
/ Glow effects /
shadow-lg shadow-blue-500/20
/ Smooth transitions /
transition-all duration-200
/ Hover lift /
hover:-translate-y-0.5 hover:shadow-lg
```
---
xterm.js Theme
Current terminal theme in Terminal.tsx:
```typescript
const terminal = new XTerm({
theme: {
background: '#1e1e1e',
foreground: '#d4d4d4',
cursor: '#d4d4d4',
selectionBackground: '#264f78',
black: '#1e1e1e',
red: '#f44747',
green: '#6a9955',
yellow: '#dcdcaa',
blue: '#569cd6',
magenta: '#c586c0',
cyan: '#4ec9b0',
white: '#d4d4d4'
},
fontSize: 12,
fontFamily: 'Menlo, Monaco, "Courier New", monospace',
scrollback: 10000,
cursorBlink: false,
disableStdin: true
})
```
Alternative themes to consider:
```typescript
// Dracula
theme: {
background: '#282a36',
foreground: '#f8f8f2',
cursor: '#f8f8f2',
red: '#ff5555',
green: '#50fa7b',
yellow: '#f1fa8c',
blue: '#bd93f9',
magenta: '#ff79c6',
cyan: '#8be9fd'
}
// One Dark
theme: {
background: '#282c34',
foreground: '#abb2bf',
cursor: '#528bff',
red: '#e06c75',
green: '#98c379',
yellow: '#e5c07b',
blue: '#61afef',
magenta: '#c678dd',
cyan: '#56b6c2'
}
```
---
Component Architecture
```
App.tsx # State: phase, credentials, agents, winner
βββ SetupWizard.tsx # Credentials input form
βββ GridView.tsx # Header bar + 2x2 grid
βββ AgentCard.tsx # Card with status badge + terminal
βββ Terminal.tsx # xterm.js instance
```
App Phases
setup- Show SetupWizardready- Show prompt input + idle gridrunning- Agents executing, cancel availablecompleted- All done, select winner
---
Cleanup
Always return unsubscribe function and call on unmount to prevent memory leaks:
```typescript
useEffect(() => {
const unsub = window.api.onAgentOutput(({ agentId, chunk }) => {
terminals[agentId].write(chunk)
})
return () => unsub()
}, [])
```