Startseite / Artikel / Claude Code per Proxy auf GPT und lokale Ollama-Modelle umleiten

Claude Code per Proxy auf GPT und lokale Ollama-Modelle umleiten

ANTHROPIC_BASE_URL auf einen Übersetzungs-Proxy umleiten, mit einem bezahlten Backend testen, auf kostenlose lokale Modelle wechseln und erfahren, was dabei kaputtgeht und wie man Aufgaben sinnvoll verteilt.

1911 Wörter

Wer ein paar KI-Abos bezahlt, hat sich vermutlich schon dabei ertappt, ein weiteres Terminal oder einen Browser-Tab zu öffnen, nur um eine Aufgabe an ein anderes Modell zu geben, weil Claude Code nur mit Claude spricht. Die Modellauswahl darin sieht vielversprechend aus, aber im Dropdown stehen ausschließlich Anthropics eigene Modelle. Einige Leute haben kleine Gateway-Plugins gebaut, die den Traffic still an andere Anbieter weiterleiten, und wie sich zeigt, ist der Trick dahinter nicht exotisch. Hier steht, was man für das Setup braucht, was unterwegs kaputtging und welche Anordnung geblieben ist.

Warum das kein Hack ist

Claude Code hat, wie die meisten Kommandozeilen-Agenten auf Basis des Anthropic SDK, api.anthropic.com nicht fest einprogrammiert. Es liest ANTHROPIC_BASE_URL, dazu ANTHROPIC_AUTH_TOKEN für den Schlüssel, und schickt jede Anfrage an diese Adresse. Die Einstellung gibt es für Firmen, die das Tool über ein internes Gateway, einen Audit-Proxy oder einen Spiegel in ihrer Region leiten. Als Modellumschalter war sie nicht gedacht, sie verhält sich aber genau so, sobald man merkt, dass der Dienst am anderen Ende überhaupt nicht Anthropic sein muss. Er muss nur das Anthropic-Messages-Format annehmen und in der Form antworten, die Claude Code erwartet, einschließlich Streaming-Events und Tool-Call-Blöcken.

Die ganze Idee ist also ein kleiner HTTP-Dienst. Er übersetzt Anthropics Anfrage- und Antwortschema in das, was das echte Backend spricht, meist das OpenAI-Chat-Completion-Format, weil sich fast alle Anbieter, lokale eingeschlossen, darauf geeinigt haben, und übersetzt die Antwort dann zurück:

Claude Code  --Anthropic Messages format-->  local proxy  --OpenAI format-->  GPT-5 / Grok / Ollama / whatever
Claude Code  <--Anthropic Messages format--  local proxy  <--OpenAI format--  (response, tool calls, streaming deltas)

So betrachtet ist die Frage, warum Claude Code nicht einfach andere Modelle unterstützt, nicht mehr spannend. Es tut das bereits, indirekt, solange in der Mitte etwas die Übersetzung erledigt.

Die verfügbaren Tools

Einen klaren Sieger gibt es nicht. Stattdessen findet man eine Handvoll kleiner, meist von einer Person betriebener Projekte, die dasselbe Übersetzungsproblem mit unterschiedlichem Umfang lösen. Diese lohnen den Vergleich:

+---------------------------+--------+------------------------------+------------------------------------------+
| Project                    | Stack  | Backends                      | Notes                                     |
+---------------------------+--------+------------------------------+------------------------------------------+
| claude-code-proxy           | Go     | OpenAI, OpenRouter, Ollama    | Single binary, pattern-based model        |
| (nielspeter)                 |        |                                | mapping (*opus*/*sonnet*/*haiku*),        |
|                              |        |                                | full streaming + tool call support        |
+---------------------------+--------+------------------------------+------------------------------------------+
| claude-code-ollama-proxy    | Python | Ollama, OpenAI (fallback),    | Built specifically for local-first use,   |
| (mattlqx)                    | / uv   | Gemini                        | uses LiteLLM under the hood for format    |
|                              |        |                                | translation                               |
+---------------------------+--------+------------------------------+------------------------------------------+
| claude-code-router          | Node   | OpenAI, Anthropic, Gemini,    | The most feature-complete option, ships   |
| (musistudio)                 |        | DeepSeek, Kimi, custom        | a UI, rule-based routing (background /    |
|                              |        | endpoints                     | think / longContext), retries, failover   |
+---------------------------+--------+------------------------------+------------------------------------------+
| LiteLLM proxy               | Python | 100+ providers                | Not built for Claude Code specifically,   |
| (generic)                    |        |                                | but exposes an Anthropic-compatible route |
|                              |        |                                | so it works the same way                  |
+---------------------------+--------+------------------------------+------------------------------------------+

Alle stehen unter MIT-Lizenz, binden standardmäßig an localhost und erledigen dieselbe Kernaufgabe. Der Unterschied liegt darin, wie viel Routing-Logik auf die Übersetzungsschicht gestapelt ist. Mit dem einfachsten anzufangen ist klug, denn so lernt man die Form von Anfragen und Antworten kennen, bevor man der Regel-Engine eines Routers Entscheidungen überlässt.

Erster Durchgang: ein bezahltes Backend

Bevor man ein lokales Modell ins Spiel bringt, sollte man prüfen, ob die Verkabelung funktioniert. Deshalb lief der erste Versuch mit OpenAI als Backend über claude-code-proxy, ein Go-Programm:

# clone and build (Go toolchain required)
git clone https://github.com/nielspeter/claude-code-proxy.git
cd claude-code-proxy
go build -o claude-code-proxy cmd/claude-code-proxy/main.go

Die Einstellungen stehen in einer einfachen env-Datei, in der Claudes Modellstufen auf das abgebildet werden, wofür man tatsächlich bezahlt:

# ~/.claude/proxy.env
OPENAI_API_KEY=sk-...
OPENAI_BASE_URL=https://api.openai.com/v1

# map Claude's model tiers to whatever you're actually paying for
ANTHROPIC_DEFAULT_OPUS_MODEL=gpt-5
ANTHROPIC_DEFAULT_SONNET_MODEL=gpt-5
ANTHROPIC_DEFAULT_HAIKU_MODEL=gpt-5-mini

Den Proxy starten und Claude Code dann statt auf Anthropics Endpunkt darauf zeigen lassen:

./claude-code-proxy &            # listens on localhost:8082 by default
export ANTHROPIC_BASE_URL=http://localhost:8082
claude

Mehr braucht es nicht. Claude Code startet wie gewohnt, die Oberfläche bleibt gleich, aber jede Nachricht läuft jetzt über GPT-5. Tool-Aufrufe, Dateiänderungen und die ganze Agentenschleife funktionierten, ohne die Konfiguration von Claude Code selbst anzufassen.

Eine Überraschung: Dieses Proxy-Muster ist älter als die Welle von Modell-Routing-Plugins, über die geschrieben wird. Es ist dieselbe Idee wie in Anthropics eigener Dokumentation zu Enterprise-Gateways, nur selbst gehostet und auf ein inoffizielles Ziel gerichtet.

Das eigentliche Ziel: ein kostenloses lokales Modell

Hinter Claude Code für GPT zu bezahlen verfehlt den halben Zweck. Besser ist es, die langweiligen 80% einer Session an etwas Kostenloses und Lokales zu geben, etwa Formatierungskorrekturen, stumpfe Refactorings und den offensichtlichen Test für eine Funktion, und bezahlte, hochwertigere Modelle für Arbeit aufzuheben, die Urteilsvermögen braucht.

Ollama macht das fast schon zu einfach, denn neuere Versionen stellen unter /v1 einen OpenAI-kompatiblen Endpunkt ohne Adapter bereit:

# install Ollama if you don't have it: https://ollama.com/download
ollama pull qwen2.5-coder:14b
ollama serve

Dann denselben Proxy statt auf OpenAI darauf richten:

# ~/.claude/proxy.env
OPENAI_BASE_URL=http://localhost:11434/v1
# no API key needed for local Ollama, the field just needs to be non-empty
OPENAI_API_KEY=ollama
ANTHROPIC_DEFAULT_SONNET_MODEL=qwen2.5-coder:14b
ANTHROPIC_DEFAULT_HAIKU_MODEL=qwen2.5-coder:7b

Genauso starten wie vorher:

./claude-code-proxy &
export ANTHROPIC_BASE_URL=http://localhost:8082
claude

Kein API-Schlüssel, kein Abrechnungs-Dashboard, und nichts verlässt den Rechner. Wer Ollama nicht nativ installieren will, nimmt die Docker-Variante, das gleiche Setup im Container:

# docker-compose.yml
services:
  ollama:
    image: ollama/ollama:latest
    ports:
      - "11434:11434"
    volumes:
      - ollama_data:/root/.ollama
volumes:
  ollama_data:

Dann das Modell darin herunterladen:

docker compose up -d
docker exec -it $(docker compose ps -q ollama) ollama pull qwen2.5-coder:14b

OPENAI_BASE_URL bleibt http://localhost:11434/v1, sonst ändert sich nichts.

Was schiefging

Nicht alles klappte auf Anhieb. Diese Fehlerbilder zeigen, warum „einfach auf einen Proxy zeigen lassen“ den Aufwand unterschätzt:

+-------------------------------------+--------------------------------------------------------------+
| What broke                            | Why, and what fixed it                                        |
+-------------------------------------+--------------------------------------------------------------+
| Tool calls silently stopped mid-task  | Smaller local models (7B/8B) don't reliably emit well-formed   |
|                                        | tool-call JSON under Claude Code's system prompt, which is     |
|                                        | dense and multi-step. Bumping to a 14B code-tuned model fixed  |
|                                        | most of it, not all of it.                                     |
+-------------------------------------+--------------------------------------------------------------+
| Streaming responses arrived as one     | The proxy has to translate each OpenAI streaming delta into a  |
| big chunk instead of token-by-token    | matching Anthropic streaming event. If it buffers instead of   |
|                                        | forwarding incrementally, you lose the live-typing feel, it    |
|                                        | still works, it just feels laggy.                              |
+-------------------------------------+--------------------------------------------------------------+
| Claude Code's /model picker didn't     | The simple proxies don't hook into the picker UI at all, model |
| show my local model as an option       | selection happens entirely through the env file mapping, not   |
|                                        | inside Claude Code itself. Only the router-style tools with a   |
|                                        | UI (claude-code-router) actually inject entries into /model.    |
+-------------------------------------+--------------------------------------------------------------+
| Context got truncated on long          | Local models running through Ollama default to a much smaller  |
| sessions                               | context window than the model card advertises unless you        |
|                                        | explicitly set `num_ctx` when pulling or running the model.     |
+-------------------------------------+--------------------------------------------------------------+

Das mit dem Kontextfenster ist das gemeinste. Ollama lädt bereitwillig ein Modell, das mit 128k Token beworben wird, und begrenzt den tatsächlichen Kontext dann still auf 2048 oder 4096, sofern man das nicht überschreibt. Eine lange Claude-Code-Session verkommt dann dazu, dass das Modell vergisst, wie das Gespräch begann, ganz ohne Fehlermeldung. Wer mehr als eine schnelle Einzelaufgabe erledigt, sollte den Wert explizit setzen:

ollama run qwen2.5-coder:14b --keepalive 30m
# or, more durably, in a Modelfile:
# PARAMETER num_ctx 32768

Entscheiden, was wohin geht

Die Verkabelung zum Laufen zu bringen sind die einfachen 20%. Schwieriger ist zu entscheiden, welche Arbeit an welches Modell geht, und es hilft, nicht mehr in der Gegenüberstellung lokal gegen bezahlt zu denken, sondern an die Form der Aufgabe:

+----------------------------------+-------------------------------+---------------------------+
| Task type                          | What I route it to             | Why                        |
+----------------------------------+-------------------------------+---------------------------+
| Mechanical edits, renames,          | Local Ollama model              | Free, fast enough, doesn't |
| boilerplate, formatting fixes       | (qwen2.5-coder:14b)             | need real judgment          |
+----------------------------------+-------------------------------+---------------------------+
| Everyday feature work, most         | Mid-tier hosted model           | Good enough reasoning at a  |
| refactors, writing tests            | (gpt-5-mini class)               | fraction of top-tier cost   |
+----------------------------------+-------------------------------+---------------------------+
| Architecture decisions, gnarly      | Whatever your best model is     | This is where model quality |
| bugs, anything security-adjacent    | (Claude Opus, GPT-5, etc.)       | differences actually show    |
+----------------------------------+-------------------------------+---------------------------+

Wer nur danach routet, ob etwas billig oder kostenlos ist, verlangt von einem lokalen 14B-Modell Dinge, die es nicht zuverlässig kann, und verbrennt mit dem Debuggen seiner selbstbewusst falschen Tool-Aufrufe mehr Zeit, als man bei der Inferenz gespart hat. Der Proxy macht Routing technisch möglich. Die Entscheidung nimmt er einem nicht ab, und das wurde mit keinem der getesteten Tools einfacher. Einfacher wurde es erst, als ich die Erwartung aufgab, ein Plugin würde automatisch entscheiden, und die env-Datei je nach anstehender Frage von Hand tauschte.

Ein Sicherheitshinweis

Den Proxy auf localhost lassen. Wer die Bind-Adresse auf 0.0.0.0 ändert, um ihn von einem anderen Rechner zu erreichen, stellt einen Endpunkt ohne Authentifizierung ins Netz, der für jeden, der ihn erreicht, echtes Geld beim konfigurierten bezahlten Backend ausgeben kann. Keiner der ausprobierten Proxys aktiviert Authentifizierung standardmäßig. Braucht man Fernzugriff, gehört etwas davor, das tatsächlich Zugangsdaten prüft. Nicht einfach den Port öffnen.

Was im Einsatz geblieben ist

Die einfachste Variante hat gewonnen: claude-code-proxy mit zwei env-Dateien zum Umschalten. Eine zeigt auf ein bezahltes Modell für alles, was echtes Reasoning braucht, die andere auf lokales Ollama für mechanische Arbeit. Ein vollständiger Router mit Oberfläche war nicht nötig, denn die eigentliche Entscheidung ist grob, zwei Töpfe statt fünf, und eine Konfigurationsdatei zu tauschen ist weniger Aufwand, als eine Regel-Engine zu lernen.

Die größere Lehre gilt nicht nur für Claude Code. Ein Coding-Agent und das Modell dahinter sind stärker getrennt, als die Oberfläche vermuten lässt, und hat man einmal einen Übersetzungs-Proxy von vorne bis hinten nachvollzogen, wirkt diese Trennung nicht mehr wie ein Trick, sondern wie die Architektur, die den meisten dieser Tools zugrunde liegt. Claude Code ist hier einfach das täglich genutzte Tool, also lohnte es sich, genau das anzubinden.

Wer das ausprobiert, sollte mit einem bezahlten Backend anfangen. Es ist viel leichter zu erkennen, ob das Proxy-Setup kaputt ist oder das Modell schlicht zu klein für die Aufgabe, wenn man nicht beides gleichzeitig debuggt.