🎯

electron-ipc

🎯Skill

from seanchiuai/multishot

VibeIndex|
What it does

electron-ipc skill from seanchiuai/multishot

electron-ipc

Installation

npxRun with npx
npx tsc --init
npxRun with npx
npx tailwindcss init -p
npm runRun npm script
npm run dev
πŸ“– Extracted from docs: seanchiuai/multishot
1
-
Last UpdatedJan 24, 2026

Skill Details

SKILL.md

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 config
  • src/main/ipc.ts - IPC handlers
  • src/preload/index.ts - Context bridge API
  • src/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

  1. setup - Show SetupWizard
  2. ready - Show prompt input + idle grid
  3. running - Agents executing, cancel available
  4. completed - 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()

}, [])

```