Summary
The Dashboard embedded chat (/chat) fails with "gateway exited" when both .venv/ and venv/ directories exist under the hermes-agent root, but .venv is an incomplete virtual environment (missing dependencies like python-dotenv).
Root Cause
ui-tui/dist/gatewayClient.js resolves the Python interpreter via resolvePython(), which checks candidates in this order:
// gatewayClient.js — resolvePython()
const hit = [
venv && resolve(venv, 'bin/python'), // VIRTUAL_ENV
venv && resolve(venv, 'Scripts/python.exe'),
resolve(root, '.venv/bin/python'), // ← matched first
resolve(root, '.venv/bin/python3'),
resolve(root, 'venv/bin/python'), // ← correct one, never reached
resolve(root, 'venv/bin/python3')
].find(p => p && existsSync(p));
When .venv/bin/python exists (created by uv during initial setup), it is selected before venv/bin/python. However, .venv was never fully set up — it's missing packages like python-dotenv that tui_gateway.entry requires at import time.
The result:
$ .venv/bin/python -m tui_gateway.entry
Traceback (most recent call last):
File "<frozen runpy>", line 198, in _run_module_as_main
File "/Users/…/tui_gateway/entry.py", line 19, in <module>
from tui_gateway import server
File "/Users/…/tui_gateway/server.py", line 19, in <module>
from hermes_cli.env_loader import load_hermes_dotenv
File "/Users/…/hermes_cli/env_loader.py", line 9, in <module>
from dotenv import load_dotenv
ModuleNotFoundError: No module named 'dotenv'
The TUI's GatewayClient sees the subprocess exit with code 1, and renders "error: gateway exited" with no further detail — the crash log (~/.hermes/logs/tui_gateway_crash.log) is never written because the process dies before entry.py:main() runs.
Reproduction
- Install hermes-agent (creates both
.venv/ and venv/)
- Ensure
.venv/ exists but is incomplete (no pip install -e '.[all]' was run in it)
- Run
HERMES_DASHBOARD_TUI=1 hermes dashboard
- Open
http://127.0.0.1:9119/chat
- Observe "gateway exited" in the chat terminal
Suggested Fix
Either:
- Validate the resolved Python — after
resolvePython(), verify the Python can actually import tui_gateway before using it. Fall through to the next candidate on failure.
- Prefer
venv/ over .venv/ — swap the search order so the pip-managed venv is checked first.
- Remove stale
.venv/ — if the installer creates .venv/ via uv but then builds deps in venv/, clean up the incomplete .venv/ afterward.
Option 1 is the most robust since it handles any misconfigured venv, not just this specific ordering issue.
Workaround
Set HERMES_PYTHON in ~/.hermes/.env to bypass the resolution logic:
HERMES_PYTHON=/path/to/hermes-agent/venv/bin/python3
Environment
- macOS 14 (Darwin 24.6.0, aarch64)
- hermes-agent installed via pip
.venv created by uv 0.11.9, venv created by hermes installer
- Both point to cpython-3.11.15
Summary
The Dashboard embedded chat (
/chat) fails with "gateway exited" when both.venv/andvenv/directories exist under the hermes-agent root, but.venvis an incomplete virtual environment (missing dependencies likepython-dotenv).Root Cause
ui-tui/dist/gatewayClient.jsresolves the Python interpreter viaresolvePython(), which checks candidates in this order:When
.venv/bin/pythonexists (created byuvduring initial setup), it is selected beforevenv/bin/python. However,.venvwas never fully set up — it's missing packages likepython-dotenvthattui_gateway.entryrequires at import time.The result:
The TUI's
GatewayClientsees the subprocess exit with code 1, and renders "error: gateway exited" with no further detail — the crash log (~/.hermes/logs/tui_gateway_crash.log) is never written because the process dies beforeentry.py:main()runs.Reproduction
.venv/andvenv/).venv/exists but is incomplete (nopip install -e '.[all]'was run in it)HERMES_DASHBOARD_TUI=1 hermes dashboardhttp://127.0.0.1:9119/chatSuggested Fix
Either:
resolvePython(), verify the Python can actually importtui_gatewaybefore using it. Fall through to the next candidate on failure.venv/over.venv/— swap the search order so the pip-managed venv is checked first..venv/— if the installer creates.venv/viauvbut then builds deps invenv/, clean up the incomplete.venv/afterward.Option 1 is the most robust since it handles any misconfigured venv, not just this specific ordering issue.
Workaround
Set
HERMES_PYTHONin~/.hermes/.envto bypass the resolution logic:Environment
.venvcreated by uv 0.11.9,venvcreated by hermes installer