Files
webui/README.md
Hermes 7019c25021 Hermes Web UI — Sprints 11-14: multi-provider models, settings, session QoL, alerts, polish
Sprint 11 (v0.13): multi-provider model support, streaming smoothness
- Dynamic model dropdown populated from configured API keys (OpenAI, Anthropic,
  Google, DeepSeek, GLM, Kimi, MiniMax, OpenRouter, Nous Portal)
- Scroll pinning during streaming (no forced scroll when user has scrolled up)
- All route handlers extracted to api/routes.py (server.py now ~76 lines)

Sprint 12 (v0.14): settings panel, SSE reconnect, session QoL
- Settings panel (gear icon) -- persist default model and workspace server-side
- SSE auto-reconnect on network blips
- Pin/star sessions to top of sidebar
- Import session from JSON export

Sprint 13 (v0.15): cron alerts, background errors, session duplicate, tab title
- Cron completion alerts: toast per completion + unread badge on Tasks tab
- Background agent error banner when a non-active session errors mid-stream
- Session duplicate button
- Browser tab title reflects active session name

Sprint 14 (v0.16): Mermaid diagrams, file ops, session archive/tags, timestamps
- Mermaid diagram rendering inline (dark theme, lazy CDN load)
- File rename (double-click in file tree) and create folder
- Session archive (hide without deleting, toggle to show)
- Session tags -- #hashtag in title becomes colored chip + click-to-filter
- Message timestamps (HH:MM on hover, full date as tooltip)

Test suite: 224 tests across 14 sprint files + regression gate, 0 failures.
2026-03-31 07:02:47 +00:00

8.3 KiB

Hermes Web UI

A lightweight, dark-themed browser interface for Hermes. Full parity with the CLI experience -- everything you can do from a terminal, you can do from this UI. No build step, no framework, no bundler. Just Python and vanilla JS.

Layout: three-panel Claude-style. Left sidebar for sessions and tools, center for chat, right for workspace file browsing.

image

This gives you nearly 1:1 parity with Hermes CLI from a convenient web UI which you can access securely through an SSH tunnel from your Hermes setup. Single command to start this up, and a single command to SSH tunnel for access on your computer. Every single part of the web UI leverages your existing Hermes agent, existing models, without requiring any setup.


Quick start

git clone https://github.com/nesquena/hermes-webui.git hermes-webui
cd hermes-webui
./start.sh

That is it. The script will:

  1. Locate your Hermes agent checkout automatically.
  2. Find (or create) a Python environment with the required dependencies.
  3. Start the server.
  4. Print the URL (and SSH tunnel command if you are on a remote machine).

What start.sh discovers automatically

Thing How it finds it
Hermes agent dir HERMES_WEBUI_AGENT_DIR env, then ~/.hermes/hermes-agent, then sibling ../hermes-agent
Python executable Agent venv first, then .venv in this repo, then system python3
State directory HERMES_WEBUI_STATE_DIR env, then ~/.hermes/webui-mvp
Default workspace HERMES_WEBUI_DEFAULT_WORKSPACE env, then ~/workspace, then state dir
Port HERMES_WEBUI_PORT env or first argument, default 8787

If discovery finds everything, nothing else is required.


Overrides (only needed if auto-detection misses)

export HERMES_WEBUI_AGENT_DIR=/path/to/hermes-agent
export HERMES_WEBUI_PYTHON=/path/to/python
export HERMES_WEBUI_PORT=9000
./start.sh

Or inline:

HERMES_WEBUI_AGENT_DIR=/custom/path ./start.sh 9000

Full list of environment variables:

Variable Default Description
HERMES_WEBUI_AGENT_DIR auto-discovered Path to the hermes-agent checkout
HERMES_WEBUI_PYTHON auto-discovered Python executable
HERMES_WEBUI_HOST 127.0.0.1 Bind address
HERMES_WEBUI_PORT 8787 Port
HERMES_WEBUI_STATE_DIR ~/.hermes/webui-mvp Where sessions and state are stored
HERMES_WEBUI_DEFAULT_WORKSPACE ~/workspace Default workspace
HERMES_WEBUI_DEFAULT_MODEL openai/gpt-5.4-mini Default model
HERMES_HOME ~/.hermes Base directory for Hermes state (affects all paths above)
HERMES_CONFIG_PATH ~/.hermes/config.yaml Path to Hermes config file

Accessing from a remote machine

The server binds to 127.0.0.1 by default (loopback only). If you are running Hermes on a VPS or remote server, use an SSH tunnel from your local machine:

ssh -N -L <local-port>:127.0.0.1:<remote-port> <user>@<server-host>

Example:

ssh -N -L 8787:127.0.0.1:8787 user@your.server.com

Then open http://localhost:8787 in your local browser.

start.sh will print this command for you automatically when it detects you are running over SSH.


Manual launch (without start.sh)

If you prefer to launch the server directly:

cd /path/to/hermes-agent          # or wherever sys.path can find Hermes modules
HERMES_WEBUI_PORT=8787 venv/bin/python /path/to/hermes-webui/server.py

Note: use the agent venv Python (or any Python environment that has the Hermes agent dependencies installed). System Python will be missing openai, httpx, and other required packages.

Health check:

curl http://127.0.0.1:8787/health

Running tests

Tests discover the repo and the Hermes agent dynamically -- no hardcoded paths.

cd hermes-webui
python -m pytest tests/ -v

Or using the agent venv explicitly:

/path/to/hermes-agent/venv/bin/python -m pytest tests/ -v   # or any Python with deps installed

Tests run against an isolated server on port 8788 with a separate state directory. Production data and real cron jobs are never touched.


Features

Chat and agent

  • Streaming responses via SSE (tokens appear as they are generated)
  • Multi-provider model support -- any Hermes API provider (OpenAI, Anthropic, Google, DeepSeek, Nous Portal, OpenRouter); dynamic model dropdown populated from configured keys
  • Send a message while one is processing -- it queues automatically
  • Edit any past user message inline and regenerate from that point
  • Retry the last assistant response with one click
  • Cancel a running task from the activity bar
  • Tool call cards inline -- each shows the tool name, args, and result snippet
  • Mermaid diagram rendering inline (flowcharts, sequence diagrams, gantt charts)
  • Approval card for dangerous shell commands (allow once / session / always / deny)
  • SSE auto-reconnect on network blips (SSH tunnel resilience)
  • File attachments persist across page reloads
  • Message timestamps (HH:MM next to each message, full date on hover)

Sessions

  • Create, rename, duplicate, delete, search by title and message content
  • Pin/star sessions to the top of the sidebar
  • Archive sessions (hide without deleting, toggle to show)
  • Session tags -- add #tag to titles for colored chips and click-to-filter
  • Grouped by Today / Yesterday / Earlier in the sidebar
  • Download as Markdown transcript, full JSON export, or import from JSON
  • Sessions persist across page reloads and SSH tunnel reconnects
  • Browser tab title reflects the active session name

Workspace file browser

  • Browse directory tree with type icons
  • Preview text, code, Markdown (rendered), and images inline
  • Edit, create, delete, and rename files; create folders
  • Right panel is drag-resizable
  • Syntax highlighted code preview (Prism.js)

Settings and configuration

  • Settings panel (gear icon in topbar) -- persist default model and default workspace server-side
  • Cron completion alerts -- toast notifications and unread badge on Tasks tab
  • Background agent error alerts -- banner when a non-active session encounters an error

Panels

  • Chat -- session list, search, pin, archive, new conversation
  • Tasks -- view, create, edit, run, pause/resume, delete cron jobs; completion alerts
  • Skills -- list all skills by category, search, preview, create/edit/delete
  • Memory -- view and edit MEMORY.md and USER.md inline
  • Todos -- live task list from the current session
  • Spaces -- add, rename, remove workspaces; quick-switch from topbar

Architecture

server.py               HTTP routing shell (~76 lines)
api/
  routes.py             All GET + POST route handlers
  config.py             Discovery + globals + model provider detection
  helpers.py            HTTP helpers: j(), bad(), require(), safe_resolve()
  models.py             Session model + CRUD
  workspace.py          File ops: list_dir, read_file_content, workspace helpers
  upload.py             Multipart parser, file upload handler
  streaming.py          SSE engine, run_agent integration, cancel support
static/
  index.html            HTML template
  style.css             All CSS
  ui.js                 DOM helpers, renderMd, Mermaid, tool cards, file tree
  workspace.js          File tree, preview, file ops
  sessions.js           Session CRUD, list rendering, search, tags, archive
  messages.js           send(), SSE event handlers, approval, transcript
  panels.js             Cron, skills, memory, workspace, todo, switchPanel, alerts
  boot.js               Event wiring + boot IIFE
tests/
  conftest.py           Isolated test server (port 8788, separate HERMES_HOME)
  test_sprint1-14.py    Feature tests per sprint
  test_regressions.py   Permanent regression gate

State lives outside the repo at ~/.hermes/webui-mvp/ by default (sessions, workspaces, settings, last_workspace). Override with HERMES_WEBUI_STATE_DIR.


Docs

  • ROADMAP.md -- feature roadmap and sprint history
  • ARCHITECTURE.md -- system design, all API endpoints, implementation notes
  • TESTING.md -- manual browser test plan and automated coverage reference
  • CHANGELOG.md -- release notes

Repo

git@github.com:nesquena/hermes-webui.git