Repository navigation
Claude (and other pool-based) cards disappear when Desktop is on a named profile that has no auth.json of its own #36
Description
Summary
When Hermes Desktop is switched to a named profile (~/.hermes/profiles/<name>) that has no auth.json of its own, the Claude card disappears, even though that profile is actively running on the base install's Claude Pro OAuth login. Switching back to the default profile brings the card back.
Environment
- hermes-resetwatch 0.2.21 (sha
d460334), installed via Desktop catalog - macOS (Apple Silicon), Hermes Desktop with three profiles:
default,curry,him - Claude Pro login stored only in the base
~/.hermes/auth.json→credential_pool.anthropic(auth_type: oauth,source: manual:hermes_pkce) profiles/curry/auth.jsonandprofiles/him/auth.jsondo not exist. Hermes falls back to the base credentials, and thecurryprofile runs on Claude Pro without problems.
Steps to reproduce
- Log in to Claude via Hermes on the default profile (credentials land in
~/.hermes/auth.json). - Create a named profile without its own
auth.jsonand set its provider to Anthropic. - Open ResetWatch on the default profile: the Claude card shows.
- Switch Desktop to the named profile and reload: the Claude card is gone, and only the cards from outside Hermes (e.g. Codex via
~/.codex) remain.
Evidence
Per-profile probe caches from the same machine, minutes apart:
| Cache | Claude card | Codex card |
|---|---|---|
~/.hermes/cache/resetwatch/probe_snapshots.full.json |
✅ Pro | ✅ |
~/.hermes/profiles/curry/cache/resetwatch/probe_snapshots.full.json |
❌ | ✅ |
~/.hermes/profiles/him/cache/resetwatch/probe_snapshots.full.json |
❌ | ✅ |
No anthropic_usage.*.ratelimit files were present, so this isn't throttling.
Root cause
With --profile <name>, _hermes_homes() returns only the profile home:
def _hermes_homes() -> list[Path]:
if _profile_home is not None:
return [_profile_home]_pool_entries() therefore reads only profiles/<name>/auth.json, which doesn't exist, so _pool_entries("anthropic") returns [] and the card is dropped. Hermes itself falls back to the base home's credentials in this case, so the probe and the agent disagree about which login the profile uses.
Suggested fix
Fall back to the base home for auth.json credential pools only, and only when the profile has no auth.json of its own. This mirrors Hermes's behaviour while keeping the existing profile isolation for cache dirs and .env lookups. Tested locally: after the patch, --profile curry, --profile him and --profile default all return the Anthropic Pro card plus Codex.
@@ def _pool_entries(provider: str) -> list[dict]:
- for home in _hermes_homes():
+ for home in _auth_store_homes():
store = _read_auth_store(home / "auth.json")
+def _auth_store_homes() -> list[Path]:
+ """Homes to search for auth.json credential pools.
+
+ Hermes profiles without their own auth.json use the base home's
+ credentials, so mirror that here. Profile first; base only as a
+ fallback when the profile has no auth.json.
+ """
+ homes = _hermes_homes()
+ if _profile_home is not None and not (_profile_home / "auth.json").is_file():
+ if _profile_home.parent.name == "profiles":
+ base = _profile_home.parent.parent
+ if base not in homes and (base / "auth.json").is_file():
+ homes = [*homes, base]
+ return homesHappy to open a PR if that's useful.
Activity
Adolanium commentedon Oct 9, 2026
Thanks for the thorough report. You're right about the cause, and yes, a PR would be great.
One change to the approach, though. Hermes decides the fallback per provider, not per file.
read_credential_pool()inhermes_cli/auth.pyuses the base home's rows for a provider whenever the profile has no rows for that provider, even if the profile has its ownauth.json. With the suggested patch, a profile whoseauth.jsononly holds an OpenRouter key, for example, would still lose the Claude card, while Hermes runs that profile on the base Claude login._pool_entries()already returns the first home that has rows for the provider, so adding the base home after the profile home gives the same rule:Please keep the change inside
_pool_entries(), so.envlookups, caches and.anthropic_oauth.jsonstay per-profile. Hermes also reads that OAuth file only from the profile's own home.These three test cases would cover it:
auth.jsongets the base home's Claude rows.auth.jsononly has another provider still gets the base home's Claude rows.Then run
python scripts/build_catalog.pysocatalog/desktop/probe.pygets the same change. CI runs it with--check.Adolanium commentedon Oct 17, 2026
Fixed in #43 with the per-provider fallback described above, and released in catalog-v0.2.23. A profile with no Claude rows of its own now shows the base login's Claude card. Catalog installs get it once the catalog update (NousResearch/hermes-agent#140366) is merged, through
hermes plugins update.fix(probe): fall back to the base credential pool per provider and ke…