Я долго думал, что Claude Code намертво привязан к аккаунту claude.ai. Оказалось, нет: это обычный клиент к HTTP-эндпоинту, и куда он ходит — настраивается двумя переменными. Понадобилось мне это по скучной причине: на работе появился внутренний LLM-шлюз, и весь трафик к моделям должен идти через него. Пока разбирался, наступил на все грабли, которые есть. Ниже — что именно нужно Claude Code от эндпоинта, как его подключить тремя способами, как проверить до запуска и что означают ошибки, которые вы обязательно увидите.
Сервисы и роутеры называть не буду — принципиально. Всё ниже одинаково работает с корпоративным шлюзом, вашим собственным прокси и любым сторонним эндпоинтом, лишь бы он говорил на нужном протоколе.
Что Claude Code просит от эндпоинта
Claude Code разговаривает по Anthropic Messages API. Ему нужен HTTPS-адрес, на котором отвечает POST /v1/messages, и ключ. Всё. Если эндпоинт отдаёт только OpenAI-совместимый /v1/chat/completions — с Claude Code он напрямую не заработает, это другой протокол. Уточните у владельца шлюза, какой формат у него есть, прежде чем что-то настраивать.
Второй вопрос, который надо задать владельцу: в каком заголовке он ждёт ключ. Вариантов два, и от ответа зависит, какую переменную вы будете ставить:
-
Authorization: Bearer <ключ>— тогда нужна переменнаяANTHROPIC_AUTH_TOKEN -
x-api-key: <ключ>— тогдаANTHROPIC_API_KEY
Если не сказали — ставьте ANTHROPIC_AUTH_TOKEN, а проверка ниже покажет, угадали ли вы. Половина всех 401 в этой теме — ключ положили в переменную, которая отправляет его не в тот заголовок.
Способ 1. Переменные в shell
Самый быстрый, годится чтобы попробовать:
export ANTHROPIC_BASE_URL=https://llm-gateway.example.comexport ANTHROPIC_AUTH_TOKEN=sk-gateway-keyclaude
Минус — живёт только в этом терминале. Откроете новую вкладку, и Claude Code снова пойдёт в claude.ai.
Способ 2. settings.json
Постоянный вариант. Файл ~/.claude/settings.json (на Windows — %USERPROFILE%\.claude\settings.json), блок env:
{ "env": { "ANTHROPIC_BASE_URL": "https://llm-gateway.example.com", "ANTHROPIC_AUTH_TOKEN": "sk-gateway-key" }}
Два момента, о которых не пишут крупным шрифтом. Первый: если одна и та же переменная задана и в shell, и в settings.json, побеждает settings.json. Я час искал, почему export не действует, — вот поэтому. Второй: не кладите ключ в .claude/settings.json внутри проекта. Этот файл коммитится и уезжает всем, кто клонирует репозиторий. Для проекта есть .claude/settings.local.json, он в .gitignore по умолчанию.
Способ 3. apiKeyHelper
Если ключ ротируется или лежит в хранилище секретов, вместо статической переменной можно указать команду, которая печатает ключ в stdout:
{ "apiKeyHelper": "~/bin/get-gateway-key.sh"}
Команда должна печатать только ключ, без баннеров и логов, иначе Claude Code возьмёт мусор и вы получите загадочное «Your apiKeyHelper script is failing». Ключ из хелпера отправляется сразу в обоих заголовках, так что вопрос «bearer или x-api-key» здесь отпадает.
Проверьте эндпоинт до запуска Claude Code
Это главный совет статьи. Не запускайте claude, пока не убедитесь curl-ом, что эндпоинт живой и ключ подходит:
curl -X POST "$ANTHROPIC_BASE_URL/v1/messages" \ -H "Authorization: Bearer $ANTHROPIC_AUTH_TOKEN" \ -H "anthropic-version: 2023-06-01" \ -H "content-type: application/json" \ -d '{"model":"claude-sonnet-4-6","max_tokens":32,"messages":[{"role":"user","content":"ping"}]}'
Если шлюз ждёт x-api-key, замените заголовок Authorization на x-api-key: $ANTHROPIC_API_KEY.
Как читать ответ:
-
Пришёл JSON, который начинается с
{"id":"msg_и содержит"content":[...]— всё работает. -
Пришла ошибка про неизвестную модель — тоже хорошо: адрес и ключ верные, шлюз вас авторизовал и только потом отказал в модели. Значит, надо узнать, как модели называются именно на этом шлюзе (см. ниже).
-
401 — ключ не тот или не в том заголовке. Попробуйте второй заголовок, прежде чем писать владельцу.
-
403 с HTML-телом вроде «403 Forbidden», а в логах шлюза запроса вообще нет — вас режет что-то по дороге: CDN, корпоративный прокси, региональный фильтр. Это не проблема Claude Code.
Только после зелёного curl запускайте claude, отправьте любое сообщение и наберите /status. Во вкладке Status должны быть две строки: Base URL с вашим адресом и Auth token (или API key) с именем переменной. Если вместо этого там Login method с аккаунтом claude.ai — переменные до процесса не доехали.
Имена моделей
Claude Code внутри оперирует алиасами opus, sonnet, haiku, а фоновые задачи гоняет на haiku-классе. Если на вашем шлюзе модели называются иначе, чем в Anthropic, или каких-то нет, — пропишите соответствие:
{ "env": { "ANTHROPIC_BASE_URL": "https://llm-gateway.example.com", "ANTHROPIC_AUTH_TOKEN": "sk-gateway-key", "ANTHROPIC_DEFAULT_SONNET_MODEL": "имя-sonnet-на-шлюзе", "ANTHROPIC_DEFAULT_OPUS_MODEL": "имя-opus-на-шлюзе", "ANTHROPIC_DEFAULT_HAIKU_MODEL": "имя-haiku-на-шлюзе" }}
Особенно важна строка про haiku: Claude Code дёргает эту модель для служебных вещей, и если её на шлюзе нет, вы получите 404 в самый неожиданный момент, хотя основная модель работает. Переменная ANTHROPIC_MODEL задаёт модель по умолчанию для новых сессий, а флаг --model перебивает всё на одну сессию.
Что вы теряете, уходя со шлюза claude.ai
Честно перечислю, потому что об этом узнаёшь постфактум:
-
Подписка claude.ai не используется, пока задана переменная с ключом. Трафик тарифицируется по токенам тому, чей ключ, и лимиты подписки к нему не относятся.
-
Remote Control и голосовой ввод недоступны — они завязаны на аккаунт claude.ai.
-
Всё, что шлюз не умеет пробрасывать (новые beta-заголовки, thinking, кэш), у вас работать не будет. Claude Code обновляется часто; шлюз должен успевать.
Типовые ошибки, коротко
-
Предупреждение при старте про два источника авторизации, «auth may not work as expected». Одновременно активны ключ из переменной и сохранённый логин claude.ai. Либо уберите переменную, либо
/logout, чтобы остался только ключ. -
401 invalid token. Ключ не выпущен этим шлюзом или отправлен не в том заголовке. Сверьтесь с таблицей выше.
-
Claude Code просит логин, хотя curl проходит. Переменные не унаследовались процессом: терминал новый, IDE стартовала не из этого shell. Перенесите их в settings.json.
-
400 с упоминанием thinking или adaptive. Шлюз не понимает новые параметры Claude Code. Это к владельцу шлюза.
-
Таймауты на длинных ответах. По умолчанию запрос ждёт 10 минут;
API_TIMEOUT_MSв миллисекундах, если надо больше. Если через прокси — проверьте, что сам прокси не режет соединение раньше.
Два слова про прокси
HTTPS_PROXY и ANTHROPIC_BASE_URL — про разное. Первое говорит, через что ходить наружу, второе — куда. Их можно сочетать: базовый URL на шлюз, а прокси — потому что до шлюза иначе не достучаться. NO_PROXY через запятую исключает хосты. Если Claude Code «не работает через VPN», в девяти случаях из десяти проблема в том, что прокси задан для shell, но не для процесса, из которого стартует IDE.
Вместо вывода
Claude Code — обычный клиент, и его можно направить куда угодно, лишь бы там был Messages API. Но «можно направить» не значит «стоит доверять»: по ответу шлюза можно проверить как минимум две вещи — что вернулось в поле model и появляется ли cache_read_input_tokens в usage на повторных запросах. Как это делать системно, по списку эндпоинтов, — отдельная история, соберу в следующий раз.
ссылка на оригинал статьи https://habr.com/ru/articles/1080716/