← Blog archive

How to run a Codex subscription in Claude Code and Conductor

A simple CLIProxyAPI setup for using Codex-backed models from Claude Code and Conductor.

How to run a Codex subscription in Claude Code and Conductor

Claude Code expects Anthropic-style configuration. Conductor can run Codex directly, but if you want to use Conductor's Claude Code runner with a Codex subscription, CLIProxyAPI can sit in the middle and expose a local Anthropic-compatible endpoint while routing requests to Codex-backed OpenAI models.

The setup is:

  • Claude Code points at CLIProxyAPI
  • Conductor's Claude Code runner uses that Claude Code config
  • CLIProxyAPI maps Claude-looking model names to Codex-backed models

So the chain becomes:

Interactive field map

Codex subscription routing chain

4 steps · 3 connections

Selected stepConductor Claude Code runner

Continues to Claude Code.

Direct connections

Select a step to trace its immediate path. Arrow keys move through the map in reading order.

This post is the version that finally worked.

Install and log in to CLIProxyAPI

On macOS:

ShellCode
brew install cliproxyapi
brew services start cliproxyapi

Then log in with the Codex/OpenAI account you want to use:

ShellCode
cliproxyapi -codex-login

CLIProxyAPI stores auth files under:

Plain textCode
~/.cli-proxy-api/

The proxy config is usually:

Plain textCode
/opt/homebrew/etc/cliproxyapi.conf

The local API server listens on:

Plain textCode
http://localhost:8317

Check that it is alive:

ShellCode
brew services info cliproxyapi
lsof -nP -iTCP:8317 -sTCP:LISTEN

Confirm the proxy model list

Do not copy random model names from old docs. Query your local proxy.

Get one of your local proxy API keys from cliproxyapi.conf, then:

ShellCode
curl -sS \
  -H "Authorization: Bearer YOUR_LOCAL_PROXY_KEY" \
  http://localhost:8317/v1/models | jq -r '.data[]?.id'

In my case, the useful Codex-backed models included:

Plain textCode
gpt-5.5
gpt-5.4
gpt-5.4-mini

The older gpt-5-codex(...) examples were stale for this setup.

Configure Claude Code directly

Conductor exposes this in its UI as:

Plain textCode
Claude Code executable path
Claude settings
~/.claude/settings.json

So the most reliable place to configure the Anthropic-compatible proxy is Claude Code's own settings file.

Edit:

Plain textCode
~/.claude/settings.json

Use this shape:

JSONCode
{
  "theme": "dark",
  "model": "gpt-5.5",
  "env": {
    "ANTHROPIC_AUTH_TOKEN": "YOUR_LOCAL_PROXY_KEY",
    "ANTHROPIC_BASE_URL": "http://localhost:8317",
    "API_TIMEOUT_MS": "3000000",
    "ANTHROPIC_DEFAULT_OPUS_MODEL": "gpt-5.5",
    "ANTHROPIC_DEFAULT_SONNET_MODEL": "gpt-5.5",
    "ANTHROPIC_DEFAULT_HAIKU_MODEL": "gpt-5.4",
    "ANTHROPIC_MODEL": "gpt-5.5",
    "ANTHROPIC_SMALL_FAST_MODEL": "gpt-5.4"
  }
}

Because this file contains a key, lock it down:

ShellCode
chmod 600 ~/.claude/settings.json

Then test Claude Code without relying on your shell environment:

ShellCode
env \
  -u ANTHROPIC_AUTH_TOKEN \
  -u ANTHROPIC_API_KEY \
  -u ANTHROPIC_BASE_URL \
  -u ANTHROPIC_MODEL \
  -u ANTHROPIC_SMALL_FAST_MODEL \
  -u ANTHROPIC_DEFAULT_OPUS_MODEL \
  -u ANTHROPIC_DEFAULT_SONNET_MODEL \
  -u ANTHROPIC_DEFAULT_HAIKU_MODEL \
  claude -p "Reply exactly: ok" \
  --output-format text \
  --no-session-persistence

Expected:

Plain textCode
ok

If that works, Claude Code itself is fine.

Mirror the env in Conductor if needed

Conductor also has Environment settings. In my case, putting the values only in ~/.claude/settings.json was not enough for every Conductor run, so I mirrored the provider env values into Conductor's local environment store.

From the UI, add local/shared env vars equivalent to:

Plain textCode
ANTHROPIC_BASE_URL=http://localhost:8317
ANTHROPIC_AUTH_TOKEN=YOUR_LOCAL_PROXY_KEY
ANTHROPIC_API_KEY=YOUR_LOCAL_PROXY_KEY
API_TIMEOUT_MS=3000000
ANTHROPIC_DEFAULT_OPUS_MODEL=gpt-5.5
ANTHROPIC_DEFAULT_SONNET_MODEL=gpt-5.5
ANTHROPIC_DEFAULT_HAIKU_MODEL=gpt-5.4
ANTHROPIC_MODEL=gpt-5.5
ANTHROPIC_SMALL_FAST_MODEL=gpt-5.4

I kept the model names plain here. Reasoning/effort can be controlled by Conductor or CLIProxyAPI, but the first goal is to make routing boring.

Configure Conductor's defaults

Conductor's settings file lives at:

Plain textCode
~/.conductor/settings.toml

Mine ended up like this:

TOMLCode
"$schema" = "https://conductor.build/schemas/settings.schema.json"
claude_provider = "anthropic"
codex_provider = "default"

[git]
branch_prefix_type = "github_username"

[models]
default = "gpt-5.5"
review = "gpt-5.5"

[models.claude_code]
default_effort_level = "medium"
review_effort_level = "xhigh"

[models.codex]
default_thinking_level = "high"
review_thinking_level = "high"

This handles the Conductor side of the UI. But it was not the final fix.

The real gotcha: Conductor still sent Claude model IDs

Even after changing the settings above, Conductor kept sending requests like:

JSONCode
{
  "model": "claude-opus-4-8"
}

CLIProxyAPI then did the reasonable thing:

Plain textCode
providers=claude, model=claude-opus-4-8

But I had only logged in with Codex/OpenAI, not Claude. So CLIProxyAPI returned:

Plain textCode
503 auth_unavailable: no auth available

This is the point where the architecture becomes clearer:

  • Conductor may keep insisting on Claude-looking model IDs.
  • Claude Code may accept those IDs.
  • CLIProxyAPI routes by model name.
  • If the model name starts with claude-*, CLIProxyAPI tries Claude auth unless told otherwise.

So the proxy itself needs to translate those Claude-looking names into Codex-backed models.

Add CLIProxyAPI aliases for Conductor

Edit:

Plain textCode
/opt/homebrew/etc/cliproxyapi.conf

Add:

YAMLCode
# Route Claude Code / Conductor Claude model IDs to Codex OAuth models.
# Conductor may still send claude-* IDs even when configured for GPT models.
oauth-model-alias:
  codex:
    - name: "gpt-5.5"
      alias: "claude-opus-4-8"
      fork: true
    - name: "gpt-5.5"
      alias: "claude-opus-4-8-1m"
      fork: true
    - name: "gpt-5.5"
      alias: "claude-opus-4-7"
      fork: true
    - name: "gpt-5.5"
      alias: "claude-opus-4-7-1m"
      fork: true
    - name: "gpt-5.5"
      alias: "claude-opus-4-6"
      fork: true
    - name: "gpt-5.5"
      alias: "claude-opus-4-6-1m"
      fork: true
    - name: "gpt-5.5"
      alias: "claude-sonnet-4-6"
      fork: true
    - name: "gpt-5.5"
      alias: "claude-sonnet-4-6-1m"
      fork: true
    - name: "gpt-5.4"
      alias: "claude-haiku-4-5-20251001"
      fork: true

oauth-excluded-models:
  claude:
    - "claude-*"

Then restart the proxy:

ShellCode
brew services restart cliproxyapi

If Homebrew gets stuck stopping the service, run the restart outside a sandboxed shell or restart the LaunchAgent from your normal terminal.

Test the exact model Conductor sends

This was the important test:

ShellCode
curl -sS \
  -H "Authorization: Bearer YOUR_LOCAL_PROXY_KEY" \
  -H "Content-Type: application/json" \
  -H "anthropic-version: 2023-06-01" \
  http://localhost:8317/v1/messages \
  -d '{
    "model": "claude-opus-4-8",
    "max_tokens": 24,
    "messages": [
      {
        "role": "user",
        "content": "reply ok"
      }
    ]
  }'

Once this returned 200, Conductor worked.

I also tested the other names Conductor might send:

Plain textCode
claude-opus-4-8
claude-opus-4-8-1m
claude-sonnet-4-6
claude-sonnet-4-6-1m
claude-haiku-4-5-20251001

All returned 200 after the alias config.

Keep your shell clean

I initially put the Anthropic env vars in ~/.zshrc. That worked for a normal terminal, but it is cleaner to keep this setup in ~/.claude/settings.json and Conductor's own environment settings.

That way shell startup does not secretly override unrelated tools.

Debug checklist

If this setup fails, check in this order.

1. Does CLIProxyAPI run?

ShellCode
brew services info cliproxyapi
lsof -nP -iTCP:8317 -sTCP:LISTEN

2. Does the local key work?

ShellCode
curl -sS \
  -H "Authorization: Bearer YOUR_LOCAL_PROXY_KEY" \
  http://localhost:8317/v1/models

You should get 200.

3. Does Claude Code read ~/.claude/settings.json?

ShellCode
env \
  -u ANTHROPIC_AUTH_TOKEN \
  -u ANTHROPIC_API_KEY \
  -u ANTHROPIC_BASE_URL \
  claude -p "Reply exactly: ok" \
  --output-format text \
  --no-session-persistence

4. What model is Conductor actually sending?

Look at CLIProxyAPI logs:

ShellCode
ls -lt ~/.cli-proxy-api/logs | head

Open the newest error-v1-messages-*.log and search for:

Plain textCode
"model":

If you see claude-opus-4-8, your Conductor settings are not the deciding layer. Add a proxy alias.

5. Test that exact model directly

ShellCode
curl -sS \
  -H "Authorization: Bearer YOUR_LOCAL_PROXY_KEY" \
  -H "Content-Type: application/json" \
  -H "anthropic-version: 2023-06-01" \
  http://localhost:8317/v1/messages \
  -d '{"model":"claude-opus-4-8","max_tokens":24,"messages":[{"role":"user","content":"reply ok"}]}'

If this returns 200, the proxy side is fixed.

Final shape

Once the aliases are in place, the Claude Code runner path in Conductor can use the same local proxy path:

Interactive field map

Working Conductor routing chain

4 steps · 3 connections

Selected stepConductor Claude Code runner

Continues to Claude Code.

Direct connections

Select a step to trace its immediate path. Arrow keys move through the map in reading order.

The main trick is not the Claude Code env. It is making sure the proxy translates the Claude model IDs that Conductor actually sends.

Quick answers

Frequently asked questions

Why use CLIProxyAPI with Conductor?

Conductor can run Codex directly too. This setup is specifically for its Claude Code runner, which expects Anthropic-style configuration. CLIProxyAPI can expose a local Anthropic-compatible endpoint backed by Codex/OpenAI OAuth, so that Claude Code path can route to Codex-backed models.

Does this require a separate Anthropic API key?

No. The point of this setup is to expose an Anthropic-compatible local endpoint through CLIProxyAPI, while the actual model requests route to Codex/OpenAI OAuth-backed models.

Why did Conductor still send claude-opus model names?

Conductor may keep model choices in its own session state and still ask Claude Code for Claude model IDs. The practical fix is to configure CLIProxyAPI aliases so those Claude-looking model IDs resolve to Codex-backed GPT models.

Where should the Claude Code environment variables live?

For Conductor, put them in ~/.claude/settings.json under the env key, and optionally mirror them in Conductor's Environment settings. New Conductor windows or sessions are needed for changes to take effect.

Discussion