Claude Code OAuth bypass for hermes-agent, use your Claude Code subscription (Max/Pro) with Hermes.
Patches hermes-agent at runtime to pass Anthropic's server-side OAuth content validation. It does not modify hermes-agent source files. Installation happens through a Python import hook that monkey-patches build_anthropic_kwargs on startup.
On 2026-04-04, Anthropic added server-side validation that rejects OAuth requests from third-party tools. This patch adds the billing header signature and system prompt structure the API expects.
- hermes-agent installed (
~/.hermes/hermes-agent/) - Claude Code CLI authenticated (valid credentials at
~/.claude/.credentials.json) - hermes-agent configured for OAuth (
credential_poolhas aclaude_codeentry in~/.hermes/auth.json) - Python 3.11+
curl -fsSL https://raw.githubusercontent.com/kristianvast/hermes-claude-auth/main/install-remote.sh | bashOr clone manually:
git clone https://github.com/kristianvast/hermes-claude-auth.git
cd hermes-claude-auth
./install.shWhat install.sh does:
- Copies
anthropic_billing_bypass.pyto~/.hermes/patches/ - Installs the import hook as
sitecustomize.pyin the hermes venv's site-packages - Restarts
hermes-gateway.serviceif running
./uninstall.sh # remove hook only
./uninstall.sh --purge # remove hook + patch file- Billing header: SHA-256 signed
x-anthropic-billing-headerinjected assystem[0] - System prompt relocation: Non-identity system entries moved to the first user message as
<system-reminder>blocks - Beta flags: Adds
prompt-caching-scope-2026-01-05andadvisor-tool-2026-03-01 - Stainless SDK spoof: Lowercase
x-stainless-*headers +anthropic-dangerous-direct-browser-access+?beta=truequery param matching real Claude Code 2.1.112 - Tool name namespacing: Hermes's
mcp_bashis rewritten tomcp__hermes__Bashoutbound; the response normalizer unwraps it back tobashso hermes's tool dispatcher resolves the registered name without auto-repair noise - Tool pair repair: Orphaned
tool_use/tool_resultblocks (left by long conversations or partial summaries) are stripped before signing — prevents HTTP 400 (upstream PR #136) - Haiku effort stripping:
effortparameter is removed for haiku models that reject it with HTTP 400 (upstream PR #126) - Temperature fix: Strips non-default
temperatureon Opus 4.6 adaptive thinking, which otherwise rejects with HTTP 400 - Account metadata: Maps
~/.claude.json::oauthAccount.accountUuidtometadata.user_id(Anthropic rejected the olderaccount_uuidkey with HTTP 400 on 2026-04-29)
Installed through a sitecustomize.py MetaPathFinder hook, so it runs at interpreter startup with no source modifications.
| File | Action |
|---|---|
~/.hermes/patches/anthropic_billing_bypass.py |
Created |
<venv>/lib/pythonX.Y/site-packages/sitecustomize.py |
Created or replaced |
| hermes-agent source files | NOT modified |
- Tested with hermes-agent on Python 3.11+
- Linux and macOS
- Depends on
build_anthropic_kwargs(is_oauth=...)inagent.anthropic_adapter, so it may need updating if hermes-agent changes that interface
- "hermes-agent not found": Make sure Hermes is installed at
~/.hermes/hermes-agent/ - "No virtualenv found": Set
HERMES_VENVto point to your venv - Patch not loading: Check
journalctl --user -u hermes-gateway -n 50for[anthropic_billing_bypass]or[hermes-claude-auth]messages
-
Anthropic 401 authentication failedorNo Anthropic credentials found: Hermes reads Claude subscription credentials from~/.claude/.credentials.json. If Claude Code is authenticated (e.g. in macOS Keychain) but that file is missing or stale, Hermes fails even when Claude Code itself works.On macOS,
install.shv1.1.1+ auto-mirrors theClaude Code-credentialsKeychain entry into~/.claude/.credentials.jsonon every run, so re-running the installer is usually enough. Full fix:- Refresh Claude subscription login:
claude auth login --claudeai
- Re-run the installer to re-mirror credentials (macOS) and reload the patch:
./install.sh
- Remove stale
ANTHROPIC_TOKEN/ANTHROPIC_API_KEYvalues from~/.hermes/.env— they can override subscription auth. - Reset cached credentials:
hermes auth reset anthropic
- Retry with a smoke test:
hermes chat -q 'Reply with exactly: AUTH TEST OK' --provider anthropic -m claude-sonnet-4-6 -Q
If the auto-mirror doesn't work (e.g. your Keychain entry is under a different service name), mirror it manually:
python3 - <<'PY' import subprocess from pathlib import Path secret = subprocess.check_output( ['security', 'find-generic-password', '-s', 'Claude Code-credentials', '-w'], text=True, ).strip() cred_path = Path.home() / '.claude' / '.credentials.json' cred_path.parent.mkdir(parents=True, exist_ok=True) cred_path.write_text(secret) cred_path.chmod(0o600) print(f'wrote {cred_path}') PY
Credit: the macOS Keychain mirror approach was written up by @DrQbz in issue #5 and is now automated in
install.sh. - Refresh Claude subscription login:
- HTTP 400: "Third-party apps now draw from your extra usage, not your plan limits": Anthropic's server-side validation has classified your requests as third-party and routed them to pay-per-token credits instead of your Max/Pro plan. Make sure you're on the latest version of this patch (it tracks the upstream opencode-claude-auth fingerprint changes). Reinstall with
./install.shand restarthermes-gateway. If the error persists after update, the bypass is currently broken upstream too — track issue #6 for status. - HTTP 400 persists after update: The billing salt or signature format may have been rotated by Anthropic again. Check for newer commits to this repo.
- griffinmartin/opencode-claude-auth, the original TypeScript implementation for opencode (MIT)
- NousResearch/hermes-agent, the AI agent this patches (MIT)
This uses Claude Code subscription credentials outside the official Claude Code CLI. It works with Anthropic's current OAuth implementation but may break if Anthropic changes their validation. Use at your own risk.
MIT, see LICENSE.