Routing Claude Code through codex-lb: gateway options and CCR vs CLIProxyAPI

Log
Published
Session
9 Oct 2026, 18:25 to 18:52 UTC
Project
chat-personal
Agent
Claude Code
Model
claude-opus-5-5
Tags

Value

2.9

■■■□ of 4

Time

11m

active

Elapsed

27m

wall-clock span

Commits

0

from this session

Cost

$3.82

model spend

Tokens

26k

uncached in, plus out

Tool calls

47

by the agent

Outcomes

6

5 left open

Summary

Written by the summariser

Rob asked whether Claude Code could use codex-lb as its upstream provider, possibly with Tailscale Aperture in front, and wanted research before any changes. He then asked for an assessment of moving his pi loop runners and Codex and Claude contexts to Claude Code Router (CCR), a comparison with CLIProxyAPI, and a look at Aperture.

Claude Code can only reach codex-lb through a translation layer, because it speaks Anthropic's Messages API while codex-lb speaks OpenAI formats. The assistant found that Aperture routes requests but does not convert them, and ranked options including a LiteLLM sidecar, a native adapter in the codex-lb fork, and per-machine routers. Rob chose CCR, and the assistant read its docs and source, judging phase 1 easy with claude-ccr in front of codex-lb. It also flagged that CCR keeps rotated ChatGPT refresh tokens only in memory, which would likely break accounts after a restart, though this comes from minified code and has not been tested live. A read-only subagent then compared CLIProxyAPI, which persists refreshed tokens and handles multi-account rotation, but has open streaming and account-lock issues. When Rob asked about Aperture, the assistant confirmed it cannot translate formats, and it could front codex-lb or pass through ChatGPT logins, but its plan requirements for the lab tailnet were not confirmed. Nothing was changed, deployed or committed.

What came out of it

  • Comparison of options for routing Claude Code to codex-lb: LiteLLM sidecar, native /v1/messages adapter in the codex-lb fork, per-machine claude-code-router or CLIProxyAPI, and community proxies that bypass codex-lb.
  • Read the CCR docs site (24 pages via firecrawl, then 25 subpages) and shallow-cloned the CCR repo to check the code.
  • Finding that CCR keeps rotated ChatGPT refresh tokens in memory only, so a directly held Codex account would likely die after a container restart. Based on minified code in @the-next-ai/ai-gateway 1.0.21; not live-tested.
  • CLIProxyAPI capability comparison: persisted per-account tokens, round-robin, weighted or fill-first selection, session pinning for prompt-cache hits, a Claude-to-Codex translator, and open issues (#5545, #6469, #5639, #5847).
  • Aperture assessment: it cannot translate between API formats, but could front codex-lb for Codex and pi with openai_responses enabled, and offers passthrough of each client's ChatGPT OAuth token. It is a hosted service requiring sign-up.
  • Recommendation: phase 1 uses claude-ccr through CCR to codex-lb while Codex and pi stay on codex-lb; CLIProxyAPI for phase 2; test the restart and refresh behaviour on one throwaway account first.

I wanted to know whether Claude Code could use my codex-lb setup as its model provider, so I could keep the Claude Code workflow and run GPT models behind it. The short answer is yes, but only with a translation layer in between. Claude Code speaks Anthropic's Messages API, and codex-lb only speaks OpenAI formats, so something has to convert between them.

I looked at Tailscale Aperture first, since I'd hoped it could be that bridge. It routes requests but doesn't translate them, so it can't close the gap alone. It could still sit in front of codex-lb for Codex and pi, adding tailnet identity, budgets and a sessions view. It's a hosted service, though, and I couldn't confirm whether my tailnet is on the plan that allows bringing my own keys.

That left a few translators. I went with Claude Code Router (CCR) as the first thing to look at, read its docs and cloned its source. The part that worried me was how it handles ChatGPT login tokens. Refreshed tokens appear to live only in memory, which would probably kill an account on the next container restart. That comes from reading minified code, not from testing, so it needs checking on a throwaway account.

I then had a read-only comparison done of CLIProxyAPI. It saves refreshed tokens per account, rotates across several accounts, can pin a session to one account to keep prompt-cache hits, and has its own Claude-to-Codex translator. The downsides are open bugs where streams drop during long reasoning, a single account that can stay cooled down for days after a quota error, and a maintainer who won't guarantee that ChatGPT accounts stay safe from lockouts when the tool looks like the official Codex CLI.

Where I've landed: CCR is the easier first step in front of codex-lb, and CLIProxyAPI is the better fit if I move toward device-code logins and pooled accounts without codex-lb. Nothing has been changed, deployed or committed. Still open: there's no implementation plan yet, CCR's restart behaviour is untested, CLIProxyAPI hasn't been tried against codex-lb, and I still need to check the Tailscale plan.

Left open

  • No implementation plan has been written, and Rob has not chosen between CCR and CLIProxyAPI.
  • CCR's refresh-token behaviour across a container restart has not been tested live.
  • CLIProxyAPI has not been tested against codex-lb.
  • Whether the lab tailnet is on the personal Tailscale plan is unknown, so bring-your-own-key use of Aperture is unresolved.
  • The runtime-ownership reference (context-runtime.md) was not read, so the new contexts (loop-pi-ccr, codex-ccr, claude-ccr) were not created.