Open Harness: What the 5-Minute claudex Alias Doesn't Tell You

On 12 July 2026, Tibo Sottiaux — who works on Codex and ChatGPT at OpenAI — posted a three-step recipe for pointing Claude Code at GPT-5.6 Sol through CLIProxyAPI. Install the proxy, connect it, define an alias. Five minutes. It has since passed 2.8 million views.

What made it notable was not the technique. It was the direction it came from: an OpenAI engineer telling people to keep the coding harness they already like and swap the model underneath it. I called that an open harness, and I mean it as a description of where the tooling is heading — the harness and the model are becoming separate purchases.

I have been running that setup as my daily driver. The alias is the easy part. What follows is what the five-minute version does not cover, learned by breaking it.

The recipe as published

Tibo's alias, from the original post:

alias claudex='CLAUDE_CODE_SUBAGENT_MODEL=gpt-5.6-sol \
CLAUDE_CODE_ALWAYS_ENABLE_EFFORT=1 \
CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY=3 \
ENABLE_TOOL_SEARCH=false \
claude --model gpt-5.6-sol'

This works. If you want to know whether a different model feels better inside a harness you already know, stop reading and go try it.

One note before you do: routing one vendor's client at another vendor's model through a third-party proxy sits in territory your provider agreements may have opinions about. Tibo joked about owing people a quota reset if it got blocked. Read your terms and decide for yourself.

Why I replaced the alias with a settings profile

An alias sets environment variables for one invocation of one binary. That stops being enough the moment you want the setup to be a persistent, separate profile rather than a one-off override.

I moved the whole thing into a settings file and launch it with claude --settings ~/.claude/claudex-settings.json. The file carries the base URL and auth token, the model, the subagent model, the effort and concurrency flags — and two things an alias cannot hold:

  • A permissions allowlist, so the subagent wrapper I call constantly does not prompt for approval on every invocation.
  • Hooks, which is where token-proxying, logging, and review gates live.

There is a specific trap here that cost me time. If your main ~/.claude/settings.json already defines an env block, that block wins over your shell environment. So the obvious thing —

# Looks right. Returns 401.
ANTHROPIC_BASE_URL=http://<proxy-host>:8317 \
ANTHROPIC_AUTH_TOKEN=<token> \
  claude -p "..."

— fails with an authentication error, because the settings file's env silently overrides what you just exported. The fix is not to fight it inline. Put the alternate configuration in its own settings file and pass --settings. Once you understand this, the "why is my proxy setup returning 401" class of problem disappears.

Failure 1: a model alias is a runtime capability, not a config constant

Provider catalogs shift. They shift with account state, with quota resets, with model retirement, and with gateway configuration you do not control. The alias that worked last week can be absent today.

When that happens, the gateway answers 502 unknown provider for model ... — and this is where it gets expensive, because a 502 looks like a transient upstream failure. Generic retry logic dutifully retries a deterministic error. If the caller was a fan-out of parallel workers, every one of them retries, and the real cause is buried under a pile of 5xx noise.

The rule I now follow: treat the alias as a capability to be verified, not a constant to be trusted. Validate the exact model name against the live catalog at the orchestration boundary, before spawning an expensive child process. A missing alias should fail locally, synchronously, with its own exit code that no retry wrapper mistakes for a network blip. And when it does fail, do not retry the same alias — refresh the catalog and pick a different family.

Failure 2: there is no budget guard, and shared quota fails all at once

This is the one that actually hurt.

On 18 July 2026 I was running an agent plugin that encourages parallel subagent dispatch. It fanned out more than 200 subagents in half a day. Each of those subagents was free to call gpt-* models through the proxy. Those seats share one weekly pool.

The pool emptied. 429 usage_limit_reached, with a reset date a week out. Not degraded — gone, for every other use I had planned that week. The same day burned tens of millions of tokens on the Claude side as well.

Three things made this possible, and only one of them is interesting:

  1. A skill that legitimized unbounded fan-out.
  2. A subagent wrapper with no budget gate.
  3. Quota that is pooled weekly rather than metered per call — so there is no gradual signal. It works, and then it does not work for seven days.

The interesting one is the second, because of where the fix has to live.

Guardrails in instructions do not bind subagents

My first instinct was to write the rule down: cap the fan-out, reserve the expensive family for the orchestrator, put it in the agent instruction file that every session reads.

That is worth doing, and it is not sufficient. Child agents launched in a lean mode never read your instruction file. A rule written in markdown binds exactly the sessions that happen to load that markdown, which is precisely not the runaway worker you are trying to stop.

So the gate went into the binary instead. The subagent wrapper now:

  • Counts every call to the shared-quota family in a per-ISO-week counter file.
  • Refuses once the weekly cap is reached, with a dedicated exit code and a message naming which other model families are still available.
  • Requires an explicit environment override to bypass — which, by my own rules, needs a human to say yes.

Because the check runs inside the wrapper, it applies to children that read no instructions at all. That is the whole point: a budget rule enforced by prose is a suggestion; a budget rule enforced by an exit code is a budget.

Watch the meter

CLIProxyAPI keeps usage statistics in SQLite, which makes the daily burn one query away:

sqlite3 ~/.cli-proxy-api/plugins/usage-statistics/usage.db \
  "SELECT date(timestamp), provider, count(*), sum(total_tokens)
   FROM usage_records GROUP BY 1,2 ORDER BY 1 DESC LIMIT 12;"

Run it before and after any heavy session for a week or two and you will learn your own normal. The two signals worth alarming on: a daily token count well above your baseline, and a weekly counter that is already a third spent on a Monday.

Failure 3: routing discipline is a cost decision

Once you have more than one model family behind one endpoint, which family serves which job stops being about quality alone.

What I settled on: the family with pooled, shared, weekly quota is reserved for single high-value orchestrator calls — the hard reasoning step, never a loop, never a parallel worker. Mechanical high-volume work goes to families with their own separate quota, where exhausting one does not take down the others. Cross-model verification deliberately uses a different family than the one that produced the work, which is both better review and better quota spreading.

And on a quota error: stop calling that family immediately and fall back to another one. Do not retry, and do not rotate credentials to dodge the limit — that turns a capacity problem into an account problem.

What you are actually adopting

The alias takes five minutes and it genuinely works. But what you have added is not "a different model in the same tool." You have added a second quota system, with different exhaustion behavior, different error semantics, and a catalog that changes without telling you.

The harness being open is real, and it is good. Tibo is right that you should try it. Just budget an afternoon for the guardrails, not five minutes — and put those guardrails somewhere your own subagents cannot ignore.