hermes-agent/apps/desktop
brooklyn! d046169646
fix(desktop): local-only recents, per-platform sidebar sections, and Ctrl+N regressions (#42537)
* fix(desktop): keep chat recents focused and reset hotkey target

Exclude messaging platform threads from chat recents pagination so Load More returns chat sessions, and clear stale quick-create profile state before Ctrl+N starts a new session.

* fix(desktop): surface new sessions in sidebar + unstick new-chat Thinking

Two renderer regressions in the desktop chat app:

- Sidebar ordering: orderByIds/reconcileOrderIds appended ids missing from
  the persisted order to the BOTTOM. Callers pass recency-sorted lists
  (newest first), so a brand-new Ctrl+N session sank below the saved order
  and read as "my latest session never showed up". Prepend fresh ids so new
  activity surfaces at the top.

- New-chat stuck on "Thinking": terminal/attention state transitions
  (turn finished, error, or agent now waiting on user) were RAF-batched.
  Electron throttles requestAnimationFrame to ~0 while the window is
  backgrounded, occluded, or unfocused, stranding the deferred flush. Flush
  critical transitions (!busy || needsInput) synchronously; keep the busy
  heartbeat RAF-batched to avoid scroll churn.

Does not touch the messaging-source exclusion in chat recents queries.

* fix(desktop): stop excluding messaging platforms from chat recents

The "keep chat recents focused" change excluded every messaging-platform
source (telegram, discord, slack, …) from the recents query. That silently
undid the messaging-source-folder feature already on main (ede4f5a4a): the
sidebar builds those folders purely from the loaded recents page, so once the
sources were filtered out the folders never rendered — telegram and friends
vanished from the left sidebar.

Only cron stays excluded (it has its own dedicated section). Messaging
sessions belong in the sidebar and render with their platform folder/icon.
Removes the now-unused MESSAGING_SESSION_SOURCE_IDS export.

* fix(desktop): give each messaging platform its own self-managed sidebar section

Recents are local-only again: cron and every messaging platform are excluded
from the chat-recents query, so "Load more" pages through interactive local
chats instead of interleaving gateway threads that bury them.

Each messaging platform (telegram, discord, ...) is now fetched as its own
slice (refreshMessagingSessions) and rendered as a self-managed sidebar
section with its platform icon, count, and per-platform "load more" — no
source-grouping magic inside recents.

Handed-off sessions (live source becomes local after a handoff) keep their
origin-platform badge on the row via handoff_platform, so a Telegram thread
continued in the desktop still reads as Telegram.

* fix(desktop): self-heal a stranded routed session in route-resume

An intermittent create/stream race can leave selected/active session ids
null while the route stays on /:sid — the transcript then sticks empty
even though the turn completed and persisted (the "second Ctrl+N shows no
response" symptom). The pathname didn't change, so route-resume's normal
gate skipped and the view stayed stuck.

Resume whenever the routed session isn't the loaded one, gated on
freshDraftReady so the /:sid -> /new transition (which also momentarily
nulls selected/active a render before the pathname flips) is NOT treated
as stranded. selectedStoredSessionIdRef is set synchronously at resume
entry, so this can't loop, and the resume cached fast-path restores the
already-streamed messages without a refetch.

* fix(desktop): bypass smooth reveal on primary markdown stream

Render main assistant text through deferred markdown directly instead of the smooth-reveal wrapper. This isolates the wrapper to reasoning surfaces and avoids the intermittent blank-response regression after consecutive new-session flows.
2026-06-09 14:24:25 +00:00
..
assets Add Hermes desktop app (#20059) 2026-05-31 17:46:56 -05:00
electron fix(desktop): stream the transcript while the window is backgrounded (#42399) 2026-06-08 17:01:08 -05:00
pr-assets Show messaging source folders in desktop sessions 2026-06-07 23:44:04 -07:00
public feat(desktop): unified overlay design system, BrandMark & onboarding redesign (#40708) 2026-06-06 16:32:47 -05:00
scripts fix(desktop): fail loudly instead of blank-paging when the renderer bundle is missing (#41729) 2026-06-07 22:04:39 -07:00
src fix(desktop): local-only recents, per-platform sidebar sections, and Ctrl+N regressions (#42537) 2026-06-09 14:24:25 +00:00
.prettierrc Add Hermes desktop app (#20059) 2026-05-31 17:46:56 -05:00
components.json Add Hermes desktop app (#20059) 2026-05-31 17:46:56 -05:00
DESIGN.md docs(desktop): add DESIGN.md design-system guide + close two consistency gaps (#40823) 2026-06-06 22:13:17 +00:00
eslint.config.mjs Add Hermes desktop app (#20059) 2026-05-31 17:46:56 -05:00
index.html fix(desktop): triage batch of GUI quality-of-life fixes (#37536) 2026-06-02 16:33:22 -04:00
package.json fix(desktop): fail loudly instead of blank-paging when the renderer bundle is missing (#41729) 2026-06-07 22:04:39 -07:00
preview-demo.html Add Hermes desktop app (#20059) 2026-05-31 17:46:56 -05:00
README.md docs: remove --include-desktop install instructions (#39762) 2026-06-05 06:53:58 -07:00
tsconfig.json fix(desktop): set tsconfig lib/target to ES2023 for findLast/findLastIndex 2026-06-08 22:14:28 -07:00
vite.config.ts fix(desktop): pin empty PostCSS config so Vite stops walking up the home tree (#40609) 2026-06-07 18:10:32 -07: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:

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 only the Electron shell. On first launch it installs the Hermes Agent runtime into HERMES_HOME (~/.hermes, or %LOCALAPPDATA%\hermes on Windows) — the same layout a CLI install uses, so the two are interchangeable. The renderer (React, in src/) talks to a hermes dashboard backend over the standard gateway APIs and reuses the embedded TUI rather than reimplementing chat. The install, backend-resolution, and self-update logic all live in electron/main.cjs.

Verification

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

npm run fix
npm run type-check
npm run lint
npm run test:desktop:all

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.