| name | hermes-in-buzz |
| description | Use when connecting a remote Hermes gateway to Buzz end-to-end. Do not use for a Buzz-managed ACP runtime; use the official buzz-acp relay-bridge guide instead. |
| version | 1.0.0 |
| author | Hermes Agent |
| license | MIT |
| platforms | ["linux","macos","windows"] |
| metadata | {"hermes":{"tags":["hermes","buzz","gateway","nostr","nip-oa","messaging","cross-platform"],"related_skills":["hermes-agent"]}} |
Hermes in Buzz
Overview
Set up a dedicated Hermes Agent running on one machine as a native messaging agent in a Buzz community used from another machine. The default topology is:
Buzz Desktop / web client
|
v
Buzz relay
^
| Nostr WebSocket + buzz CLI
|
Remote Hermes gateway
The client PC does not SSH into the Hermes host. Both independently connect to the same Buzz relay, and Buzz Desktop may be offline while Hermes continues running.
This skill executes the setup, not merely describes it. Continue until the CLI works, relay authorization succeeds, the gateway logs buzz connected, and one inbound plus outbound message has been verified.
Authoritative docs change quickly. At the start of every run, load the hermes-agent skill and inspect:
If docs and this skill differ, follow the docs and patch this skill after the successful run.
When to Use
Use when:
- Buzz Desktop is on one computer and Hermes should run continuously on another;
- a user says they created a Buzz agent but the Hermes gateway is silent;
- errors progress through
buzz CLI binary not found, relay_membership_required, zero channels, or ignored mentions;
- moving an existing native Buzz/Hermes gateway to Linux, macOS, Windows, or WSL.
Do not use this native-gateway workflow when the user explicitly wants Buzz to own the runtime and show ACP activity. In that case use the official buzz-acp relay-bridge guide. Do not improvise an SSH-stdio bridge unless the user explicitly requests an experimental design.
Hard Security Rules
- Use a dedicated agent identity. Never reuse the human Buzz
nsec as BUZZ_PRIVATE_KEY.
- Never ask for an
nsec, API token, or owner key in chat or via clarify.
- Secret input must be local and hidden (
getpass, Read-Host -AsSecureString, or equivalent), never argv.
- Never print, log, persist temporarily, or return owner private-key material.
- Store the agent key and
BUZZ_AUTH_TAG only in the active profile's Hermes secret environment file. Resolve HERMES_HOME; do not assume ~/.hermes when a profile is active.
- Use
hermes config set for non-secret settings. Never hand-edit config.yaml.
- Default to
allow_all_users: false, an explicit owner allowlist, and require_mention: true. Do not broaden access merely to diagnose delivery.
- Ask approval before installing Rust, Git, build tools, downloading Buzz, or changing persistence/service configuration.
- An ACP-hosted Hermes can execute terminal tools without a visible approval because Buzz may auto-answer ACP permissions. Keep ACP agents owner-only. Native gateway approvals retain Hermes gateway semantics.
Phase 1: Discover the Host and Choose the Architecture
- Detect OS, architecture, shell, active Hermes home/profile, service manager, and tool availability. Check at least
hermes, git, cargo, rustc, and buzz/buzz.exe. On Windows distinguish native Windows from WSL.
- Run
hermes status, hermes gateway status, and inspect redacted BUZZ_* presence. Never print secret values.
- Confirm the intended architecture:
- Native gateway (default): full Hermes memory, skills, normal sessions, DMs, cron delivery, images, reactions, threaded replies, and multiple messaging platforms in one gateway.
- Relay bridge (
buzz-acp): Buzz owns transport; Hermes runs in ACP mode on the server; reduced ACP-oriented surface and stronger owner-only warning.
- Buzz Desktop runtime: Hermes runs on the same computer as Buzz Desktop, not the remote-host goal.
- Collect only non-secret facts in chat: relay URL, desired agent display name, owner public
npub, intended channels/home channel, and whether other community members may invoke it.
Completion criterion: topology and access policy are explicit, no secret has appeared in conversation, and native gateway is selected unless the user chose otherwise.
Phase 2: Obtain a Dedicated Buzz Identity
Preferred native-gateway identity:
- dedicated agent
nsec and matching npub;
- direct relay membership when a relay administrator can add it; or
- NIP-OA owner attestation when a hosted/closed community uses managed agents.
For Buzz Desktop-managed identities:
- Have the user create the agent in Buzz Desktop and save the one-time displayed agent
nsec locally.
- Use
scripts/update_buzz_credentials.py set-agent-key on the Hermes host. The script prompts locally with hidden input and atomically writes BUZZ_PRIVATE_KEY.
- Do not assume creating or adding an agent to a channel makes it a direct relay member. Channel membership and relay/community admission differ.
- If direct authentication returns
relay_membership_required and the configured public key exactly matches the Buzz agent, keep the key and proceed to NIP-OA attestation. Do not regenerate identities repeatedly.
Resolve a Python interpreter the user can invoke locally:
- Linux/macOS/WSL: prefer the active Hermes venv Python, then
python3.
- Native Windows: prefer
%HERMES_HOME%\hermes-agent\venv\Scripts\python.exe, then py -3 or python.
Run the bundled updater from a real local terminal so the user—not the agent chat—enters the secret:
<python> <skill-dir>/scripts/update_buzz_credentials.py set-agent-key --hermes-home <resolved-HERMES_HOME>
Completion criterion: BUZZ_PRIVATE_KEY exists with restricted permissions where supported, but no secret value was printed.
Phase 3: Install the Buzz CLI Portably
Outbound messages always require the external buzz CLI even when inbound WebSocket transport is healthy.
3.1 Prefer a verified prebuilt CLI
- Query the current stable
block/buzz release API.
- Inspect asset names and content—not just the release title.
- Use a prebuilt asset only if it is a standalone Buzz CLI matching the exact OS and architecture.
- Verify its published digest when available, install it to a user-writable path, mark executable on Unix, and run
buzz --help.
Desktop .dmg, .deb, .rpm, .AppImage, or Windows desktop installers are not automatically standalone CLI assets.
3.2 Build from a pinned stable release when necessary
Ask approval before downloads or installs. Install prerequisites using the native package mechanism:
| Host | Typical prerequisites |
|---|
| Linux | Git, Rustup/Cargo, C/C++ compiler, make, cmake, pkg-config; use the detected distro package manager |
| macOS | Xcode Command Line Tools, Git, Rustup/Cargo; Homebrew is optional, not assumed |
| Windows native | Git, Rustup MSVC toolchain, Visual Studio C++ Build Tools; prefer winget when present |
| WSL | Follow Linux branch; enable systemd for managed-service persistence or use foreground mode |
Do not hardcode main. Resolve the latest stable release tag from GitHub, show the pinned tag, then clone into a cache/temp build directory:
git clone --depth 1 --branch <stable-tag> https://github.com/block/buzz.git <build-dir>
cargo build --release -p buzz-cli
Install to a user path:
- Linux/macOS/WSL:
~/.local/bin/buzz
- Windows:
%USERPROFILE%\.local\bin\buzz.exe
Use the absolute path in Hermes config so service PATH differences cannot break it. On macOS, rerun hermes gateway install --force after adding executables so launchd snapshots the current PATH.
3.3 Build the safe NIP-OA helper
When a hosted managed agent may need owner attestation, copy linked file scripts/hermes_buzz_credential_helper.rs into the pinned Buzz checkout as:
crates/buzz-sdk/examples/hermes_buzz_credential_helper.rs
Build it with the same pinned source:
cargo build --release -p buzz-sdk --example hermes_buzz_credential_helper
Install beside the Buzz CLI as hermes-buzz-credential-helper (append .exe on Windows). This helper reads private input from stdin; never alter it to accept private keys via argv.
Completion criterion: the installed absolute CLI path executes --help; if attestation may be needed, the credential helper also runs and its smoke test with a generated disposable key returns a structurally valid result.
Phase 4: Configure Non-Secret Hermes Settings
Use hermes config set, with the active profile selected when applicable. Set:
gateway.platforms.buzz.enabled = true
gateway.platforms.buzz.extra.relay_url = <relay URL>
gateway.platforms.buzz.extra.cli_path = <absolute CLI path>
gateway.platforms.buzz.extra.channels = [] or explicit UUID list
gateway.platforms.buzz.extra.home_channel = <UUID when outbound cron/notifications are wanted>
gateway.platforms.buzz.extra.poll_interval = 4
gateway.platforms.buzz.extra.require_mention = true
gateway.platforms.buzz.extra.allow_all_users = false
gateway.platforms.buzz.extra.allowed_users = [<owner npub or hex>]
display.platforms.buzz.interim_assistant_messages = false
display.platforms.buzz.tool_progress = off
Use JSON array syntax accepted by the live hermes config set implementation. Verify each value with hermes config get; do not infer success from exit code alone.
Migrate legacy or wizard-created environment-only setups. Environment variables override canonical config, so an old BUZZ_ALLOW_ALL_USERS=true silently defeats allow_all_users: false. After copying every non-secret value into canonical config and verifying it, atomically remove these overrides from the active profile's .env:
BUZZ_RELAY_URL
BUZZ_CHANNELS
BUZZ_HOME_CHANNEL
BUZZ_ALLOWED_USERS
BUZZ_ALLOW_ALL_USERS
BUZZ_POLL_INTERVAL
BUZZ_CLI_PATH
BUZZ_TRANSPORT
Retain credential material such as BUZZ_PRIVATE_KEY, BUZZ_AUTH_TAG, and any documented API token. Before removal, show only variable names and redacted set/unset state; never print values. Restart and re-read effective config after migration.
If the user explicitly wants community-wide invocation, explain that every community member who can address the agent may trigger tools, obtain approval, then set allow_all_users: true. Keep owner/admin command authorization separate.
Completion criterion: canonical non-secret configuration is present, no legacy environment variable overrides it, owner-only access is effective by default, and cli_path is absolute.
Phase 5: Verify Identity and Relay Admission
Load credentials with Hermes' dotenv parser or the bundled updater—not by shell-sourcing .env. Raw BUZZ_AUTH_TAG JSON loses quotation marks when shell-sourced and produces a false invalid JSON diagnosis.
- Run the helper's
public command through the Python updater to derive safe public values from the stored agent key:
<python> update_buzz_credentials.py public --hermes-home <home> --helper <helper-path>
- Compare the emitted public
npub/hex with the agent shown in Buzz.
- Invoke
buzz channels list with the exact dotenv values passed through a subprocess environment.
- Interpret results:
- binary missing: fix install path/service PATH;
- malformed auth tag only after shell sourcing: retest without shell parsing;
relay_membership_required plus matching public key: direct membership or NIP-OA is missing;
- successful auth but zero channels: attach the agent to intended channels;
- identity mismatch: replace the wrong agent key before doing anything else.
Completion criterion: public identity matches and direct CLI channel discovery succeeds, or the failure is specifically proven to require NIP-OA.
Phase 6: Generate NIP-OA Attestation Safely When Needed
Buzz Desktop-managed agents have both an agent key and an owner-signed auth tag. Desktop injects the tag into locally launched managed agents but may reveal only the agent nsec during creation.
If no relay-admin membership path exists:
- Confirm the agent public key matches.
- Ask the user to open Buzz Desktop on the owner PC and locate the human/owner private key under Identity settings.
- On the Hermes host, run:
<python> update_buzz_credentials.py set-auth-tag \
--hermes-home <home> \
--helper <absolute-helper-path> \
--agent-pubkey <64-char-agent-hex>
The updater uses hidden local input, sends the owner key to the Rust helper over stdin, validates a JSON four-string tag whose first value is auth, atomically writes only BUZZ_AUTH_TAG, and discards the owner key from memory. Never request that key in chat.
Then rerun direct channel discovery using exact dotenv parsing.
Completion criterion: CLI authentication succeeds and visible channel UUIDs are listed.
Phase 7: Install and Start the Gateway by OS
Linux with systemd
hermes gateway install --force
hermes gateway start
hermes gateway status
For a remote user service that must survive logout, explain and request approval before:
sudo loginctl enable-linger "$USER"
A Linux system service is an explicit alternative: sudo hermes gateway install --system.
macOS
hermes gateway install --force
hermes gateway start
hermes gateway status
This installs/reloads a launchd agent. Reinstall after PATH changes.
WSL2
Preferred persistent route: enable systemd in /etc/wsl.conf, restart WSL, then use Linux commands. Otherwise run hermes gateway run in a durable terminal/tmux, or create a Windows Task Scheduler job launching:
wsl -d <Distro> -- bash -lc 'hermes gateway run'
Native Windows
Do not claim systemd/launchd service support. Start with:
hermes gateway run
For persistence, use Windows Task Scheduler to launch the full Hermes executable path at user logon with arguments gateway run --external-supervisor, a working directory under the active Hermes home, restart-on-failure enabled, and the intended user account. Verify in foreground before creating the task. Never create persistence without explicit approval.
Completion criterion: exactly one gateway instance is running for the profile and survives according to the persistence method the user approved.
Phase 8: End-to-End Verification
Do not declare success from process state alone.
hermes gateway status shows a running gateway.
- Inspect
gateway.log and OS service logs for:
Connecting to buzz...
connected to <relay> as <name>, watching N channel(s)
buzz connected
- Confirm channel count and intended UUIDs.
- Ask the user to send:
- one DM (
Hello) to the agent;
- one channel mention (
@Agent hello).
- Verify logs show
inbound message: platform=buzz, response ready, and [Buzz] Sending response for each path.
- Confirm the replies actually appear in Buzz; logs alone do not prove UI delivery.
- If the displayed agent name is wrong, change the Buzz profile name separately; do not confuse host name, Hermes identity, and Buzz display name.
Completion criterion: one inbound message reached Hermes, Hermes generated a response, Buzz accepted the outbound send, and the user saw the response.
Failure Ladder
Treat each new error as progress to the next layer:
buzz CLI binary not found — missing executable or service PATH/cli_path problem.
relay_membership_required / 403 — valid signing key but no direct membership or NIP-OA attestation.
- Zero channels — relay admission works; channel attachment/filtering is wrong.
- Messages ignored — mention gating, allowlist, access policy, or self-echo suppression.
- Inbound works, outbound fails — CLI path, media path, or exact subprocess environment.
- Gateway appears stuck on another platform — read
gateway.log, not only journal/stderr; successful INFO-level connection messages may not appear in system journal. Do not disable an unrelated platform before checking the file log.
After every repair: restart once, read the newest failure, and continue until the end-to-end criterion passes.
Common Pitfalls
- Assuming a Buzz Desktop package contains the CLI.
- Building unpinned
main instead of a stable tag.
- Copying the agent
nsec but omitting its NIP-OA auth tag on a closed hosted relay.
- Treating channel membership as relay membership.
- Asking the user to paste an owner key into chat.
- Passing private keys in process argv.
- Shell-sourcing dotenv JSON and misdiagnosing a valid auth tag as malformed.
- Setting
BUZZ_ALLOW_ALL_USERS=true as a quick test and forgetting it.
- Running a second foreground gateway beside a managed service.
- Declaring success from
gateway status without a real inbound/outbound Buzz exchange.
- Assuming Windows native has Linux/macOS service management; use foreground verification and Task Scheduler only with approval.
- Forgetting to copy this entire skill directory, including
scripts/, to the new device.
Verification Checklist
Invocation and Transfer
Invoke in a fresh Hermes session with:
/hermes-in-buzz
or ask: “Use the hermes-in-buzz skill to connect this Hermes host to my Buzz community.”
To install on another device, copy the whole hermes-in-buzz directory into that profile's skills directory, preserving SKILL.md and scripts/, then start a new Hermes session so skill discovery refreshes.