Problem or Use Case
When running hermes setup (or hermes model), the inference-provider configuration step silently skips the API-key prompt if any value is already present in ~/.hermes/.env — regardless of whether that value is a valid key, a malformed key, or even completely unrelated text. The only indication is a green checkmark:
DeepSeek API key: sk-c7be8... ✓
The ✓ only means "a non-empty string exists for DEEPSEEK_API_KEY". It does not validate:
- Length/format of the key (I accidentally pasted 343 characters of junk starting with
sk-, and the wizard treated it as configured).
- Whether the key actually works against the provider's endpoint.
Impact for the user: if you ever paste the wrong thing into an API-key prompt (extra whitespace, wrong provider's key, a JWT, a multi-line paste that got concatenated, etc.), you get stuck in a loop:
hermes → chat fails with HTTP 401: Authentication Fails, Your api key: ****xxxx is invalid.
- Error message says:
💡 Is the key valid? Run: hermes setup.
- You run
hermes setup → wizard shows API key: sk-xxx... ✓ and jumps straight past the key entry, going to the Base URL prompt.
- No way inside the wizard to say "the stored key is bad, let me enter a new one."
The only recovery today is to exit, manually nano ~/.hermes/.env, delete the DEEPSEEK_API_KEY= line, and re-run hermes setup. That's unfriendly for new users and directly contradicts the error message that tells them to run hermes setup.
This affects every provider configured via the same code path — the API key: xxxxx... ✓ / else-branch pattern appears in hermes_cli/main.py at lines 3811, 3930, and 4324 (and a similar "already configured" short-circuit exists throughout hermes_cli/setup.py for Modal, Daytona, Telegram, Discord, Slack, Matrix, Mattermost, BlueBubbles, Webhooks, etc.).
Reproduction
# 1. Put a malformed value in the key
echo "DEEPSEEK_API_KEY=sk-this-is-not-a-real-key-but-a-long-string-of-junk" >> ~/.hermes/.env
# 2. Run setup
hermes setup
# Wizard prints "DeepSeek API key: sk-this-... ✓" and moves on.
# There is no prompt to replace it.
Environment
- Hermes Agent
0.11.0 (commit 6c873718)
- WSL2 Ubuntu 24.04, Python 3.11
- Provider: DeepSeek (reproducible on any provider that stores its key directly in
.env)
Proposed Solution
Change the else branch that currently just prints the ✓ line into an interactive "keep / replace / clear" menu. Concretely, in hermes_cli/main.py around lines 3810, 3929, 4323, replace:
else:
print(f" {pconfig.name} API key: {existing_key[:8]}... ✓")
print()
with something like:
else:
print(f" {pconfig.name} API key: {existing_key[:8]}... (stored, not validated)")
action = prompt_choice(
"What would you like to do?",
[
"Keep current key",
"Replace with a new key",
"Remove key",
],
default=0,
)
if action == 1:
new_key = getpass.getpass(f"{key_env}: ").strip()
if new_key:
save_env_value(key_env, new_key)
existing_key = new_key
print("API key replaced.")
elif action == 2:
save_env_value(key_env, "")
existing_key = ""
print("API key removed.")
print()
Optionally, pair this with a lightweight validity probe — make a single unauthenticated-friendly request (GET /models for OpenAI-compatible endpoints, or a 1-token ping) and show ✓ verified vs ⚠ unverified — server returned 401 next to the key. That would turn the current checkmark from a misleading claim into a meaningful one.
Why this is worth doing
- The current flow sends users into a manual-file-edit dead end that the error message itself cannot recover from.
- It's a small, self-contained change (one helper, three call sites in
main.py, plus a similar pattern across setup.py for other credentials).
- It also sets the pattern right for any future provider added to
PROVIDER_REGISTRY — the else-branch boilerplate gets copy-pasted each time.
Alternatives Considered
- Add a CLI flag like
hermes setup --reset-keys that nukes all stored credentials before running the wizard. Works, but requires the user to know the flag exists and is a much bigger hammer than "let me change one key."
- Document the workaround (edit
.env manually) more prominently in the 401 error message. Solves discoverability but doesn't solve the UX issue; it still requires users to hand-edit a dotfile.
- Auto-validate the key on startup and invalidate if 401 — opinionated, could fail on transient network errors, probably not desirable.
The proposed "keep / replace / clear" menu is the smallest change that restores the promise implied by the wizard's own error message ("run hermes setup").
Feature Type
CLI improvement
Scope
Small (single file, < 50 lines)
Problem or Use Case
When running
hermes setup(orhermes model), the inference-provider configuration step silently skips the API-key prompt if any value is already present in~/.hermes/.env— regardless of whether that value is a valid key, a malformed key, or even completely unrelated text. The only indication is a green checkmark:The
✓only means "a non-empty string exists forDEEPSEEK_API_KEY". It does not validate:sk-, and the wizard treated it as configured).Impact for the user: if you ever paste the wrong thing into an API-key prompt (extra whitespace, wrong provider's key, a JWT, a multi-line paste that got concatenated, etc.), you get stuck in a loop:
hermes→ chat fails withHTTP 401: Authentication Fails, Your api key: ****xxxx is invalid.💡 Is the key valid? Run: hermes setup.hermes setup→ wizard showsAPI key: sk-xxx... ✓and jumps straight past the key entry, going to the Base URL prompt.The only recovery today is to exit, manually
nano ~/.hermes/.env, delete theDEEPSEEK_API_KEY=line, and re-runhermes setup. That's unfriendly for new users and directly contradicts the error message that tells them to runhermes setup.This affects every provider configured via the same code path — the
API key: xxxxx... ✓/ else-branch pattern appears inhermes_cli/main.pyat lines 3811, 3930, and 4324 (and a similar "already configured" short-circuit exists throughouthermes_cli/setup.pyfor Modal, Daytona, Telegram, Discord, Slack, Matrix, Mattermost, BlueBubbles, Webhooks, etc.).Reproduction
Environment
0.11.0(commit6c873718).env)Proposed Solution
Change the
elsebranch that currently just prints the✓line into an interactive "keep / replace / clear" menu. Concretely, inhermes_cli/main.pyaround lines 3810, 3929, 4323, replace:with something like:
Optionally, pair this with a lightweight validity probe — make a single unauthenticated-friendly request (
GET /modelsfor OpenAI-compatible endpoints, or a 1-token ping) and show✓ verifiedvs⚠ unverified — server returned 401next to the key. That would turn the current checkmark from a misleading claim into a meaningful one.Why this is worth doing
main.py, plus a similar pattern acrosssetup.pyfor other credentials).PROVIDER_REGISTRY— the else-branch boilerplate gets copy-pasted each time.Alternatives Considered
hermes setup --reset-keysthat nukes all stored credentials before running the wizard. Works, but requires the user to know the flag exists and is a much bigger hammer than "let me change one key.".envmanually) more prominently in the 401 error message. Solves discoverability but doesn't solve the UX issue; it still requires users to hand-edit a dotfile.The proposed "keep / replace / clear" menu is the smallest change that restores the promise implied by the wizard's own error message ("run
hermes setup").Feature Type
CLI improvement
Scope
Small (single file, < 50 lines)