How a terminal-based AI agent evolved into a full native desktop application — from first commit to today, told through the people and decisions that shaped it.
The first commit to the Hermes Agent repository. Pure Python + CLI — no GUI, no desktop. A terminal-based AI agent with tool calling, session management, and a messaging gateway (Telegram, Discord, Feishu).
The hermes dashboard command arrives — a React + Vite web UI that connects to the Python backend via WebSocket. This is the precursor to the desktop app.
The first commit to apps/desktop/. A structured chat app in Electron with a three-panel layout (sidebar + chat + right rail). 558 lines of main process code. No installer, no update system — just the shell.
The desktop app is merged into the Hermes main branch, becoming a first-class component alongside the CLI and Gateway. This single PR dwarfs everything else in scale — bringing cross-platform installers, self-update, onboarding, remote backend, NSIS installer with winget auto-dependency provisioning, and electron-builder integration. The version label: 0.0.2.
Adds HERMES_DESKTOP_REMOTE_URL and HERMES_DESKTOP_REMOTE_TOKEN — run the Hermes backend inside WSL2, render the Electron GUI on native Windows. The motivating use case that drove the remote connection architecture.
A staged bootstrap process: detect Python/Git, clone repo, create venv, install deps. On Windows, the NSIS installer detects missing dependencies and auto-installs them via winget. On macOS/Linux, a shell-based fallback runs the same stages.
The tui_gateway/ Python package emerges — a dedicated WebSocket server for the desktop and TUI modes. No longer sharing the dashboard's backend, the desktop gets its own message protocol, project tree scanning, git probing, and event publishing.
The desktop can now update itself on macOS: hermes update pulls latest code, npm run pack rebuilds the .app, a swap script dittos the fresh bundle over the running copy, and the app relaunches. The in-app update cycle is complete.
The desktop gets a real embedded terminal using @xterm/xterm + WebGL rendering accelerator, backed by node-pty native bindings. Users can run shell commands directly inside the desktop window — the same terminal I read from with read_terminal.
Each chat can be popped out into its own OS window — perfect for monitoring subagent executions while continuing your main conversation. Background throttling explicitly disabled so streaming output keeps painting in unfocused windows.
A transparent, always-on-top pet window that follows the Hermes mascot. The pet spins up its own tiny Electron surface (win=overlay) with no gateway connection — just a React component mounting a pet renderer.
Full i18n framework with Simplified Chinese (zh-Hans) as the first non-English locale. The I18nProvider wraps the entire React tree.
A series of fixes to prevent background spawns from popping cmd windows on Windows. The terminal pop-up problem plagued the desktop for weeks — resolved through careful windowsHide options and process creation flags.
Electron-builder-created NSIS installers, afterPack hooks to stamp executables with the Hermes identity, AppUserModelID for proper notifications. The Windows desktop experience catches up to macOS.
A complete redesign of the settings surface. Skills hub, tool management, and MCP server configuration all converge into a single Capabilities tab — with master-detail layout, real-time status probes, and React Query-backed data fetching.
The desktop's component library is extracted into @nous-research/ui, shared between the desktop, web dashboard, and TUI apps. This formalizes the design system that was previously copy-pasted between projects.
The onboarding overlay gets a full OAuth flow — sign in with Nous Portal, Anthropic, or OpenAI Codex via PKCE/device-code. API key entry is demoted to a fallback link. The very first paint of the app is now the welcome card, not a blank chat shell.
Two macOS-specific issues: the packaged Electron app loads from file://, which the WebSocket origin guard rejected (fixed by trusting non-web origins on loopback binds). macOS Tahoe (macOS 26) moved the traffic light buttons, breaking window layout — fixed by reading the native overlay width at runtime.
The model picker now shows per-model $/Mtok pricing, free/paid tier badges, and disables paid models for free Nous accounts — mirroring the CLI's hermes model experience.
The automated desktop release pipeline is removed in favor of manual builds + uploads per platform. Installers are published to GitHub Releases by hand; the website points at them via environment variables. The project reaches a steady-state maintenance rhythm.
Hermes Desktop is an Electron app with React 19, Tailwind CSS v4, embedded xterm.js terminal, pet overlay, multi-window support, i18n, self-update, OAuth onboarding, and the full agent toolset accessible through a native GUI. It runs the same Python backend as the CLI, sharing config, sessions, skills, and memory — all in a single ~/.hermes/ home.
Extracted from 15,000+ git commits to apps/desktop/
All data sourced from github.com/NousResearch/hermes-agent · MIT License
Written with the Hermes Agent itself — reading its own git history to tell its own story.