Skip to content

Keep the Harness, Change the Model: Run GPT Inside Claude Code

21 min read

Keep the Harness, Change the Model: Run GPT Inside Claude Code

· 21 min read
Black-ink terminal harness with two swappable model engines, representing Claude Code running Claude or GPT models.

I wanted to use GPT models without rebuilding the Claude Code workflow I had already shaped around them. My hooks, skills, MCP servers, permission decisions, and terminal muscle memory were part of how I work. Changing the model should not require discarding that investment.

Claude Code is an agent harness, not only a route to one model family. Its documented ANTHROPIC_BASE_URL setting can send a launched process through a proxy, while claude-code-proxy v0.1.21 provides a loopback Anthropic-compatible endpoint at 127.0.0.1:18765 (Anthropic Claude Code environment variables, 2026; claude-code-proxy README, 2026).

The outcome is deliberately boring: run claude for the normal Anthropic path, or run claudegpt for a GPT-backed Claude Code process. That is a session-level provider choice, not automatic routing. One command chooses the backend for the whole process, while one documented MCP search behavior changes below.

Key Takeaways

  • One harness can have two explicit launch paths: claude for Anthropic and claudegpt for a GPT-backed session.
  • The launcher preserves tools, hooks, skills, MCP servers, permissions, and familiar terminal workflow. Dynamic MCP tool search changes as noted below.
  • OpenAI says Codex is included with ChatGPT Plus and Pro, subject to plan limits. The proxy README documents how its Codex login uses that ChatGPT identity.
  • This is an unofficial translation boundary. Keep its unauthenticated endpoint on loopback only.

Claude Code is the harness, not the model

The harness is the part that owns the work loop. It reads your repository, invokes tools, honors permissions, loads hooks and skills, and connects MCP servers. Model selection matters, but it sits behind that operating surface. Keeping the surface stable makes experiments easier to reverse.

One MCP behavior does change with this path. Current Claude Code documentation says a non-first-party ANTHROPIC_BASE_URL disables dynamic MCP tool search by default, while eagerly loaded MCP tools remain available (Anthropic Claude Code environment variables, 2026). I leave that default intact rather than prescribing an unverified override.

That separation is why the best harness and best model need not come from one vendor. I can keep the behaviors I have tuned and start a different backend without treating the ecosystem as permanent.

The boundary should stay visible. claudegpt does not make Claude Code dynamically decide every request’s provider. It starts one process with a local base URL and a selected model. To return to the direct path, exit that process and start claude.

What claudegpt actually changes

The v0.1.21 proxy documents a limited Anthropic-compatible surface that translates Messages requests to Codex Responses requests, not full Anthropic API equivalence (claude-code-proxy README, 2026). That limitation is the point: compatibility is a boundary, not a replacement.

The request path is short. claudegpt exports ANTHROPIC_BASE_URL=http://127.0.0.1:18765, then starts the real claude binary with a GPT model identifier. Claude Code sends its normal compatible request to the local listener. The proxy translates it for the ChatGPT Codex API and returns the result to the unchanged harness.

The left path needs no new environment. The right path adds only a local translation service. That is also why the proxy must remain local: version 0.1.21 documents no incoming-client authentication, so a listener exposed beyond loopback would need separate network and authentication controls.

Install and authenticate the proxy

Citation capsule: Install the proxy, authenticate Codex, and confirm the loopback health endpoint before invoking the launcher. The v0.1.21 README documents three installation paths, four Codex authentication commands, and the default listener 127.0.0.1:18765 (claude-code-proxy README, 2026). This walkthrough uses its macOS Homebrew route.

Run these commands in order. The login flow opens a browser; codex auth device is the headless alternative. Confirm the installed version before applying version-specific guidance. The final curl should return {"ok":true}.

brew install raine/claude-code-proxy/claude-code-proxy
claude-code-proxy --version  # walkthrough verified with: claude-code-proxy 0.1.21
claude-code-proxy codex auth login
claude-code-proxy codex auth status
brew services start raine/claude-code-proxy/claude-code-proxy
curl --silent --fail http://127.0.0.1:18765/healthz

Homebrew installs the formula’s current release, not a permanently pinned version. If the version command does not report 0.1.21, use the documentation for your installed release and repeat the route checks below. Do not assume that a newer translation layer has identical model aliases or compatibility boundaries.

On macOS, the verified status check reported credentials stored in Keychain. That is the only authentication detail worth carrying forward. Do not paste account identifiers, tokens, cookies, or the status output into shell history, issues, or screenshots.

OpenAI’s Using Codex with your ChatGPT plan says Codex is included with ChatGPT Plus and Pro and that usage limits vary by plan. The pinned proxy README documents the separate mechanism: its Codex login uses a ChatGPT identity rather than an API-platform account (claude-code-proxy README, 2026). Model access and shared limits remain account-dependent.

On Linux, the project documents its install script followed by a manually started process:

curl -fsSL https://raw.githubusercontent.com/raine/claude-code-proxy/main/scripts/install.sh | bash
claude-code-proxy --version
claude-code-proxy serve --no-monitor

The installer follows main, so verify the installed version rather than assuming v0.1.21.

On Windows, download the matching claude-code-proxy-windows-amd64.zip or claude-code-proxy-windows-arm64.zip from the v0.1.21 release, extract it, and place the executable on PATH. The launcher itself requires Bash and curl, so use WSL or Git Bash, then replace its Homebrew-only start_proxy block with a manually managed serve --no-monitor process. Native PowerShell and CMD launchers are outside this macOS-tested walkthrough.

Add the claudegpt launcher

Citation capsule: The launcher makes the alternate path explicit by setting a custom base URL, model identifier, utility model, compaction window, and effort value before process replacement. Anthropic documents the endpoint and model settings (Anthropic Claude Code environment variables, 2026). Its syntax accepts five effort values; local checks verified default xhigh end to end and low through a stub.

Prepare the directory first:

mkdir -p "$HOME/.local/bin"

Save this complete audited script as ~/.local/bin/claudegpt. It preserves the command interface and defaults while hardening credential isolation, provider selection, health-response validation, and effort precedence.

#!/usr/bin/env bash
# Standalone claudegpt launcher
set -euo pipefail

default_proxy_url='http://127.0.0.1:18765'
proxy_url="${CLAUDEGPT_PROXY_URL:-$default_proxy_url}"
proxy_url="${proxy_url%/}"
utility_model="${CLAUDEGPT_UTILITY_MODEL:-gpt-5.6-sol[1m]}"
context_window="${CLAUDEGPT_CONTEXT_WINDOW:-272000}"
requested_model='sol'
selected_effort="${CLAUDEGPT_EFFORT:-xhigh}"

if [[ "$proxy_url" =~ ^http://127\.0\.0\.1:([0-9]{1,5})$ ]]; then
  proxy_port="${BASH_REMATCH[1]}"
elif [[ "$proxy_url" =~ ^http://\[::1\]:([0-9]{1,5})$ ]]; then
  proxy_port="${BASH_REMATCH[1]}"
else
  printf 'claudegpt: CLAUDEGPT_PROXY_URL must be an exact loopback HTTP URL with a port.\n' >&2
  exit 1
fi
if (( 10#$proxy_port < 1 || 10#$proxy_port > 65535 )); then
  printf 'claudegpt: CLAUDEGPT_PROXY_URL has an invalid port.\n' >&2
  exit 1
fi

no_proxy_value="${NO_PROXY:-${no_proxy:-}}"
if [[ -n "$no_proxy_value" ]]; then
  no_proxy_value="127.0.0.1,::1,$no_proxy_value"
else
  no_proxy_value='127.0.0.1,::1'
fi
export NO_PROXY="$no_proxy_value"
export no_proxy="$no_proxy_value"

print_models() {
  cat <<'EOF'
Usage: claudegpt [model|--model MODEL] [claude arguments]

Models:
  sol       gpt-5.6-sol (default)
  sol-fast  gpt-5.6-sol, priority service tier
  terra     gpt-5.6-terra
  luna      gpt-5.6-luna
  5.5       gpt-5.5
  5.4       gpt-5.4
  mini      gpt-5.4-mini
  5.3       gpt-5.3-codex
  spark     gpt-5.3-codex-spark
  5.2       gpt-5.2
EOF
}

validate_effort() {
  case "$1" in
    low|medium|high|xhigh|max) ;;
    *)
      printf "claudegpt: unsupported effort '%s'\n" "$1" >&2
      return 1
      ;;
  esac
}

resolve_model() {
  case "$1" in
    sol|gpt-5.6-sol|'gpt-5.6-sol[1m]')
      selected_model='gpt-5.6-sol[1m]'; model_name='GPT-5.6 Sol' ;;
    sol-fast|gpt-5.6-sol-fast|'gpt-5.6-sol-fast[1m]')
      selected_model='gpt-5.6-sol-fast[1m]'; model_name='GPT-5.6 Sol Fast' ;;
    terra|gpt-5.6-terra|'gpt-5.6-terra[1m]')
      selected_model='gpt-5.6-terra[1m]'; model_name='GPT-5.6 Terra' ;;
    luna|gpt-5.6-luna|'gpt-5.6-luna[1m]')
      selected_model='gpt-5.6-luna[1m]'; model_name='GPT-5.6 Luna' ;;
    5.5|gpt-5.5|'gpt-5.5[1m]')
      selected_model='gpt-5.5[1m]'; model_name='GPT-5.5' ;;
    5.4|gpt-5.4|'gpt-5.4[1m]')
      selected_model='gpt-5.4[1m]'; model_name='GPT-5.4' ;;
    mini|5.4-mini|gpt-5.4-mini|'gpt-5.4-mini[1m]')
      selected_model='gpt-5.4-mini[1m]'; model_name='GPT-5.4 Mini' ;;
    5.3|gpt-5.3-codex|'gpt-5.3-codex[1m]')
      selected_model='gpt-5.3-codex[1m]'; model_name='GPT-5.3 Codex' ;;
    spark|5.3-spark|gpt-5.3-codex-spark)
      selected_model='gpt-5.3-codex-spark'; model_name='GPT-5.3 Codex Spark' ;;
    5.2|gpt-5.2|'gpt-5.2[1m]')
      selected_model='gpt-5.2[1m]'; model_name='GPT-5.2' ;;
    *)
      printf "claudegpt: unsupported model '%s'\n" "$1" >&2
      print_models >&2
      return 1
      ;;
  esac
}

case "${1:-}" in
  models|--models)
    print_models
    exit 0
    ;;
  --model|-m)
    if [[ $# -lt 2 ]]; then
      printf 'claudegpt: %s requires a model\n' "$1" >&2
      exit 2
    fi
    requested_model="$2"
    shift 2
    ;;
  --model=*)
    requested_model="${1#--model=}"
    shift
    ;;
  sol|gpt-5.6-sol|'gpt-5.6-sol[1m]'|\
  sol-fast|gpt-5.6-sol-fast|'gpt-5.6-sol-fast[1m]'|\
  terra|gpt-5.6-terra|'gpt-5.6-terra[1m]'|\
  luna|gpt-5.6-luna|'gpt-5.6-luna[1m]'|\
  5.5|gpt-5.5|'gpt-5.5[1m]'|\
  5.4|gpt-5.4|'gpt-5.4[1m]'|\
  mini|5.4-mini|gpt-5.4-mini|'gpt-5.4-mini[1m]'|\
  5.3|gpt-5.3-codex|'gpt-5.3-codex[1m]'|\
  spark|5.3-spark|gpt-5.3-codex-spark|\
  5.2|gpt-5.2|'gpt-5.2[1m]')
    requested_model="$1"
    shift
    ;;
esac

effective_effort="$selected_effort"
has_explicit_effort=0
while (( $# > 0 )); do
  case "$1" in
    --effort)
      if (( $# < 2 )); then
        printf 'claudegpt: --effort requires a value\n' >&2
        exit 2
      fi
      validate_effort "$2"
      effective_effort="$2"
      has_explicit_effort=1
      shift 2
      ;;
    --effort=*)
      effective_effort="${1#--effort=}"
      validate_effort "$effective_effort"
      has_explicit_effort=1
      shift
      ;;
    --model|-m|--model=*)
      printf 'claudegpt: the model selector must be the first argument.\n' >&2
      exit 2
      ;;
    *)
      break
      ;;
  esac
done

if [[ "$has_explicit_effort" -eq 0 ]]; then
  validate_effort "$effective_effort"
fi
resolve_model "$requested_model"

claude_bin="${CLAUDEGPT_REAL_CLAUDE:-}"
if [[ -z "$claude_bin" ]]; then
  claude_bin="$(command -v claude || true)"
fi
if [[ -z "$claude_bin" || ! -x "$claude_bin" ]]; then
  printf 'claudegpt: Claude Code is missing or not executable.\n' >&2
  exit 1
fi

health_check() {
  local response
  response="$(curl --silent --fail --connect-timeout 0.1 --max-time 0.25 "$proxy_url/healthz" 2>/dev/null)" || return 1
  response="${response//[$' \t\r\n']/}"
  [[ "$response" == '{"ok":true}' ]]
}

start_proxy() {
  if [[ "$proxy_url" != "$default_proxy_url" ]]; then
    return 1
  fi
  if command -v brew >/dev/null 2>&1; then
    brew services start raine/claude-code-proxy/claude-code-proxy >/dev/null 2>&1 || true
  fi
  attempt=0
  while (( attempt < 50 )); do
    if health_check; then
      return 0
    fi
    attempt=$((attempt + 1))
    sleep 0.1
  done
  return 1
}

if [[ "${CLAUDEGPT_SKIP_HEALTH_CHECK:-0}" != '1' ]] && ! health_check; then
  if ! start_proxy; then
    printf 'claudegpt: proxy did not become healthy at %s/healthz\n' "$proxy_url" >&2
    exit 1
  fi
fi

unset ANTHROPIC_API_KEY \
  ANTHROPIC_CUSTOM_HEADERS \
  CLAUDE_CODE_USE_BEDROCK \
  CLAUDE_CODE_USE_VERTEX \
  CLAUDE_CODE_USE_FOUNDRY \
  CLAUDE_CODE_USE_ANTHROPIC_AWS
export ANTHROPIC_BASE_URL="$proxy_url"
export ANTHROPIC_AUTH_TOKEN='unused'
export ANTHROPIC_MODEL="$selected_model"
export ANTHROPIC_DEFAULT_HAIKU_MODEL="$utility_model"
export ANTHROPIC_SMALL_FAST_MODEL="$utility_model"
export ANTHROPIC_CUSTOM_MODEL_OPTION="$selected_model"
export ANTHROPIC_CUSTOM_MODEL_OPTION_NAME="$model_name (OpenAI subscription)"
export CLAUDE_CODE_AUTO_COMPACT_WINDOW="$context_window"
export CLAUDE_CODE_ALWAYS_ENABLE_EFFORT="${CLAUDE_CODE_ALWAYS_ENABLE_EFFORT:-1}"
export CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK='1'
unset CLAUDE_CODE_EFFORT_LEVEL

claude_command=("$claude_bin" --model "$selected_model" --effort "$effective_effort")

exec "${claude_command[@]}" "$@"

Make it executable and verify shell discovery:

chmod +x "$HOME/.local/bin/claudegpt"
command -v claudegpt

If the check prints nothing, add export PATH="$HOME/.local/bin:$PATH" to ~/.zshrc, open a new terminal, then repeat it.

The first group accepts only an exact loopback HTTP URL with a valid port, which rejects URL userinfo, remote hosts, paths, queries, and fragments. It resolves friendly aliases or full supported model identifiers, and validates effort. The model selector must come first, so a later forwarded --model cannot conflict with the launcher-controlled route. An explicit --effort is checked before CLAUDEGPT_EFFORT, so the CLI value wins even when the environment default is invalid. Launcher-only effort options must appear before forwarded Claude arguments. Parsing stops at the first non-launcher argument, including --, so option values later in the command are not mistaken for launcher configuration. Syntactically, the launcher accepts low, medium, high, xhigh, or max; local checks verified default xhigh end to end and low through a stub, not every value upstream.

The second group finds the real Claude binary. It uses CLAUDEGPT_REAL_CLAUDE when set, otherwise command -v claude, and requires an executable result. This escape hatch is useful when your normal claude command is not on PATH.

The third group requires the health endpoint to return the proxy’s expected {"ok":true} body, not merely any HTTP success. This is a liveness and protocol-shape check, not authenticated service identity; an unauthenticated loopback process can imitate it. It auto-starts Homebrew only for the default URL, then polls up to 50 times. A custom loopback URL must already be running, which prevents a custom-port launch from silently starting the default service and waiting on the wrong socket. Keep CLAUDEGPT_SKIP_HEALTH_CHECK=1 for controlled stub tests, not routine use. The fourth group exports the Anthropic-compatible environment. Its defaults are intentionally explicit:

CLAUDEGPT_PROXY_URL=http://127.0.0.1:18765
CLAUDEGPT_UTILITY_MODEL=gpt-5.6-sol[1m]
CLAUDEGPT_CONTEXT_WINDOW=272000
CLAUDEGPT_EFFORT=xhigh

The v0.1.21 README describes [1m] as a Claude Code compaction hint that the proxy strips before upstream submission, and recommends a 272,000 compaction value for GPT-5.6 Sol (claude-code-proxy README, 2026). If you prefer a smaller utility model, set CLAUDEGPT_UTILITY_MODEL=gpt-5.6-luna[1m]. The utility default stays on Sol even when the main alias is terra, luna, or another model; it does not follow the selected main model.

The fourth group prepends the literal loopback addresses to both NO_PROXY and no_proxy, preserving an existing bypass list so an inherited HTTP proxy does not carry this local route off-machine. It then removes an inherited ANTHROPIC_API_KEY, ANTHROPIC_CUSTOM_HEADERS, and the Bedrock, Vertex, Foundry, and Anthropic-on-AWS provider selectors before setting the local route. This prevents normal API credentials or custom authorization headers from being forwarded to the unofficial proxy and prevents shell-level cloud-provider flags from bypassing it.

Claude Code settings are a second configuration layer. An env entry in user, project, or managed settings can override launcher exports at startup. Remove settings that restore ANTHROPIC_API_KEY or ANTHROPIC_CUSTOM_HEADERS, replace ANTHROPIC_AUTH_TOKEN, set a different ANTHROPIC_BASE_URL, remove the loopback entries from NO_PROXY, select a cloud provider, or configure an apiKeyHelper for this path. Managed settings that force another provider are incompatible with the launcher (Anthropic Claude Code settings, 2026).

The fourth group uses ANTHROPIC_DEFAULT_HAIKU_MODEL as the primary utility-model setting. Claude Code documentation deprecates ANTHROPIC_SMALL_FAST_MODEL in favor of that setting, but the launcher retains it for compatibility. It also sets CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK=1, which actively disables fallback to non-streaming model responses when streaming fails. This audited version does not set CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, because that setting also disables automatic updates, fast-mode availability checks, and gateway model discovery (Anthropic Claude Code environment variables, 2026).

The fifth group builds the final command and uses exec, so the launcher is replaced by Claude Code and every remaining argument is forwarded. A launcher --effort placed before forwarded Claude arguments wins over the environment default. The launcher is thin by design: it is configuration and startup logic, not a second agent.

Use Anthropic and GPT side by side

Use claude for the normal Anthropic configuration and claudegpt for a separate GPT-backed process. Anthropic says ANTHROPIC_BASE_URL changes where requests go, while model aliases select a model within that endpoint (Anthropic Claude Code model configuration, 2026). The launch command therefore chooses the provider for the session.

claude
claudegpt
claudegpt terra
claudegpt sol-fast
claudegpt --model 5.4 --effort high
CLAUDEGPT_UTILITY_MODEL='gpt-5.6-luna[1m]' claudegpt sol
claudegpt sol --print "Reply with exactly CLAUDEGPT_OK and nothing else."

claude uses your normal Anthropic configuration. claudegpt creates a separate process with ANTHROPIC_BASE_URL pointed at the local proxy. The aliases choose the proxy-supported identifiers for that process, and an explicit effort value overrides the launcher’s default.

Do not expect /model to cross the provider boundary. It can change identifiers within the active base URL, but it cannot switch that process back to Anthropic. Exit, then run claude to return to the direct Anthropic path. Session-level provider choice is not per-call routing, and keeping that distinction explicit makes debugging much simpler.

Verify the complete path

Citation capsule: Verify the path in three stages: confirm proxy version and the expected health response, inspect Claude Code’s effective route, then run one constrained request. The v0.1.21 proxy documents /healthz on 127.0.0.1:18765 (claude-code-proxy README, 2026). Separately, one sanitized local observation recorded a successful Codex-provider Messages request.

Start with the service test. It verifies the tested binary version and expected health shape, but the unauthenticated endpoint cannot prove which local process answered. Use this only on a machine whose local processes you trust.

claude-code-proxy --version
curl --silent --fail http://127.0.0.1:18765/healthz

The expected outputs are claude-code-proxy 0.1.21 and {"ok":true}. Before sending a request, start an interactive session:

claudegpt sol

Run /status inside Claude Code. Confirm that the effective base URL is the loopback proxy and that no API key helper or cloud provider is active. The earlier settings check must already have cleared custom authorization headers, because /status is not a substitute for reviewing them. If /status shows a settings-level override, exit and remove that conflict. Only after that check should you run the constrained request:

claudegpt sol --print "Reply with exactly CLAUDEGPT_OK and nothing else."

Run claudegpt --models to see the identifiers accepted by this launcher. Run claude-code-proxy codex auth status to confirm authentication without printing credentials. If either command fails, fix that layer before judging model behavior.

That local success proves only the configured path worked at that moment. It does not prove model identity from self-description, quality, latency, entitlement for every alias, or an upstream context guarantee. That restraint matters when a compatibility layer sits in the middle.

Where the compatibility layer stops

Citation capsule: The proxy is useful because it translates a focused interface, not because it makes providers identical. Its v0.1.21 README documents a 272,000 compaction recommendation, shared limits, transformed reasoning, optional WebSocket previous-response continuation, and an unauthenticated local listener (claude-code-proxy README, 2026). Keep the boundary visible and manageable.

First, shared account rate limits and model access are account-dependent. A listed identifier can still be unavailable to your account. The launcher can validate an alias, but it cannot grant upstream entitlement.

Second, translation changes some response details. The proxy translates reasoning summaries, but raw Codex reasoning blocks are not exposed as native Claude reasoning. Images inside Codex function-call outputs are missing. Optional WebSocket previous-response continuation is held in memory only when CCP_CODEX_PREVIOUS_RESPONSE_ID=1 is explicitly enabled; it defaults to disabled. Restarting the proxy clears only that optional continuation optimization. Default full-request operation does not depend on it.

Third, treat diagnostics and context settings with care. CCP_TRAFFIC_LOG=1 can emit sensitive request material, so keep it off unless you are debugging a controlled environment. The 272,000 value configures Claude Code compaction behavior; [1m] is stripped before upstream submission. Neither one gives GPT a one-million-token context guarantee.

Finally, keep the local listener on loopback. Version 0.1.21 documents no incoming-client authentication. Anthropic also says it does not endorse, maintain, audit, or support routing Claude Code to non-Claude models through a third-party gateway (Anthropic Claude Code gateway documentation, 2026). This is an unofficial layer, so update it deliberately and re-test after either side changes.

One naming wrinkle deserves plain language. The pinned README uses gpt-5.6-terra in its routing sections but gpt-5.6-iterra in one configuration table. The launcher retains the terra alias, but the documentation’s terra versus iterra inconsistency remains unresolved. Upstream availability is account-dependent, and no local test resolves whether iterra is accepted.

When this setup is worth it

This setup is worth using when the Claude Code workflow is already valuable and you want a reversible GPT-backed session. The proxy README lists nine base routed GPT identifiers, but actual availability remains account-dependent (claude-code-proxy README, 2026). Start with a narrow comparison, not a migration.

Use it if you already rely on Claude Code’s project instructions, skills, hooks, MCP servers, and permission habits. You can then test a model while holding the agent environment still, rather than changing the tool, prompt discipline, and model together.

Do not use it just to chase a model name. Instead, evaluate the models on your own repository with tasks, tests, and review criteria that resemble real work. A separate session-level path is valuable only when it makes that comparison cleaner.

Troubleshooting

Most setup failures occur in one of seven layers: the real Claude binary, Codex authentication, proxy version and health, effective settings, model availability, effort validation, or the active base URL. The proxy README documents four Codex authentication commands (claude-code-proxy README, 2026). The launcher syntactically validates five effort values.

SymptomLikely causeResolution
Claude Code is missing or not executableclaude is absent from PATHInstall Claude Code or set CLAUDEGPT_REAL_CLAUDE
Codex authentication is missing or expiredOAuth state is unavailableRun claude-code-proxy codex auth login, then check codex auth status
The proxy never becomes healthyThe Homebrew service is stopped, the version differs, or a custom URL is not runningCheck claude-code-proxy --version; start the default service or manually start the custom loopback listener
/status shows an API key helper or cloud providerClaude Code settings override the launch environmentRemove the conflicting user, project, or managed setting before using claudegpt
The proxy rejects a modelThe alias is invalid or the account lacks accessRun claudegpt --models and verify account access
The launcher rejects effortThe value is outside its accepted setUse low, medium, high, xhigh, or max
/model does not return to AnthropicThe process still points at the proxy base URLExit and launch a new claude process

If the proxy is healthy but a request fails, resist the urge to turn on traffic logging immediately. Confirm the model alias and account access first. Sensitive diagnostics are a last resort, not a default operating mode.

FAQ

Can Claude Code use GPT models?

Yes, Claude Code can use supported GPT identifiers through a compatible local proxy. claude-code-proxy v0.1.21 documents a loopback endpoint at 127.0.0.1:18765 that translates the Messages interface for Codex, while Anthropic documents custom base URLs for proxies and gateways (claude-code-proxy README, 2026; Anthropic Claude Code environment variables, 2026).

Does claudegpt replace Claude Code?

No, claudegpt starts the real Claude Code binary with a different endpoint and model environment. The local launcher keeps its five responsibility groups narrow: alias and effort handling, binary discovery, proxy health, environment setup, and final exec. Your normal claude command remains the direct Anthropic launch path.

Can /model switch between Anthropic and GPT?

No, /model can select an identifier within the active base URL but cannot change the provider endpoint of that running process. Anthropic’s documentation says endpoint changes that apply at startup require a relaunch (Anthropic Claude Code environment variables, 2026). Exit claudegpt, then start claude for Anthropic.

Is claude-code-proxy official?

No, claude-code-proxy is an unofficial third-party compatibility layer. Anthropic’s gateway documentation says it does not endorse, maintain, audit, or support routing Claude Code to non-Claude models through third-party gateways (Anthropic Claude Code gateway documentation, 2026). Keep it local, update it consciously, and re-test compatibility after upgrades.

Does [1m] give GPT a one-million-token context window?

No, [1m] is a Claude Code compaction hint, not an upstream GPT context-window promise. The v0.1.21 proxy README says it strips the suffix before submission and recommends a 272,000 compaction setting for GPT-5.6 Sol (claude-code-proxy README, 2026). Treat context behavior as a boundary to test.

The harness is the stable layer

The v0.1.21 proxy documents a limited compatibility surface at its loopback endpoint, not full API equivalence (claude-code-proxy README, 2026). Treat that boundary as deliberate.

That does not erase the compatibility boundary. It makes it legible: one unofficial translator, one loopback listener, one process-level choice, and a clean way back. Evaluate the models on your own repository, keep secrets out of diagnostics, and favor the setup you can understand when it fails.

Sources

Share this post

If it was useful, pass it along.

What the link looks like when shared.
X LinkedIn Bluesky

Search posts, projects, resume, and site pages.

Jump to

  1. Home Engineering notes from the agent era
  2. Resume Work history, skills, and contact
  3. Projects Selected work and experiments
  4. About Who I am and how I work
  5. Contact Email, LinkedIn, and GitHub