RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Configs/AGENTS.md/NousResearch/hermes-agent

AGENTS.md

apps/desktop/AGENTS.md
AGENTS.md

Quality

44/100

Scores the file, not the repository.

Length

1,708 words

13 headings · 0 code blocks

Repository

225k

— · pushed 0 days ago

Last changed

3 days ago

First indexed 3 days ago.
NousResearch/hermes-agent/apps/desktop/AGENTS.mdRawGitHub
1# Desktop Engineering Guide
2 
3How to build Hermes Desktop well. This is a judgment guide, not an inventory —
4it teaches the invariants and the reasoning behind them so a change fits the app
5even as files move. Read it with the repository `AGENTS.md` (root rules still
6apply) and [`DESIGN.md`](./DESIGN.md) for the visual and interaction contract.
7 
8When a rule here and the code disagree, trust the code and fix whichever is
9wrong — but never break an invariant to make a change easier.
10 
11## What this app is
12 
13Desktop is its own native chat surface. It is not the browser dashboard and it
14does not embed the TUI. Three parties, each authoritative for one thing:
15 
16- **Electron** owns the machine: process lifecycle, native filesystem/git/
17 windows, install/update, and a narrow, typed capability bridge.
18- **The renderer** owns the experience: navigation, presentation, and ephemeral
19 interaction state.
20- **The agent backend** owns the work: sessions, tools, model calls, streaming.
21 
22Keep the seams clean. The renderer never reaches for Node or Electron directly;
23native power arrives through a deliberate capability, not a general escape hatch.
24Agent behavior lives behind the gateway, never reimplemented in React. When a
25change blurs a seam, that is the smell — fix the seam, don't widen it.
26 
27## Decide state by authority
28 
29The first question for any piece of state is *who is allowed to be right about
30it*, not where it is convenient to store it. Put state with its authority:
31 
32- The **backend** is authoritative for anything another Hermes surface can also
33 change. Treat the renderer's copy as a cache of that truth.
34- **Electron** is authoritative for machine and runtime facts.
35- The **renderer** owns only what is purely about this window's presentation.
36 
37From that, everything else follows: shared renderer state lives in small stores
38owned by the feature that owns the concern; request-shaped server data that wants
39invalidation lives in the query layer; short-lived interaction detail stays in
40the component; hot coordination that must not paint stays in a ref. Reach for the
41narrowest home that still lets the state be correct. A new global store is a
42claim that many distant surfaces need it — earn that claim.
43 
44Persisted state must declare its scope in its own key: is this global, or does it
45belong to a connection, a profile, a stored session, a project, or a window?
46Getting the scope wrong is how one profile's setting bleeds into another.
47 
48## Identity is not incidental
49 
50Sessions have more than one identity, and conflating them is a recurring source
51of "session not found" and vanishing history. Reason about which identity a
52surface needs: durable navigation and anything the user pins or persists key off
53the stable/durable identity; live streaming keys off the runtime identity; state
54that must outlive compression keys off the lineage root. Keep the mapping between
55them explicit and translate at the boundary rather than passing the wrong id
56inward.
57 
58## Server truth is cached, not owned
59 
60The renderer paints from a cache of backend truth, so it must reconcile, not
61assume:
62 
63- **Merge, don't clobber.** A refresh is new information layered over what you
64 already know, not a replacement that can drop live or pinned rows.
65- **Be optimistic, then honest.** Direct manipulation should paint immediately
66 from a snapshot; a failed write rolls back visibly and an authoritative
67 refresh gets the last word.
68- **Guard against the past.** Async results can arrive out of order; a stale
69 response must never overwrite newer intent. Generation counters and request
70 tokens exist for this.
71- **Isolate the foreground.** Only the surface the user is looking at may publish
72 into the shared view; background work updates its own cache quietly.
73- **Coalesce noise, flush signal.** Batch high-frequency cosmetic updates, but
74 let terminal transitions (a turn finishing, needing input, failing) reach the
75 user immediately.
76- **Preserve reference identity on no-ops.** Handing React a fresh array that
77 contains the same data re-renders expensive trees for nothing.
78 
79## Switching context is a re-home, not a reboot
80 
81Changing profile, connection, or mode is a workspace switch, not a cold start.
82The shell and whatever the user was doing stay put; only the gateway-bound view
83is cleared and repopulated, and the previous context must not leak into the next
84one. Reserve the full-screen boot/connecting experience for a genuinely unusable
85backend.
86 
87There are three distinct switch shapes, and conflating them is the classic bug:
88 
89- A **connection/mode apply** (local ↔ remote ↔ cloud) is the soft re-home:
90 shell mounted, gateway-bound stores explicitly wiped, then reconnect. Query
91 invalidation alone cannot evict live session stores — wipe them.
92- A **runtime home change** (switching the underlying `HERMES_HOME` profile) is
93 a hard re-home: the window legitimately reloads and state resets by remount.
94- A **live profile swap** in the same window activates another profile's socket
95 while background profiles keep streaming; lists merge rather than wipe, and
96 only an explicit user selection starts a fresh foreground draft.
97 
98Treating a soft switch as hard flickers the app; treating a hard one as soft
99strands stale rows. After any swap, the active socket, active profile, and
100connection atoms must agree, or REST and filesystem calls route to the wrong
101backend.
102 
103## Cross everything as an observable ladder
104 
105Desktop lives at the seams: versions, profiles, local vs remote vs cloud,
106partially installed runtimes, stale caches, older backends. The durable technique
107for all of it is the same — an ordered ladder of candidates:
108 
1091. Precedence is written down, in one place, as data or a pure function.
1102. A candidate is trusted only after it is validated at the right boundary.
111 Existence is not proof; probe what you're about to rely on.
1123. A failed *read* falls to the next rung; a failed *authoritative write*
113 surfaces or rolls back rather than silently retargeting.
1144. A missing capability and a transient failure are different: the first may
115 enable a compatibility path or a disabled state; the second should retry.
1165. Retries are bounded and end in a real recovery affordance — never an infinite
117 spinner or a hot loop.
1186. One resolver owns each policy so every caller gets the same answer. Scatter is
119 how two call sites drift apart.
120 
121This is the shape of backend discovery, command/version fallbacks, connection and
122auth resolution, workspace-cwd selection, capability detection, and preview
123normalization alike. Learn the shape, not a snapshot of the current rungs.
124 
125Two auth-flavored corollaries worth naming because they are easy to get wrong:
126 
127- **One-time credentials are never reused.** An OAuth gateway connection mints a
128 fresh WebSocket ticket on every dial and never falls back to the cached URL.
129 Only a confirmed 401/403 (or an explicitly tagged auth rejection) means
130 reauthentication; timeout, network, malformed-response, and server failures
131 remain connectivity errors. Only long-lived token/local auth may reuse a
132 cached URL as a lower rung.
133- **A connection test must exercise the leg you'll actually use.** An HTTP
134 status probe passing while the WebSocket/auth leg fails is a false positive
135 that ships as "it said connected but nothing works."
136 
137## Compatibility without carrying the past forever
138 
139Desktop and its runtime update on separate clocks, so a change can meet an older
140backend. Keep those users working: preserve the current feature, keep the
141fallback narrow and tied to an identified older runtime, and cover it with a
142test. A fallback that quietly degrades the feature it's meant to protect is worse
143than the crash it replaced.
144 
145## Keep the waist narrow, grow at the edges
146 
147The root contribution rubric governs here too. New capability should arrive at
148the smallest surface that solves it: extend what exists, add a feature locally,
149lean on an existing seam — before you invent a framework. The shell's internal
150registries are composition seams, not a public plugin ABI; do not build a
151universal extension system, a manifest, or a plugin adapter for a single
152consumer. Design a shared contract only once more than one real consumer proves
153its shape. "Plugin" means several unrelated things across Hermes — do not assume
154one surface's extension model runs in another.
155 
156## Respect the person using it
157 
158Design and engineering meet at intent. The user's attention and context are
159sacred:
160 
161- Never navigate, move focus, or open a surface because something *happened* in
162 the background. Offer; don't hijack.
163- The states around loading are distinct experiences — empty, loading,
164 reconnecting, degraded/stale, and exhausted-recovery each deserve their own
165 honest copy and their own way out.
166- Keyboard ownership follows focus. The focused surface wins its keys; one
167 cancel gesture does exactly one thing.
168- Expensive, stateful surfaces (terminals, live tools) stay alive when hidden.
169 Visibility is not lifecycle.
170 
171## Make it feel instant
172 
173Performance is a feature the user feels, especially in drag, resize, scroll,
174typing, streaming, and terminals. The principles are timeless even as the code
175changes: keep hot-path state local or narrowly derived; don't subscribe heavy
176trees to per-frame updates; coalesce pointer work; avoid reading layout right
177after writing style; and don't mount expensive content mid-gesture. Prove speed
178against realistic content — a fast empty demo proves nothing about a long
179transcript. If motion is masking latency, remove the motion, don't tune it.
180 
181## Testing as a habit of proof
182 
183Test the behavior that would actually break a user, not a snapshot of today's
184data. Favor invariants over frozen values. Exercise the real path for anything
185at a seam — resolver precedence and its failure rungs, identity and scope
186boundaries, optimistic rollback and stale-response ordering, and both sides of a
187local/remote adapter with its profile routing intact. Match how the suite is
188actually run rather than inventing a command; when in doubt, read the scripts.
189 
190## The taste test before you hand off
191 
192- Does every piece of state live with its authority, at the narrowest scope?
193- Would a background event ever steal the foreground or the user's focus?
194- Does each resolver have one home, a validated ladder, and a bounded, recoverable
195 end?
196- Do local, remote, and profile routing still agree?
197- Does async failure leave a usable UI and a way forward?
198- Do hot interactions stay cheap under realistic load?
199- Does the change pass the [`DESIGN.md`](./DESIGN.md) checklist and update all
200 locales?
201 
202If any answer is "not sure," that's the part to go verify.
203 

Sections

  • Desktop Engineering Guide
  • What this app is
  • Decide state by authority
  • Identity is not incidental
  • Server truth is cached, not owned
  • Switching context is a re-home, not a reboot
  • Cross everything as an observable ladder
  • Compatibility without carrying the past forever
  • Keep the waist narrow, grow at the edges
  • Respect the person using it
  • Make it feel instant
  • Testing as a habit of proof
  • The taste test before you hand off

What it covers

testsecurityagent-behaviour

Stack — with the evidence

typescript

(1.00)

python

(1.00)

node

(1.00)

vite

(1.00)

vitest

(1.00)

playwright

(1.00)

docker

(1.00)

ai-agent

(0.90)

react

(0.70)

express

(0.70)

fastapi

(0.70)

tailwind

(0.70)

desktop-app

(0.70)

javascript

(0.60)

eslint

(0.60)

github-actions

(0.60)

Format

AGENTS.md

A plain-markdown README for coding agents, deliberately unopinionated: no frontmatter, no globs, no vendor keys. That minimalism is why it became the one file a dozen different agents will read, and why it carries the least per-file targeting power of any format here.

What the corpus says about it

Repository

Owner
NousResearch
Language
—
License
—
Archived
no

All configs in this repo

Also in NousResearch/hermes-agent

Diff this repo’s formats

One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?

The other instruction files in this repository
RepositoryFormatStackCoversScoreChanged
NousResearch/hermes-agentAGENTS.md · 225kAGENTS.mdpythonnode+14setupbuildtestlint-format+1184/1003 days ago
Diff against AGENTS.md

Similar configs

Same format, overlapping stack, ranked by quality.

Same format, overlapping stack, ranked by quality
RepositoryFormatStackCoversScoreChanged
n8n-io/n8npackages/@n8n/agents/AGENTS.md · 199kAGENTS.mdtypescriptlangchain+16buildteststylearch+3100/1003 days ago
aaif-goose/gooseAGENTS.md · 52kAGENTS.mdrusttypescript+2setupbuildtestlint-format+6100/1003 days ago
SkeneTechnologies/skene-cookbookAGENTS.md · 51AGENTS.mdpythoneslint+4setupbuildtestlint-format+7100/1002 days ago
duckduckgo/content-scope-scriptsspecial-pages/AGENTS.md · 70AGENTS.mdtypescriptjavascript+5buildteststylearch+3100/1003 days ago
mui/material-uiAGENTS.md · 99kAGENTS.mdtypescriptjavascript+13setupbuildtestlint-format+9100/1003 days ago
OnlyTerp/prompt-cache-skillsAGENTS.md · 112AGENTS.mdpythongithub-actionssetupbuildtestlint-format+5100/1003 days ago
trick77/agents-md-syncAGENTS.md · 2AGENTS.mdtypescriptnode+4setupbuildteststyle+5100/1003 days ago
vllm-project/vllmAGENTS.md · 88kAGENTS.mdpythonpytorch+3setuptestlint-formatstyle+5100/1003 days ago
RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack