hermes-agent/apps/desktop
Brooklyn Nicholson 07648318ad feat(voice): "Hey Hermes" wake word to start a hands-free session
Opt-in, fully on-device wake word — the "Hey Siri" pattern — across all three
local surfaces (CLI, TUI, desktop GUI), with one configurable owner. Say the
phrase and Hermes opens a fresh session and starts hands-free voice; talk
back-and-forth; end it and the wake word re-arms. "Hey Hermes" works out of the
box (a trained model ships with Hermes). Off by default — nothing listens until
you turn it on.

Footprint: no new core model tool (config + a CLI command + gateway RPCs);
cache-safe (on wake we hand a transcript to the normal input path, never a
system-prompt/toolset mutation); .env only carries PORCUPINE_ACCESS_KEY.

- tools/wake_word.py: shared, engine-pluggable detector (openWakeWord default,
  free/local; Porcupine premium) over the existing 16 kHz sounddevice capture.
  Background daemon thread with pause()/resume() so it yields the mic during a
  voice turn, and reset() on every (re)start so a resume can't re-fire on stale
  audio. Ships a bundled "hey hermes" openWakeWord model (tools/wakewords/,
  trained with the openWakeWord pipeline, Apache-2.0) as the default; a built-in
  name or a custom .onnx/.tflite path still works. download_models() is called
  for any model so a fresh install fetches the shared feature models (else it
  crashed on a missing melspectrogram.onnx).
- wake_word.surface ("auto"|"cli"|"tui"|"gui") + wake_surface_enabled() gate so
  exactly one surface owns the listener and the session it opens.
- CLI: in-process detector; on wake → new session + single-utterance capture via
  the existing voice pipeline, with an idle watchdog that re-arms the mic.
  /wake [on|off|status] command.
- TUI + desktop GUI: share the Python tui_gateway, which runs the detector
  server-side and exposes wake.start/stop/pause/resume/status + a wake.detected
  event (routed back over the same transport that armed it). Desktop arms it on
  connect, opens a fresh session + starts voice on wake, and hands the mic
  between the detector and its browser voice loop.
- config.yaml wake_word section; [wake] extra + uv.lock; packaging ships the
  bundled model in wheel and sdist.
- Also: collapse ElevenLabs voice-list 401 log spam; treat an empty STT
  transcript (silence) as a quiet re-listen, not a "transcription failed" toast.
- Tests (mocked, no live audio/network) + packaging guard + feature docs.
2026-07-22 10:36:37 -05:00
..
assets
e2e fix: tool_calls double-encoding on import (#68856) 2026-07-21 18:53:05 +00:00
electron fix(desktop-auth): make RFC 8252 native login work end-to-end at runtime 2026-07-22 06:50:50 -07:00
pr-assets chore(desktop): drop PR screenshot assets from tree 2026-07-07 13:04:32 -07:00
public fix(providers): align Fireworks integration with project policy 2026-07-11 05:43:35 -07:00
scripts feat(desktop/e2e): Playwright E2E suite with visual regression diffs 2026-07-20 11:44:40 -04:00
src feat(voice): "Hey Hermes" wake word to start a hands-free session 2026-07-22 10:36:37 -05:00
AGENTS.md fix(desktop): avoid false remote gateway reauthentication (#68250) 2026-07-20 20:54:36 -04:00
components.json feat(desktop): add shared project UI primitives 2026-06-25 16:40:27 -05:00
DESIGN.md feat(desktop): button tooltip keybind hints + keybinds settings tab + unified worktree dialog (#65204) 2026-07-16 18:26:21 -04:00
eslint.config.mjs refactor(lint): hoist shared eslint + prettier config to root 2026-07-16 01:42:02 +05:30
index.html
package.json chore(desktop): drop unrelated assistant-ui bump + lockfile churn 2026-07-22 06:50:50 -07:00
playwright.config.ts fix(desktop): address review — overlay a11y, e2e typecheck, nits 2026-07-20 14:37:39 -04:00
preview-demo.html
README.md Merge pull request #63103 from NousResearch/bb/desktop-docs-alignment 2026-07-12 04:34:21 -05:00
tsconfig.e2e.json fix(desktop): address review — overlay a11y, e2e typecheck, nits 2026-07-20 14:37:39 -04:00
tsconfig.electron.json feat(desktop): ts-ify everything 2026-07-08 16:24:16 -07:00
tsconfig.json fix(desktop): minor type fixes and devShell cage dep 2026-07-20 11:44:40 -04:00
vite.config.ts feat(desktop): billing settings tab (#61054) 2026-07-18 19:38:02 +05:30
vitest.config.ts fix(desktop): bump skills test timeout to fix cold-start flake (#68235) 2026-07-20 21:27:34 +00:00
vitest.setup.ts test(desktop): widen Testing Library async deadline to de-flake UI panels (#67849) 2026-07-20 04:09:40 +00:00

Hermes Desktop ☤

Download Documentation Discord License: MIT

The native desktop app for Hermes Agent — the self-improving AI agent from Nous Research. Same agent, same skills, same memory as the CLI and gateway, in a polished native window — chat with streaming tool output, side-by-side previews, a file browser, voice, and settings, no terminal required. Available for macOS, Windows, and Linux.

Chat with the full agentStreaming responses, live tool activity, structured tool summaries, and the same conversation history as every other Hermes surface.
Side-by-side previewsRender web pages, files, and tool outputs in a right-hand pane while you keep chatting.
File browserExplore and preview the working directory without leaving the app.
VoiceTalk to Hermes and hear it back.
Settings & onboardingManage providers, models, tools, and credentials from a real UI. First-run setup gets you to your first message in seconds.
Stays currentBuilt-in updates pull the latest agent and rebuild the app in place.

Install

Already have the Hermes CLI? Just run:

hermes desktop

It builds and launches the GUI against your existing install — same config, keys, sessions, and skills. On first launch Hermes walks you through picking a provider and model; nothing else to configure.

Prebuilt installers

Prebuilt installers are built and distributed via the Hermes Desktop website..


Updating

The app checks for updates in the background and offers a one-click update when one is ready. You can also update any time from the CLI:

hermes update

Requirements

The installer handles everything for you (Python 3.11+, a portable Git, ripgrep).


Development

Want to hack on the app itself? Install workspace deps from the repo root once, then run the dev server from this directory:

npm install          # from repo root — links apps/desktop, web, apps/shared
cd apps/desktop
npm run dev          # Vite renderer + Electron, which boots the Python backend

Point the app at a specific source checkout, or sandbox it away from your real config:

# throwaway HERMES_HOME, separate Electron userData, distinct app name to avoid the single-instance lock
../scripts/dev-sandbox.sh npm run dev
HERMES_DESKTOP_HERMES_ROOT=/path/to/clone npm run dev
HERMES_HOME=/tmp/throwaway npm run dev
npm run dev:fake-boot   # exercise the startup overlay with deterministic delays

Building installers

npm run dist:mac     # DMG + zip
npm run dist:win     # NSIS + MSI
npm run dist:linux   # AppImage + deb + rpm
npm run pack         # unpacked app under release/ (no installer)

Installers are built and uploaded to GitHub Releases manually. macOS/Windows signing & notarization happen automatically when the relevant credentials are present in the environment (CSC_LINK / CSC_KEY_PASSWORD / APPLE_* for macOS, WIN_CSC_* for Windows).

How it works

The packaged app ships the Electron shell and a native React chat surface. On first launch it can install the Hermes Agent runtime into HERMES_HOME (~/.hermes, or %LOCALAPPDATA%\hermes on Windows), using the same layout as a CLI install.

The app has three boundaries:

  • Electron resolves and validates a runnable backend, owns native filesystem/git/window capabilities, and exposes a narrow preload bridge.
  • React owns the Desktop routes, panes, interaction state, and @assistant-ui/react transcript.
  • Hermes Agent runs as a headless hermes serve process and exposes the tui_gateway JSON-RPC/WebSocket API. The renderer connects through apps/shared, which is also used by the browser dashboard.

Backend resolution is an ordered ladder:

  1. HERMES_DESKTOP_HERMES_ROOT
  2. the current source checkout during development
  3. a completed managed install
  4. HERMES_DESKTOP_HERMES, or hermes on PATH
  5. a system Python that can import the Hermes runtime
  6. the first-launch bootstrap installer

Candidates are probed before use; an existing shim or interpreter is not enough. A runtime that predates serve falls back to headless dashboard --no-open. This is compatibility for the backend command only and does not launch or embed the dashboard UI.

The Electron orchestration entry point is electron/main.ts; pure resolution, probe, hardening, and platform policies live in focused modules beside it. The renderer is under src/, with shared atoms in src/store and transport/native adapters in src/lib.

Before changing the app, read:

  • AGENTS.md: architecture, state ownership, resolver/fallback, transport, performance, and testing rules.
  • DESIGN.md: visual system, information architecture, motion, direct manipulation, and keyboard behavior.

Connections, projects, and switching

Desktop supports a managed local backend, explicit remote gateways, and Hermes Cloud connections. Remote and cloud modes use the same remote-capability path; authentication and discovery differ, not the renderer feature model.

Projects are the workspace abstraction. A project may own multiple folders, repositories, worktrees, and sessions; a bare new chat remains detached unless the user enters a project or configures a default project directory. Use the Projects UI rather than adding a second per-session folder-picker workflow.

Changing profiles or connection modes is a soft workspace switch, not another cold boot. The shell and current management overlay remain mounted while gateway-bound nanostores are wiped, query-backed data is invalidated, and the new connection repopulates skeletons. This prevents rows or transcripts from the previous gateway bleeding into the next one.

Verification

Run before opening a PR (lint may surface pre-existing warnings but must exit cleanly):

npm run fix
npm run typecheck
npm run lint
npm run test:ui
npm run test:desktop:platforms

Run npm run test:desktop:all for install, boot, update, packaging, or other release-path changes.

Troubleshooting

Boot logs land in HERMES_HOME/logs/desktop.log (includes backend output and recent Python tracebacks) — check it first if the app reports a boot failure.

macOS / Linux:

# Force a clean first-launch setup
rm "$HOME/.hermes/hermes-agent/.hermes-bootstrap-complete"
# Rebuild a broken Python venv
rm -rf "$HOME/.hermes/hermes-agent/venv"
# Reset a stuck macOS microphone prompt (macOS only)
tccutil reset Microphone com.nousresearch.hermes

Windows (PowerShell):

# Force a clean first-launch setup
Remove-Item "$env:LOCALAPPDATA\hermes\hermes-agent\.hermes-bootstrap-complete"
# Rebuild a broken Python venv
Remove-Item -Recurse -Force "$env:LOCALAPPDATA\hermes\hermes-agent\venv"

The default Hermes home on Windows is %LOCALAPPDATA%\hermes. Set the HERMES_HOME env var if you've relocated it.


Community


License

MIT — see LICENSE.

Built by Nous Research.