Docs

Processes configuration

Running code outside the main process — a pre-built OS executable, or your own Node.js worker — under processes.externalCommands and processes.utilityProcesses in electron.config.ts. Both are inert (no-op) with no configured aliases, so leaving them empty is safe.

Mental model: externalCommands vs utilityProcesses

Both are alias → trusted-config allowlists — the renderer only ever names an alias, never a file path or an arbitrary command — but they run different kinds of code:

  • externalCommands.<alias> runs an external OS executable (ffmpeg, git, a compiled CLI tool, ...). Communication is stdin/stdout/stderr as text/bytes; it has timeoutMs and maxOutputBytes because the model is "run it, capture its output."
  • utilityProcesses.<alias> runs your own Node.js code as a separate, Electron-managed process (Electron.utilityProcess.fork()) — the modern replacement for spawning node yourself via child_process. Communication is structured postMessage/onMessage, like a Web Worker but on the Node.js side. Useful for offloading heavy or crash-prone work (big computations, image processing, native addon calls) so it can't freeze or take down the main process.

processes.externalCommands.<alias>

Field Purpose
command Executable name or path. The renderer can only reference the alias, never choose the command itself.
resolve 'app' (default) resolves from the packaged app's bin directory (resources/app/bin). 'path' resolves through the host PATH (command must be a bare executable name). 'absolute' uses an absolute path.
cwd Optional working directory. Relative paths resolve from the app base for resolve: 'app'.
platforms Optional OS allowlist using Node.js process.platform values, e.g. ['win32'].
allowedArgs Optional exact argument allowlist — every runtime arg must match one entry.
timeoutMs Default 30000. 0 disables the timeout. Timed-out commands receive SIGTERM, then SIGKILL after a short grace period.
maxOutputBytes Default 1048576. 0 disables result capture while still streaming output events.

Renderer side: window.Electron.externalCommands.run(alias, options) / .start(alias, options) / .kill(id), plus .onOutput(callback) / .onExit(callback) — see Usage.

processes.utilityProcesses.<alias>

Field Purpose
modulePath Path to the Node.js entry module, resolved against the packaged app's resources/app/ (mirrors externalCommands's resolve: 'app'). Ship it via extraResources in electron-builder.config.ts — see Deployment.
args Extra argv entries passed to the module's process.argv.
env Extra environment variables merged over the current process.env.

Renderer side: window.Electron.utilityProcess.start(alias, args) / .postMessage(id, message) / .kill(id), plus .onMessage(callback) / .onExit(callback).

Example — offload a heavy computation to a worker

// electron.config.ts
processes: {
  utilityProcesses: {
    heavyMath: { modulePath: 'workers/heavy-math.js' },
  },
},
// workers/heavy-math.js — plain Node.js, no @devioarts/electron import.
// Talks to the main process via Electron's own parentPort, not process.send().
process.parentPort.on('message', (event) => {
  const { type, payload } = event.data;
  if (type === 'sumOfSquares') {
    let total = 0;
    for (let i = 0; i < payload.n; i++) total += i * i;
    process.parentPort.postMessage({ type: 'result', total });
  }
});
// renderer
const { id } = await window.Electron.utilityProcess.start('heavyMath');

const unsubscribe = window.Electron.utilityProcess.onMessage(({ id: msgId, message }) => {
  if (msgId !== id) return;
  console.log('Result:', message.total);
  unsubscribe();
});

await window.Electron.utilityProcess.postMessage(id, {
  type: 'sumOfSquares',
  payload: { n: 100_000_000 },
});

// later:
await window.Electron.utilityProcess.kill(id);

Next: App & lifecycle · Security · UI configuration

Last updated on July 17, 2026