One bootstrap token replaces N plaintext API keys. Hermes pulls every credential from your Bitwarden vault at every startup — so your keys are never scattered across .env files and never forgotten.
<user>, <YOUR_TELEGRAM_USER_ID>,
<BOT_TOKEN>, <your-agentmail-inbox>, and
<your-tailscale-host>.ts.net are placeholders
standing in for the real values on your own machine — usernames, user/chat
IDs, tokens, hostnames, and home paths differ on every install and have been
removed for privacy. Replace each <placeholder> with the
matching value for your system before running any command..env (optional)AI agents like Hermes need many API keys to do their job — an LLM
provider (e.g. OpenRouter), messaging bots (Telegram, Discord, Signal), an email
gateway, a workflow engine (n8n), a decision service (TypeSafe), phone messaging
(Twilio), and more. The naive way is to paste them all into a
~/.hermes/.env file. That breeds two recurring problems:
Bitwarden Secrets Manager fixes both. One small bootstrap token replaces all of those keys, they live encrypted in a central vault, and they are injected into every new Hermes process automatically at startup.
The architecture is deliberately simple:
BWS_ACCESS_TOKEN) — the only secret stored
on your machine.bws secret list <project_id> to fetch the whole project.OPENROUTER_API_KEY sets
OPENROUTER_API_KEY), and its value is the key.override_existing: true), vault values win over
anything baked into .env.Result: rotate any credential by changing it once in the Bitwarden web app, and the next Hermes start picks it up automatically. No editing files, no pasting secrets into chat, no "forgetting."
OPENROUTER_API_KEY, DISCORD_BOT_TOKEN,
TELEGRAM_BOT_TOKEN, N8N_API_KEY,
TYPESAFE_API_KEY, PHOTON_PROJECT_ID,
PHOTON_PROJECT_SECRET, ELEVENLABS_API_KEY,
TWILIO_AUTH_TOKEN, SIGNAL_ACCOUNT, and any other
env-var credentials Hermes reads. Plain non-secret config (base URLs, home
channels) usually stays in .env as before.bws CLI. Hermes auto-installs its pinned copy with
hermes secrets bitwarden install, or honours a bws
already on PATH.hermes installation.Do this part in the browser at vault.bitwarden.com. (An agent cannot do it for you — it has no browser session with your vault login, and your password must never pass through chat.)
OPENROUTER_API_KEY). The name
must match the variable exactly — a typo silently loads under
the wrong variable.~/.hermes/.env).hermes-1), set an expiry (or none) →
Create. Copy the token string now — it is
shown only once.BWS_ACCESS_TOKEN is
high-value — anyone holding it reads every secret in the project. Keep it
only in ~/.hermes/.env, never in config.yaml.Run this yourself in a terminal. It is interactive and prompts for the access token with hidden input:
hermes secrets bitwarden setup
The wizard will: install bws if absent → prompt for the
access token (hidden) → store it in ~/.hermes/.env as
BWS_ACCESS_TOKEN → ask for the Bitwarden region
(US Cloud = vault.bitwarden.com) → list the projects your
machine account can see → pick the one (e.g. Hermes keys). Then it
tests a fetch.
There is also a non-interactive equivalent (useful in automation — the token is passed via env, never typed in chat):
BWS_ACCESS_TOKEN="$BWS_ACCESS_TOKEN" hermes secrets bitwarden setup \
--access-token "$BWS_ACCESS_TOKEN" \
--server-url https://vault.bitwarden.com \
--project-id
hermes secrets bitwarden status # config + binary version + token valid?
hermes secrets bitwarden sync # dry-run: show what would be applied
hermes secrets bitwarden sync --apply # pull + export into current shell
On the first fresh Hermes start with secrets applied you'll see a one-line
summary in stderr. Then restart Hermes (or start a new
hermes invocation, gateway, or cron job) so the fetched secrets land
in the process environment.
env -i HOME=$HOME PATH="$PATH" \
HERMES_HOME=$HOME/.hermes \
/path/to/venv/bin/hermes chat -q "Reply with exactly: BITWARDEN_KEY_OK"After verifying status is green and a restarted process
picked up the keys, strip the migrated secrets from ~/.hermes/.env
for a single source of truth. Keep the non-secret config entries. If you'd rather
keep a plaintext fallback for offline safety, leave them — Bitwarden wins
anyway thanks to override_existing: true.
| Benefit | What it means day-to-day |
|---|---|
| Keys never "forgotten" | Every fresh Hermes process pulls all secrets from the vault at startup — a key can't silently go missing from a local file. |
| One token replaces N keys | One small BWS_ACCESS_TOKEN instead of a dozen formats on disk. |
| Central, encrypted storage | Secrets live in your Bitwarden vault, not scattered as plaintext in .env files, backups, or git history. |
| Instant rotation | Change a value once in the web app; the next start picks it up. Revoke a leaked key in seconds. |
| No secrets in chat | The wizard's hidden-input prompt keeps BWS_ACCESS_TOKEN and all keys out of chat logs. |
| Never blocks startup | If Bitwarden is unreachable, Hermes logs a one-line warning and continues with whatever .env already had (a local cache covers offline boots). |
hermes secrets bitwarden token
(paste the fresh token with hidden input). Also revoke the old token in the
web app (Machine accounts → Access tokens).hermes secrets bitwarden disablesecrets:
bitwarden:
enabled: true # master switch
access_token_env: BWS_ACCESS_TOKEN
project_id: "<project-uuid>" # set by wizard
server_url: "https://vault.bitwarden.com" # US; EU = vault.bitwarden.eu; empty = US default
cache_ttl_seconds: 300
encrypted_cache:
enabled: false
max_stale_seconds: 0
override_existing: true # Bitwarden wins over .env
auto_install: true
| Symptom | Cause | Fix |
|---|---|---|
BWS_ACCESS_TOKEN is not set | Enabled but token missing from .env | re-run hermes secrets bitwarden setup |
invalid_client | Token revoked/expired, machine deleted, or region mismatch (EU token hitting US endpoint) | hermes secrets bitwarden token; check server_url |
bws exited 1: invalid access token | Token revoked/wrong | hermes secrets bitwarden token |
bws timed out | Network blocked to api.bitwarden.com | check connectivity / proxy |
bws binary not available | No package manager + no binary on PATH | hermes secrets bitwarden install |
| Key loads under wrong variable | Secret Name doesn't exactly match the env var name | rename the secret in the web app to the exact env var name |
bw (personal
vault CLI) and bws (Secrets Manager CLI) are different tools.
Hermes uses bws only. Also, Hermes refuses to let Bitwarden
overwrite BWS_ACCESS_TOKEN itself — if you store it inside
the project it is silently skipped, so don't bother.~/.hermes/.env replaces every plaintext key; rotate anything in the vault and the next Hermes start picks it up.