Anthropic Explicitly Blocking OpenCode
161–164 of 164 posts
Re: Anthropic Explicitly Blocking OpenCode
#162It’ll be interesting to see how far they take this cat and mouse game. Will “model attestation” become a new mechanism for enforcing tight coupling between client and inference endpoint? It could get weird, with secret shibboleths inserted into model weights…
There ain't no client validation mechanism you can't fake with enough time, patience, reverse-engineering, and good-old-fashioned stubborn hacker ethos.
Re: Anthropic Explicitly Blocking OpenCode
#163The title is misleading if you don’t read the whole text: Anthropic is not blocking OpenCode from the API that they sell. They’ve blocked OpenCode from accessing the private Claude Code endpoints. These were not advertised or sold as usable with anything else. OpenCode reverse engineered the API and was trying to use it. The private API isn’t intended for use with other tools. Any tool that used it would get blocked.
I reverse engineered this over the past week. Both Claude Code and regular API users hit the same endpoint: https://api.anthropic.com/v1/messages
The only difference is the auth method - OAuth bearer token (sk-ant-oat01-...) vs API key (sk-ant-api03-...). The "blocking" is request body fingerprinting on the server side.
Here's what a working Claude Code request looks like:
{
"model": "claude-sonnet-4-20250514",
"max_tokens": 32000,
"stream": true,
"metadata": {
"user_id": "user__account__session_"
},
"system": [
{"type": "text", "text": "You are a Claude agent, built on Anthropic's Claude Agent SDK."},
{"type": "text", "text": ""}
],
"tools": [
{"name": "Task", ...},
{"name": "Bash", ...},
// 17 tools total, PascalCase names
],
"messages": [...]
}
And here's what OpenCode sends (blocked): {
"model": "claude-sonnet-4-20250514",
"max_tokens": 16000,
"temperature": 0, // Claude Code doesn't send this
"stream": true,
// no metadata.user_id - required
"system": [
{"type": "text", "text": "You are OpenCode, an interactive CLI..."}
],
"tools": [
{"name": "bash", ...}, // lowercase, wrong schema
{"name": "edit", ...},
// 11 tools total
],
"messages": [...]
}
The API validates at least 5 things:(1) system prompt must start with "You are a Claude agent, built on Anthropic's Claude Agent SDK."
(2) tools must match Claude Code's exact 17 tool definitions with PascalCase names
(3) headers must include anthropic-beta, x-app: cli, and claude-cli user-agent
(4) metadata.user_id must be present in a specific format
(5) temperature field must be absent.
Fail any of these:
400 | This credential is only authorized for use with Claude Code
and cannot be used for other API requests.
It's bypassable though. I wrote a local proxy that lets OpenCode (and other third-party clients) work with a Max subscription. The approach: run legit Claude Code through the proxy once to capture its exact request format - the full system prompt, all 17 tool schemas, headers. Cache that. Then when OpenCode sends a request, the proxy swaps its templates with Claude Code's cached ones, adds the required headers/metadata, and strips temperature. The OAuth token is already on disk at ~/.claude/.credentials.json (written by "claude login") - the proxy just reads it for each request.Same endpoint, same request size, just different templates. Returns 200. OpenCode works with Max subscription again.
It's not endpoint separation, it's request body validation. The OAuth token is tied to an expected request format, but the format can be mimicked.