Route Hermes API requests through your Claude Max/Pro subscription instead of Extra Usage billing.
Tested models: Claude Opus 4.8, Opus 4.7, Opus 4.6, Sonnet 4.6, Haiku 4.5, Gemini 2.5 Pro/Flash
Sits between Hermes and the Anthropic/Gemini APIs as a transparent HTTP proxy. Hermes sends requests to the proxy, which forwards them to upstream with:
- Claude Code's billing identifier injected into the system prompt
- Your Claude Code OAuth token replacing Hermes's auth (auto-refreshed)
- Hermes-specific keywords sanitized to avoid detection
- Gemini requests auto-routed to Google Cloud Code API
- Model-aware beta headers (long-context betas only sent for Opus)
- Correct TLS fingerprint (Node.js HTTPS client)
Zero external dependencies. Linux only. Node.js 18+.
Hermes (Python) --> HTTP proxy:18801 --> HTTPS Node.js --> api.anthropic.com (Anthropic models)
--> cloudcode-pa.googleapis.com (Gemini models)
The proxy performs bidirectional request/response processing:
Outbound (to API):
- Billing Header -- Injects Claude Code billing identifier into system prompt
- Token Swap -- Replaces auth token with your Claude Code OAuth token
- Keyword Replacement -- Replaces Hermes-specific terms (configurable)
- System Prompt Sanitization -- Strips structured config blocks if present
- CC Tool Stubs -- Injects Claude Code tool stubs for fingerprint camouflage
Inbound (to Hermes): 6. Reverse Mapping -- Restores all original keywords in SSE and JSON responses
- Node.js 18+
- Claude Max or Pro subscription
- Claude Code CLI installed and authenticated
- Hermes running on the same machine
npm install -g @anthropic-ai/claude-code
claude auth loginVerify:
claude auth status
# Should show: loggedIn: true, subscriptionType: max (or pro)# 1. Clone
git clone https://github.com/croll83/openclaw-billing-proxy hermes-billing-proxy
cd hermes-billing-proxy
# 2. Run setup (auto-detects credentials and Hermes)
node setup.js
# 3. Start the proxy
node index.js
# 4. Point Hermes ANTHROPIC_BASE_URL to the proxy addressThe config.json file (generated by setup or created manually):
{
"port": 18801,
"credentialsPath": "~/.claude/.credentials.json",
"stripSystemConfig": true,
"injectCCStubs": true,
"replacements": [
["~/.hermes/", "~/.config/app/"],
["hermes_tools", "code_tools"],
["hermes_telegram", "tg_channel"],
["hermes-secrets.env", "secrets.env"],
["Plan mode for Hermes", "Plan mode"],
["hermes_cli", "cli_module"],
["from hermes", "from app"],
["Hermes", "Assistant"],
["hermes", "assistant"]
],
"reverseMap": [
["~/.config/app/", "~/.hermes/"],
["code_tools", "hermes_tools"],
["tg_channel", "hermes_telegram"],
["secrets.env", "hermes-secrets.env"],
["Plan mode", "Plan mode for Hermes"],
["cli_module", "hermes_cli"],
["from app", "from hermes"],
["Assistant", "Hermes"],
["assistant", "hermes"]
]
}If you find new keywords that trigger detection, add them to both replacements and reverseMap:
{
"replacements": [["new_hermes_term", "new_safe_term"]],
"reverseMap": [["new_safe_term", "new_hermes_term"]]
}cat > ~/.config/systemd/user/hermes-billing-proxy.service << EOF
[Unit]
Description=Hermes Billing Proxy
After=network-online.target
Wants=network-online.target
[Service]
Environment="DEBUG_DUMP=1"
Type=simple
ExecStart=$(which node) $(pwd)/index.js
WorkingDirectory=$(pwd)
Restart=always
RestartSec=5
TimeoutStopSec=10
[Install]
WantedBy=default.target
EOF
systemctl --user daemon-reload
systemctl --user enable hermes-billing-proxy
systemctl --user start hermes-billing-proxyThe proxy auto-refreshes the OAuth token:
- Proactive: refreshes 5 minutes before expiry on the next request
- Reactive: on 401 from upstream, refreshes and retries once transparently
- Token is persisted to
~/.claude/.credentials.jsonafter refresh
No manual intervention needed. The token refresh uses platform.claude.com/v1/oauth/token.
curl http://127.0.0.1:18801/healthnode troubleshoot.js"Could not find credentials file"
- Run
claude auth loginto authenticate - Check
~/.claude/.credentials.jsonexists and is non-empty
Proxy returns 400 "extra usage"
- Add more keyword patterns to
config.json - Check proxy console for
DETECTION!log lines
429 Rate Limit
- Normal if you have active Claude Code sessions sharing the rate bucket
- Wait and retry
Token Expired / 401
- Should auto-recover via built-in refresh
- If persistent, check
journalctl --user -u hermes-billing-proxyfor[AUTH]lines - Manual fallback:
claude -p "ping" --max-turns 1 --no-session-persistence
MIT