Last Updated: 2026-03-11 17:34 ET (America/New_York)
This document covers the inter-process communication system between main and renderer processes.
-
src/main/ipc/handlers/index.tsis the authoritative registry. Add new handlers there and ensure they are registered before any BrowserWindow is created. -
Domain handlers:
backend-handlers.ts,calibration-handlers.ts,camera-handlers.ts,component-dialog-handlers.ts,connection-handlers.ts,control-handlers.ts,dialog-handlers.ts,job-handlers.ts,material-handlers.ts,palette-handlers.ts,printer-settings-handlers.ts,shortcut-config-handlers.ts,spoolman-handlers.ts,theme-handlers.ts,update-handlers.ts,webui-handlers.ts. -
Supporting modules:
src/main/ipc/camera-ipc-handler.ts(legacy camera IPC surface),src/main/ipc/printer-context-handlers.ts(context CRUD + switching),src/main/ipc/WindowControlHandlers.ts(custom title bar), andsrc/main/ipc/DialogHandlers.ts(loading overlay + connection dialogs). Keep APIs in sync with the preload's whitelist. -
When adding IPC channels, update
src/preload/index.tschannel allowlists plus any typed surface (PrinterContextsAPI,SpoolmanAPI, etc.). Dialog-specific handlers should route throughcomponent-dialog-handlers.tsunless they are part of the legacyDialogHandlerspath.
Renderer Process (Sandboxed)
↓ window.api calls
Preload Script (Privileged)
↓ Channel validation
↓ contextBridge
ipcRenderer
↓ Whitelisted channels
ipcMain Handlers
↓ Business logic
Services/Managers
- ~63 send channels
- ~46 receive channels
- ~51 invoke channels
- Specialized namespaces:
config,dialog,loading,camera,printerContexts,spoolman
- Mirrors main preload API with scoped channel validation
- Adds
componentDialogAPIfor lifecycle:componentDialogAPI = { receive: (channel, func) => void // channels: 'component-dialog:init', 'polling-update', 'theme-changed' send: (channel, ...data) => void // channels: 'component-dialog:close' invoke: (channel, ...data) => Promise<unknown> // channels: 'component-dialog:get-info', 'component-dialog:get-polling-data' }
- Exposed via
window.api.dialog.component - Same security guarantees as main preload
const validSendChannels = ['request-printer-data', 'pause-print', ...];
send: (channel, data) => {
if (validSendChannels.includes(channel)) {
ipcRenderer.send(channel, data);
}
}export function registerAllIpcHandlers(managers: AppManagers) {
registerConnectionHandlers(connectionManager, windowManager);
registerBackendHandlers(backendManager, windowManager);
registerJobHandlers(backendManager, windowManager);
registerDialogHandlers(configManager, windowManager);
registerCalibrationHandlers();
registerMaterialHandlers(backendManager);
registerControlHandlers(backendManager);
registerWebUIHandlers();
registerCameraHandlers(managers);
initializePrinterSettingsHandlers();
registerPaletteHandlers();
registerShortcutConfigHandlers();
registerComponentDialogHandlers();
registerUpdateHandlers(configManager, windowManager);
registerSpoolmanHandlers();
registerThemeHandlers();
}1. Domain handlers (via registerAllIpcHandlers)
2. Multi-context handlers (printer contexts, connection state)
3. Legacy handlers (dialog handlers)
4. Window controls
5. THEN create windows
printer-selection:start-discoveryprinter-connection:connect-to-ipprinter-selection:cancel
request-model-previewrequest-printer-dataget-material-station-statusprinter:get-features
- Temperature:
set-bed-temp,set-extruder-temp,turn-off-*-temp - LED:
led-on,led-off - Print:
pause-print,resume-print,cancel-print - Operations:
home-axes,set-filtration,clear-status
job-picker:get-local-jobs,job-picker:get-recent-jobs(legacy + modern printers)job-picker:start-job(with material mapping for AD5X)uploader:browse-file,uploader:upload-job,uploader:cancel(job upload workflow)upload-file-ad5x(AD5X-specific upload with material station support)request-thumbnail,request-legacy-thumbnail(with caching viaThumbnailCacheService)job-selected,close-job-picker(dialog lifecycle)
spoolman:open-dialog- Open spool selection dialogspoolman:search-spools- Search spools via REST APIspoolman:select-spool- Broadcast spool selection to renderersspoolman:get-active-spool- Get active spool for contextspoolman:set-active-spool- Set active spool for contextspoolman:test-connection- Test connection to Spoolman serverspoolman:get-status- Get Spoolman status for context (enabled/disabled + reason)spoolman:retry-connection- Manual retry viaSpoolmanHealthMonitor
open-component-palette,close-component-palette,palette:closepalette:get-components(invoke)palette:remove-component,palette:add-componentpalette:opened,palette:toggle-edit-mode
- Settings:
calibration:get-settings,calibration:update-settings - Workspace:
calibration:get-workspace,calibration:create-workspace,calibration:clear-workspace - File operations:
calibration:open-config-file,calibration:open-shaper-csv-file,calibration:open-ssh-key-file - Mesh:
calibration:load-config,calibration:get-profiles,calibration:parse-mesh,calibration:analyze-mesh,calibration:compute-workflow - History:
calibration:get-history,calibration:add-history,calibration:clear-history - Reports:
calibration:export-report,calibration:save-report,calibration:save-config - SSH:
calibration:ssh-connect,calibration:ssh-disconnect,calibration:ssh-status,calibration:ssh-is-connected,calibration:ssh-execute - SSH transfers:
calibration:ssh-fetch-config,calibration:ssh-fetch-shaper,calibration:ssh-upload-config,calibration:ssh-download-file,calibration:ssh-upload-file,calibration:ssh-list-dir,calibration:ssh-file-exists - SSH config persistence:
calibration:get-ssh-config,calibration:save-ssh-config,calibration:clear-ssh-config - Input shaper:
calibration:analyze-shaper,calibration:generate-shaper-config,calibration:save-shaper-result,calibration:get-shaper-definitions
printer-settings:get- Get per-printer settings (camera, LEDs, legacy mode)printer-settings:update- Update per-printer settingsprinter-settings:get-printer-name- Get printer name for active context
theme-profile-operation(profile CRUD)theme-updated(broadcast)
check-for-updates,download-update,install-updateopen-installer,open-release-pageget-update-status,set-update-channel
webui:start,webui:stop,webui:get-statuswebui:set-password,webui:get-auth-statuswebui:get-port,webui:set-port
// Renderer
const result = await window.api.invoke('printer-contexts:switch', contextId);
// Main
ipcMain.handle('printer-contexts:switch', async (_event, contextId) => {
contextManager.switchContext(contextId);
});// Renderer
window.api.send('pause-print');
// Main
ipcMain.on('pause-print', async () => {
await backendManager.pausePrint(contextId);
});// Main
mainWindow.webContents.send('polling-update', data);
// Renderer
window.api.receive('polling-update', (data) => {
updateUI(data);
});interface ElectronAPI {
send/receive/removeListener/invoke
config: ConfigAPI
dialog: DialogNamespace
loading: LoadingAPI
camera: CameraAPI
printerContexts: PrinterContextsAPI
connectionState: ConnectionStateAPI
printerSettings: PrinterSettingsAPI
spoolman: SpoolmanAPI
}IPC & Windows
src/main/ipc/handlers/index.ts+ domain handlers insrc/main/ipc/handlers/*.tssrc/main/ipc/camera-ipc-handler.ts,src/main/ipc/printer-context-handlers.ts,src/main/ipc/WindowControlHandlers.ts,src/main/ipc/DialogHandlers.tssrc/main/windows/WindowManager.ts,src/main/windows/WindowFactory.ts,src/main/windows/factories/*,src/main/windows/dialogs/*src/preload/index.ts,src/renderer/src/ui/component-dialog/component-dialog-preload.ts