Hermes Agent is a sophisticated autonomous agent that lives on your server, accessed via a terminal or messaging apps, that 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. Left sidebar for sessions and navigation, center for chat, right for workspace file browsing. Model, profile, and workspace controls live in the composer footer — always visible while composing. A circular context ring shows token usage at a glance. All settings and session tools are in the Hermes Control Center (launcher at the sidebar bottom).
|
Light mode with full profile support |
Customize your settings, configure a password |
Workspace file browser with inline preview |
Session projects, tags, and tool call cards |
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 uses your existing Hermes agent and existing models, without requiring any additional setup.
Most AI tools reset every session. They don't know who you are, what you worked on, or what conventions your project follows. You re-explain yourself every time.
Hermes retains context across sessions, runs scheduled jobs while you're offline, and gets smarter about your environment the longer it runs. It uses your existing Hermes agent setup, your existing models, and requires no additional configuration to start.
What makes it different from other agentic tools:
vs. the field (landscape is actively shifting — see HERMES.md for the full breakdown):
| OpenClaw | Claude Code | Codex CLI | OpenCode | Hermes | |
|---|---|---|---|---|---|
| Persistent memory (auto) | Yes | Partial† | Partial | Partial | Yes |
| Scheduled jobs (self-hosted) | Yes | No‡ | No | No | Yes |
| Messaging app access | Yes (15+ platforms) | Partial (Telegram/Discord preview) | No | No | Yes (10+) |
| Web UI (self-hosted) | Dashboard only | No | No | Yes | Yes |
| Self-improving skills | Partial | No | No | No | Yes |
| Python / ML ecosystem | No (Node.js) | No | No | No | Yes |
| Provider-agnostic | Yes | No (Claude only) | Yes | Yes | Yes |
| Open source | Yes (MIT) | No | Yes | Yes | Yes |
† Claude Code has CLAUDE.md / MEMORY.md project context and rolling auto-memory, but not full automatic cross-session recall
‡ Claude Code has cloud-managed scheduling (Anthropic infrastructure) and session-scoped /loop; no self-hosted cron
The closest competitor is OpenClaw — both are always-on, self-hosted, open-source agents with memory, cron, and messaging. The key differences: Hermes writes and saves its own skills automatically as a core behavior (OpenClaw's skill system centers on a community marketplace); Hermes is more stable across updates (OpenClaw has documented release regressions and ClawHub has had security incidents involving malicious skills); and Hermes runs natively in the Python ecosystem. See HERMES.md for the full side-by-side.
Run the repo bootstrap:
git clone https://github.com/nesquena/hermes-webui.git hermes-webui
cd hermes-webui
python3 bootstrap.py
Or keep using the shell launcher:
./start.sh
For self-hosted VM or homelab installs, ctl.sh wraps the common daemon lifecycle commands without requiring fuser or pkill:
./ctl.sh start # background daemon, PID at ~/.hermes/webui.pid
./ctl.sh status # PID, uptime, bound host/port, log path, /health
./ctl.sh logs --lines 100 # tail ~/.hermes/webui.log
./ctl.sh restart
./ctl.sh stop
ctl.sh start runs the bootstrap in foreground/no-browser mode behind the daemon wrapper, writes logs to ~/.hermes/webui.log, and respects .env plus inline overrides such as HERMES_WEBUI_HOST=0.0.0.0 ./ctl.sh start.
The bootstrap will:
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash)./health.--no-browser.Native Windows is not supported for this bootstrap yet. Use Linux, macOS, or WSL2. For Windows / WSL auto-start at login, see
docs/wsl-autostart.md.
If provider setup is still incomplete after install, the onboarding wizard will point you to finish it with hermes model instead of trying to replicate the full CLI setup in-browser.
Pre-built images (amd64 + arm64) are published to GHCR on every release.
For a comprehensive setup guide covering all 3 compose files, common failure modes, and bind-mount migration, see docs/docker.md. The README covers the 5-minute happy path.
The simplest setup: one WebUI container that runs the agent in-process.
git clone https://github.com/nesquena/hermes-webui
cd hermes-webui
cp .env.docker.example .env
# Edit .env if your host UID isn't 1000 (e.g. macOS where UIDs start at 501)
docker compose up -d
# Open http://localhost:8787
The container auto-detects your UID/GID from the mounted ~/.hermes volume so files written by the agent stay readable by you on the host.
To enable password protection (required if you expose the port outside 127.0.0.1):
echo "HERMES_WEBUI_PASSWORD=change-me-to-something-strong" >> .env
docker compose up -d --force-recreate
docker pull ghcr.io/nesquena/hermes-webui:latest
docker run -d \
-e WANTED_UID=$(id -u) -e WANTED_GID=$(id -g) \
-v ~/.hermes:/home/hermeswebui/.hermes \
-e HERMES_WEBUI_STATE_DIR=/home/hermeswebui/.hermes/webui \
-v ~/workspace:/workspace \
-p 127.0.0.1:8787:8787 \
ghcr.io/nesquena/hermes-webui:latest
docker build -t hermes-webui .
docker run -d \
-e WANTED_UID=$(id -u) -e WANTED_GID=$(id -g) \
-v ~/.hermes:/home/hermeswebui/.hermes \
-e HERMES_WEBUI_STATE_DIR=/home/hermeswebui/.hermes/webui \
-v ~/workspace:/workspace \
-p 127.0.0.1:8787:8787 \
hermes-webui
If you want the agent and WebUI in separate containers (for isolation, or because you're already running an agent gateway elsewhere):
# Agent + WebUI
docker compose -f docker-compose.two-container.yml up -d
# Agent + Dashboard + WebUI
docker compose -f docker-compose.three-container.yml up -d
Both compose files use named Docker volumes by default, which solves the UID/GID problem by construction. If you need bind mounts to share an existing host directory, see docs/docker.md for the full migration recipe.
Known limitation (#681): in the two-container setup, tools triggered from the WebUI run in the WebUI container, not the agent container. If you need git/node/etc. on the WebUI's filesystem, either use the single-container setup, extend the WebUI Dockerfile, or use the community all-in-one image.
| Symptom | Likely cause | Fix |
|---|---|---|
PermissionError at startup | UID mismatch on bind mount | Set UID=$(id -u) in .env |
.env: permission denied (#1389) | fix_credential_permissions() enforced 0600 | Set HERMES_SKIP_CHMOD=1 in .env |
| Workspace appears empty | UID mismatch on /workspace mount | Set UID=$(id -u) in .env |
git: command not found in chat | Two-container architectural limit (#681) | Use single-container or extend Dockerfile |
| WebUI can't find agent source | hermes-agent-src volume misconfigured | Use the named volumes from compose files as-is |
Podman shared .hermes fails | Podman 3.4 keep-id limitation | Use Podman 4+ or single-container |
For the deep dive on each of these, see docs/docker.md.
Note: By default, Docker Compose binds to
127.0.0.1(localhost only). To expose on a network, change the port to"8787:8787"indocker-compose.ymland setHERMES_WEBUI_PASSWORDto enable authentication.
| 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.
export HERMES_WEBUI_AGENT_DIR=/path/to/hermes-agent
export HERMES_WEBUI_PYTHON=/path/to/python
export HERMES_WEBUI_PORT=9000
export HERMES_WEBUI_AUTO_INSTALL=1 # enable auto-install of agent deps (disabled by default)
./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 (0.0.0.0 for all IPv4, :: for all IPv6, ::1 for IPv6 loopback) |
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_WEBUI_EXTENSION_DIR | (unset) | Optional local directory served at /extensions/; must point to an existing directory before extension injection is enabled |
HERMES_WEBUI_EXTENSION_SCRIPT_URLS | (unset) | Optional comma-separated same-origin script URLs to inject; see WebUI Extensions |
HERMES_WEBUI_EXTENSION_STYLESHEET_URLS | (unset) | Optional comma-separated same-origin stylesheet URLs to inject; see WebUI Extensions |
HERMES_HOME | ~/.hermes | Base directory for Hermes state (affects all paths) |
HERMES_CONFIG_PATH | ~/.hermes/config.yaml | Path to Hermes config file |
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.
Tailscale is a zero-config mesh VPN built on WireGuard. Install it on your server and your phone, and they join the same private network -- no port forwarding, no SSH tunnels, no public exposure.
The Hermes Web UI is fully responsive with a mobile-optimized layout (hamburger sidebar, sidebar top tabs in the drawer, touch-friendly controls), so it works well as a daily-driver agent interface from your phone.
Setup:
HERMES_WEBUI_HOST=0.0.0.0 HERMES_WEBUI_PASSWORD=your-secret ./start.sh
http://<server-tailscale-ip>:8787 in your phone's browser
(find your server's Tailscale IP in the Tailscale app or with
tailscale ip -4 on the server).That's it. Traffic is encrypted end-to-end by WireGuard, and password auth protects the UI at the application level. You can add it to your home screen for an app-like experience.
Tip: If using Docker, set
HERMES_WEBUI_HOST=0.0.0.0in yourdocker-compose.ymlenvironment (already the default) and setHERMES_WEBUI_PASSWORD.
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
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: 3309 tests across 100+ test files.
⋯ dropdown per session — pin, move to project, archive, duplicate, delete/usage command)config.yaml at creation time, so Ollama, LMStudio, and other local endpoints can be configured without editing files manuallyHERMES_WEBUI_PASSWORD env var or Settings panel/login/theme command:root[data-theme="name"] CSS block and it works — see THEMES.md/usage command)/ in the composer for autocomplete dropdown/help, /clear, /compress [focus topic], /compact (alias), /model <name>, /workspace <name>, /new, /usage, /themeserver.py HTTP routing shell + auth middleware (~154 lines)
api/
auth.py Optional password authentication, signed cookies (~201 lines)
config.py Discovery, globals, model detection, reloadable config (~1110 lines)
helpers.py HTTP helpers, security headers (~175 lines)
models.py Session model + CRUD + CLI bridge (~377 lines)
onboarding.py First-run onboarding wizard, OAuth provider support (~507 lines)
profiles.py Profile state management, hermes_cli wrapper (~411 lines)
routes.py All GET + POST route handlers (~2250 lines)
state_sync.py /insights sync — message_count to state.db (~113 lines)
streaming.py SSE engine, run_agent, cancel support (~660 lines)
updates.py Self-update check and release notes (~257 lines)
upload.py Multipart parser, file upload handler (~82 lines)
workspace.py File ops, workspace helpers, git detection (~288 lines)
static/
index.html HTML template (~600 lines)
style.css All CSS incl. mobile responsive, themes (~1050 lines)
ui.js DOM helpers, renderMd, tool cards, context indicator (~1740 lines)
workspace.js File preview, file ops, git badge (~286 lines)
sessions.js Session CRUD, collapsible groups, search, reload recovery (~800 lines)
messages.js send(), SSE handlers, live streaming, session recovery (~655 lines)
panels.js Cron, skills, memory, profiles, settings (~1438 lines)
commands.js Slash command autocomplete (~267 lines)
boot.js Mobile nav, voice input, boot IIFE (~524 lines)
tests/
conftest.py Isolated test server (port 8788)
61 test files 961 test functions
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.
HERMES.md -- why Hermes, mental model, and detailed comparison to Claude Code / Codex / OpenCode / CursorROADMAP.md -- feature roadmap and sprint historyARCHITECTURE.md -- system design, all API endpoints, implementation notesTESTING.md -- manual browser test plan and automated coverage referenceCHANGELOG.md -- release notes per sprintSPRINTS.md -- forward sprint plan with CLI + Claude parity targetsTHEMES.md -- theme system documentation, custom theme guidedocs/troubleshooting.md -- diagnostic flows for common failures (e.g. "AIAgent not available")Hermes WebUI is built with help from the open-source community. Every PR — whether merged directly or incorporated via batch release — shapes the project, and we're grateful to everyone who has taken the time to contribute.
66 contributors have shipped code that landed in a release tag as of v0.50.245. The full credit roll lives in CONTRIBUTORS.md. The highlights:
| # | Contributor | PRs | First → latest release |
|---|---|---|---|
| 1 | @franksong2702 | 22 | v0.50.49 → v0.50.245 |
| 2 | @bergeouss | 18 | v0.50.49 → v0.50.240 |
| 3 | @aronprins | 8 | v0.47.0 → v0.50.77 |
| 4 | @iRonin | 6 | v0.41.0 |
| 5 | @24601 | 6 | v0.50.201 |
| 6 | @KingBoyAndGirl | 4 | v0.50.232 → v0.50.237 |
| 7 | @renheqiang | 4 | v0.50.93 |
| 8 | @ccqqlo | 3 | v0.50.83 → v0.50.207 |
| 9 | @deboste | 3 | v0.16.1 |
| 10 | @frap129 | 3 | v0.50.157 → v0.50.166 |
See CONTRIBUTORS.md for the full ranked list of all 66 contributors, including everyone with one or two merged PRs and the special-thanks roll for design and architectural contributions.
@aronprins — v0.50.0 UI overhaul (PR #242)
The biggest single contribution to the project: a complete UI redesign that moved model/profile/workspace controls into the composer footer, replaced the gear-icon settings panel with the Hermes Control Center (tabbed modal), removed the activity bar in favor of inline composer status, redesigned the session list with a ⋯ action dropdown, and added the workspace panel state machine. 26 commits, thoroughly designed and iterated through multiple review rounds.
@iRonin — Security hardening sprint (PRs #196–#204) Six consecutive security and reliability PRs: session memory leak fix (expired token pruning), Content-Security-Policy + Permissions-Policy headers, 30-second slow-client connection timeout, optional HTTPS/TLS support via environment variables, upstream branch tracking fix for self-update, and CLI session support in the file browser API. This is the kind of focused, high-quality security work that makes a self-hosted tool trustworthy.
@DavidSchuchert — German translation (PR #190)
Complete German locale (de) covering all UI strings, settings labels, commands, and system messages — and in doing so, stress-tested the i18n system and exposed several elements that weren't yet translatable, which got fixed as part of the same PR.
@Jordan-SkyLF — Live streaming, session recovery, workspace fallback (PRs #366, #367)
Three interlocking improvements: workspace fallback resolution so the server recovers gracefully when the configured workspace is deleted or unavailable; live reasoning cards that upgrade the generic thinking spinner to a real-time reasoning display as the model thinks; and durable session state recovery via localStorage so in-flight tool cards, partial assistant output, and the live SSE stream all survive a full page reload or session switch.
@gabogabucho — Spanish locale + onboarding wizard (PRs #275, #285)
Full Spanish (es) locale covering all 175 UI strings, plus the one-shot bootstrap onboarding wizard that guides new users through provider setup on first launch — the feature most responsible for new users actually getting started.
@bergeouss — Provider management UI + gateway sync + Docker hardening (18 PRs, v0.50.49 → v0.50.240)
Real-time gateway session sync (Telegram/Discord/Slack into the WebUI sidebar via SSE), the provider management UI for adding/editing custom providers from Settings, the two-container Docker setup docs, OAuth provider status detection, profile isolation hardening (per-profile .env secrets), and the bulk of what users see when they touch Settings → Providers.
@ccqqlo — Terminal approval UX + custom model discovery + mobile close button (PRs #224, #225, #238, #333) A run of focused quality-of-life improvements: terminal tool approval prompts that stay visible long enough to actually be read, restored custom model API key discovery, and the redundant mobile close button fix that had been confusing users on narrow screens.
@kevin-ho — OLED theme (PR #168) Added the 7th built-in theme: pure black backgrounds with warm accents tuned to reduce burn-in risk. Small diff, big impact for anyone on an OLED display.
@Bobby9228 — Mobile Profiles button + Android Chrome fixes (PRs #253, #263, #265) Added the Profiles entry to the mobile navigation flow, making profile switching reachable on phones, plus a set of Android Chrome-specific fixes for the profile dropdown.
@franksong2702 — Most prolific external contributor (22 PRs, v0.50.49 → v0.50.245)
The session title guard, breadcrumb workspace navigation, mobile workspace panel sliver fix (#1300), composer footer container queries, streaming session sidebar exemption (#1327), session sidecar repair, cron output preservation (#1295), profile default workspace persistence, and a long tail of polish across the session sidebar, mobile responsive layout, and workspace state machine.
@betamod — Security hardening (PR #171) A comprehensive security audit PR covering CSRF protection, SSRF guards, XSS escaping improvements, and the env race condition between concurrent agent sessions — foundational security work that shipped in v0.39.0.
@TaraTheStar — Bot name + thinking blocks + login refactor (PRs #132, #176, #181) Made the assistant display name configurable throughout the UI, added thinking/reasoning block display in chat, and refactored the login page to use template variables instead of inline string replacement.
@thadreber-web — CLI session bridge (PR #56) The original CLI session bridge: reads CLI sessions from the agent's SQLite state store and surfaces them in the WebUI sidebar. This was the first bridge between the CLI and WebUI session worlds.
@deboste — Reverse proxy auth + mobile responsive layout + model routing (PRs #3, #4, #5) Three of the very first community PRs: fixed EventSource/fetch to use the URL origin for reverse proxy setups, corrected model provider routing from config, and added mobile responsive layout with dvh viewport fix. Early foundation work.
@Hinotoi-agent — Profile .env secret isolation (PR #351)
Fixed API key leakage between profiles on switch — switching from a profile with OPENAI_API_KEY to one without it left the key in the process environment for the duration of the session, effectively leaking credentials. A subtle and important security fix.
@lawrencel1ng — Bandit security fixes B310/B324/B110 + QuietHTTPServer (PR #354)
Systematic bandit security scan fixes: URL scheme validation before urlopen, MD5 usedforsecurity=False, and 40+ bare except: pass blocks replaced with proper logging — plus QuietHTTPServer to stop client-disconnect log spam from SSE streams.
@lx3133584 — CSRF fix for reverse proxy on non-standard ports (PR #360) Fixed CSRF rejection for deployments behind Nginx Proxy Manager or similar on non-standard ports — a real-world blocker for anyone hosting on a port other than 80/443.
@DelightRun — session_search fix for WebUI sessions (PR #356)
The session_search tool silently returned "Session database not available" in every WebUI session. Tracked down the missing SessionDB injection in the streaming path and fixed it.
@shaoxianbilly — Unicode filename downloads (PR #378)
Fixed UnicodeEncodeError crashes when downloading workspace files with Chinese, Japanese, or other non-ASCII names. Implemented proper Content-Disposition header with RFC 5987 filename*=UTF-8''... encoding.
@huangzt — Cancel interrupts agent (PR #244) Made the Cancel button actually interrupt the running agent and clean up UI state, rather than just hiding the button while the agent kept running.
@tgaalman — Thinking card fix (PR #169) Fixed top-level reasoning fields being missed in the thinking card display — an edge case in how Claude's extended thinking blocks surface in the API response.
@smurmann — Custom provider routing fix (PR #189) Fixed model routing for slash-prefixed custom provider models, which were being misrouted in the model selector. A precise fix for a real edge case in multi-provider setups.
@jeffscottward — Claude Haiku model ID fix (PR #145)
Caught and corrected the Claude Haiku model ID (3-5 → 4-5) immediately after the Anthropic release — the kind of quick community catch that keeps the model dropdown accurate.
@kcclaw001 — Credential redaction in API responses (PR #243) Added credential redaction to all API response paths so API keys, tokens, and other secrets in session data or error messages are masked before reaching the browser.
@mbac — Phantom "Custom" provider group fix (PR #191) Removed the phantom "Custom" optgroup that appeared in the model dropdown even when no custom provider was configured — a small but consistently confusing UI noise issue.
@andrewy-wizard — Chinese localization (PR #177)
Added Simplified Chinese (zh) locale to the WebUI. One of the first non-English locales and the most-used non-English locale in the codebase.
@mmartial — Docker UID/GID matching (PR #237) Added Docker support for running as an arbitrary UID/GID matching the host user, eliminating permission issues with bind-mounted volumes — essential for Docker deployments where the host user isn't UID 1000.
@vCillusion — pip package resolution fix (PR #76) Fixed agent dependency resolution to prefer packages from the venv's site-packages over the agent directory itself, preventing shadowing bugs when developing locally.
@carlytwozero — API key pass-through for non-Anthropic providers (PR #78)
Fixed api_key not being passed to AIAgent for non-Anthropic /anthropic providers — a quiet regression that silently broke any non-default provider.
@mangodxd — Type hints cleanup (PR #115) Added missing type hints across 10 files and corrected 9 inaccurate existing ones — the kind of maintenance work that makes the codebase easier to reason about.
@Argonaut790 — HTML entity decode + Traditional Chinese locale (PR #239)
Fixed double-escaping of HTML entities in renderMd() — LLM output containing <code> was being escaped a second time, rendering as literal text instead of the intended markdown. The same PR also completed the Simplified Chinese translation (40+ missing keys) and added a full Traditional Chinese (zh-Hant) locale.
@indigokarasu — Visual redesign proposal: icon rail + design token system + 7 themes (PR #213)
A CSS-only redesign of the full UI — proper design tokens (--bg-primary, --text-info, spacing scale), an icon rail sidebar replacing the emoji tab strip, consistent form cards, breadcrumb nav, and 7 built-in themes as custom properties. The PR didn't merge as-is but directly shaped the design language and theme architecture that shipped in v0.50.0.
@zenc-cp — Anti-hallucination guard for ReAct loop (PR #133)
Added a streaming token buffer and post-run message scrub to streaming.py to detect and strip fake tool execution JSON that weaker models write inline instead of calling tools properly. A three-layer approach: ephemeral anti-hallucination prompt, live token filtering, and session history cleanup. The pattern influenced later streaming.py improvements.
Want to contribute? See ARCHITECTURE.md for the codebase layout and TESTING.md for how to run the test suite. The best contributions are focused, well-tested, and solve a real problem — exactly what every person on this list did.
git@github.com:nesquena/hermes-webui.git