This release is a pre-release and may not be stable for production use.
hermes-mordred
Privacy-preserving plugins for the Hermes agent: at-rest secret encryption, hardware-backed keys, Tor/VPN routing, local-LLM policy enforcement, and end-to-end encryption for Slack and Discord gateway messages.
Status: active alpha — current release 0.1.0a16.
New here? Follow the Quickstart for the shortest path from an existing Hermes install to encrypted secrets.
The plugins
The package exposes six hermes_agent.plugins entry points:
| Plugin | Purpose |
|---|---|
mordred_privacy_check |
Skill-metadata policy enforcement and audit logging |
mordred_wizard |
The hermes-mordred CLI |
mordred_llm_guard |
Strict-mode local-LLM enforcement |
mordred_network |
Tor, VPN, and clearnet path management |
mordred_keyvault |
Secure Enclave / TPM-backed key management |
mordred_e2e |
Encrypted Slack and Discord gateway commands and replies |
Requirements
- Python 3.11 or newer; CI currently tests 3.11–3.13.
hermes-agent>=0.13.0. Use the canonicalhermes-mordredcommand across the supported Hermes range.- macOS or Linux. macOS can fall back from Secure Enclave to a software P-256 key in the login Keychain. Linux requires TPM 2.0 and fails closed when its helper is unavailable.
Install (users, from PyPI)
Start with an installed Hermes Agent, then run the Mordred installer:
curl -fsSL https://raw.githubusercontent.com/InternetMaximalism/mordred-hermes/main/scripts/install.sh | bash
The script follows Hermes's own install layout: it resolves the environment
behind the hermes on your PATH, checks the Hermes version, selects the
macOS or Linux dependencies, installs the PyPI package there, and writes a
hermes-mordred launcher next to hermes that scrubs PYTHONPATH /
PYTHONHOME exactly as Hermes's own launcher does. It does not configure
Mordred or create keys.
When upgrading from mordred-hermes==0.1.0a15 or older, the installer first
confirms that a real hermes-mordred>=0.1.0a16 release is available. Only then
does it uninstall the legacy distribution and install the canonical one. This
avoids two distributions owning the same mordred_hermes files; configuration,
keys, audit data, and other state under ~/.hermes/ are not changed.
To inspect the script first, download it and run less mordred-install.sh
before bash mordred-install.sh. The equivalent manual commands are:
# macOS
uv pip install --python ~/.hermes/hermes-agent/venv/bin/python3 \
"hermes-mordred[macos]==0.1.0a16"
# Linux
uv pip install --python ~/.hermes/hermes-agent/venv/bin/python3 \
"hermes-mordred[keyvault]==0.1.0a16"
See the Quickstart for the inspect-before-running sequence and first-time setup.
Optional extras:
| Extra | Use it for |
|---|---|
keyvault |
Cross-platform cryptography used by encryption and keyvault |
macos |
keyvault plus Secure Enclave and macOS system bridges |
ethereum |
HD-wallet derivation and signing |
tor-control |
Deep Tor liveness checks |
messaging |
Terminal QR codes for extension pairing |
extension |
Browser-extension WebSocket server and wallet RPC transport |
Enable the plugins
The first configure run adds all six mordred_* entries to
plugins.enabled in ~/.hermes/config.yaml. No manual edit is normally
required.
Use it
Start with the standalone command:
hermes-mordred configure # policy / LLM / harness setup
hermes-mordred network init # optional: Tor / VPN / clearnet
Prepare the platform key helper, then create the keyvault:
# macOS: unattended keys work in background gateways without Touch ID prompts
hermes-mordred keyvault enable-se
MORDRED_SEKEY_UNATTENDED=1 hermes-mordred keyvault init
# Linux: run these instead
hermes-mordred keyvault enable-tpm
hermes-mordred keyvault init
Turn on encryption and verify it:
hermes-mordred encryption enable env
hermes-mordred status # the env row should read [on] enrolled
Everyday commands:
hermes-mordred status
hermes-mordred encryption status
hermes-mordred encryption enable <env|config|memory|workspace|all>
hermes-mordred network use <tor|vpn|clearnet>
hermes-mordred network status
hermes-mordred audit tail
Once Hermes 0.19.0+ is configured and the plugins are enabled,
hermes mordred <command> exposes the same command tree. On older Hermes
versions, or before the first configure, keep using hermes-mordred.
See the Quickstart for expected output and the usage guide for every command and interactive prompt.
Verify discovery
hermes-mordred plugins list
# mordred_e2e / mordred_keyvault / mordred_llm_guard / mordred_network /
# mordred_privacy_check / mordred_wizard
hermes plugins list scans plugin directories and does not list package entry
points. Use Mordred's command above when checking this package.
Browser-extension WebSocket gateway (preview)
The optional extension server listens on ws://127.0.0.1:7788/ext, validates
the local peer and browser origin, and supports pairing, encrypted chat,
history, wallet accounts, and approval-bound signing.
The one-line installer deliberately installs only the platform keyvault extra,
so extension serve exits with code 2 and prints how to add the extension
extra until it is installed:
uv pip install --python ~/.hermes/hermes-agent/venv/bin/python3 \
"hermes-mordred[macos,extension,ethereum]==0.1.0a16"
How it works
The extension authenticates with a one-time pairing flow and a rotated local
token. Gateway messaging uses the context-bound ENC:v3 wire and rejects
plaintext Slack/Discord agent commands. Security model and protocol details
are in the
Extension guide.
Run it (standalone)
hermes-mordred extension serve # foreground; Ctrl+C to stop
# second terminal
hermes-mordred extension pair
Use --port 7799 when another Hermes gateway already owns port 7788.
Standalone behavior notes
extension serve runs the real Hermes agent when its runtime is installed.
It does not start automatically because Hermes currently exposes no plugin
boot hook for long-running services. See the
Extension guide
for deployment, protocol, wallet, and troubleshooting details.
Install (development)
Use the repository's editable .venv; do not replace the production Hermes
environment for normal development:
git clone https://github.com/InternetMaximalism/mordred-hermes.git
cd mordred-hermes
uv sync --all-extras
.venv/bin/python -c "import mordred_hermes; print(mordred_hermes.__file__)"
.venv/bin/hermes-mordred status
The printed module path should be under this checkout's src/. Local commands
still use real ~/.hermes state unless isolated:
env HERMES_HOME=/tmp/mordred-test-home \
.venv/bin/hermes-mordred configure
Only replace ~/.hermes/hermes-agent/venv with an editable install when an
end-to-end production-profile test specifically requires it. The full workflow,
including how to restore the PyPI wheel, is in
development setup.
Run the standard checks:
uv run pytest -q
uv run ruff check src tests scripts
uv run ruff format --check src tests scripts
uv run mypy --strict src tools scripts/keyvault_offline_digest.py
shellcheck scripts/*.sh native/*/build.sh # brew/apt install shellcheck
Troubleshooting
| Symptom | What to do |
|---|---|
| A background gateway starts without vault-managed secrets | The vault likely uses an attended Secure Enclave key. Follow the verified backup/recovery procedure in USAGE §4.3 and create the replacement key with MORDRED_SEKEY_UNATTENDED=1. Re-running enable-se alone does not change an existing key policy. |
extension serve reports port 7788 in use |
Run lsof -nP -iTCP:7788 -sTCP:LISTEN. If Hermes already owns it, the API is running; otherwise stop the stale process or use --port 7799. |
| Tor/VPN communication stops | Run hermes-mordred network status, then re-establish the selected route with hermes-mordred network use <tor|vpn|clearnet>. Restart Hermes after changing routes. |
The audit log is plaintext and contains mordred.degraded.audit_encryption_unavailable |
Restart the process from a context that can access the device key. Recovery is automatic; purge rotated plaintext logs with hermes-mordred audit purge --before YYYY-MM-DD --yes if required. |
| The recovery passphrase is lost | If the current device key still works, run hermes-mordred encryption change-passphrase. If both the passphrase and device key are gone, the encrypted data cannot be recovered. |
Upgrading
Package upgrades and config migration are separate operations.
Upgrade the installed package
Re-run the installer to upgrade Mordred without upgrading Hermes:
curl -fsSL https://raw.githubusercontent.com/InternetMaximalism/mordred-hermes/main/scripts/install.sh | bash
The installer performs the old-name ownership transfer automatically. For a
manual upgrade from 0.1.0a15, uninstall the legacy real distribution before
installing the new one:
uv pip uninstall --python ~/.hermes/hermes-agent/venv/bin/python3 mordred-hermes
uv pip install --python ~/.hermes/hermes-agent/venv/bin/python3 \
"hermes-mordred[macos]==0.1.0a16" # use [keyvault] on Linux
For a version-pinned upgrade, install the desired version manually into the Hermes environment:
# macOS; use [keyvault] on Linux
uv pip install --python ~/.hermes/hermes-agent/venv/bin/python3 \
"hermes-mordred[macos]==<new-version>"
The equivalent manual command for the newest release is:
uv pip install --python ~/.hermes/hermes-agent/venv/bin/python3 \
--upgrade-package hermes-mordred "hermes-mordred[macos]"
Restart the Hermes gateway or extension serve after upgrading.
When Hermes itself is updated
An in-place Hermes update normally preserves the Mordred wheel, but does not upgrade it. If Hermes recreates its venv, reinstall Mordred and verify the loaded path:
~/.hermes/hermes-agent/venv/bin/python3 -c \
"import mordred_hermes; print(mordred_hermes.__file__)"
Migrate config with hermes-mordred upgrade
hermes-mordred upgrade migrates an existing Hermes or OpenClaw configuration. It is
idempotent and safe to repeat:
hermes-mordred upgrade
hermes-mordred upgrade --non-interactive --policy-conflict keep-existing
Fresh installations should use configure, not upgrade.
Uninstall
Decrypt data before removing the package or keys:
hermes-mordred encryption disable all
hermes-mordred vault disable-config-decrypt
hermes-mordred encryption status # verify every target is off
Optionally destroy profile-owned keys only after verifying the plaintext data:
hermes-mordred keyvault reset --yes # irreversible
Remove the six mordred_* entries from plugins.enabled, then uninstall:
uv pip uninstall --python ~/.hermes/hermes-agent/venv/bin/python3 \
mordred-hermes hermes-mordred
# the launcher lands next to `hermes`, wherever that is
rm -f "$(dirname "$(command -v hermes)")/hermes-mordred"
State under ~/.hermes/mordred/ and installed native helpers are intentionally
left behind. Remove them manually only after confirming no encrypted data or
backup still depends on them.
Repository layout
src/mordred_hermes/ plugins and shared internals
native/ Secure Enclave and TPM helper sources
skills/ read-only Mordred status skill
scripts/install.sh user installer for the Hermes-managed environment
tools/ release and compatibility tooling
tests/ unit and opt-in integration tests
docs/user/ operator documentation
docs/dev/ specification and developer documentation
Documentation
| Audience | Document | Purpose |
|---|---|---|
| Users | Quickstart | PyPI install to protected secrets |
| Users | Usage guide | Complete command reference and ceremonies |
| Users | Extension guide | Browser extension, E2E messaging, and wallet bridge |
| Users | Hermes basics | Running the base Hermes agent |
| Developers | Development index | Current sources of truth and historical records |
| Developers | Development setup | Editable environment and validation workflow |
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hermes_mordred-0.1.0a16.tar.gz.
File metadata
- Download URL: hermes_mordred-0.1.0a16.tar.gz
- Upload date:
- Size: 1.3 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1f7f52b918b613feb13c21974ccfb8dce453cc56409ae2d22c349341c8118098
|
|
| MD5 |
175e98e2c996462130530c734d4f5013
|
|
| BLAKE2b-256 |
dade66cd5f8dc6906fd698a0462deb46fd2f788004217383c4a98c261e9c0d96
|
Provenance
The following attestation bundles were made for hermes_mordred-0.1.0a16.tar.gz:
Publisher:
release.yml on InternetMaximalism/mordred-hermes
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hermes_mordred-0.1.0a16.tar.gz -
Subject digest:
1f7f52b918b613feb13c21974ccfb8dce453cc56409ae2d22c349341c8118098 - Sigstore transparency entry: 2434476270
- Sigstore integration time:
-
Permalink:
InternetMaximalism/mordred-hermes@aa07fbdb4223044c42e5df25571015cb775abece -
Branch / Tag:
refs/heads/main - Owner: https://github.com/InternetMaximalism
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@aa07fbdb4223044c42e5df25571015cb775abece -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file hermes_mordred-0.1.0a16-py3-none-any.whl.
File metadata
- Download URL: hermes_mordred-0.1.0a16-py3-none-any.whl
- Upload date:
- Size: 861.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ff5f4644385b1b3947fa9936e43a3e0fd85b205929033df2518606ed7da37522
|
|
| MD5 |
e9f531c3c5564de551382cb5132603ce
|
|
| BLAKE2b-256 |
13a1e18de7a4a9f83311de8e49031a4769b6129b6eb3f7b608ebe0399ae97a1e
|
Provenance
The following attestation bundles were made for hermes_mordred-0.1.0a16-py3-none-any.whl:
Publisher:
release.yml on InternetMaximalism/mordred-hermes
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hermes_mordred-0.1.0a16-py3-none-any.whl -
Subject digest:
ff5f4644385b1b3947fa9936e43a3e0fd85b205929033df2518606ed7da37522 - Sigstore transparency entry: 2434476440
- Sigstore integration time:
-
Permalink:
InternetMaximalism/mordred-hermes@aa07fbdb4223044c42e5df25571015cb775abece -
Branch / Tag:
refs/heads/main - Owner: https://github.com/InternetMaximalism
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@aa07fbdb4223044c42e5df25571015cb775abece -
Trigger Event:
workflow_dispatch
-
Statement type: