nesquena-hermes 33fca2383c docs: v0.29 release notes + roadmap/sprint plan updates
- CHANGELOG.md: add v0.29 entry covering all Sprint 23 deliverables
  (token/cost display, subagent cards, skill picker, linked files viewer,
  workspace tree persistence, timestamp fixes, XSS + security fixes)
- ROADMAP.md: update to v0.29, add Sprint 23 to history table, check off
  token/cost, skill linked files, skill picker in cron (3 items closed)
- TESTING.md: update automated test count 415 -> 424
- SPRINTS.md: add Sprint 24 (web polish bug fix pass) and Sprint 25
  (macOS native desktop app) forward plans; remove stale stub entries

Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
2026-04-03 19:36:18 -07:00

Hermes Web UI

Hermes Agent is a sophisticated autonomous agent that lives on your server, accessed via a terminal or messaging apps, remembers what it learns, and gets more capable the longer it runs.

Hermes WebUI is a lightweight, dark-themed web app interface in your browser for Hermes Agent. 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

First, you need to install and configure Hermes Agent. Once installed:

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).

Docker

Pre-built images (amd64 + arm64) are published to GHCR on every release:

docker pull ghcr.io/nesquena/hermes-webui:latest
docker run -d -p 8787:8787 -v ~/.hermes:/root/.hermes ghcr.io/nesquena/hermes-webui:latest

Or run with Docker Compose (recommended):

docker compose up -d

Or build locally:

docker build -t hermes-webui .
docker run -d -p 8787:8787 -v ~/.hermes:/root/.hermes hermes-webui

Open http://localhost:8787 in your browser.

To enable password protection:

docker run -d -p 8787:8787 -e HERMES_WEBUI_PASSWORD=your-secret -v ~/.hermes:/root/.hermes ghcr.io/nesquena/hermes-webui:latest

Session data persists in a named volume (hermes-data) across restarts.

Note: By default, Docker Compose binds to 127.0.0.1 (localhost only). To expose on a network, change the port to "8787:8787" in docker-compose.yml and set HERMES_WEBUI_PASSWORD to enable authentication.


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_WEBUI_PASSWORD (unset) Set to enable password authentication
HERMES_HOME ~/.hermes Base directory for Hermes state (affects all paths)
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
pytest tests/ -v --timeout=60

Or using the agent venv explicitly:

/path/to/hermes-agent/venv/bin/python -m pytest tests/ -v

Tests run against an isolated server on port 8788 with a separate state directory. Production data and real cron jobs are never touched. Current count: 426 tests across 22 test files.


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, MiniMax, Z.AI); 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; expand/collapse all toggle for multi-tool turns
  • Mermaid diagram rendering inline (flowcharts, sequence diagrams, gantt charts)
  • Thinking/reasoning display -- collapsible gold-themed cards for Claude extended thinking and o3 reasoning blocks
  • 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)
  • Code block copy button with "Copied!" feedback
  • Syntax highlighting via Prism.js (Python, JS, bash, JSON, SQL, and more)
  • Safe HTML rendering in AI responses (bold, italic, code converted to markdown)

Sessions

  • Create, rename, duplicate, delete, search by title and message content
  • Pin/star sessions to the top of the sidebar (gold indicator)
  • Archive sessions (hide without deleting, toggle to show)
  • Session projects -- named groups with colors for organizing sessions
  • 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

  • Directory tree with expand/collapse (single-click toggles, double-click navigates)
  • Breadcrumb navigation with clickable path segments
  • Preview text, code, Markdown (rendered), and images inline
  • Edit, create, delete, and rename files; create folders
  • Binary file download (auto-detected from server)
  • File preview auto-closes on directory navigation (with unsaved-edit guard)
  • Right panel is drag-resizable
  • Syntax highlighted code preview (Prism.js)

Voice input

  • Microphone button in the composer (Web Speech API)
  • Tap to record, tap again or send to stop
  • Live interim transcription appears in the textarea
  • Auto-stops after ~2s of silence
  • Appends to existing textarea content (doesn't replace)
  • Hidden when browser doesn't support Web Speech API (Chrome, Edge, Safari)

Profiles

  • Profile picker in the topbar -- purple chip with dropdown showing all profiles
  • Gateway status dots (green = running), model info, skill count per profile
  • Profiles management panel -- create, switch, and delete profiles from the sidebar
  • Clone config from active profile on create
  • Seamless switching -- no server restart; reloads config, skills, memory, cron, models
  • Per-session profile tracking (records which profile was active at creation)

Authentication and security

  • Optional password auth -- off by default, zero friction for localhost
  • Enable via HERMES_WEBUI_PASSWORD env var or Settings panel
  • Signed HMAC HTTP-only cookie with 24h TTL
  • Minimal dark-themed login page at /login
  • Security headers on all responses (X-Content-Type-Options, X-Frame-Options, Referrer-Policy)
  • 20MB POST body size limit
  • CDN resources pinned with SRI integrity hashes

Settings and configuration

  • Settings panel (gear icon) -- default model, default workspace, send key preference
  • Send key: Enter (default) or Ctrl/Cmd+Enter
  • Cron completion alerts -- toast notifications and unread badge on Tasks tab
  • Background agent error alerts -- banner when a non-active session encounters an error

Slash commands

  • Type / in the composer for autocomplete dropdown
  • Built-in: /help, /clear, /model <name>, /workspace <name>, /new
  • Arrow keys navigate, Tab/Enter select, Escape closes
  • Unrecognized commands pass through to the agent

Panels

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

Mobile responsive

  • Hamburger sidebar -- slide-in overlay on mobile (<640px)
  • Bottom navigation bar -- 5-tab iOS-style fixed bar
  • Files slide-over panel from right edge
  • Touch targets minimum 44px on all interactive elements
  • Composer positioned above bottom nav
  • Desktop layout completely unchanged

Architecture

server.py               HTTP routing shell + auth middleware (~81 lines)
api/
  auth.py               Optional password authentication, signed cookies (~149 lines)
  config.py             Discovery, globals, model detection, reloadable config (~702 lines)
  helpers.py            HTTP helpers, security headers (~71 lines)
  models.py             Session model + CRUD (~146 lines)
  profiles.py           Profile state management, hermes_cli wrapper (~366 lines)
  routes.py             All GET + POST route handlers (~1180 lines)
  streaming.py          SSE engine, run_agent, cancel support (~272 lines)
  upload.py             Multipart parser, file upload handler (~78 lines)
  workspace.py          File ops, workspace helpers (~245 lines)
static/
  index.html            HTML template (~364 lines)
  style.css             All CSS incl. mobile responsive (~670 lines)
  ui.js                 DOM helpers, renderMd, tool cards, file tree (~1002 lines)
  workspace.js          File preview, file ops (~191 lines)
  sessions.js           Session CRUD, list rendering, search (~556 lines)
  messages.js           send(), SSE handlers, approval, transcript (~337 lines)
  panels.js             Cron, skills, memory, profiles, settings (~1030 lines)
  commands.js           Slash command autocomplete (~156 lines)
  boot.js               Mobile nav, voice input, boot IIFE (~338 lines)
tests/
  conftest.py           Isolated test server (port 8788)
  test_sprint{1-23}.py  22 test files, 426 test functions
  test_regressions.py   Permanent regression gate (23 tests)
Dockerfile              python:3.12-slim container image
docker-compose.yml      Compose with named volume and optional auth
.github/workflows/      CI: multi-arch Docker build + GitHub Release on tag

State lives outside the repo at ~/.hermes/webui-mvp/ by default (sessions, workspaces, settings, projects, 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 per sprint
  • SPRINTS.md -- forward sprint plan with CLI + Claude parity targets

Repo

git@github.com:nesquena/hermes-webui.git
Description
Hermes WebUI - Custom frontend for Rose Life-OS
Readme MIT 4.4 MiB
Languages
Python 66.1%
JavaScript 24.5%
CSS 5.1%
HTML 3.4%
Shell 0.8%
Other 0.1%