fix: restore Claude subscription auth parity for Claude Code 2.1.112#207
fix: restore Claude subscription auth parity for Claude Code 2.1.112#207kunal70006 wants to merge 4 commits intogriffinmartin:mainfrom
Conversation
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…tin#207) - User-Agent changed to sdk-cli entrypoint - Added x-stainless-* headers for Anthropic fingerprint validation - Request URL now includes ?beta=true for /v1/messages - Added advisor-tool-2026-03-01 to baseBetas - ccVersion updated to 2.1.98 (matches local Claude CLI) - cc_entrypoint default changed from cli to sdk-cli - Added anthropic-dangerous-direct-browser-access header - intercept-claude.ts: dedupe betas to prevent duplicate entries on update - intercept-claude.ts: only capture POST /v1/messages, extract billing from system array - Tests updated to assert new headers, version, and entrypoint
Anthropic tightened OAuth validation between 2026-04-14 and 2026-04-22. Requests are now classified as third-party and routed to extra-usage credits (or rejected with 'Third-party apps now draw from your extra usage, not your plan limits') unless the fingerprint matches real Claude Code. Ports the two upstream opencode-claude-auth fixes that address this: - PR #191 (merged, v1.4.10): PascalCase `mcp_` tool names. Hermes prefixes tools with lowercase `mcp_bash`; the validator now flags that as non-Claude-Code. Real CC uses `mcp_Bash` / `mcp_Read` / `mcp_Background_output`. Adds a request-side rewrite hook plus a response-side unhook that lowercases the first char after hermes strips the prefix, so the tool dispatcher continues to receive the original lowercase names. - PR #207 (open, attempted fix for Claude Code 2.1.112): updates the billing fingerprint. Changes the `cc_entrypoint` in the signed billing header from `cli` to `sdk-cli`, adds the `advisor-tool-2026-03-01` beta flag, injects the Stainless SDK headers that real CC sends (`x-stainless-*`) plus `anthropic-dangerous-direct-browser-access: true`, and appends `?beta=true` to the /v1/messages query string. All non-body signals ride the Anthropic Python SDK's per-request `extra_headers` and `extra_query` kwargs so we don't need to rewrap the HTTP client. Other changes: - Bump __version__ to 1.1.0 and document the rationale above in the module docstring. - Extend `_EXTRA_OAUTH_BETAS` so both prompt-caching and advisor-tool betas are appended to hermes's `_OAUTH_ONLY_BETAS` list. - 10 new unit tests covering PascalCase rewrite (request + response), sdk-cli entrypoint, Stainless headers, extra_query=beta:true, and preservation of pre-existing extra_headers. Smoke-tested on Linux with hermes-agent v0.10.0 against claude-sonnet-4-6, claude-opus-4-6, and claude-opus-4-7 \u2014 all return 200 and complete responses with the new patch loaded. Billing-tier routing (plan vs extra-usage) cannot be verified from the client side; this tracks the best-known upstream bypass as of 2026-04-22 but Anthropic may tighten validation again at any time. Refs: #6 Upstream: griffinmartin/opencode-claude-auth#191 Upstream: griffinmartin/opencode-claude-auth#207
|
is this working for you ? |
Windows experience with this PR / pluginEnvironment:
What happened
Lessons learned
If other Windows users have solved this, please share your steps! Otherwise, hope this helps maintainers and others understand the current state on Windows. Thanks for the fix and all the work! |
bvironn
left a comment
There was a problem hiding this comment.
Tested locally — 214/214 tests pass.
Fingerprint update is well-scoped and matches the documented CC 2.1.112 wire format. The scripts/intercept-claude.ts fix (gating finish(captured) on POST /v1/messages rather than any response) is independently valuable — it would have masked the new fingerprint earlier.
One drift concern: x-stainless-package-version: "0.81.0" is hardcoded in getStainlessHeaders(). When Claude Code bumps the bundled @anthropic-ai/sdk, this will silently go stale. Two options:
- Promote it to
model-config.tsnext toccVersionso version drift is visible in one diff - Read via
process.env.ANTHROPIC_SDK_VERSIONwith current value as fallback
Not blocking — flagging because ccVersion followed the same pattern and got out of sync, which is exactly what triggered #206.
Resolves #206.
Summary
sdk-cliidentity, required beta flag, and missing request headers?beta=trueon/v1/messagesrequests so the plugin matches the live Claude Code request path used during subscription-authenticated callsPOST /v1/messagesrequest and billing marker instead of the initialHEAD /probeRelated issue
Closes #206.
Testing
corepack pnpm run lintcorepack pnpm run buildnpx -y tsx --test src/index.test.ts src/signing.test.tsbun scripts/intercept-claude.tsopencode run \"say hi\" -m anthropic/claude-sonnet-4-6 --print-logswithCLAUDE_AUTH_DEBUGenabled to verify the local fork loaded and returned 200 responsesChecklist
feat:,fix:,docs:,chore:, etc.)make allpasses locally (runs lint, build, and test)