5.0 KiB
Electron desktop runtime
The primary application is now Hermes Desktop. The root electron/ directory
contains the main process, sandboxed metadata preload, and utility-process entry.
The retired packages/desktop implementation is not restored.
Install and run
npm ci --ignore-scripts
npm run electron:setup
npm run dev
electron:setup downloads the pinned Electron binary and rebuilds node-pty
for Electron's ABI. dev builds the server/main/preload and starts Electron
with a Vite renderer on loopback, with hot reload. Restart dev after editing
server, main, or preload code. HERMES_WEB_UI_FRONTEND_PORT changes Vite's
default port (8649).
npm run build
npm start
npm run pack # unpacked application under release/
npm run dist # native installers under release/
Build installers on their target OS: DMG/ZIP on macOS, NSIS EXE on Windows, AppImage/DEB on Linux. The manual Electron packages workflow covers all three. Signing/notarization credentials must be supplied for public distribution. No updater endpoint is supplied: install a new desktop package to upgrade. Web npm self-update and version-preview installation are disabled in Electron.
Process and request boundaries
- Electron acquires a single-instance lock for its Chromium user-data directory.
- The utility process validates
node:sqliteandnode-pty, then starts the bundled Koa server on127.0.0.1. - A private parent port reports readiness and the actual HTTP origin. The first launch uses an OS-assigned port; subsequent launches reuse it. If occupied, another free port is selected. A port change also changes browser storage origin, so users may need to sign in again; server data stays intact.
- A sandboxed BrowserWindow loads that origin (or loopback Vite in development). Node integration is disabled, context isolation enabled, and preload exposes only platform/Electron metadata. Existing API and Socket.IO contracts remain.
- External HTTP/HTTPS/mailto links open in the system browser. Other schemes and webview attachment are blocked. Downloads use the native save dialog.
- Quit sends a private shutdown message and waits for the existing bridge, gateway, Socket.IO, HTTP and DB cleanup, with an 18-second final kill cap. Closing the last macOS window keeps the app running until Quit.
The local service checks Host and browser Origin and retains the existing login
and API authorization. LAN discovery is off for the desktop. Desktop packaging
uses ordinary files (asar: false) because Python, MCP and terminal executables
must be accessible outside Electron's virtual filesystem.
Data and external runtime
Chromium settings, login storage, saved window geometry and service port live in
Electron's userData. Service data defaults to userData/state; logs are in
state/logs. The Help menu opens these directories. Existing
HERMES_WEB_UI_HOME / HERMES_WEBUI_STATE_DIR overrides take priority. Point
one of them at an existing Web UI directory to reuse its data (stop the old
server first). No existing data is copied or deleted automatically.
HERMES_ELECTRON_USER_DATA overrides the Chromium profile for isolated testing.
Hermes Agent/Python are user-installed, and their state stays separate. Use
HERMES_BIN, HERMES_HOME, or HERMES_AGENT_BRIDGE_PYTHON as needed. Common
GUI-launch PATH locations are added to the service environment. POSIX bridge
sockets are scoped by service data directory. MCP uses the app executable in
ELECTRON_RUN_AS_NODE mode, so installed users do not need a separate Node.js.
The optional standalone web commands are dev:web, build:web, start:web.
Docker/systemd remain separate web deployment paths.
Validation
npm run harness:check
npm run test:coverage
npm run test:e2e
npm run build
npm run electron:setup
npm run test:electron
npm run pack
Local verification on 2026-10-25 (macOS arm64): coverage suite passed (2,139 tests, 2 skipped), all 69 browser tests passed, and focused additions passed. All three source Electron smoke tests passed; the packaged app passed both production smoke tests. DMG checksums and ZIP integrity were verified. Windows and Linux installers are configured but were not built on this Mac. The local macOS artifacts are unsigned and not notarized.
The native smoke test launches the real Electron executable with temporary
Chromium, service and Hermes homes, verifies local health and renderer isolation,
and confirms the service exits when the app quits. It does not call a model.
Set HERMES_ELECTRON_EXECUTABLE to a packaged executable to repeat the test
against the installer contents. Linux runners require Xvfb and Electron's
system libraries. After Electron ABI rebuilds, run npm rebuild node-pty before
using the standalone Node server if its ABI differs.
References: Electron utility processes, Electron security, native modules.