icecore2/hermes-as-a-service

WSL2/Linux terminal UI for managing Hermes Agent Gateway, Telegram, and Web Dashboard as systemd user services.

0

stars

5

commits

Python

primary language

Aug 18, 2026

updated

README

Hermes Service TUI

A small dynamic terminal UI for managing Hermes Agent's Gateway / Telegram and Web Dashboard as systemd --user services under WSL2 or Linux.

Screenshots

Hermes Service TUI Screenshot

Hermes Service TUI Diagnostics Screenshot

Features

  • Detects the current hermes executable automatically.
  • Shows Gateway and Dashboard state, enablement, PID, and the dashboard port owner.
  • Streams selected service logs live from journalctl --follow.
  • Inspects port conflicts with listening address, PID, and process name.
  • Edits the dashboard port and safely restarts an active dashboard after updating its unit.
  • Selects a Hermes profile without changing Hermes' sticky CLI default; generated units use that profile's HERMES_HOME.
  • Reports local Telegram configuration health without exposing credentials.
  • Diagnoses WSL/systemd auto-start readiness, user-manager health, and lingering.
  • Generates and updates ~/.config/systemd/user/ unit files.
  • Uses hermes gateway run --external-supervisor so systemd owns restart behavior.
  • Packages as a standalone Linux/WSL binary with PyInstaller.

Prerequisites

WSL2 must be using systemd:

ps -p 1 -o comm=

Expected:

systemd

Hermes must already be installed and available in PATH:

command -v hermes

Run the staged launcher from the repository root:

./hermes-service-tui.sh

It validates the host before changing anything:

  • Supports Linux and WSL2 only; it exits without installing on unsupported OSes.
  • Requires systemd as PID 1 and an available systemctl --user manager.
  • Requires Hermes in PATH and Python 3.10+.
  • Creates a project-local .venv when missing and installs/updates the package dependencies there.
  • Launches the TUI only after all checks succeed.

To remove this TUI's OS-level user services and its local virtual environment:

./hermes-service-tui.sh --uninstall

The uninstall command stops/disables and removes only these user unit files:

~/.config/systemd/user/hermes-gateway.service
~/.config/systemd/user/hermes-dashboard.service
~/.config/systemd/user/hermes.target

It does not remove Hermes Agent or ~/.hermes. Use --yes for a non-interactive uninstall.

Manual development setup

python3 -m venv .venv
. .venv/bin/activate
python -m pip install -e '.[dev]'
python -m hermes_service_tui

Controls

KeyAction
/ Select Gateway or Dashboard
iInstall/update systemd units using the selected profile and port
sStart selected service
xStop selected service
eRestart selected service
lStart/stop the selected service's live journal stream
pFocus the dashboard port editor; press Apply Port to save/restart
dShow Telegram, port-owner, and WSL auto-start diagnostics
rRefresh status
qQuit

The same actions are available through buttons.

How to: install and start the services

  1. Launch the TUI:
    ./hermes-service-tui.sh
    
  2. Select Gateway / Telegram or Dashboard with / .
  3. Press i to create or update the three systemd user unit files.
  4. Press s to start the selected service. Repeat for the other service.
  5. Open the dashboard at http://127.0.0.1:9119.

The TUI writes these user-level units and does not edit Hermes configuration, .env, tokens, or config.yaml:

~/.config/systemd/user/hermes-gateway.service
~/.config/systemd/user/hermes-dashboard.service
~/.config/systemd/user/hermes.target

How to: manage services from the terminal

Use the target to control both services together:

# Start both
systemctl --user start hermes.target

# Stop both
systemctl --user stop hermes.target

# Show current state
systemctl --user status hermes.target

Manage one service when needed:

# Restart the dashboard after a problem
systemctl --user restart hermes-dashboard.service

# Follow Gateway / Telegram logs
journalctl --user -u hermes-gateway.service -f

# Read the latest dashboard logs
journalctl --user -u hermes-dashboard.service -n 80 --no-pager

How to: run services after login / reboot

The TUI enables the units during Install/Update. Enable lingering if you also want the user service manager to run without an active interactive login:

sudo loginctl enable-linger "$USER"

Verify it:

loginctl show-user "$USER" -p Linger

How to: uninstall safely

Remove only the systemd units managed by this project and the project-local Python environment:

./hermes-service-tui.sh --uninstall

For scripts or CI, bypass the confirmation prompt:

./hermes-service-tui.sh --uninstall --yes

This preserves the Hermes CLI and ~/.hermes data. It does not delete tokens, profiles, or Hermes configuration.

How to: troubleshoot

WSL reports that systemd is unavailable

The launcher exits without making changes when PID 1 is not systemd. In your WSL distribution, add this to /etc/wsl.conf:

# /etc/wsl.conf
[boot]
systemd=true

Then run this from Windows PowerShell, not WSL:

wsl --shutdown

Open a new WSL terminal and confirm:

ps -p 1 -o comm=
# expected: systemd

Hermes CLI is required but was not found

Install or repair Hermes Agent, then open a new shell and confirm it is discoverable:

command -v hermes
hermes --help

Dashboard does not open

Check its state, recent logs, and whether port 9119 listens locally:

systemctl --user status hermes-dashboard.service
journalctl --user -u hermes-dashboard.service -n 80 --no-pager
ss -ltnp | grep ':9119'

Restart it after resolving the reported issue:

systemctl --user restart hermes-dashboard.service

Gateway / Telegram does not start

Read the service log first. Fix the Hermes configuration error it reports, then restart the service:

journalctl --user -u hermes-gateway.service -n 80 --no-pager
systemctl --user restart hermes-gateway.service

How to: run tests

.venv/bin/python -m pytest -q

How to: use profiles, ports, and diagnostics

  1. Select a profile from Profile. This changes only the unit configuration; it does not run hermes profile use or change your normal CLI default.
  2. Enter a port from 1 to 65535 and select Apply Port. The TUI rejects a port owned by another visible process and shows its PID/process name.
  3. Press l on either service to follow its journal live. Press l again to stop.
  4. Press d to inspect the selected profile's local Telegram credential presence, the dashboard port owner, and WSL auto-start readiness. Credential values never appear in the TUI.

Profiles use Hermes' documented HERMES_HOME isolation. Selecting coder, for example, writes HERMES_HOME=~/.hermes/profiles/coder to both generated unit files.

How to: build a standalone binary

Build a self-contained Linux/WSL executable with PyInstaller:

./scripts/build-binary.sh

The script installs only the build extra into this project's .venv, then produces:

dist/hermes-service-tui
release/hermes-service-tui-<version>-linux-x86_64.tar.gz
release/hermes-service-tui-<version>-linux-x86_64.tar.gz.sha256

Run the artifact on the same target family used to build it:

./dist/hermes-service-tui

For deployment, copy the versioned archive to the target Linux/WSL x86-64 system, verify it with sha256sum -c <archive>.sha256, extract it, and run the bundled hermes-service-tui executable. The archive also includes the README and license.

PyInstaller binaries are OS-specific. Build separately on Linux/WSL, macOS, and Windows if you add support for those targets.

Contributors

icecore2

5 commits

icecore2/hermes-as-a-service

WSL2/Linux terminal UI for managing Hermes Agent Gateway, Telegram, and Web Dashboard as systemd user services.

0

stars

5

commits

Python

primary language

Aug 18, 2026

updated

README

Hermes Service TUI

A small dynamic terminal UI for managing Hermes Agent's Gateway / Telegram and Web Dashboard as systemd --user services under WSL2 or Linux.

Screenshots

Hermes Service TUI Screenshot

Hermes Service TUI Diagnostics Screenshot

Features

  • Detects the current hermes executable automatically.
  • Shows Gateway and Dashboard state, enablement, PID, and the dashboard port owner.
  • Streams selected service logs live from journalctl --follow.
  • Inspects port conflicts with listening address, PID, and process name.
  • Edits the dashboard port and safely restarts an active dashboard after updating its unit.
  • Selects a Hermes profile without changing Hermes' sticky CLI default; generated units use that profile's HERMES_HOME.
  • Reports local Telegram configuration health without exposing credentials.
  • Diagnoses WSL/systemd auto-start readiness, user-manager health, and lingering.
  • Generates and updates ~/.config/systemd/user/ unit files.
  • Uses hermes gateway run --external-supervisor so systemd owns restart behavior.
  • Packages as a standalone Linux/WSL binary with PyInstaller.

Prerequisites

WSL2 must be using systemd:

ps -p 1 -o comm=

Expected:

systemd

Hermes must already be installed and available in PATH:

command -v hermes

Run the staged launcher from the repository root:

./hermes-service-tui.sh

It validates the host before changing anything:

  • Supports Linux and WSL2 only; it exits without installing on unsupported OSes.
  • Requires systemd as PID 1 and an available systemctl --user manager.
  • Requires Hermes in PATH and Python 3.10+.
  • Creates a project-local .venv when missing and installs/updates the package dependencies there.
  • Launches the TUI only after all checks succeed.

To remove this TUI's OS-level user services and its local virtual environment:

./hermes-service-tui.sh --uninstall

The uninstall command stops/disables and removes only these user unit files:

~/.config/systemd/user/hermes-gateway.service
~/.config/systemd/user/hermes-dashboard.service
~/.config/systemd/user/hermes.target

It does not remove Hermes Agent or ~/.hermes. Use --yes for a non-interactive uninstall.

Manual development setup

python3 -m venv .venv
. .venv/bin/activate
python -m pip install -e '.[dev]'
python -m hermes_service_tui

Controls

KeyAction
/ Select Gateway or Dashboard
iInstall/update systemd units using the selected profile and port
sStart selected service
xStop selected service
eRestart selected service
lStart/stop the selected service's live journal stream
pFocus the dashboard port editor; press Apply Port to save/restart
dShow Telegram, port-owner, and WSL auto-start diagnostics
rRefresh status
qQuit

The same actions are available through buttons.

How to: install and start the services

  1. Launch the TUI:
    ./hermes-service-tui.sh
    
  2. Select Gateway / Telegram or Dashboard with / .
  3. Press i to create or update the three systemd user unit files.
  4. Press s to start the selected service. Repeat for the other service.
  5. Open the dashboard at http://127.0.0.1:9119.

The TUI writes these user-level units and does not edit Hermes configuration, .env, tokens, or config.yaml:

~/.config/systemd/user/hermes-gateway.service
~/.config/systemd/user/hermes-dashboard.service
~/.config/systemd/user/hermes.target

How to: manage services from the terminal

Use the target to control both services together:

# Start both
systemctl --user start hermes.target

# Stop both
systemctl --user stop hermes.target

# Show current state
systemctl --user status hermes.target

Manage one service when needed:

# Restart the dashboard after a problem
systemctl --user restart hermes-dashboard.service

# Follow Gateway / Telegram logs
journalctl --user -u hermes-gateway.service -f

# Read the latest dashboard logs
journalctl --user -u hermes-dashboard.service -n 80 --no-pager

How to: run services after login / reboot

The TUI enables the units during Install/Update. Enable lingering if you also want the user service manager to run without an active interactive login:

sudo loginctl enable-linger "$USER"

Verify it:

loginctl show-user "$USER" -p Linger

How to: uninstall safely

Remove only the systemd units managed by this project and the project-local Python environment:

./hermes-service-tui.sh --uninstall

For scripts or CI, bypass the confirmation prompt:

./hermes-service-tui.sh --uninstall --yes

This preserves the Hermes CLI and ~/.hermes data. It does not delete tokens, profiles, or Hermes configuration.

How to: troubleshoot

WSL reports that systemd is unavailable

The launcher exits without making changes when PID 1 is not systemd. In your WSL distribution, add this to /etc/wsl.conf:

# /etc/wsl.conf
[boot]
systemd=true

Then run this from Windows PowerShell, not WSL:

wsl --shutdown

Open a new WSL terminal and confirm:

ps -p 1 -o comm=
# expected: systemd

Hermes CLI is required but was not found

Install or repair Hermes Agent, then open a new shell and confirm it is discoverable:

command -v hermes
hermes --help

Dashboard does not open

Check its state, recent logs, and whether port 9119 listens locally:

systemctl --user status hermes-dashboard.service
journalctl --user -u hermes-dashboard.service -n 80 --no-pager
ss -ltnp | grep ':9119'

Restart it after resolving the reported issue:

systemctl --user restart hermes-dashboard.service

Gateway / Telegram does not start

Read the service log first. Fix the Hermes configuration error it reports, then restart the service:

journalctl --user -u hermes-gateway.service -n 80 --no-pager
systemctl --user restart hermes-gateway.service

How to: run tests

.venv/bin/python -m pytest -q

How to: use profiles, ports, and diagnostics

  1. Select a profile from Profile. This changes only the unit configuration; it does not run hermes profile use or change your normal CLI default.
  2. Enter a port from 1 to 65535 and select Apply Port. The TUI rejects a port owned by another visible process and shows its PID/process name.
  3. Press l on either service to follow its journal live. Press l again to stop.
  4. Press d to inspect the selected profile's local Telegram credential presence, the dashboard port owner, and WSL auto-start readiness. Credential values never appear in the TUI.

Profiles use Hermes' documented HERMES_HOME isolation. Selecting coder, for example, writes HERMES_HOME=~/.hermes/profiles/coder to both generated unit files.

How to: build a standalone binary

Build a self-contained Linux/WSL executable with PyInstaller:

./scripts/build-binary.sh

The script installs only the build extra into this project's .venv, then produces:

dist/hermes-service-tui
release/hermes-service-tui-<version>-linux-x86_64.tar.gz
release/hermes-service-tui-<version>-linux-x86_64.tar.gz.sha256

Run the artifact on the same target family used to build it:

./dist/hermes-service-tui

For deployment, copy the versioned archive to the target Linux/WSL x86-64 system, verify it with sha256sum -c <archive>.sha256, extract it, and run the bundled hermes-service-tui executable. The archive also includes the README and license.

PyInstaller binaries are OS-specific. Build separately on Linux/WSL, macOS, and Windows if you add support for those targets.

Contributors

icecore2

5 commits

Languages

Python

81.5%

Shell

18.5%