- PVSM.RU - https://www.pvsm.ru -
Я долго думал, что Claude Code намертво привязан к аккаунту claude.ai. Оказалось, нет: это обычный клиент к HTTP-эндпоинту, и куда он ходит — настраивается двумя переменными. Понадобилось мне это по скучной причине: на работе появился внутренний LLM-шлюз, и весь трафик к моделям должен идти через него. Пока разбирался, наступил на все грабли, которые есть. Ниже — что именно нужно 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 в этой теме — ключ положили в переменную, которая отправляет его не в тот заголовок.
Самый быстрый, годится чтобы попробовать:
export ANTHROPIC_BASE_URL=https://llm-gateway.example.com
export ANTHROPIC_AUTH_TOKEN=sk-gateway-key
claude
Минус — живёт только в этом терминале. Откроете новую вкладку, и Claude Code снова пойдёт в claude.ai.
Постоянный вариант. Файл ~/.claude/settings.json (на Windows — %USERPROFILE%.claudesettings.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 по умолчанию.
Если ключ ротируется или лежит в хранилище секретов, вместо статической переменной можно указать команду, которая печатает ключ в stdout:
{
"apiKeyHelper": "~/bin/get-gateway-key.sh"
}
Команда должна печатать только ключ, без баннеров и логов, иначе Claude Code возьмёт мусор и вы получите загадочное «Your apiKeyHelper script is failing». Ключ из хелпера отправляется сразу в обоих заголовках, так что вопрос «bearer или x-api-key» здесь отпадает.
Это главный совет статьи. Не запускайте 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 не используется, пока задана переменная с ключом. Трафик тарифицируется по токенам тому, чей ключ, и лимиты подписки к нему не относятся.
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 на повторных запросах. Как это делать системно, по списку эндпоинтов, — отдельная история, соберу в следующий раз.
Автор: Corkyz0011
Источник [1]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/proksi/457675
Ссылки в тексте:
[1] Источник: https://habr.com/ru/articles/1080716/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1080716
Нажмите здесь для печати.