# Hermes Web UI [Hermes Agent](https://hermes-agent.nousresearch.com/) 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](https://hermes-agent.nousresearch.com/). 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](https://hermes-agent.nousresearch.com/). Once installed: ```bash 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 Run with Docker Compose (recommended): ```bash docker compose up -d ``` Or build and run manually: ```bash docker build -t hermes-webui . docker run -d -p 8787:8787 -v ~/.hermes:/root/.hermes:ro hermes-webui ``` Open http://localhost:8787 in your browser. To enable password protection: ```bash docker run -d -p 8787:8787 -e HERMES_WEBUI_PASSWORD=your-secret -v ~/.hermes:/root/.hermes:ro hermes-webui ``` 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) ```bash 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: ```bash 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: ```bash ssh -N -L :127.0.0.1: @ ``` Example: ```bash 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: ```bash 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: ```bash curl http://127.0.0.1:8787/health ``` --- ## Running tests Tests discover the repo and the Hermes agent dynamically -- no hardcoded paths. ```bash cd hermes-webui pytest tests/ -v --timeout=60 ``` Or using the agent venv explicitly: ```bash /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: **415 tests** across 21 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 `, `/workspace `, `/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 (~701 lines) helpers.py HTTP helpers, security headers (~71 lines) models.py Session model + CRUD (~137 lines) profiles.py Profile state management, hermes_cli wrapper (~246 lines) routes.py All GET + POST route handlers (~1180 lines) streaming.py SSE engine, run_agent, cancel support (~236 lines) upload.py Multipart parser, file upload handler (~78 lines) workspace.py File ops, workspace helpers (~77 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 (~977 lines) workspace.js File preview, file ops (~185 lines) sessions.js Session CRUD, list rendering, search (~533 lines) messages.js send(), SSE handlers, approval, transcript (~297 lines) panels.js Cron, skills, memory, profiles, settings (~974 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-20b}.py 21 test files, 415 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 ``` 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 ```