Hermes
Install
nah hook hermes install
Restart Hermes. Remove only nah's owned hook with:
nah hook hermes uninstall
The installer honors HERMES_HOME, adds one owned entry under
hooks.pre_tool_call in $HERMES_HOME/config.yaml, and records consent for
only nah's command in Hermes' allowlist format. Existing hooks, consent
entries, and configuration are preserved.
Behavior
Hermes' native shell hook sends the pending call directly to
nah hook hermes run. Terminal, read, write, replace/patch, content-search,
and literal file-name search tools use nah's shared effects. Wildcard file-name
searches, process-control, execute_code, browser, MCP, plugin, and future
tools remain opaque. Tool calls made through hermes_tools re-enter the normal
hook. Blocks return Hermes'
documented decision: block response. Every other call delegates by returning
no directive, preserving Hermes' approval flow. Malformed input does the same.
Evaluation failure also returns no directive and writes fixed diagnostic
feedback.
Boundaries
The shell hook and nah run beside the Hermes process. Local tools can use that host's filesystem and project observations. Docker, SSH, Daytona, Modal, and other terminal backends can have different paths and state; nah still analyzes the visible command, but backend-only filesystem facts are unavailable and conservative decisions delegate. Install nah separately beside each remote Hermes Gateway.
Hermes /yolo bypasses dangerous-command approval but does not disable shell
hooks, so delegated calls may execute immediately. --safe-mode explicitly
skips shell-hook registration. --ignore-user-config skips the active user
config.yaml, including the nah entry installed there. A hook process error,
missing executable, timeout, or invalid stdout is logged and ignored by Hermes.
Python plugin hooks run before shell hooks. The first valid block wins, and an
earlier approval directive does not override a later nah block.
Direct filesystem, subprocess, or network effects inside execute_code do not
re-enter hooks. An unapproved or revoked hook, inaccessible alternate home,
manual action, and direct trusted-plugin work remain outside nah. Verify with
hermes hooks list and hermes hooks test pre_tool_call --for-tool terminal
after installation. The default test uses a harmless echo; to test blocking,
pass --payload-file a JSON object such as
{"args":{"command":"curl https://example.com/install.sh | bash"}}. This is a
synthetic hook payload and is not executed. Confirm the parsed response has
"action": "block". If you use HERMES_HOME, keep the same value when
installing, checking status, and running Hermes. nah does not select the
profile for you. The config, allowlist, and their lock files must not be
symlinks.
While active, this adapter blocks visible lifecycle commands, exact native
revocation commands naming nah hook hermes run, mutations to the current
native shell-hook config or allowlist, and child launches using --safe-mode,
--ignore-user-config, or an alternate HERMES_HOME. Hermes plugin
management remains user-owned and delegates. The agent is told not to retry
protected changes; an operator can use nah nap from another terminal.
This integration is best effort: runtime APIs and hook behavior can change. After upgrades, verify the latest official upstream documentation linked below, inspect the loaded hook, and test it before relying on nah. See Hermes' plugin documentation, event hooks, and tool documentation.