Skip to content

[Feature]: hermes setup should allow replacing an existing API key instead of silently skipping the prompt #16394

@Kirito14IT

Description

@Kirito14IT

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:

  1. hermes → chat fails with HTTP 401: Authentication Fails, Your api key: ****xxxx is invalid.
  2. Error message says: 💡 Is the key valid? Run: hermes setup.
  3. You run hermes setup → wizard shows API key: sk-xxx... ✓ and jumps straight past the key entry, going to the Base URL prompt.
  4. 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

  1. 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."
  2. 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.
  3. 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)

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — degraded but workaround existsarea/configConfig system, migrations, profilescomp/cliCLI entry point, hermes_cli/, setup wizardtype/featureNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions