cliproxyapi · oauth llm proxy

CLIProxyAPI — install & connect

Один Go-бинарь превращает OAuth-подписки Claude Max, Codex/ChatGPT и Antigravity в единый OpenAI/Anthropic-совместимый endpoint — без API-ключей провайдеров. Management WebUI уже встроен в бинарь.

CLIProxyAPI (MIT) собирает OAuth-креды нескольких подписок в один пул и раздаёт их всем harness'ам через привычные API: /v1/chat/completions для любого OpenAI-клиента, нативный /v1/messages для Claude Code и pi, Responses API для Codex. Несколько аккаунтов одного провайдера → round-robin и failover; логины и квоты видны в Management WebUI (/management.html), который вшит прямо в бинарь.

Ниже — generic-установка по upstream-докам плюс наш боевой deployment на maestro как образец production-обвязки: systemd, auto-update с rollback, hot-reload кредов.

1 Установка (upstream)

Официальные пути из Quick Start; готовые бинарники лежат на GitHub Releases.

Linux — one-click installer

curl -fsSL https://raw.githubusercontent.com/router-for-me/cliproxyapi-installer/refs/heads/master/cliproxyapi-installer | bash

Docker

docker run --rm -p 8317:8317 \
  -v /path/to/your/config.yaml:/CLIProxyAPI/config.yaml \
  -v /path/to/your/auth-dir:/root/.cli-proxy-api \
  -v /path/to/your/plugins-dir:/CLIProxyAPI/plugins \
  eceasy/cli-proxy-api:latest

Сборка из исходников

git clone https://github.com/router-for-me/CLIProxyAPI.git
cd CLIProxyAPI
go build -o cli-proxy-api ./cmd/server

Запуск с явным конфигом (стандартное расположение по докам — ~/.cli-proxy-api/config.yaml):

./cli-proxy-api --config /path/to/your/config.yaml

Порт по умолчанию — 8317. Для macOS есть Homebrew (brew install cliproxyapi), для Arch — AUR cli-proxy-api-bin.

2 Минимальный config.yaml

Выжимка из официального примера — ровно то, что нужно, чтобы подняться:

host: ""                      # "" = слушать все интерфейсы; "127.0.0.1" — только локально
port: 8317                    # у нас — 23020

auth-dir: "~/.cli-proxy-api"  # сюда складываются OAuth-креды (*.json); у нас — /opt/cliproxyapi/auths

api-keys:                     # ключи, которыми ходят клиенты (Bearer)
  - "your-api-key-1"

remote-management:
  allow-remote: false         # true — открыть management-доступ с LAN
  secret-key: ""              # пусто = Management API выключен целиком (404 на /v0/management);
                              # ключ обязателен даже с localhost — plaintext хэшируется при старте

routing:
  strategy: "round-robin"     # round-robin (default) | fill-first
  session-affinity: false     # session-sticky routing; failover при отвале креда всегда включён

request-retry: 3              # retry при 403/408/500/502/503/504

webui  Чтобы работал Management WebUI и логины через браузер, secret-key должен быть задан — это тот самый management key, по которому открывается /management.html. Пустое значение отключает весь management-контур.

3 Наш deployment на maestro — образец обвязки

Живая инсталляция (v7.2.97 на момент написания): maestro-loki, 10.10.0.23:23020 (конвенция 23xxx; 23010 занят T3 Code).

Бинарь + конфиг/opt/cliproxyapi/ (cli-proxy-api, config.yaml, config.example.yaml)
OAuth-креды/opt/cliproxyapi/auths/*.json — hot-reload, сервис не перезапускать
Ключи/opt/cliproxyapi/.keys (0600) — management + api key, значения продублированы в secret-хранилище
Логи/opt/cliproxyapi/logs/ (cap 512MB)
systemdcliproxyapi.service — system-level, User=god, enabled
WebUILAN: https://cliproxy.oklabs.uk/management.html (quota: #/quota); direct: http://10.10.0.23:23020/management.html — вход по management key
API endpointhttp://10.10.0.23:23020/v1 (OpenAI-compat) + нативный /v1/messages (Claude) + Responses API (Codex)

Auto-update: checksum → atomic replace → rollback

Ручные обновления поверх /opt запрещены. Helper ~/.local/bin/update-cliproxyapi вызывается каждые 4 часа из общего AI-update таймера: скачивает только official GitHub release, требует совпадения SHA-256 из checksums.txt, атомарно подменяет binary и хранит последние три backup-копии. Restart idle-aware: при занятом :23020 остаётся pending marker, activation повторится на следующем прогоне. После restart проверяются running version и authenticated /v1/models; при failure прежний binary возвращается автоматически.

~/.local/bin/update-cliproxyapi                           # обычный guarded run
CLIPROXY_FORCE_RESTART=1 ~/.local/bin/update-cliproxyapi  # operator-forced activation

Управление и проверка

sudo systemctl status cliproxyapi
journalctl -u cliproxyapi -f
# список моделей пула:
curl -s http://127.0.0.1:23020/v1/models -H "Authorization: Bearer <api-key>" | jq -r '.data[].id'

4 Добавить OAuth-креды

Два пути; в обоих случаях новый .json появляется в auths/ и подхватывается hot-reload — restart сервиса не нужен:

sudo -u god /opt/cliproxyapi/cli-proxy-api --config /opt/cliproxyapi/config.yaml -claude-login
# также: -codex-device-login, -antigravity-login, -kimi-login, -xai-login

Несколько аккаунтов одного провайдера образуют пул автоматически: round-robin + failover (в config.yaml — routing.strategy, session-affinity: true). Пример нашего пула: claude-<max-account> (Max 20x) + claude-<pro-account> (Pro) как failover-пара, codex-<account> (ChatGPT Pro), antigravity-<account> (Gemini-only), xai-<account>.

5 Подключить клиентов

EndpointКто ходит
/v1/chat/completions, /v1/modelsOpenAI-compatible — opencode и любой OpenAI SDK
/v1/messagesнативный Anthropic Messages — Claude Code, pi
Responses APICodex (wire_api = responses)
/management.html, /v0/management/*WebUI и Management API — вход по management key

Claude Code — env поверх обычного claude

Wrapper claude-proxy (или shell-функция) выставляет две переменные и запускает штатный CLI; env-auth приоритетнее claude.ai-логина:

ANTHROPIC_BASE_URL=http://10.10.0.23:23020
ANTHROPIC_AUTH_TOKEN=<api-key из config.yaml>

Для демонов тот же приём — systemd env drop-in: у maestro-оркестратора это maestro.service.d/cliproxy.conf, у T3 Code на workstation — t3-code.service.d/cliproxy.conf (user-level). Spawn-команды не трогаются; откат = удалить drop-in → daemon-reload → restart.

грабля  ANTHROPIC_BASE_URL — без /v1 на конце: клиент дописывает его сам, с /v1 в переменной получится /v1/v1/messages → 404. То же у pi: baseUrl без /v1.

Codex — отдельный профиль

codex --profile proxy
codex exec --profile proxy      # headless-проверка

Конфиг: ~/.codex/config.toml с блоком [model_providers.cliproxy] (wire_api = responses) + профиль в ~/.codex/proxy.config.toml. Codex 0.142+ не принимает [profiles.X] внутри config.toml — профиль обязан жить в отдельном файле ~/.codex/X.config.toml. Без --profile proxy блок инертен: обычный codex продолжает ходить напрямую.

opencode / pi

opencode run -m cliproxy/claude-sonnet-5     # провайдер cliproxy (@ai-sdk/openai-compatible) в opencode.jsonc
pi --provider cliproxy --model claude-sonnet-5

6 Gotchas