Главная / Статьи / Как направить Claude Code на GPT и локальные модели Ollama через прокси

Как направить Claude Code на GPT и локальные модели Ollama через прокси

Перенаправьте ANTHROPIC_BASE_URL на транслирующий прокси, проверьте на платном бэкенде, перейдите на бесплатные локальные модели и узнайте, что ломается и как разумно распределять задачи.

1911 слов

Если вы платите за несколько ИИ-подписок, то наверняка ловили себя на том, что открываете ещё один терминал или вкладку браузера, просто чтобы отдать задачу другой модели, ведь Claude Code говорит только с Claude. Выбор модели внутри выглядит многообещающе, но в выпадающем списке только модели самой Anthropic. Некоторые написали небольшие плагины-шлюзы, которые тихо направляют его трафик другим провайдерам, и оказалось, что трюк за ними совсем не экзотический. Вот что нужно для настройки, что сломалось по дороге и какая схема в итоге прижилась.

Почему это не хак

Claude Code, как и большинство консольных агентов на Anthropic SDK, не зашивает в код api.anthropic.com. Он читает ANTHROPIC_BASE_URL, а ключ — из ANTHROPIC_AUTH_TOKEN, и отправляет каждый запрос по этому адресу. Настройка существует для компаний, которые пускают инструмент через внутренний шлюз, аудит-прокси или зеркало в своём регионе. Она не задумывалась как переключатель моделей, но ведёт себя именно так, как только замечаешь, что сервис на другом конце вовсе не обязан быть Anthropic. Ему достаточно принимать формат Anthropic Messages и отвечать в той форме, которую ждёт Claude Code, включая события стриминга и блоки вызовов инструментов.

Так что вся идея — небольшой HTTP-сервис. Он переводит схему запросов и ответов Anthropic в то, на чём говорит реальный бэкенд, обычно формат OpenAI chat completion, потому что почти все провайдеры, включая локальные, сошлись на нём, а потом переводит ответ обратно:

Claude Code  --Anthropic Messages format-->  local proxy  --OpenAI format-->  GPT-5 / Grok / Ollama / whatever
Claude Code  <--Anthropic Messages format--  local proxy  <--OpenAI format--  (response, tool calls, streaming deltas)

С такой точки зрения вопрос, почему Claude Code просто не поддерживает другие модели, перестаёт быть интересным. Он уже поддерживает, косвенно, если кто-то посередине занимается переводом.

Доступные инструменты

Очевидного победителя нет. Вместо этого есть горстка небольших проектов, в основном одиночных, которые решают одну и ту же задачу перевода с разным охватом. Вот те, что стоит сравнить:

+---------------------------+--------+------------------------------+------------------------------------------+
| Project                    | Stack  | Backends                      | Notes                                     |
+---------------------------+--------+------------------------------+------------------------------------------+
| claude-code-proxy           | Go     | OpenAI, OpenRouter, Ollama    | Single binary, pattern-based model        |
| (nielspeter)                 |        |                                | mapping (*opus*/*sonnet*/*haiku*),        |
|                              |        |                                | full streaming + tool call support        |
+---------------------------+--------+------------------------------+------------------------------------------+
| claude-code-ollama-proxy    | Python | Ollama, OpenAI (fallback),    | Built specifically for local-first use,   |
| (mattlqx)                    | / uv   | Gemini                        | uses LiteLLM under the hood for format    |
|                              |        |                                | translation                               |
+---------------------------+--------+------------------------------+------------------------------------------+
| claude-code-router          | Node   | OpenAI, Anthropic, Gemini,    | The most feature-complete option, ships   |
| (musistudio)                 |        | DeepSeek, Kimi, custom        | a UI, rule-based routing (background /    |
|                              |        | endpoints                     | think / longContext), retries, failover   |
+---------------------------+--------+------------------------------+------------------------------------------+
| LiteLLM proxy               | Python | 100+ providers                | Not built for Claude Code specifically,   |
| (generic)                    |        |                                | but exposes an Anthropic-compatible route |
|                              |        |                                | so it works the same way                  |
+---------------------------+--------+------------------------------+------------------------------------------+

Все под лицензией MIT, по умолчанию слушают localhost и делают одну и ту же основную работу. Различаются они тем, сколько логики маршрутизации навёрнуто поверх слоя перевода. Начинать с самого простого разумно: так вы разберётесь в форме запросов и ответов до того, как доверите решения движку правил какого-нибудь роутера.

Первый заход: платный бэкенд

Прежде чем тащить туда локальную модель, убедитесь, что вся обвязка работает. Поэтому первый запуск использовал OpenAI в качестве бэкенда через claude-code-proxy, программу на Go:

# clone and build (Go toolchain required)
git clone https://github.com/nielspeter/claude-code-proxy.git
cd claude-code-proxy
go build -o claude-code-proxy cmd/claude-code-proxy/main.go

Настройки лежат в обычном env-файле, где уровни моделей Claude сопоставляются с тем, за что вы на самом деле платите:

# ~/.claude/proxy.env
OPENAI_API_KEY=sk-...
OPENAI_BASE_URL=https://api.openai.com/v1

# map Claude's model tiers to whatever you're actually paying for
ANTHROPIC_DEFAULT_OPUS_MODEL=gpt-5
ANTHROPIC_DEFAULT_SONNET_MODEL=gpt-5
ANTHROPIC_DEFAULT_HAIKU_MODEL=gpt-5-mini

Запустите прокси, затем направьте на него Claude Code вместо эндпоинта Anthropic:

./claude-code-proxy &            # listens on localhost:8082 by default
export ANTHROPIC_BASE_URL=http://localhost:8082
claude

Вот и всё. Claude Code запускается как обычно, интерфейс не меняется, но каждое сообщение теперь идёт через GPT-5. Вызовы инструментов, правки файлов и весь цикл агента работали без изменений в собственной конфигурации Claude Code.

Один сюрприз: этот паттерн с прокси появился раньше волны плагинов для маршрутизации моделей, о которых пишут. Та же идея лежит в собственной документации Anthropic по корпоративным шлюзам, только здесь всё у себя и направлено в неофициальную сторону.

Настоящая цель: бесплатная локальная модель

Платить за GPT за спиной Claude Code — значит потерять половину смысла. Лучшая цель — отдать скучные 80% сессии чему-то бесплатному и локальному: правки форматирования, механический рефакторинг, очевидный тест для функции, — а платные и более качественные модели оставить для работы, где нужно суждение.

Ollama делает это почти неприлично простым: свежие версии отдают OpenAI-совместимый эндпоинт по адресу /v1 без всяких адаптеров:

# install Ollama if you don't have it: https://ollama.com/download
ollama pull qwen2.5-coder:14b
ollama serve

Затем направьте тот же прокси на него вместо OpenAI:

# ~/.claude/proxy.env
OPENAI_BASE_URL=http://localhost:11434/v1
# no API key needed for local Ollama, the field just needs to be non-empty
OPENAI_API_KEY=ollama
ANTHROPIC_DEFAULT_SONNET_MODEL=qwen2.5-coder:14b
ANTHROPIC_DEFAULT_HAIKU_MODEL=qwen2.5-coder:7b

Запускайте точно так же, как раньше:

./claude-code-proxy &
export ANTHROPIC_BASE_URL=http://localhost:8082
claude

Ни API-ключа, ни дашборда с биллингом, и ничего не покидает машину. Если не хочется ставить Ollama нативно, Docker-версия — та же конфигурация в контейнере:

# docker-compose.yml
services:
  ollama:
    image: ollama/ollama:latest
    ports:
      - "11434:11434"
    volumes:
      - ollama_data:/root/.ollama
volumes:
  ollama_data:

Затем скачайте модель внутри него:

docker compose up -d
docker exec -it $(docker compose ps -q ollama) ollama pull qwen2.5-coder:14b

OPENAI_BASE_URL остаётся http://localhost:11434/v1, и больше ничего не меняется.

Что пошло не так

Не всё заработало с первого раза. Эти сценарии сбоев объясняют, почему «просто направь на прокси» преуменьшает усилия:

+-------------------------------------+--------------------------------------------------------------+
| What broke                            | Why, and what fixed it                                        |
+-------------------------------------+--------------------------------------------------------------+
| Tool calls silently stopped mid-task  | Smaller local models (7B/8B) don't reliably emit well-formed   |
|                                        | tool-call JSON under Claude Code's system prompt, which is     |
|                                        | dense and multi-step. Bumping to a 14B code-tuned model fixed  |
|                                        | most of it, not all of it.                                     |
+-------------------------------------+--------------------------------------------------------------+
| Streaming responses arrived as one     | The proxy has to translate each OpenAI streaming delta into a  |
| big chunk instead of token-by-token    | matching Anthropic streaming event. If it buffers instead of   |
|                                        | forwarding incrementally, you lose the live-typing feel, it    |
|                                        | still works, it just feels laggy.                              |
+-------------------------------------+--------------------------------------------------------------+
| Claude Code's /model picker didn't     | The simple proxies don't hook into the picker UI at all, model |
| show my local model as an option       | selection happens entirely through the env file mapping, not   |
|                                        | inside Claude Code itself. Only the router-style tools with a   |
|                                        | UI (claude-code-router) actually inject entries into /model.    |
+-------------------------------------+--------------------------------------------------------------+
| Context got truncated on long          | Local models running through Ollama default to a much smaller  |
| sessions                               | context window than the model card advertises unless you        |
|                                        | explicitly set `num_ctx` when pulling or running the model.     |
+-------------------------------------+--------------------------------------------------------------+

Ситуация с контекстным окном самая коварная. Ollama спокойно загрузит модель, заявленную со 128k токенов, а потом молча ограничит реальный контекст 2048 или 4096, если не переопределить это. Длинная сессия Claude Code тогда деградирует до того, что модель забывает начало разговора, и при этом никакой ошибки. Если вы делаете что-то сложнее быстрого разового запроса, задайте значение явно:

ollama run qwen2.5-coder:14b --keepalive 30m
# or, more durably, in a Modelfile:
# PARAMETER num_ctx 32768

Что куда отправлять

Заставить обвязку работать — это лёгкие 20%. Сложнее решить, какая работа уходит какой модели, и тут помогает перестать думать в бинарных категориях «локально или платно» и думать о форме задачи:

+----------------------------------+-------------------------------+---------------------------+
| Task type                          | What I route it to             | Why                        |
+----------------------------------+-------------------------------+---------------------------+
| Mechanical edits, renames,          | Local Ollama model              | Free, fast enough, doesn't |
| boilerplate, formatting fixes       | (qwen2.5-coder:14b)             | need real judgment          |
+----------------------------------+-------------------------------+---------------------------+
| Everyday feature work, most         | Mid-tier hosted model           | Good enough reasoning at a  |
| refactors, writing tests            | (gpt-5-mini class)               | fraction of top-tier cost   |
+----------------------------------+-------------------------------+---------------------------+
| Architecture decisions, gnarly      | Whatever your best model is     | This is where model quality |
| bugs, anything security-adjacent    | (Claude Opus, GPT-5, etc.)       | differences actually show    |
+----------------------------------+-------------------------------+---------------------------+

Маршрутизация только по принципу «дёшево или бесплатно» приводит к тому, что 14B-модель локально просят о том, чего она надёжно делать не умеет, и вы тратите на отладку её уверенно неверных вызовов инструментов больше времени, чем сэкономили на инференсе. Прокси делает маршрутизацию технически возможной. Решение за вас он не принимает, и ни в одном из проверенных инструментов это не стало проще. Проще стало только после того, как я перестал ждать, что плагин решит всё автоматически, и начал вручную менять env-файл в зависимости от того, что собирался спросить.

Предупреждение о безопасности

Держите прокси на localhost. Если сменить адрес привязки на 0.0.0.0, чтобы достучаться с другой машины, в вашей сети появится эндпоинт без аутентификации, который может тратить реальные деньги на настроенный платный бэкенд для любого, кто до него доберётся. Ни один из опробованных прокси не включает аутентификацию по умолчанию. Если нужен удалённый доступ, поставьте перед ним что-то, что действительно проверяет учётные данные. Не открывайте порт просто так.

Что осталось в работе

Победил самый простой вариант: claude-code-proxy и два env-файла для переключения. Один указывает на платную модель для всего, где нужно настоящее рассуждение, другой — на локальную Ollama для механической работы. Полноценный роутер с интерфейсом не понадобился, потому что реальное решение грубое — две корзины, а не пять, — и поменять конфиг проще, чем осваивать движок правил.

Главный урок касается не только Claude Code. Агент для программирования и модель за ним разделены сильнее, чем подсказывает интерфейс, и стоит один раз пройти транслирующий прокси от начала до конца, как это разделение перестаёт казаться трюком и начинает выглядеть как архитектура, лежащая в основе большинства таких инструментов. Claude Code — просто тот, которым я пользуюсь каждый день, поэтому его и стоило подключить.

Если будете пробовать, начните с платного бэкенда. Гораздо проще понять, сломана ли настройка прокси или модель просто слишком мала для задачи, когда не отлаживаешь и то и другое одновременно.