Claude Code Is the Best Harness. The Best Engine For Me Is OpenAI. So I Use Both.
Language Mismatch Disclaimer: Please be aware that the language of this article may not match the language settings of your browser or device.
Do you want to read articles in English instead ?
TL;DR: Claude Code is my daily driver, but every request goes to OpenAI GPT models through a local proxy called CLIProxyAPI. Why: Claude Code is the best harness, and Anthropic's models felt slow, while OpenAI's models are fast. How: one shell alias points Claude Code at the proxy, the proxy translates Anthropic API calls to OpenAI's Codex backend, and Claude Code never knows the difference.
The short answer
Claude Code talks to any Anthropic-compatible endpoint through one environment variable, ANTHROPIC_BASE_URL. Run CLIProxyAPI locally: it accepts Anthropic-format requests on 127.0.0.1, translates them to OpenAI's Codex backend, and signs in with your existing OpenAI account through OAuth. Map Claude Code's model slots to GPT tiers with the ANTHROPIC_DEFAULT_*_MODEL variables, and Claude Code runs GPT models without knowing anything changed.
Everything lives in one shell function called co. The shape matters more than the exact values:
co () {
env \
ANTHROPIC_BASE_URL=http://127.0.0.1:8317 \
ANTHROPIC_AUTH_TOKEN="$local_proxy_key" \
ANTHROPIC_DEFAULT_FABLE_MODEL='gpt-5.6-sol' \
ANTHROPIC_DEFAULT_OPUS_MODEL='gpt-5.6-terra' \
ANTHROPIC_DEFAULT_SONNET_MODEL='gpt-5.6-luna' \
ANTHROPIC_DEFAULT_HAIKU_MODEL='gpt-5.4-mini' \
claude --model opus "$@"
}
When I pick Fable, Opus, Sonnet, or Haiku in the /model picker, I am really picking a GPT tier: Sol, Terra, Luna, or a mini model. The names stay familiar, the ladder stays meaningful, and /effort still controls reasoning depth. That is the whole trick. The rest of this post is why I built it and what it taught me.
Every AI coding tool is two products sold as one. There is the harness: the agent loop, the tool calls, the permission system, skills, hooks, session resume, the whole cockpit you sit in all day. And there is the engine: the model that does the thinking. An agent is a model plus a harness. Neither half is an agent alone. Vendors bundle the two halves and sell the bundle. You pick a tool, you get their harness and their models, take it or leave it.
Nobody talks about the harness. Every benchmark, every launch thread, every hot take is about engines. But the harness is where your day actually happens. It decides how the agent explores your codebase, how it asks before touching things, how sessions resume, how you script it, how you extend it. A great engine in a weak harness still wastes your time.
Why I moved away from Anthropic engines
Let me say it plainly. Anthropic models are good. But they can be slow, and in my daily loop they were slow often enough to matter.
I do not care how smart a model is if I spend my day waiting on it. Speed is not a nice-to-have in an agent loop. The agent reads files, runs commands, thinks, edits, runs tests, thinks again. Every one of those steps carries the model's latency. A slightly better answer that arrives noticeably later, many times per hour, is a worse trade. And the answers were not better enough to cover that gap.
So I did what the bundles force you to do. I switched tools to switch engines.
The Codex detour
I moved to Codex, OpenAI's harness, to get their GPT models. Half of the experiment worked perfectly. The models are fast. The usage limits reset frequently, so I rarely think about rationing a session. I was not waiting on the engine anymore.
The other half is the reason this post exists. Codex the harness is fine. But coming from Claude Code, it felt like a downgrade everywhere it matters to me: the tool ecosystem, skills, subagents, the permission model, the way sessions and context are managed. I kept reaching for things that were not there.
My favorite example is a small one: AskUserQuestion. Claude Code can stop mid-task and hand me a little form. Two to four options, each with its trade-off, a recommended pick marked. I click, it keeps moving. It turns "the agent guessed wrong and burned ten minutes" into "the agent asked and lost ten seconds". That is pure harness work. No engine, however smart, can give you that interaction if the cockpit does not have it.
That detour taught me the real lesson. The engine was never my problem. The bundle was. I wanted one vendor's harness and another vendor's engine, and no one sells that.
The unbundling
Turns out you can build it. Claude Code lets you point it at any Anthropic-compatible endpoint with one environment variable, ANTHROPIC_BASE_URL. That is the whole opening.
The piece in the middle is an open source project called CLIProxyAPI. It is a small local server that speaks the Anthropic Messages API on one side and translates every request to OpenAI's Codex backend on the other. It maps model names, streaming events, tool calls, and auth. It signs in with my existing OpenAI account through OAuth.
I found it the way you find most of this stack: by asking whether someone had already solved the translation problem, and reading issues until one project clearly had. It runs on my machine, on localhost, one binary.
CLIProxyAPI is not the only bridge. LiteLLM, OpenRouter, and small purpose-built proxies can put other models behind ANTHROPIC_BASE_URL too. I picked CLIProxyAPI because it signs into the Codex subscription itself, instead of metering an API key, and because it is small enough to read and fork. The community has even started calling this exact pattern Claudex: Claude Code as the cockpit, Codex models as the engine.
So the loop is now: Claude Code speaks Anthropic-format to 127.0.0.1, the proxy rewrites the request for Codex, the GPT model answers, the proxy translates the response back, and Claude Code renders it like nothing happened. Best harness. Fast engines. Same terminal.
The proxy runs as a launchd agent with KeepAlive, so it starts at login and restarts if it dies. And claude without the alias still talks to Anthropic directly. The two worlds do not touch.
The full setup, step by step
The short answer above is the shape. Here is the whole path from zero:
- Install the proxy. One binary. The official installer is
curl -fsSL https://raw.githubusercontent.com/router-for-me/cliproxyapi-installer/refs/heads/master/cliproxyapi-installer | bash, or build from source with Go. - Write a minimal config.
~/.cli-proxy-api/config.yamlneeds four things:host: "127.0.0.1", a port, anapi-keyslist with one long random string (this is your local client key, not an OpenAI key), andauth-dirfor stored credentials. Keep everything else off: remote management, control panel, request logging. - Sign in once. Start the proxy and run its OAuth login for your OpenAI account. It opens a browser, you approve, and the credential lands in
auth-dir. From then on the proxy refreshes it itself. - Wire the
cofunction. The shell function from the top of this post. Read the client key from a file with owner-only permissions instead of hardcoding it. - Keep it alive. A
launchdagent (or systemd unit on Linux) with KeepAlive, so the proxy survives reboots and crashes. A proxy that is down looks like every AI session on your machine breaking at once. - Verify.
curl http://127.0.0.1:<port>/v1/models -H "Authorization: Bearer <key>"should list the GPT models. Then launchcoand open/model: your slots should show the mapped names.
And the whole thing as one copy-paste block:
# 1. Install the proxy (one binary)
curl -fsSL https://raw.githubusercontent.com/router-for-me/cliproxyapi-installer/refs/heads/master/cliproxyapi-installer | bash
# 2. Minimal config + a private local client key
mkdir -p ~/.cli-proxy-api
KEY=$(openssl rand -hex 32)
cat > ~/.cli-proxy-api/config.yaml <<EOF
host: "127.0.0.1"
port: 8317
auth-dir: "~/.cli-proxy-api"
api-keys:
- "$KEY"
remote-management:
allow-remote: false
disable-control-panel: true
debug: false
logging-to-file: false
EOF
chmod 600 ~/.cli-proxy-api/config.yaml
# 3. Sign in to your OpenAI account once (opens a browser)
cli-proxy-api --config ~/.cli-proxy-api/config.yaml --codex-login
# 4. Start the proxy (put it under launchd/systemd once this works)
cli-proxy-api --config ~/.cli-proxy-api/config.yaml &
# 5. Verify the catalog
curl -s http://127.0.0.1:8317/v1/models -H "Authorization: Bearer $KEY" | head
# 6. Add the co function from the top of this post to your shell rc,
# reading the key from the config file instead of hardcoding it.
If you hit "Your input exceeds the context window"
This is the error that will eventually find you in any proxy setup, so here is the fix upfront.
It means the session history has grown past what the routed model accepts. The cruel part: /compact fails with the same error, because compaction sends the full oversized history too. And an open terminal tab can never recover on its own, because it resends its in-memory history with every retry.
The rescue, per stuck session:
- Close the stuck tab. Not optional. The on-disk transcript is fine; the tab's memory is the problem.
- Resume the session headless, forcing a bigger-window model at launch. A launch-time
--modelbeats the model the session remembers:
claude --resume <session-id> --model 'gpt-5.4' -p "/compact"
- Confirm it worked: the session file under
~/.claude/projects/gains acompact_boundaryline. - Reopen normally with
co --resume <session-id>and switch back to your usual model.
Prevention is three rules. Never pair a [1m] model variant with a backend window you have not measured yourself: one throwaway probe with a few hundred thousand tokens of filler settles what docs, catalogs, and incident writeups all disagree on. Make sure your proxy reports token usage honestly so auto-compact fires before the wall, not after. And do not overcorrect. After the crash I set the auto-compact window to a panicked 120K, barely above the 50-70K a session already burns on system prompt, tools, and instructions before the first user message. One session compacted 19 times, each cycle restarting near the trigger, until the usable band between compactions shrank to a few tool calls. The threshold has to clear your fixed baseline plus a real working band, not just sit under the wall.
What owning the middle layer bought me
Here is the part that turned this from a clever hack into something I actually trust: the proxy is mine. When the seam leaks, I can fix the seam.
And it leaked. Claude Code shows a context meter, and that meter is a fraction. The client computes both halves. The numerator comes from token usage fields in each response, and my proxy was inflating them by folding cached tokens into the input count. The denominator is a guess: Claude Code picks the context window from the model name string, and a [1m] suffix on my default model made it assume a million tokens on a model whose real ceiling was a fraction of that. The caps are per model, and the model name string is a poor guide to them. When I later probed the backend with oversized payloads, GPT 5.5 rejected everything past 272K, the GPT 5.6 family walled at about 372K, and only GPT 5.4 swallowed a genuine near-million.
So the meter lied in both directions. Sessions grew past the real limit without ever triggering auto-compact, and then every request returned the same hard error: input exceeds the context window. Even /compact failed, because compaction sends the oversized history too. Nine of my sessions died like this, across seven projects, some holding hours of work.
Because the middle layer is a small Go server on my disk, this was a patch, not a support ticket. I forked the proxy and fixed the usage translation, so cached tokens report in their own fields and the meter's numerator became honest. I added a recovery path: on a real overflow, the proxy makes one call to Codex's compact endpoint and retries once with the compacted history. And I added a status endpoint so a co status command shows me the proxy's real numbers next to Claude Code's estimate.
The nine dead sessions came back with one trick. Claude Code lets a launch-time model override beat the model a resumed session remembers. The Codex catalog still serves GPT 5.4 with a true one-million-token window. So for each dead session, one headless command:
claude --resume <session-id> --model 'gpt-5.4' -p "/compact"
The giant history finally fit, /compact did its job, and every session resumed where it left off. All nine. Try filing that as a feature request against a closed bundle.
There is also a legitimate way to run that million-token window every day, not just in rescues. The same [1m] suffix that burned me is honest when the backend really delivers: put gpt-5.4[1m] in ANTHROPIC_DEFAULT_SONNET_MODEL and Claude Code strips the suffix before sending, so the proxy sees a model name it knows, while the client budgets the session as a true million. My launcher grew a co 1m mode that does exactly that, auto-compact set at 900K. Two caveats keep it a special-occasion lane: past 272K of input, Codex bills the whole session at 2x input and 1.5x output, and GPT 5.4 already carries a deprecation notice in the catalog, pointing everyone at a 5.6 family that is still capped far lower. A million tokens of context, available only on the model they are retiring. Enjoy the window while it is open.
Where this lands
I did not set out to build infrastructure. I set out to stop waiting on the engine, without giving up the best harness in the business. The unbundled setup has been my daily driver since: Claude Code's cockpit, OpenAI's engines, a proxy I can read and patch sitting between them.
The bigger point is that harness and engine are separable, and the seam is just an HTTP endpoint. Once you have mixed them once, you stop judging bundles and start judging parts. I do not think I go back.
The worry I will leave you with
All of this rides on subscription economics that are generous today. Usage limits reset every few hours, so the meter never really stops me. Those terms exist because model vendors are fighting for market share, not because the tokens cost that little.
It will not stay this way. At some point the subsidies fade, and what is left is API pricing, which costs several times more for the same work. By then agentic coding will not be a novelty. It will be how a whole generation of us works. Some of us will have quietly forgotten how to code without it.
That is the real dependency in every setup like mine. I unbundled the harness from the engine, and I can swap either side in an afternoon. The habit is the part I cannot swap. When the real bill arrives, we either pay whatever it says, or we remember how to drive without the cockpit. I am honestly not sure which one is harder.