Hermes WebUI — Messages UI InventoryEvery message-area element & combination, wired to the real static/style.css. · Two-stage proposal (#536) →
Theme
1 · Empty state
First load / no messages
Renders inside #messages when S.messages is empty. Logo + title + subtitle + 3 suggestion buttons.
.empty-state
H
What can I help with?
Ask anything, run commands, explore files, or manage your scheduled tasks.
2 · User messages
Right-aligned bubble, attachments, and edit mode
User rows have no avatar/label — the right-edge alignment and tinted bubble identify the sender. Timestamp + edit/copy live in a .msg-foot below the bubble, revealed on hover (forced visible here).
.msg-row[data-role="user"] — plain
How do I run the dev server and point it at a specific workspace path?
10:42
.msg-files — attachments above body (right-aligned)
Assistant output is a single .msg-row.assistant-turn that holds one role header + an .assistant-turn-blocks column of one-or-more .assistant-segment children. Each segment may contain a .thinking-card, a .msg-body, and its own .msg-foot (copy / regen). This lets a turn stream reasoning → text → tool calls → more text without repeating the Hermes avatar each time.
.msg-body — rich prose
HHermes
Running the dev server
You can start Hermes with the built-in launcher. The simplest path is no docker, no proxy — the CLI handles everything.
Prerequisites
Node >= 18
A workspace directory you own
Read/write permissions
No existing .hermes folder
An API key set via HERMES_API_KEY
Steps
Clone the repo
Run npm install
Start with npm run dev -- --workspace ~/code
Tip: the --workspace flag accepts absolute or ~-prefixed paths. Relative paths are resolved against the CWD.
graph LR
U[User] --> C[Composer]
C --> API[/api/chat/]
API --> M((Model))
M --> T{tool?}
T -- yes --> X[Tool Runner]
T -- no --> R[Reply]
X --> R
R --> U
7 · Thinking / reasoning
Bordered panel (collapsed / open, animated), live loader, streaming cursor
Thinking cards are rendered at the top of an .assistant-segment. They're now bordered gold-tinted panels (no more left-rule-only look) and expand/collapse with a max-height + opacity transition. Click the header in either example below to see the animation live.
The user is asking about launching the dev server.
Options: npm script, docker, or the bundled CLI.
The CLI is the simplest — no container runtime needed.
I should show the exact commands and the --workspace flag,
then mention the env var for the API key at the end.
Here's the shortest path…
.thinking — live 3-dot loader (pre-reasoning)
HHermes
Thinking
[data-live-assistant="1"] — streaming cursor at end of last child
HHermes
Sure — the simplest way is to run npm run dev. The CLI will pick up the default
Tool cards sit in .tool-card-row wrappers (no longer nested under .msg-row). The details panel now animates open/closed via max-height + opacity — click any header below to see the transition.
src/server.ts:42:7 - error TS2345: Argument of type 'string | undefined'
is not assignable to parameter of type 'number'.
42 app.listen(opts.port, () => {
~~~~~~~~~
.tool-cards-toggle — Expand/Collapse All (≥2 cards)
📄read_filepackage.json▶
🔎grep"listen" in src/▶
⚡bashnpm run typecheck · exit 0 · 4.1s▶
9 · Meta affordances
Role timestamp tooltip, footer action toolbar, token-usage badge
Assistant timestamps live on the .msg-roletitle attribute (hover for full date). Copy/regen buttons sit in the per-segment .msg-foot, 45% opacity at rest, full on turn hover. The .msg-usage badge is always visible at the bottom of the turn.
Full hover state — .msg-foot actions + .msg-usage
HHermes
Built and type-checked successfully — server is running on :3000.
3.2K in · 481 out · ~$0.012
10 · Full composition
User turn → assistant turn (segment 1: thinking + body + tool cards) → usage
A realistic turn: one role header up top, then the segment hosting a thinking card plus the first body; tool cards follow as siblings of the turn inside .messages-inner; the usage badge closes the turn.
All-in-one turn
📎 server.ts
The build fails — can you type-check and explain?
10:40
HHermes
💡Thought for 2.1s▶
Attached server.ts — probably typing issue.
Run typecheck to confirm, then patch.
The build fails because opts.port can be undefined. Two fixes below — pick the one that matches your intent.
Option A — require the port
export function startServer(opts: { port: number }) {
app.listen(opts.port);
}
Option B — default to 3000
export function startServer(opts: { port?: number } = {}) {
const port = opts.port ?? 3000;
app.listen(port);
}
Opt-in via body.bubble-layout — extra bubble padding for assistant too
The default layout already right-aligns user messages (the redesign adopted it globally), so this toggle mostly affects additional padding / boundary handling. Flip the Bubble layout toggle in the header to see the mode applied.
Conversation sample
Can you add a retry button next to the regenerate one?
HHermes
Yes — it can share .msg-action-btn and live in the same .msg-actions container. I'll wire it up on _lastError.
Perfect, go for it.
12 · System / inline notes
Compression, cancellation, errors — rendered as italicised assistant messages
Italic system notices (still italic — info, not errors)
HHermes
[Context was auto-compressed to continue the conversation]
Task cancelled.
.assistant-segment[data-error="1"] — real error card, red accent, no italic
HHermes
Error: Connection lost. Your last message was saved — refresh to continue.
Error: Upstream rate-limited (429). Retrying in 30s…
12b · Turn boundaries & date separators
Right-alignment separates user turns · day-change separator
The dashed divider before each user turn was removed — the right-edge bubble alignment is its own visual break, so only a small vertical gap (10px top margin) remains between turns. Day changes still get a centred .msg-date-sep.
.msg-date-sep — Today / Yesterday / weekday / date
Yesterday
Can you summarise the PR I opened earlier?
HHermes
Yes — three files changed, net +42 / -18. Main change is the new rail variable…
Today
Did CI pass overnight?
HHermes
All green — three jobs, 4m 12s total. Here's the breakdown: