Skip to content

fix: Anthropic OAuth token refresh URL migration + WSL credential path detection#3237

Closed
LucidPaths wants to merge 1 commit into
NousResearch:mainfrom
LucidPaths:fix/anthropic-oauth-wsl
Closed

fix: Anthropic OAuth token refresh URL migration + WSL credential path detection#3237
LucidPaths wants to merge 1 commit into
NousResearch:mainfrom
LucidPaths:fix/anthropic-oauth-wsl

Conversation

@LucidPaths

Copy link
Copy Markdown
Contributor

Summary

Anthropic migrated their developer console from console.anthropic.com to platform.claude.com. The old domain now 302-redirects. This breaks OAuth token refresh and leaves display URLs stale. Additionally, on WSL, read_claude_code_credentials() can never find credentials because Claude Code on Windows writes to a different filesystem than WSL's Path.home().

Bug 1: Stale OAuth Token Refresh URL

_refresh_oauth_token() POSTs to https://console.anthropic.com/v1/oauth/token (line 233). Anthropic's token endpoint now lives at https://platform.claude.com/v1/oauth/token. The 302 redirect breaks the token exchange because the refresh request fails when followed through a redirect.

Impact: Every user's OAuth token refresh silently fails once their initial token expires. This is a ticking time bomb — works until the first expiry, then auth is dead until the user manually re-authenticates.

Fix: Update the URL to platform.claude.com.

Evidence: Claude Code v2.1.84's own source (cli.js) uses platform.claude.com for all OAuth endpoints. Manual token exchange against the old endpoint returns invalid_grant.

Bug 2: WSL Cannot Find Claude Code Credentials

read_claude_code_credentials() reads from Path.home() / ".claude" / ".credentials.json". On WSL:

  • WSL home: /home/<user>/ (Linux filesystem)
  • Windows home: /mnt/c/Users/<user>/ (mounted Windows filesystem)

Claude Code (running on Windows) writes credentials to C:\Users\<user>\.claude\.credentials.json. WSL's Path.home() resolves to /home/<user>/ where no .credentials.json exists. Result: read_claude_code_credentials() always returns None on WSL.

Impact: All WSL users who run Claude Code on Windows cannot use the native Anthropic provider — credentials are never found.

Fix: Add WSL detection via /proc/version and resolve the Windows-side credential path via cmd.exe %USERPROFILE% with a /mnt/c/Users/ enumeration fallback. read_claude_code_credentials() now checks both native Linux and WSL-mounted Windows paths.

Additional: Display URL Updates

Three user-facing messages in setup.py, main.py, and run_agent.py point users to console.anthropic.com/settings/keys — updated to platform.claude.com/settings/keys.

Changes

File Change
agent/anthropic_adapter.py Token refresh URL: console.anthropic.complatform.claude.com
agent/anthropic_adapter.py Add _is_wsl(), _wsl_windows_credential_path(), _get_credential_paths()
agent/anthropic_adapter.py read_claude_code_credentials() iterates candidate paths
hermes_cli/setup.py Display URL update
hermes_cli/main.py Display URL update
run_agent.py Display URL update
tests/conftest.py Disable WSL detection in test suite (autouse fixture)

Testing

  • 77/77 tests pass in test_anthropic_adapter.py
  • WSL credential resolution verified manually on WSL2 + Windows 11
  • Non-UTF-8 cmd.exe output (German locale) handled gracefully with errors='replace'

Context: Claude 4 Models + OAuth

During debugging, we also discovered that Claude 4+ models (Sonnet 4, Opus 4, Opus 4.6) require the Claude Code system prompt prefix ("You are Claude Code, Anthropic's official CLI for Claude.") when authenticating via OAuth tokens. Without it, the API returns a bare 400 {"error": {"message": "Error"}} with no details. This is already handled correctly by build_anthropic_kwargs() when is_oauth=True — but the OAuth path was never reached because of Bugs 1 and 2, making it appear broken.

Claude 3 models (Haiku 3, Haiku 4.5) work without the prefix. This is an Anthropic-side behavior that ideally should return a descriptive error.

Anthropic migrated their developer console from console.anthropic.com to
platform.claude.com. The old domain now 302-redirects to the new one.

This broke:
1. OAuth token refresh (_refresh_oauth_token) — the token exchange endpoint
   at console.anthropic.com/v1/oauth/token no longer works directly
2. Display URLs pointing users to console.anthropic.com/settings/keys

Additionally, on WSL (Windows Subsystem for Linux), Claude Code runs on the
Windows host and writes credentials to the Windows user profile
(C:\Users\<name>\.claude\.credentials.json), but Hermes reads from
Path.home() which resolves to /home/<user>/ on WSL — a different filesystem.
This means read_claude_code_credentials() always returns None on WSL.

Changes:
- Update OAuth token refresh URL to platform.claude.com/v1/oauth/token
- Update 3 display URLs in setup.py, main.py, run_agent.py
- Add _is_wsl() detection via /proc/version
- Add _wsl_windows_credential_path() to resolve Windows-side credential file
  via cmd.exe %USERPROFILE% with /mnt/c/Users fallback
- read_claude_code_credentials() now checks both native and WSL paths
- Handle non-UTF-8 cmd.exe output (e.g. German locale) gracefully
- Disable WSL detection in test suite via conftest autouse fixture

Tested: 77/77 tests pass in test_anthropic_adapter.py
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the thorough investigation @LucidPaths!

A few notes on the current state:

OAuth refresh URL (Bug 1) — This was already fixed in PR #3246. Main already has a dual-endpoint approach that tries platform.claude.com first and falls back to console.anthropic.com for older tokens. Your PR would actually regress this by removing the fallback.

Display URLs — Good catch, these are still stale. We'll merge those updates directly.

WSL credential detection (Bug 2) — We're going to pass on this one. The complexity (spawning cmd.exe, enumerating /mnt/c/Users/) is high for a narrow edge case. WSL users can set ANTHROPIC_API_KEY in ~/.hermes/.env directly, which is the simpler path.

Closing this PR since the core issue is already resolved and we'll handle the display URLs separately. Thanks for the contribution!

@teknium1 teknium1 closed this Mar 29, 2026
teknium1 added a commit that referenced this pull request Mar 29, 2026
Anthropic migrated their developer console from console.anthropic.com
to platform.claude.com. Three user-facing display URLs were still
pointing to the old domain.

Spotted by @LucidPaths in PR #3237.
teknium1 added a commit that referenced this pull request Apr 19, 2026
Anthropic migrated their developer console from console.anthropic.com
to platform.claude.com. Two user-facing display URLs were still pointing
to the old domain:

- hermes_cli/main.py — API key prompt in the Anthropic model flow
- run_agent.py — 401 troubleshooting output

The OAuth token refresh endpoint was already migrated in PR #3246
(with fallback).

Spotted by @LucidPaths in PR #3237.

(Salvage of #3758 — dropped the setup.py hunk since that section was
refactored away and no longer contains the stale URL.)
teknium1 added a commit that referenced this pull request Apr 19, 2026
Anthropic migrated their developer console from console.anthropic.com
to platform.claude.com. Two user-facing display URLs were still pointing
to the old domain:

- hermes_cli/main.py — API key prompt in the Anthropic model flow
- run_agent.py — 401 troubleshooting output

The OAuth token refresh endpoint was already migrated in PR #3246
(with fallback).

Spotted by @LucidPaths in PR #3237.

(Salvage of #3758 — dropped the setup.py hunk since that section was
refactored away and no longer contains the stale URL.)
angelburgosrosado pushed a commit to angelburgosrosado/hermes-agent that referenced this pull request Apr 28, 2026
Anthropic migrated their developer console from console.anthropic.com
to platform.claude.com. Three user-facing display URLs were still
pointing to the old domain.

Spotted by @LucidPaths in PR NousResearch#3237.
ulasbilgen pushed a commit to ulasbilgen/hermes-adhd-agent that referenced this pull request May 1, 2026
Anthropic migrated their developer console from console.anthropic.com
to platform.claude.com. Two user-facing display URLs were still pointing
to the old domain:

- hermes_cli/main.py — API key prompt in the Anthropic model flow
- run_agent.py — 401 troubleshooting output

The OAuth token refresh endpoint was already migrated in PR NousResearch#3246
(with fallback).

Spotted by @LucidPaths in PR NousResearch#3237.

(Salvage of NousResearch#3758 — dropped the setup.py hunk since that section was
refactored away and no longer contains the stale URL.)
aj-nt pushed a commit to aj-nt/hermes-agent that referenced this pull request May 1, 2026
Anthropic migrated their developer console from console.anthropic.com
to platform.claude.com. Two user-facing display URLs were still pointing
to the old domain:

- hermes_cli/main.py — API key prompt in the Anthropic model flow
- run_agent.py — 401 troubleshooting output

The OAuth token refresh endpoint was already migrated in PR NousResearch#3246
(with fallback).

Spotted by @LucidPaths in PR NousResearch#3237.

(Salvage of NousResearch#3758 — dropped the setup.py hunk since that section was
refactored away and no longer contains the stale URL.)
02356abc pushed a commit to 02356abc/hermes-agent that referenced this pull request May 14, 2026
Anthropic migrated their developer console from console.anthropic.com
to platform.claude.com. Two user-facing display URLs were still pointing
to the old domain:

- hermes_cli/main.py — API key prompt in the Anthropic model flow
- run_agent.py — 401 troubleshooting output

The OAuth token refresh endpoint was already migrated in PR NousResearch#3246
(with fallback).

Spotted by @LucidPaths in PR NousResearch#3237.

(Salvage of NousResearch#3758 — dropped the setup.py hunk since that section was
refactored away and no longer contains the stale URL.)
CumulusService pushed a commit to Cumulus-Service-GmbH/hermes-agent that referenced this pull request May 30, 2026
Anthropic migrated their developer console from console.anthropic.com
to platform.claude.com. Three user-facing display URLs were still
pointing to the old domain.

Spotted by @LucidPaths in PR NousResearch#3237.
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
Anthropic migrated their developer console from console.anthropic.com
to platform.claude.com. Two user-facing display URLs were still pointing
to the old domain:

- hermes_cli/main.py — API key prompt in the Anthropic model flow
- run_agent.py — 401 troubleshooting output

The OAuth token refresh endpoint was already migrated in PR NousResearch#3246
(with fallback).

Spotted by @LucidPaths in PR NousResearch#3237.

(Salvage of NousResearch#3758 — dropped the setup.py hunk since that section was
refactored away and no longer contains the stale URL.)
Egavasyug pushed a commit to Egavasyug/hermes-agent that referenced this pull request Jun 10, 2026
Anthropic migrated their developer console from console.anthropic.com
to platform.claude.com. Two user-facing display URLs were still pointing
to the old domain:

- hermes_cli/main.py — API key prompt in the Anthropic model flow
- run_agent.py — 401 troubleshooting output

The OAuth token refresh endpoint was already migrated in PR NousResearch#3246
(with fallback).

Spotted by @LucidPaths in PR NousResearch#3237.

(Salvage of NousResearch#3758 — dropped the setup.py hunk since that section was
refactored away and no longer contains the stale URL.)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants