CliRelay

kittorsMIT活跃维护

自托管的 AI 网关,把 OpenAI、Claude、Gemini、Codex 等编码 CLI 统一到一个兼容端点,并提供多租户控制台、请求日志和费用配额管理。

Self-hosted AI gateway for coding CLIs — one OpenAI/Claude/Gemini/Codex-compatible endpoint, with a multi-tenant web console, request logs, and spend quotas.

v0.6.0发布于 2026-11-07 13:25 UTC1,053star +1 / 7 天135fork同步于 2026-11-10 11:51 UTC

怎么上手

由 README 提炼,执行前请确认
git clone https://github.com/kittors/CliRelay.git
cd CliRelay
docker compose up -d
硬件要求按 README 说明

README 未说明硬件要求;部署依赖 PostgreSQL 15+ 和 Redis 7+,推荐用 Docker Compose 启动。

有 Docker 镜像
下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

自托管 AI 网关,把多种编码 CLI 订阅和 API Key 统一到一个兼容端点,并带多租户控制台

自托管的 AI 网关,把 OpenAI、Claude、Gemini、Codex 等编码 CLI 统一到一个兼容端点,并提供多租户控制台、请求日志和费用配额管理。

核心能力

  • 用单一端点兼容 OpenAI、Anthropic、Gemini 协议
  • 按渠道组路由,支持轮询、填充优先和会话粘性调度
  • 账号配额耗尽或失败时自动冷却并故障转移
  • 记录每个请求的 token、延迟和成本,并提供监控中心
  • 按门户账号分组客户端 Key,设置日、周期和终身配额

容易踩的坑

首次启动前,Linux 绑定挂载需给非 root 容器用户 10001:10001 写权限;全新安装没有客户端 Key,必须先创建门户账号和 Key,否则请求会被拒绝;config.yaml 需对 10001 用户可读,若要在面板保存配置还需可写。

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

5 个版本v0.6.0
  1. v0.6.0v0.6.0 - Privacy Masking, Per-Model Quotas, Virtual Models, and Alerts最新正式版2026-11-07 · 2026-11-07 13:25 UTC

    v0.6.0 - Privacy Masking, Per-Model Quotas, Virtual Models, and Alerts

    The largest release since v0.5.0: 52 pull requests since v0.5.9. Pair it with codeProxy v0.7.0 and update the panel first. Back up your database before upgrading: one migration permanently masks the client API keys stored in the request log. See Upgrade Notes.

    Highlights

    1. Privacy masking

    • Sensitive values are replaced with placeholders before a request leaves CliRelay, and the reply gets the real values back. Upstream providers and third-party relays see only the placeholders. The masking engine is ported from magpie (#1235).
    • Per-tenant settings, portal access, masking records and their management APIs (#1237). Only the tenant admin decides what is masked (#1239, #1240).
    • Outbound secret masking per tenant, with the secrets restored in replies (#1229).

    2. Sensitive-word guard

    • Words and RE2 rules that block, replace or log. They are layered platform → tenant → key, with scan scopes (#1219). Portal accounts can keep their own words (#1232, #1233).
    • Moderation now covers tool output, history and respelled keywords, and scans the newest input (#1203). Platform-shared channels apply the credential owner's profile (#1199).

    3. Per-model quotas and model routes

    • Per-model quotas, windowed request and token limits, and model routes for accounts, permission templates and keys (#1168).
    • Requests in flight count against a key's budgets (#1215).

    4. Routing and scheduling

    • Virtual models: one model name that falls back across channel groups (#1223).
    • Route simulation: see where a request would go, stage by stage and credential by credential (#1220). Each request also records its route trace, and the requests in flight can be listed (#1221).
    • Streams fail over before the first byte by default. There is also a first-token timeout and an opt-in, bounded busy wait (#1214).
    • Quota spending: quota that a reset is about to wipe out is spent first (#1217). Channel groups can follow upstream models (#1198).
    • Cooldowns:
      • they follow upstream retry hints, Codex 401s are told apart, and a single model can be retried right away (#1209);
      • each channel and account can override cooling (#1195);
      • OpenAI-compatible upstreams' Retry-After on 429 is honoured (#1193).

    5. Operations

    • Quota, account and spending alerts with chat or webhook delivery, plus pool capacity (#1224).
    • A loop guard that stops repeated replies and tool-call loops. It stays off until a tenant or key opts in (#1222).
    • Prometheus metrics on /metrics (#1212), and dry runs of payload rules on a sample body (#1218).
    • Deploys no longer cut off in-flight requests: the new build starts in the idle slot and the old one drains before it stops (#1169). The single-node setup gets an offsite database backup and a watchdog that only checks the active slot (#1200).

    6. Tenancy and accounts

    • The system tenant's proxies and AI accounts can be shared with other tenants (#1157).
    • Warmups stay inside the caller's tenant, and a shared platform account doesn't reveal whose it is (#1227).
    • CliRelay counts copies of a tenant's accounts that other tenants hold (#1230).
    • CC Switch import presets for OpenCode, OpenClaw and Hermes, each with an explicit Codex context window (#1158, #1159). Codex accounts can use the Ultrafast tier (#1180).

    7. Protocol fixes

    • Codex:
      • live quota windows, the Chat cache key, zstd request bodies, and recovery of reasoning ciphertext (#1210);
      • only an explicit imagegen call pins the image tool, and image calls carry no effort (#1241);
      • the Responses WebSocket lets Codex send only what each turn adds (#1242).
    • Claude:
      • requests are shaped for each model's request surface (#1204);
      • unpaired tool_use / tool_result blocks are repaired before sending (#1205);
      • Opus 4.7 and later get adaptive thinking (#1197);
      • prefixing tools no longer copies the request repeatedly
  2. v0.5.9v0.5.9 - Gemini Images on /v1/images, config.yaml Saves That Stop Losing Settings, and Codex Models That Survive Restarts2026-10-11 · 2026-10-11 22:19 UTC
    查看更新说明

    v0.5.9 - Gemini Images on /v1/images, config.yaml Saves That Stop Losing Settings, and Codex Models That Survive Restarts

    Pair it with codeProxy v0.6.2, which adds the Gemini image pickers and shows why a config.yaml save was rejected. Either upgrade order works; see Upgrade Notes. PUT /v0/management/config.yaml now rejects saves it used to accept and then silently lose, so scripts that write config.yaml should read the Upgrade Notes first.

    Highlights

    1. Antigravity's Gemini image model on /v1/images and the console

    • What was wrong: gemini-3.1-flash-image on Antigravity already returned pictures through the chat endpoints, but nothing on the images side could reach it. /v1/images/*, the console's image page and the model probe listed only gpt-image, Grok and MiniMax, and the Antigravity executor did not understand an images request.
    • What's new:
      • /v1/images/generations and /v1/images/edits serve Gemini image models while an Antigravity credential offers them. A model Antigravity publishes later needs no code change.
      • aspect_ratio and image_size map onto Gemini's image settings: the fourteen ratios upstream accepts (1:1 to 21:9) and the 512 / 1K / 2K / 4K tiers. A WIDTHxHEIGHT size maps to the nearest ratio and tier, so existing clients keep working.
      • Ratios are sent in upstream's own spelling. 21:9 used to be reduced to 7:3, which upstream rejects (#1148).
      • Reference images can be uploaded or sent as base64 data URIs. Remote URLs are not fetched, and masks are refused.
      • Responses report the real output_format (Gemini returns JPEG), the pixel size and token usage. A request that returns no image (a safety block, a text-only answer) fails as an invalid request, so the account is not cooled down.
      • The chat endpoints are unchanged.

    2. config.yaml saves no longer report success while losing settings

    • What was wrong: PUT /v0/management/config.yaml answered 200 {"ok": true} in two cases where the change then existed nowhere:
      • The runtime settings a save spelled out (proxy-url, debug, request-retry, payload and others) were stored one key at a time, after the file was written. A key that failed to store was only logged. The reload then stripped it from the file and restored the old stored value.
      • The sections the database owns (routing, proxy-pool, api-keys, api-key-entries, api-key-permission-profiles) were written to the file, then dropped or overridden by the stored value. Hand-typed API keys even worked as keys of that one node until its next start.
    • The fix:
      • Runtime settings are stored first, in one transaction. If that fails, nothing changes and the save is rejected with 409 config_version_conflict or with a 500 that gives the cause.
      • A save that would change a database-owned section is rejected with 422 config_yaml_database_owned_sections before anything is stored or written. The message names each section and the page where it is edited: Channel Groups, Outbound Proxies, API Keys or Portal Account Permissions. A copy of the stored value still passes, as do the published example keys and sections the database does not hold yet.
      • Once the database holds API keys, a reload drops api-keys / api-key-entries from config.yaml, so hand-typed keys no longer act as keys of one node only.
      • Only hand-typed YAML is affected. The panel's dedicated pages use their own endpoints.

    3. Codex model lists survive restarts

    • What was wrong: on 2026-10-11 a deploy restarted production, and for half an hour Codex clients got 502 unknown provider for model gpt-6.1-sol. The live model list was kept only in memory, and fetching it again failed. The fetch looked up each credential's proxy_id in the system tenant's proxy pool instead of the credential's own tenant, and the system pool still pointed at retired proxy endpoints.
    • The fix:
      • Every model list fetched fr
  3. v0.5.8v0.5.8 - Go Security Update, Sign-in Lockout Warnings, and No More Idle HTTP/2 Connection Pile-ups2026-10-09 · 2026-10-09 16:20 UTC
    查看更新说明

    v0.5.8 - Go Security Update, Sign-in Lockout Warnings, and No More Idle HTTP/2 Connection Pile-ups

    This release fixes eleven Go standard library and golang.org/x/net vulnerabilities; upgrade promptly. Pair it with codeProxy v0.6.1, whose sign-in forms use the fields added here to show the attempts left and to count a lock down. Either upgrade order works; see Upgrade Notes.

    Highlights

    1. Go 1.26.9 security update

    • What was wrong: v0.5.7 was built with Go 1.26.6 and golang.org/x/net v0.57.0. govulncheck now reports eleven vulnerabilities, GO-2026-6603 to GO-2026-6617, that CliRelay's code can reach:
      • HTTP/2 server: a crash from an HPACK encoder race, memory exhaustion from trailer headers, excessive CPU from repeated window changes, and a flow-control accounting error;
      • HTTP/2 client: malformed framing-related headers were accepted;
      • HTTP/1: connections could fall out of sync after a CONNECT response, on the server and on the client;
      • Header parsing: Range headers had no size limit, and MIME header parsing could bypass its memory limit;
      • crypto/tls: malformed ECH extension references were not rejected;
      • Windows only: os.Root directory creation could follow junctions out of the root.
    • The fix:
      • Builds use Go 1.26.9 and golang.org/x/net v0.60.0, and govulncheck reports no vulnerabilities that the code reaches.
      • The Docker image built its updater binary with Go 1.26.1; it now uses 1.26.9 as well.
    • Upgrade promptly: CliRelay is both an HTTP server and an HTTP/2 client.

    2. Sign-in warns before it locks, and says how long a lock lasts

    • What was wrong: users were locked out of sign-in without warning and then given the wrong explanation, so they kept guessing.
      • The admin sign-in locked on the third wrong password, without saying so.
      • During that lock, wrong passwords still got "invalid credentials". Only the correct password got account_locked, which the panel shows as "This account is disabled or locked. Contact your tenant administrator." In production, an administrator typed the correct password during a lock, read that message, and gave up for an hour and a half.
      • Neither the admin nor the portal sign-in said how many attempts were left. The failure that tripped a lock looked like one more wrong password.
      • Throttle rejections carried the wait only in the Retry-After header, which the panel does not read.
    • The fix:
      • The admin panel and the portal now share one cooldown ladder:

        FailuresLock
        51 minute
        105 minutes
        1515 minutes
        2030 minutes
        25, and every 5th after60 minutes

        The count restarts after 15 minutes without a failure. There is no permanent lock. The admin panel's first lock moves from 3 failures to 5, matching the portal.

      • The admin sign-in checks the lock before it checks the password. A sign-in during a lock gets 429 login_cooldown, whatever password is typed. account_locked now means only a lock set by an administrator.

      • A wrong password that does not trip a lock gets 401 invalid_credentials with details.remaining_attempts. For an ordinary run of mistypes the number is the same whether or not the username exists, so it does not reveal which accounts exist.

      • The wrong password that trips a lock gets 429, with the longest of the per-IP, per-account and cooldown waits.

      • login_rate_limited and login_cooldown responses carry details.retry_after_seconds in the body, as well as the Retry-After header.

    3. Idle HTTP/2 connections to chatgpt.com no longer pile up

    • What was wrong: a user reported 373 connections from one relay to chatgpt.com:443. They were hours old, and each was exchanging only about 4.7 kB an hour in each direction. Production showed the same: 218 such connections 3.5 hours after a deploy. Two problems combined:
      • The Codex quota probe built
  4. v0.5.7v0.5.7 - Monitor Center API, Credential Imports, and Faster Recovery From Dead Connections2026-10-07 · 2026-10-07 18:40 UTC
    查看更新说明

    v0.5.7 - Monitor Center API, Credential Imports, and Faster Recovery From Dead Connections

    Pair this release with codeProxy v0.6.0. The redesigned panel's monitor center, guided "Add AI account" dialog and credential imports use the endpoints added here. Upgrade the backend first; see Upgrade Notes.

    Highlights

    1. Monitor center endpoints

    • What was missing: the monitor page could only read /usage/chart-data: request counts, a success rate and token totals. There were no latency percentiles, first-token times, failure sources, rankings or live traffic.
    • Overview: GET /v0/management/usage/monitor/overview.
      • Ranges 1h, 6h, 24h, today, 7d, 14d and 30d, filterable by portal user or API key, model and channel.
      • Totals compared with the previous period of equal length, and continuous zero-filled series.
      • Latency and first-token P50 / P90 / P95 / P99 / max / avg with a histogram.
      • Model, channel and portal-user rankings with sparklines, a weekday × hour heatmap, the consumer → model → channel flow, and recent failures.
    • Realtime: GET /v0/management/usage/monitor/realtime covers the last hour per minute, current and peak RPM / TPM, and a five-minute window. It is cheap enough to poll every 15 seconds.
    • Built to stay cheap:
      • Totals, series, rankings, heatmap and flows read the rollup buckets, so they cover the whole history.
      • Percentiles read request details only inside their retention window, and the response says where coverage starts.
      • A section that fails is logged and returned empty instead of failing the page.
      • Both endpoints are tenant-scoped and need monitor.read.
    • Timezone label: services started without TZ reported their zone as Local. The label is now the IANA name, or the UTC offset (UTC+08:00) when the zone has no name. Bucket edges are unchanged.

    2. Add AI accounts from credentials you already hold

    • What's new: besides the browser and device sign-ins, an account can now be added from a credential you hold. CliRelay exchanges it for the same tokens a browser login would mint and saves the account under the caller's tenant. Four imports are supported:
      • a claude.ai session cookie;
      • an OpenAI / Codex CLI refresh token;
      • a Google / Antigravity refresh token;
      • a Grok web SSO cookie.
    • Errors that say what went wrong:
      • A bad credential returns 422. It is never 401, which the panel would read as its own session expiring.
      • A Cloudflare challenge returns 502 and is reported as an egress problem rather than a bad credential. A timeout returns 504.
      • Secrets an upstream echoes back are masked in the message.
    • The permission is auth_files.oauth, the same as for OAuth sign-in.

    3. OAuth sign-ins report how they finish

    • What was wrong: the panel only received a URL and a state, so it showed one generic "paste the callback URL" box for every provider, including device-code providers where there is nothing to paste. A login that had expired, or that had been replaced by a newer one, also read as {"status":"ok"}, which the panel showed as success.
    • The fix:
      • The *-auth-url endpoints now return flow (redirect, code or device), expires_at, and for device logins user_code, verification_uri and expires_in.
      • Claude accepts ?callback_mode=code. Anthropic's own code page is then used, so a remote panel never sends the browser to a localhost forwarder.
      • Expired and superseded logins are reported as such. Late callbacks get 409 with oauth_login_expired or oauth_login_superseded, on a single node and in cluster mode.

    4. Dead HTTP/2 connections are detected in about 45 seconds instead of about 15 minutes

    • What was wrong: the fingerprinted transports, for Anthropic and the TLS-fingerprinted providers, reuse one HTTP/2 connection per host. A connection that had silently died still looked usable. A request written onto it was retransmitted
  5. v0.5.6v0.5.6 - 多节点集群、滚动发布与 Codex 新模型即时可用 / Multi-node Cluster, Rolling Deploys, and Live Codex Models2026-09-30 · 2026-09-30 02:02 UTC
    查看更新说明

    v0.5.6 - 多节点集群、滚动发布与 Codex 新模型即时可用 / Multi-node Cluster, Rolling Deploys, and Live Codex Models

    核心更新亮点 / Highlights

    1. Codex 新模型不用再等一次发版 / New Codex models work without a release

    • 请求带上当前官方 CLI 版本:ChatGPT 会按客户端版本拒绝模型。gpt-6.1-sol 在 codex_cli_rs/0.149.1 和清单里写的 0.153.0 上都会被拒,当前稳定版 0.159.1 可以通过。请求现在使用官方 Codex CLI 的最新稳定版本;版本源暂时不可用时,退回到已经验证能过门的版本,有更新的版本会自动跟上。
    • 根目录渠道自动带上新模型:默认渠道组的允许列表不再挡住 Codex 刚刚发现的模型。模型广场不用再去根目录渠道手动勾选。已经排除的模型仍然排除,其它渠道组保持原来的固定名单。

    2. 多节点集群 / Multi-node cluster

    • 共享运行时状态:凭证、配置、路由、会话亲和、账号并发、API Key 与终端用户限额、冷却、登录节流可以跨节点共享。
    • 节点身份与就绪:进程带上节点身份,/readyz 能区分本节点和集群。用量日志在数据库中断时仍会留下,配额在最近一次用量读数上继续放行。
    • DNS 与出口:clirelay-dnswatch 按节点健康和出口探测调整记录,避免把流量切到出不了网的节点。
    • 备份:PostgreSQL 基础备份、WAL 归档,以及每周恢复演练。

    3. 发布改为单实例替换 / Deploys replace the one live process

    • 不再另起第二个槽:同一台机器上的第二个进程会抢同一个集群节点身份。发布现在替换 nginx 正在转发的那一个进程,失败时把上一份二进制换回去。
    • 多节点仍逐台滚动:一台健康之后才继续下一台,并支持经跳板机连接。

    详细改动记录 / Detailed Changes

    后端 CliRelay

    • fix(codex):请求使用当前官方 CLI 版本;默认渠道组自动接纳 Codex 发现的新模型(#1109)。
    • feat(cluster):PostgreSQL 协调器、Redis 共享状态、跨节点限额 / 会话 / 冷却 / 配置 / 凭证(#1092–#1099)。
    • feat(deploy):逐节点滚动发布、节点自己的资源限制、可选跳板机(#1094、#1098)。
    • feat(egress):/readyz/egress,DNS 优先选择出口正常的节点(#1100)。
    • feat(cluster):基础备份、WAL 与每周恢复演练(#1107)。
    • fix(update):更新器缺失时返回 503 而不是 502(#1106)。
    • fix(cluster):降级节点重新加入时不再拖住整个集群;蓝绿继任者保留原节点的成员行(#1099、#1105)。

    升级提示 / Upgrade Notes

    • 单节点部署会替换当前正在服务的进程,切换期间有短暂中断,不再并行启动第二个槽。
    • 集群模式需要按 deploy/cluster 的说明准备 PostgreSQL、Redis 和节点身份。没打开集群配置的单节点行为与原来一致,只是发布方式改成单实例替换。
    • 面板请搭配 codeProxy v0.5.4。

    未进入本次发版、仍开在 dev 上的 PR:#1108、#1104、#1101、#1086、#1085。

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    Contents

    What is CliRelay?

    A heavily extended fork of CLIProxyAPI, rebuilt around a production management layer, a web control panel and day-2 operations.

    CliRelay turns AI CLI subscriptions, OAuth credentials, provider API keys and OpenAI-compatible upstreams into one managed API layer. Clients talk to a single endpoint using the OpenAI, Anthropic or Gemini protocol; CliRelay authenticates them with its own client keys, picks a healthy upstream account, translates the request when needed, and records what happened.

    It is built to be run by a team. Tenants keep their accounts, keys and data apart; users get roles with fine-grained permissions; every security-sensitive change lands in an audit log; and portal accounts let end users hold several API keys and check their own usage without asking an admin.

    PostgreSQL 15+ is the source of truth for runtime data. Redis 7+ holds caches, locks, rate limits, queues and other rebuildable state.

    Highlights

    🔌 One endpoint, every providerClaude, Codex, Gemini CLI, Antigravity, Vertex, Bedrock, xAI/Grok, Qwen, Kimi, iFlow, OpenCode Go, ClinePass, Ollama Cloud, Command Code and any OpenAI-compatible upstream behind http://your-host:8317, speaking OpenAI Chat / Responses, Anthropic Messages and Gemini.
    🧭 Routing that survives bad daysChannel groups and custom paths decide where traffic may go; round-robin, fill-first and session-sticky scheduling spread it; cooldowns and automatic failover move it off exhausted or failing accounts.
    📈 See everythingA monitor center with a health score, per-minute live traffic, P50–P99 latency and time to first token, failure analysis and a portal user → model → channel traffic flow, plus a searchable log of every request with tokens, latency and cost.
    💳 Control spendClient keys grouped under portal accounts, reusable permission profiles, daily / period / lifetime quotas, RPM and TPM limits, per-model pricing and one-click period resets.
    🏛️ Built for teamsTenants, users, roles, resource.action permissions, a curated menu per tenant and an audit trail for security-sensitive changes.
    🖥️ Operate from the browserA /manage control panel to add accounts with guided sign-in or credential import, edit config visually, manage models and pricing, and check for updates — in English, Simplified Chinese and Russian.

    How a request flows

    flowchart LR
        subgraph clients["Your tools"]
            cc["Claude Code"]
            cx["Codex CLI"]
            gc["Gemini CLI"]
            oa["Any OpenAI-compatible client"]
        end
    
        subgraph relay["CliRelay :8317"]
            auth["Client key<br/>portal account · permission profile"]
            quota["Quotas & rate limits"]
            route["Channel group routing<br/>scheduling · cooldown · failover"]
            exec["Provider executors<br/>protocol translation"]
            auth --> quota --> route --> exec
        end
    
        subgraph upstreams["Upstream accounts"]
            oauth["OAuth accounts<br/>Claude · Codex · Gemini · Antigravity · Grok · Qwen · Kimi · iFlow"]
            keys["Provider keys<br/>OpenAI-compatible · Vertex · Bedrock · OpenCode Go · ClinePass · Ollama Cloud"]
        end
    
        clients --> auth
        exec --> oauth
        exec --> keys
        relay -. "request logs, usage rollups" .-> pg[("PostgreSQL")]
        relay -. "cache, locks, limits" .-> rd[("Redis")]
    
    1. Authenticate. A client key resolves to its portal account and permission profile, which decide the allowed channel groups, models and quotas.
    2. Admit. Daily, period and lifetime spending, request quotas, RPM, TPM and concurrency are checked before anything reaches an upstream — for HTTP and for Responses WebSocket turns alike.
    3. Route. The request goes to a healthy channel (an AI account or a provider key) inside the allowed groups, following the scheduling strategy; failures cool the channel down and fail over to the next one.
    4. Translate and record. The executor speaks the upstream's protocol, streams the answer back, and writes a request log row and usage rollups that power the dashboards.

    A tour of the control panel

    The control panel (kittors/codeProxy) is served by CliRelay at /manage. The screenshots below follow its own navigation and were taken from a live deployment; names, keys, addresses and accounts are replaced with sample values.

    Observability

    Monitor center — traffic and reliability over timeMonitor center — rankings, traffic flow and active hours
    DashboardRequest logs
    • Monitor center answers four questions at a glance: is it healthy, is it slow, what is failing, and where is traffic going.
      • The health score combines success rate, the share of traffic on failing channels and P95 latency against the previous period, and explains each check.
      • Six tiles cover requests, success rate, P95 latency, time to first token, tokens with cache hit rate, and cost — each with a period-over-period change and a sparkline.
      • Below them: a trend view, the latency distribution (P50 / P90 / P95 / P99), failures by channel, model or portal user, model / channel / user rankings, a traffic-flow diagram and a weekday × hour heatmap. Click any row to filter the whole page.
    • Dashboard summarises requests, success rate, tokens, cost, failures and cache ratio for today, 7 or 30 days, next to a live system monitor (CPU, memory, disk, database and log storage).
    • Request logs list every call with its channel, portal user and key, cache / input / output tokens, latency and cost. Filter by user, model, channel and status, and open the request and response bodies when body storage is enabled.
    Model performance, channel health and portal usersDark theme

    Access and credentials

    Add an AI accountImport credentials you already hold
    AI accountsAI providers
    Portal accountsPortal account permissions
    Content moderationCC Switch config
    • Add AI account groups every way in by what you will do — sign in with a browser, enter a device code, or import a credential — and walks through the steps that provider actually has, including which address to copy back and why the landing page does not load.
    • Credential import turns a held credential (Claude session key, Codex or Antigravity refresh token, Grok SSO cookie) into an account. It explains where to find each one and what handing it over means, accepts many at once, and retries failed rows on their own.
    • AI accounts show each OAuth account with its plan, quota windows, success rate and subscription expiry; AI providers hold API-key upstreams with base URL, headers, proxy binding and per-key model lists.
    • Portal accounts own one or more client keys and share a quota; permission profiles bundle channel groups, models, limits and an optional system prompt so a new user is set up in one pick.
    • Content moderation profiles can be tested against sample text and bound to accounts, keys or a provider default; CC Switch config builds one-click import presets for Claude Code and Codex.

    Models and routing

    Model plazaModel catalog
    Channel groupsOutbound proxies
    • Model plaza shows every model the current tenant can reach, with capabilities, the channels that serve it and its price per million tokens.
    • Model catalog is where models, owners, capabilities and pricing are maintained, with an optional OpenRouter sync and a built-in model test.
    • Channel groups decide which channels a key may use and how traffic is spread inside the group; groups can follow new upstream models automatically.
    • Outbound proxies are defined once and bound to the accounts or provider keys that need a fixed egress IP.

    Organization

    TenantsUsers
    Roles and permissionsAudit logs
    • Tenants carry their own accounts, keys, routing and data, with a lease period; administrators switch the effective tenant from the header.
    • Roles grant resource.action permissions such as providers.test or models.write, which decide the pages, buttons and API calls each user gets.
    • Audit logs record who changed what, from where, and whether it succeeded.

    System

    Visual config editorSystem info
    Menu managementSign-in
    • Config edits the running configuration through grouped forms with inline validation, or as YAML in the source editor; a recommended low-resource profile tunes small hosts in one click.
    • System info shows the API and management endpoints, backend and panel versions, and checks for updates.
    • Menu management curates which entries a tenant sees and which permission each requires.

    Supported providers

    Provider / channelHow it connectsNotes
    Anthropic ClaudeOAuth (browser or code page), session-key import, API keyClaude Code and Claude-compatible clients; Messages and Responses entrypoints
    OpenAI CodexOAuth, refresh-token import, API keyResponses over HTTP and WebSocket, image generation bridge
    Google GeminiOAuth (Gemini CLI), API keyGemini CLI and AI Studio style flows
    AntigravityOAuth, refresh-token importGemini and Claude model families, quota warmup
    Vertex AIService-account JSON, API keyCustom base URL, headers, aliases and exclusions
    AWS BedrockAPI key or SigV4Region-aware Bedrock Runtime with Claude model mappings
    xAI / GrokOAuth, SSO-cookie importGrok CLI identity and quota metadata
    QwenDevice codeQwen Code style sign-in
    KimiDevice codeKimi CLI identity headers
    iFlowOAuth, cookieiFlow and related model families
    OpenCode GoAPI keyUsage windows read with the same key; vision fallback model
    ClinePassAPI keyOpenAI-compatible routing with model-access control
    Ollama CloudAPI keyOpenAI-compatible routing with model-access control
    Command CodeAPI keyPlan usage windows and model access
    OpenAI-compatible upstreamsAPI keyOpenRouter and any service that speaks Chat Completions
    AmpUpstream key and model mappingsAmp CLI and IDE integration

    Quick start

    Docker Compose is the recommended installation. It starts CliRelay, PostgreSQL 15, Redis 7 and the updater sidecar.

    git clone https://github.com/kittors/CliRelay.git
    cd CliRelay
    # Linux bind mounts need write access for the non-root container user:
    # sudo chown -R 10001:10001 auths logs data
    docker compose up -d
    

    On the first start, the clirelay-init service creates .env and config.yaml if they are missing and generates the secrets it needs (CLIRELAY_ADMIN_PASSWORD, CLIRELAY_POSTGRES_PASSWORD, CLIRELAY_UPDATER_TOKEN). Existing non-empty values are kept.

    WhatWhere
    API endpointhttp://localhost:8317
    Control panelhttp://localhost:8317/manage — sign in as admin with CLIRELAY_ADMIN_PASSWORD from .env
    Logsdocker compose logs -f cli-proxy-api
    Restart / stopdocker compose restart cli-proxy-api / docker compose down
    Terminal UIdocker compose exec cli-proxy-api ./cli-proxy-api -tui

    Then, in the control panel:

    1. Add an upstream — AI Accounts → Add AI account to sign in with a subscription or import a credential, or AI Providers for an API key.
    2. Create a client key — Portal Accounts → Create user; each portal account holds one or more keys. A fresh install ships with no client key and rejects client requests until you create one; the your-api-key-* values in config.example.yaml are placeholders that are always rejected.
    3. Point your tools at CliRelay — see below.

    [!NOTE] The container runs as 10001:10001; config.yaml must be readable by it, and writable if you want to save config from the panel. If a Synology/DSM shared-folder ACL blocks the entrypoint's chown, fix ownership on the host and restart cli-proxy-api. If you pre-set CLIRELAY_ADMIN_PASSWORD, use at least 12 characters with an upper-case letter, a lower-case letter and a symbol; a weaker value is replaced on the next start.

    Connect your tools

    Use a client key created in the panel wherever a tool expects an API key.

    Claude Code

    export ANTHROPIC_BASE_URL=http://localhost:8317
    export ANTHROPIC_AUTH_TOKEN=sk-your-client-key
    claude
    

    Codex CLI (~/.codex/config.toml)

    model_provider = "clirelay"
    
    [model_providers.clirelay]
    name = "openai"
    base_url = "http://localhost:8317/v1"
    requires_openai_auth = true
    

    Any OpenAI-compatible client

    curl http://localhost:8317/v1/chat/completions \
      -H "Authorization: Bearer sk-your-client-key" \
      -H "Content-Type: application/json" \
      -d '{"model": "gpt-5.5", "messages": [{"role": "user", "content": "Hello"}]}'
    

    [!TIP] CC Switch Config in the panel builds a one-click import link for Claude Code and Codex, with the model mapping and channel group already filled in.

    Full client guides: help.router-for.me.

    Configuration essentials

    Everything below can be changed in the panel's Config page or in config.yaml.

    SettingWhat it controls
    port, hostWhere the API and panel listen (default 8317, all interfaces).
    remote-managementWhether the management API accepts non-local callers, whether /manage is served, and which repository the panel updates from (panel-github-repository, default kittors/codeProxy).
    routing.strategyDefault scheduling inside a group: round-robin, fill-first or session-sticky.
    request-retry, max-retry-interval, quota-exceededHow many times a failed request is retried and what happens when an account's quota runs out.
    proxy-url, proxy poolGlobal and per-account outbound proxies.
    request-log-storageWhether full request / response bodies are kept, for how long and up to what size. Off by default; metadata and request details are always recorded.
    auto-updateUpdate checks and the channel they follow (main by default, dev for preview builds).
    cors-allow-originsBrowser and extension origins allowed to call the API.
    # Keep full bodies for 7 days, capped at 2 GB
    request-log-storage:
      store-content: true
      content-retention-days: 7
      max-total-size-mb: 2048
    
    # Follow dev builds, or turn update checks off
    auto-update:
      enabled: true
      channel: dev
    

    Config and credential storage can also live in PostgreSQL, Git or an S3-compatible object store instead of local files, selected through environment-based bootstrap settings.

    Deployment options

    SetupWhen to use itGuide
    Single node, Docker ComposePersonal use, small teams, NASQuick start · Production checklist
    Behind nginx or another reverse proxyPublic HTTPS, custom domainReverse proxy (Chinese)
    Several nodes on one shared PostgreSQLSpreading traffic, automatic failover, rolling deploysMulti-instance deployment · Node bootstrap (Chinese)

    Online updates run through the updater sidecar: the panel shows the target version, each stage as it happens, and the result, and reconnects on its own if the API restarts during the update.

    Architecture

    CliRelay/
    ├── cmd/server/               # Binary entry point and CLI modes
    ├── internal/api/             # HTTP server, management routes, middleware
    ├── internal/auth/            # Provider OAuth, cookie and device-code flows
    ├── internal/runtime/         # Executors per provider, scheduling, cooldown
    ├── internal/translator/      # OpenAI ⇄ Anthropic ⇄ Gemini ⇄ Responses translation
    ├── internal/identity/        # Tenants, users, roles, permissions, menus, audit logs
    ├── internal/usage/           # Request logs, rollups, monitor endpoints, retention
    ├── internal/config/          # Config parsing, defaults, migrations
    ├── internal/store/           # Local, Git, PostgreSQL and object-store persistence
    ├── internal/managementasset/ # /manage panel hosting and asset sync
    ├── internal/tui/             # Terminal management UI
    ├── sdk/                      # Embeddable Go SDK, handlers and executors
    ├── deploy/                   # Cluster building blocks and deploy scripts
    └── docker-compose.yml        # Default container deployment
    
    LayerTechnology
    RuntimeGo 1.26, Gin, Docker Compose
    DataPostgreSQL 15+ via Ent, Redis 7+ for rebuildable state
    Proxy coreOpenAI Chat Completions and Responses, Anthropic Messages, Gemini; SSE and WebSocket
    Operations/manage web panel, Bubble Tea terminal UI, updater sidecar

    Documentation

    DocumentDescription
    Getting startedInstallation and client setup guides
    Management APIREST reference for the management endpoints
    Amp CLIUsing Amp CLI and IDE extensions with CliRelay
    Production checklistShared gateways and NAS installations
    PostgreSQL / Redis runtimeRuntime data stack setup and validation
    Multi-instance deploymentSeveral nodes on one PostgreSQL: failover, switchover, rolling deploys
    SDK usage · advanced · access · watcherEmbedding the proxy in Go applications

    Contributing

    git clone https://github.com/kittors/CliRelay.git
    cd CliRelay
    git fetch origin
    git switch -c feature/your-change origin/dev
    # make your change, then
    git push origin feature/your-change   # and open a pull request against dev
    

    Please target pull requests at dev, not main; main is updated by releases. See CONTRIBUTING.md for the branch and merge workflow.

    License and acknowledgements

    CliRelay is released under the MIT License.

    It stands on the core proxy logic of router-for-me/CLIProxyAPI. Our thanks to the original project and all its contributors — their foundation made it possible to build the management layer, request logging, quota control and the control panel on top.

    Privacy masking (internal/privacymask) is ported from yetone/magpie: its rules for finding keys, tokens, passwords and personal data, its placeholders and the way it puts values back in replies. Thank you to magpie's author and contributors; the ported files keep magpie's MIT copyright notice (internal/privacymask/MAGPIE_LICENSE).