How to Set Up the OmniRoute Desktop App on Windows, macOS, and Linux Using Electron

OmniRoute provides a full-featured Electron-based desktop client that bundles a Next.js server, creates a native system tray interface, and supports Windows, macOS, and Linux through platform-specific installers built with electron-builder.

The OmniRoute repository (diegosouzapw/OmniRoute) ships a cross-platform desktop application that wraps a local AI gateway. When you set up the OmniRoute desktop app, you install a self-contained Electron client that automatically manages a Next.js backend, eliminating the need for separate server configuration.

Architecture Overview

The desktop client follows a three-layer architecture that separates native window management from secure UI communication.

Main Process

The main process (electron/main.js) creates the native BrowserWindow, manages the system tray, and spawns the Next.js server. It handles single-instance locking via app.requestSingleInstanceLock() to prevent multiple windows, bootstraps the server using startNextServer(), and coordinates auto-updates through electron-updater.

Preload Script

The preload script (electron/preload.js) runs in a sandboxed context and exposes a minimal API to the React frontend via window.api.* methods. This bridges the gap between the main process and renderer without exposing full Node.js capabilities to the UI.

Package Definition

Build configuration lives in electron/package.json, which declares npm scripts including electron:dev for hot-reload development and electron:build for production binaries. The electron-builder configuration targets Windows (nsis), macOS (dmg), and Linux (AppImage).

Installation Methods

You can install the OmniRoute desktop client either through the global npm CLI or by building directly from source.

The quickest way to set up the OmniRoute desktop app uses the packaged CLI, which automatically detects your platform and launches the correct Electron binary.


# Install globally on Windows, macOS, or Linux

npm install -g omniroute

# Launch the desktop client (opens window + system tray)

omniroute

On first launch, the client automatically generates security secrets (JWT_SECRET, STORAGE_ENCRYPTION_KEY, API_KEY_SECRET) if missing and persists them to DATA_DIR/server.env.

Building from Source

For custom builds or development work, clone the repository and use the provided npm scripts:


# Clone and install dependencies

git clone https://github.com/diegosouzapw/OmniRoute.git
cd OmniRoute
npm ci

# Run in development mode with hot-reload and unsafe-eval CSP

npm run electron:dev

# Build production binaries for current platform

npm run electron:build

The electron:build script produces omniroute-<version>.exe (Windows), OmniRoute-<version>.dmg (macOS), or OmniRoute-<version>.AppImage (Linux) depending on your operating system.

Platform-Specific Setup

While the core functionality remains identical, each platform handles data persistence, autostart, and window styling differently.

Windows Setup

On Windows, the NSIS installer creates shortcuts and registers the application in %APPDATA%\omniroute for data storage. The installer handles startup shortcuts automatically, and the system tray icon provides access to port configuration and update checks.

macOS Setup

The macOS build generates a signed .dmg that installs to /Applications. The app uses a hidden title bar (titleBarStyle: "hiddenInset") for a native look and stores data in ~/Library/Application Support/omniroute. The resolveNodeExecutable helper ensures the bundled Node binary aligns with Electron's version to avoid dock icon duplication.

Linux Setup

Linux users receive either an AppImage or .deb package. Data persists to ~/.config/omniroute (or $XDG_CONFIG_HOME/omniroute). The client supports headless launching via --headless flag, and autostart integration creates a .desktop file in ~/.config/autostart using the enableLinuxDesktopAutostart function.

How the Desktop Client Works

Understanding the boot sequence helps troubleshoot setup issues and customize configuration.

Server Bootstrapping and Secrets Generation

When the main process starts, it calls startNextServer() to launch the Next.js backend as a child process using the same Node binary as Electron (resolveNodeExecutable). The client polls http://localhost:20128/api/monitoring/health via waitForServer() before displaying the UI, ensuring the dashboard loads only after the server is ready.

Content Security Policy

The main process enforces CSP via session.defaultSession.webRequest.onHeadersReceived to protect against XSS while allowing unsafe-eval during development. This security boundary ensures the React UI cannot execute arbitrary code despite running with Node.js integration disabled.

System Tray and IPC Communication

The system tray persists across restarts and provides quick actions for opening the dashboard, changing ports, and quitting. The preload script exposes methods like window.api.send('change-port', 3000) and window.api.invoke('check-for-updates'), which trigger corresponding handlers in electron/main.js.

Auto-Update Mechanism

The setupAutoUpdater function configures electron-updater to fetch releases from GitHub. Updates download silently and install on application quit, with progress streamed to the renderer via the update-status IPC channel.

Configuration and Customization

After initial setup, you can modify runtime behavior through the tray menu or direct IPC calls.

Changing the Server Port

To change the port from the default 20128, use the IPC bridge from the renderer:

// Request port change via React UI
window.api.send('change-port', 3000);

The main process executes changePort(3000), restarts the Next.js server, updates the tray menu, and broadcasts a port-changed event to the UI.

Enabling Autostart on Linux

Toggle automatic startup programmatically or via the tray:

// Enable autostart (creates ~/.config/autostart/omniroute-desktop.desktop)
window.api.invoke('enable-autostart');

The underlying enableLinuxDesktopAutostart function (lines 11213–11238 in electron/main.js) writes the desktop entry, while disableLinuxDesktopAutostart removes it.

Checking for Updates Manually

Trigger update checks outside the automatic schedule:

// Check for GitHub releases
window.api.invoke('check-for-updates');

This fires electron-updater.checkForUpdates() and streams status back through the established IPC channel.

Summary

  • OmniRoute provides an Electron-based desktop client that bundles a complete Next.js server, eliminating manual server configuration.
  • Install via npm install -g omniroute for immediate use, or build from source using npm run electron:build for custom binaries.
  • The main process (electron/main.js) handles window creation, server lifecycle, and auto-updates, while electron/preload.js secures IPC communication.
  • Platform-specific installers target Windows (nsis), macOS (dmg), and Linux (AppImage), with data stored in standard OS directories (%APPDATA%, ~/Library/Application Support, ~/.config).
  • The client enforces single-instance locking, auto-generates encryption secrets, and polls server health before displaying the UI.
  • System tray integration and IPC methods allow runtime configuration of ports, autostart settings, and manual update checks.

Frequently Asked Questions

What is the default port for the OmniRoute desktop server?

The desktop client starts the Next.js server on port 20128 by default. You can change this after initialization through the system tray menu or by sending a change-port IPC message from the renderer, which triggers the changePort() function in electron/main.js to restart the server on the new port.

Where does the OmniRoute desktop app store encryption keys and secrets?

On first launch, the client auto-generates JWT_SECRET, STORAGE_ENCRYPTION_KEY, and API_KEY_SECRET if they do not exist, persisting them to DATA_DIR/server.env. This file lives in platform-specific data directories: %APPDATA%\omniroute on Windows, ~/Library/Application Support/omniroute on macOS, and ~/.config/omniroute on Linux.

Can I run the desktop client without the graphical interface?

Yes. On Linux, you can launch the client in headless mode using the --headless flag, which starts the Next.js server and system tray without rendering the BrowserWindow. This is useful for server environments where you need the API gateway but not the dashboard UI.

How does the application handle automatic updates?

The desktop client uses electron-updater configured in electron/main.js to poll GitHub releases. When an update is available, it downloads in the background and installs automatically when you quit the application. You can also manually trigger checks via the tray menu or the check-for-updates IPC channel.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →