pass-secrets
pass (password-store) secret source for Hermes Agent — resolves secrets from your local GPG-encrypted password store into environment variables at startup. Local filesystem, git-tracked, no network dependency, no token expiry.
Why
Hermes ships Bitwarden Secrets Manager and 1Password sources. If your secrets already live in pass — GPG-encrypted, git-backed, fully offline — this lets Hermes read them as a first-class secret source instead of migrating to a hosted vault.
How it works
The plugin registers a SecretSource with the Hermes orchestrator. You fetch; the orchestrator applies — the plugin never writes os.environ itself, never prompts, never raises. Each pass entry's leaf name becomes the env var name (UPPER_SNAKE_CASE enforced).
# profile config.yaml
secrets:
sources: [pass, bitwarden] # pass primary, BWS fallback
pass:
enabled: true
store_path: ~/.password-store # default
subdirs: [shared, phoenix] # pass directories to pull
override_existing: true # pass wins over .env/shell
timeout_seconds: 30
Resolution flow:
register(ctx)runs at plugin discovery →ctx.register_secret_source(PassSource())- The orchestrator re-pulls enabled secret sources at startup (
reset_secret_source_cache+ dotenv load) fetch()walks each configured subdirectory, runspass show <path>per.gpgentry (10s timeout, GPG agent env preserved)- Merged
{ENV_VAR: value}returns to the orchestrator, which handles precedence, conflict detection, and provenance
What you'll see in session prompts
The plugin also registers a conditional system-prompt note teaching agents where secrets resolve from (declared names are injected into child process env; provider credentials are runtime-only by upstream design). It appears only when secrets.pass.enabled is true and the pass binary is resolvable — a disabled plugin contributes nothing to the prompt. The note is ~900 characters of the 4000-char prompt budget, no dynamic content.
Disclosures
- Reads your GPG-encrypted pass store by shelling out to the
passbinary per entry, withGNUPGHOME/GPG_AGENT_INFOpreserved. If your GPG key prompts a passphrase,gpg-agenthandles it — the plugin never prompts. - Bulk injection: everything in the configured subdirs becomes env vars. Configure narrowly (
subdirs:) — don't point it at a store subdirectory containing material you wouldn't put in a process environment. - No network. Ever. Pure local: subprocess + filesystem only.
- No protected env vars: pass uses GPG agent, not an env-var bootstrap token.
Requirements
passon PATH (GPG-based password store initialized:pass init <GPG_KEY_ID>)- Hermes Agent
>=0.21.4(SecretSource plugin API withregister_secret_source) - No Python dependencies beyond stdlib
Missing/broken secrets fail cleanly
passnot on PATH → typedBINARY_MISSINGerror with platform-specific install hint- Store path missing →
NOT_CONFIGUREDwithpass inithint - Individual entry fails → warning collected, remaining entries still load
License
MIT — see LICENSE.