hermes-github-mentions
Give your self-hosted Hermes Agent a task by mentioning its bot on GitHub. The plugin checks the bot's notifications, accepts requests from approved users, and asks Hermes to reply in the original thread. Discord is used automatically when available and is optional.
GitHub @mention → approved author → signed local webhook → Hermes → GitHub reply
A native Hermes plugin with no extra Python dependencies. Supports issue and PR comments, inline reviews, and Discussions. No public webhook endpoint or repository allowlist is needed. Approved users can request work wherever the bot has access and receives mention notifications.
Requirements
- Hermes 0.22.5 or newer with native directory plugins, gateway adapters, and webhooks.
- Python 3.11+ on Linux or macOS, and GitHub CLI available in Hermes' terminal environment.
- A separate, regular GitHub user account for the bot, with its own username and login, and access to the repositories it will work on.
Setup
Run these commands on the Hermes host, in the profile that should handle requests.
The examples use Bash. Replace example-bot with the bot's GitHub username and
example-owner with your own username, without @.
-
Create the bot's account and token. Register a regular GitHub user account dedicated to the bot, or use an existing dedicated account. This account's username is
example-botin the commands below; replies will appear under that username. Sign in to that account, then open Settings → Developer settings → Personal access tokens → Tokens (classic). Selectrepofor repository work and notification polling. Addworkflowif Hermes should edit GitHub Actions workflow files, andread:orgfor organization and team membership queries. A separatenotificationsscope isn't needed withrepo. See GitHub's scope reference. Authorize organization SSO if required, and accept repository invitations as the bot. GitHub's notification API requires a classic token; fine-grained tokens and GitHub App tokens do not work here. GitHub.com only. -
Install and choose who can give tasks.
hermes plugins install luantak/hermes-github-mentions --enable hermes github-mentions configure --bot example-bot --author example-ownerRepeat
--author USERNAMEin the same command to approve more users. The plugin uses Hermes' defaultin_processmode; plugin-host isolation does not support gateway adapters. Configuration warnings during initial install are resolved by completing the remaining steps. -
Save the bot credentials. Paste the token at the hidden prompt:
read -r -s -p "Bot GitHub token: " github_mentions_token printf '\n' hermes config set GITHUB_TOKEN "$github_mentions_token" unset github_mentions_token hermes config set GITHUB_MENTIONS_WEBHOOK_SECRET "$(python3 -c 'import secrets; print(secrets.token_hex(32))')"The plugin and Hermes' GitHub tools use the same
GITHUB_TOKEN. The last command creates the shared local webhook secret. Keep it unchanged unless rotating it deliberately. Secrets belong to the active Hermes profile; Desktop users can also fill the plugin's secret fields there. If your terminal runtime suppliesGH_TOKEN, it must also belong to the bot: it takes precedence overGITHUB_TOKEN. For Docker or SSH terminals, make sureghand the bot credentials are available inside that environment too. -
Configure the local webhook and check access.
hermes github-mentions routes --apply hermes github-mentions run --dry-run--applysaves the routes and enables thegithub_mentionsadapter in the active profile, preserving other platforms and routes. It grants work runs theterminal,file,web,skills, andtodotoolsets. To review the generated configuration first, useroutes --output ./hermes-routes.jsoninstead; that file contains a secret and must not be committed. The default listener is127.0.0.1:8644. If your gateway uses another port, include--webhook-url http://127.0.0.1:PORT/webhooksin step 2 before applying. A successful dry run confirms bot identity and notification access; it starts no work and writes no state. -
Restart and verify. For a gateway installed as a background service:
hermes gateway restart hermes gateway status hermes github-mentions statusFor a foreground gateway, stop it and run
hermes gateway runagain. Check thatgithub_mentionsis connected and watcher status becomes"initialized": truewith an advancing cursor. Hermes owns the worker; no separate watcher service is needed. -
Try a new mention. From an approved account, post a comment in a repository the bot can access:
@example-bot Please reply here with "GitHub mentions are working". Do not change files.Create it after the gateway starts. Polling takes at least 60 seconds, plus the agent's response time. Success is a reply from the bot in that GitHub thread, not just a Discord notice or successful webhook handoff.
For a multiplexed profile, also pass --profile NAME and
--webhook-url http://127.0.0.1:8644/p/NAME/webhooks in step 2, using that profile's
Hermes context for every command. See the settings example.
Optional Discord updates
If the same Hermes profile has Discord connected and a home channel configured,
it receives status notices and copies of replies. Otherwise work stays on GitHub.
In Discord, /github-mentions set chooses the current channel or thread,
/github-mentions status shows the destination, and /github-mentions reset
restores the home channel. Only explicitly allowed Discord users can change it.
Add --no-discord to the configure command to disable notices, or --discord to
restore automatic use. No channel ID is required. Changes affect new requests;
running requests keep their original destination. Failed notices do not block work.
Troubleshooting and recovery
| Symptom | Check |
|---|---|
| Command not found | Confirm plugin installation and enablement with hermes plugins list. |
| Token identity mismatch or HTTP 401 | Use a valid classic token owned by the configured bot. |
| No mention detected | Create a new mention from an approved user; check repository access and the bot's GitHub notifications. |
| Local webhook rejected or unreachable | Check the configured URL, shared secret, applied routes, and gateway restart. |
| Work starts but no GitHub reply | Check gh api user --jq .login inside Hermes' terminal environment; it must show the bot. Check its write permissions and gateway logs. |
| Another watcher holds the lock | Run one worker per state file. Stop foreground polling or the separate service when using the native adapter. |
State is saved under <Hermes home>/plugin-data/hermes-github-mentions/state.json.
Don't delete it to fix delivery errors. Queued requests survive restarts; stable
IDs suppress duplicate deliveries, but exactly-once execution is not guaranteed.
A fresh state starts now, without replaying old mentions. Detection depends on
notifications whose current reason is mention, not a search of all comments.
The agent is instructed to verify work and post one final reply. Those are
instructions, not an enforced publishing gate. Repository content remains
untrusted; configure Hermes' execution permissions accordingly. Optional
--progress notices read Hermes' internal SQLite schema and can break after
upgrades. Disable them if incompatible. No Hermes source patches are required.
Standalone CLI
From a checkout, without installing dependencies:
python3 -m hermes_github_mentions init --bot example-bot --author example-owner
python3 -m hermes_github_mentions routes --output ./hermes-routes.json
python3 -m hermes_github_mentions run --dry-run
python3 -m hermes_github_mentions run
Before running, set GITHUB_TOKEN in the watcher environment or token_file in
~/.config/hermes-github-mentions/config.toml, and merge the exported platforms
settings into Hermes' config.yaml, preserving existing routes, then restart it.
The standalone CLI exports configuration and does not apply it. Discord is off
by default there; set discord_notifications = true to opt in.
Use --config PATH before the subcommand for another config. For background use,
adapt the paths in the systemd service.
Choose either native or standalone operation.
Development
mkdir -p .test-tmp
TMPDIR="$PWD/.test-tmp" PYTHONDONTWRITEBYTECODE=1 python3 -m unittest discover -s tests -v
Tests use fake responses and temporary state, with unmocked network access blocked.
For native integration checks, set HERMES_TEST_ROOT and PYTHONPATH to an existing
Hermes source root and run its Python, with a disk-backed TMPDIR outside this
checkout. No live credentials are needed. See the release checks.
MIT licensed. Independent of Nous Research.