Security
What lnk-hermes installs and runs, beyond what Link's sandbox
guarantees every harness (Link's Agents Security page).
Installing it
- It runs Hermes's official installer, what
hermes-agent.nousresearch.com/install.shserves, pinned: the script comes from Hermes's repository at a release's commit, and runs only if its SHA-256 is the one in this adapter's source. - It installs that release with
--commit, a git checkout, so the commit's hash is the code's. - It runs over HTTPS, in the home and the sandbox: it can download
anything, but write only the home. Its code goes in its home
(
--dir) even for root, whom its installer would otherwise give/usr/local. - It brings its own Python, through uv, and Node, with no setup wizard
and no service of its own. Its installer runs uv's installer from
astral.shunchecked. - Its Python packages come from its
uv.lock, pinned by hash, unless that install fails and it resolves them afresh. - Hermes installs some packages on first use: its Anthropic SDK and each channel's library. This adapter installs those its settings need as it's configured, in the same sandbox as the install, so the running harness never needs a package registry for them. Hermes pins their versions, not their hashes.
- A new Hermes release comes with a release of this adapter.
Running it
- Link generates a key for Hermes's local API, on 127.0.0.1. Keys and
channels' tokens go in
~/.hermes/.envin its home, never on a command line, each channel with your id or number as the only one allowed. - Its terminal's tools get a home of their own (
terminal.home_mode profile) rather than reaching for your~/.sshand~/.gitconfig. - Signal goes through a relay of this adapter's. Hermes speaks to
signal-cli's HTTP daemon, which asks for no credential, so the daemon doesn't run: the relay answers Hermes on its port in the agent's block, only with the secret Link makes and keeps in Hermes's.env(SIGNAL_HTTP_URL, sent as Basic auth), compared in constant time. Behind it,signal-cliruns over its stdin and stdout, on no port. The relay takes its port before the gateway starts, and holds it until the gateway stops; if another program holds it, the agent doesn't start, so Hermes never talks to anything else there. - Known gap: on a Mac, anyone on the machine can reach the relay's port, on the loopback (on Linux behind its proxy it stays in the sandbox's own network). Without the secret they get nothing from it and send nothing through it: the relay reads a request's head, up to 64 KiB in 10 seconds, and answers 401 before reading any body, and it keeps at most 16 connections open that haven't shown the secret, closing the oldest when another comes. What they can still do is open connections faster than Hermes sends its head, and while they do, Hermes's connections to the relay can be closed too: the agent's Signal pauses until they stop. A body that comes with the secret is at most 64 MiB.
- Its WhatsApp bridge asks for no credential, so where it's open
you're asked first. Hermes starts it itself, on a port next to its
API's, and reaches it over HTTP on the loopback with no way to send a
secret or use a socket. Behind its proxy on Linux it stays in the
sandbox's own network. On a Mac, and anywhere without its proxy (no
sandbox, or
lan), every user and program of the machine can reach it, and through it send as the agent's WhatsApp and read its messages; Hermes also takes whatever answers on that port for its bridge. Link tellslnk-hermeswhether it runs behind its proxy, and where it doesn't,lnk-hermes needsnames it,whatsapp-bridge, and Hermes with WhatsApp doesn't start until you allow it, in a terminal, with--yes, or withlnk agent hermes allow whatsapp-bridge. Taken back (deny whatsapp-bridge), it refuses to start, and says how to go on without WhatsApp. - Hermes ignores strangers rather than offering them a pairing.
- With WhatsApp on your own number, it doesn't answer a mention in a group.
Its ports
Its API server, 8642 for main (another agent's is in its own block),
its WhatsApp bridge (+1) and Signal's relay (+2): with a local model's,
the only localhost ports the sandbox lets it connect to.
Outside its home
Unsandboxed, Hermes writes ~/.hermes, ~/.local/bin/hermes and its
own service (the LaunchAgent ai.hermes.gateway, or the systemd unit
hermes-gateway.service). lnk agent hermes show looks for these;
lnk agent hermes remove removes them with its home. Its own service
would run outside the sandbox, so lnk agent start stops it and moves
it aside. The Python it installs through uv (~/.local/share/uv) is
shared with other programs, so Link leaves it.
