AIDive

Video-Paket

Claude Code mit Ollama: der Alias claude-alt und die Wechselregel

6 Min. Lesezeit

TL;DR und Fazit

Wenn dein Claude-Plan-Limit mitten in einer Aufgabe erreicht ist, kannst du dasselbe Claude Code über Ollama gegen ein Modell auf deinem eigenen Laptop laufen lassen. Wir haben das auf einem M1 Pro mit 16 GB mit qwen3.5:9b getan und ihm zwei echte Aufgaben in einem kleinen Python-Paket gegeben.

  • Aufgabe A, eine --prefix-Option in einer Datei: ohne --bare passierte rund fünfzehn Minuten lang nichts. Mit --bare bestand sie in 93 s.
  • Aufgabe B, eine Umbenennung über mehrere Dateien: Das lokale Modell meldete die Tests als grün, und in beiden Läufen (4k und 64k Context) war ein Import kaputt. Auf dem Plan erledigte Claude sie in 38 s mit funktionierenden Imports.
  • Ollama gibt einer Maschine wie unserer standardmäßig 4k Context. OLLAMA_CONTEXT_LENGTH=65536 hebt das an.

Fazit: Der Alias lohnt sich für Aufgaben in einer Datei, die du auf einen Blick prüfen kannst. Alles über mehrere Dateien wartet auf den Plan, und du liest immer den Diff. Das Pack liefert dir den Alias-Block und eine einseitige Regelkarte.

Quellengestützte Synthese

Das Setup besteht aus drei Umgebungsvariablen und einem Modellnamen. Die Anleitung von Ollama richtet Claude Code auf http://localhost:11434 mit ANTHROPIC_AUTH_TOKEN=ollama s1. Die Doku von Claude Code sagt, dass ANTHROPIC_BASE_URL den API-Endpunkt überschreibt s17. Weil die Variablen in der Alias-Zeile stehen, nutzt das normale claude weiter deinen Plan.

Ein gesetzter API-Key ersetzt dein Abo. Die Doku von Claude Code sagt, dass ein gesetzter ANTHROPIC_API_KEY anstelle deines Abos verwendet wird, selbst wenn du angemeldet bist s17. Deshalb gehören die Variablen in den Alias und nicht in dein Shell-Profil.

Das Modell muss in den Speicher passen. qwen3.5:9b ist mit 6,6 GB bis 7,6 GB, 256K Context und Tool-Unterstützung gelistet s18. Auf unserer Maschine zeigte ollama ps 7,6 GB beim Standard-Context und 7,7 GB bei 65536.

Der Context-Standard ist die erste Falle. Ollama nutzt unter 24 GiB VRAM einen Context von 4k und sagt, Coding-Tools sollten auf mindestens 64000 gesetzt werden s3. Du hebst ihn mit OLLAMA_CONTEXT_LENGTH beim Start des Servers an, und ollama ps zeigt, ob es gegriffen hat s3. Die Anleitung von Ollama verlangt ebenfalls ein Fenster von 64k oder mehr s1.

--bare ist die zweite. Ein Artikel maß die erste Standardanfrage mit 14,0k Tokens und mit --bare mit 0,75k s8. Wir haben keine Tokens gezählt. Was wir sahen: Dieselbe Aufgabe bei demselben 4k-Context ging von nichts nach 900 s zu einem Pass nach 93 s. --bare überspringt außerdem Hooks, Plugins, Memory und CLAUDE.md, das lokale Modell sieht also nie deine Projektregeln. In unserem Claude Code 2.1.294 sagt die Hilfe, dass die Authentifizierung strikt ANTHROPIC_API_KEY oder apiKeyHelper ist, deshalb setzt der Alias ANTHROPIC_API_KEY=ollama. Einen leeren Key unter --bare haben wir nicht getestet.

Eine Header-Einstellung steckt im Alias, aber wir haben sie nicht gemessen. Die Doku von Unsloth sagt, der Attribution-Header macht den lokalen Cache ungültig und CLAUDE_CODE_ATTRIBUTION_HEADER=0 behebt das s5, und ein Claude-Code-Issue führt dieselben Cache-Fehlzugriffe darauf zurück s9. --bare überspringt die Attribution bereits, daher können wir nicht sagen, was die zusätzliche Variable in unseren Läufen bewirkt hat.

Kleine lokale Modelle scheitern oft am Tool-Vertrag, nicht am Code. Ein Benchmark fand Modelle, die write_file statt Write aufriefen s7. Der Issue-Tracker von Ollama enthält einen Bericht über abgeschnittene und verworfene Tool-Aufrufe s10. Einen Fehler beim Tool-Namen haben wir nicht gesehen. Unser Fehler war leiser: eine Umbenennung, die einen Import kaputt hinterließ.

Die ersten Züge können langsam sein. Ein Erfahrungsbericht zu qwen3.5:9b mit 64k Context auf einem Laptop mit 32 GB sah eine erste Anfrage von über 10 min und spätere Züge von 1 bis 3 min s6. Unsere Zeiten stehen in der Tabelle unten.

Was der Endpunkt nicht kann. Die Kompatibilitätsseite von Ollama für Anthropic listet Prompt Caching und erzwungene Tool-Wahl als nicht unterstützt s2. Die Doku von Anthropic sagt, dass das Routing von Claude Code auf Modelle, die nicht von Claude stammen, über kein Gateway unterstützt wird s4. Ein kritischer Test kommt zum selben Ergebnis wie wir: lokal nur für Routinearbeit s11.

Ein einfacher Alias schlägt einen Router, der dein Abo-Token wiederverwendet. Eine Setup-Anleitung berichtet, dass solche Router mit einem 401 scheitern s13.

Code

  • claude-alt.zsh

# claude-alt: one-file jobs I can check in a glance
# plan: anything across files, or that I can't check by reading the diff
# always: read the diff before committing
alias claude-alt='CLAUDE_CODE_ATTRIBUTION_HEADER=0 ANTHROPIC_AUTH_TOKEN=ollama ANTHROPIC_API_KEY=ollama ANTHROPIC_BASE_URL=http://localhost:11434 claude --bare --model qwen3.5:9b'

claude-alt.zsh on GitHub

: der Alias-Block mit der Wechselregel als drei Kommentare darüber. Füge ihn in `~/.zshrc` ein und führe dann `source ~/.zshrc` aus. -

switch-rule.md

# The switch rule

Keep this next to the claude-alt alias. Decide before your limit hits, not while you wait.

## Goes to claude-alt (local model)

- A job in one file that you can check at a glance
- Adding an option, explaining a function, testing one function
- Work where a wrong result is visible in one short diff

## Waits for the plan

- Anything that crosses files, such as a rename with callers in other modules
- Anything you cannot check by reading the diff
- Work that depends on your hooks or your project rules (the alias runs with --bare, which skips both)
- Long sessions

## Always

- Read the diff before you commit, whichever model wrote it
- After a rename, import the old names by hand. A green test run only covers what the tests cover

## Why this rule

Two tasks on a 16 GB M1 Pro with qwen3.5:9b:

- One file (add a --prefix option): passed in 93 s with --bare.
- Across files (rename a function, keep the old name as an alias): the model said the tests were green, and an import was broken in both runs.
- On the plan, Claude did the rename in 38 s with both the old and the new imports working.

Two tasks on one small package is a starting point. Widen the rule with your own runs.

switch-rule.md on GitHub

: eine einseitige Regelkarte dazu, welche Aufgaben lokal laufen, welche auf den Plan warten und welche Prüfung du immer machst. -

run-task.sh

#!/bin/zsh
# Usage: run-task.sh <name> <A|B> <plan|alt|alt-nobare> [timeout_s]
# Runs one task on a fresh copy of slugkit and records time, output, diff and the check.
set -u
NAME=$1; TASK=$2; MODE=$3; TO=${4:-1800}
SRC=${SLUGKIT:?set SLUGKIT to the slugkit repo}
OUT=${RUNS:?set RUNS to the output dir}/$NAME
rm -rf $OUT; mkdir -p $OUT; cp -R $SRC $OUT/repo; cd $OUT/repo
A='In slugkit/cli.py add a --prefix option: when given, the slug starts with the prefix and the separator (python3 -m slugkit --prefix blog Hello World prints blog-hello-world). Then run that command to check it.'
B='Rename the function smart_truncate to truncate_words everywhere in this repo (definition, imports, calls, tests, __all__). Keep smart_truncate as an alias of truncate_words in slugkit/truncate.py so old imports still work. Then run python3 -m unittest discover tests and make sure every test passes.'
[[ $TASK == A ]] && P=$A || P=$B
TOOLS=(--allowedTools "Read" "Edit" "Write" "Glob" "Grep" "Bash(python3:*)" "Bash(grep:*)" "Bash(ls:*)")
start=$(date +%s)
case $MODE in
  plan) perl -e 'alarm shift; exec @ARGV' $TO claude -p "$P" --output-format json $TOOLS > $OUT/out.json 2> $OUT/err.log ;;
  alt) CLAUDE_CODE_ATTRIBUTION_HEADER=0 ANTHROPIC_AUTH_TOKEN=ollama ANTHROPIC_API_KEY=ollama ANTHROPIC_BASE_URL=http://localhost:11434 \
       perl -e 'alarm shift; exec @ARGV' $TO claude --bare --model qwen3.5:9b -p "$P" --output-format json $TOOLS > $OUT/out.json 2> $OUT/err.log ;;
  alt-nobare) CLAUDE_CODE_ATTRIBUTION_HEADER=0 ANTHROPIC_AUTH_TOKEN=ollama ANTHROPIC_API_KEY="" ANTHROPIC_BASE_URL=http://localhost:11434 \
       perl -e 'alarm shift; exec @ARGV' $TO claude --model qwen3.5:9b -p "$P" --output-format json $TOOLS > $OUT/out.json 2> $OUT/err.log ;;
esac
rc=$?; end=$(date +%s)
git diff --stat > $OUT/diff.stat; git diff > $OUT/diff.patch
if [[ $TASK == A ]]; then python3 -m slugkit --prefix blog Hello World > $OUT/check.txt 2>&1; else python3 -m unittest discover tests > $OUT/check.txt 2>&1; grep -rn smart_truncate slugkit tests >> $OUT/check.txt; fi
echo "{\"name\":\"$NAME\",\"task\":\"$TASK\",\"mode\":\"$MODE\",\"rc\":$rc,\"seconds\":$((end-start))}" > $OUT/meta.json
cat $OUT/meta.json; tail -3 $OUT/check.txt

run-task.sh on GitHub

: das Skript, mit dem wir Aufgabe A oder B auf dem Plan oder dem Alias getaktet, den Diff gespeichert und die Prüfung ausgeführt haben. Setze zuerst `SLUGKIT` auf dein Test-Repo und `RUNS` auf einen Ausgabeordner.

Das machst du am Montag

  • Führe ollama --version und claude --version aus. Wir nutzten Ollama 0.40.13 s19 und Claude Code 2.1.294.
  • Lade ein Modell, das in deinen Speicher passt. Für 16 GB nutzten wir qwen3.5:9b, das 7,6 GB groß ist.
  • Starte Ollama mit OLLAMA_CONTEXT_LENGTH=65536 ollama serve, führe dann ollama ps aus und lies die Spalte CONTEXT.
  • Füge den Block aus claude-alt.zsh in ~/.zshrc ein und führe source ~/.zshrc aus. Prüfe, dass das normale claude weiter deinen Plan nutzt.
  • Wähle eine Aufgabe in einer Datei in einer Wegwerfkopie eines Repos und führe sie mit claude-alt aus.
  • Lies den Diff und führe die Prüfung selbst aus. Verlass dich nicht auf den Bericht des Modells.
  • Probiere in derselben Kopie eine Umbenennung über mehrere Dateien. Importiere danach die alten Namen von Hand.
  • Bewahre switch-rule.md neben dem Alias auf und ergänze sie mit dem, was deine eigenen Läufe zeigen.

Messungen

Maschine: MacBook Pro M1 Pro, 16 GB, Claude Code 2.1.294, Ollama 0.40.13, qwen3.5:9b (7,6 GB). Das Repo war ein kleines Python-Paket mit 4 Modulen und 12 unittest-Tests, geschrieben für diesen Test. Die Maschine stand die ganze Zeit unter Speicherdruck, die lokalen Zeiten sind also eine obere Schranke.

Aufgabe Weg Zeit Ergebnis
A, --prefix hinzufügen (eine Datei) Plan, Claude 21 s Bestanden, blog-hello-world
A, --prefix hinzufügen (eine Datei) Alias, 4k, ohne --bare 900 s Beim 15-Minuten-Limit abgebrochen, keine Änderungen, keine Antwort
A, --prefix hinzufügen (eine Datei) Alias, 4k, --bare 93 s Bestanden, blog-hello-world
A, --prefix hinzufügen (eine Datei) Alias, 64k, --bare 35 s Bestanden, blog-hello-world
A, --prefix hinzufügen (eine Datei) Alias, 64k, ohne --bare nicht abgeschlossen Vom System wegen zu wenig Speicher beendet, kein Ergebnis
B, Umbenennung über mehrere Dateien Plan, Claude 38 s Bestanden, 12 Tests OK, alter und neuer Import funktionieren, Tests umbenannt
B, Umbenennung über mehrere Dateien Alias, 4k, --bare 464 s Kaputt: „All 12 unit tests pass“, aber from slugkit import truncate_words löste ImportError aus
B, Umbenennung über mehrere Dateien Alias, 64k, --bare 142 s Kaputt: 12 Tests OK und als erledigt gemeldet, aber der Alias landete in __init__.py, daher löste from slugkit.truncate import smart_truncate ImportError aus

Aufgabe B verlangte, smart_truncate als Alias in slugkit/truncate.py zu behalten. Claude Code warnte außerdem, dass es das Modell nicht kenne und ein Fenster von 200k Tokens annehme. Unsere Sitzungen blieben weit darunter, und eine lange haben wir nicht getestet.

Weiterführend

Was wir weggelassen haben und wo du nachsehen kannst, wenn du es willst.

  • Gehostete Routen. Anbieter wie DeepSeek, Z.AI oder OpenRouter nutzen denselben Alias mit einer anderen Base-URL. Sie rechnen pro Token ab, und wir hatten keinen Key, also haben wir sie nicht getestet.
  • Router mit kostenlosen Kontingenten. Router, die kostenlose Kontingente bündeln, versprechen Claude Code gratis. Wir haben sie nicht getestet. Prüfe ihre Bedingungen und wohin deine Prompts gehen, bevor du einen ausprobierst.
  • Ollama-Cloud-Modelle. Es gibt kein kostenloses Kontingent mehr, sie werden also nach Verbrauch abgerechnet.
  • Größere lokale Modelle. Modelle im Bereich 26b bis 35b haben wir nicht probiert, sie passen mit 64k Context nicht in 16 GB. Mit 32 GB oder mehr ließ ein Erfahrungsbericht ein 35b-Modell durch sechs bewertete Aufgaben laufen und bekam alle sechs hin, bei etwa der 8-fachen Zeit der Cloud-Modelle s12.
  • Hybrides Routing. Lokal für Subagents und der Plan für die Hauptschleife ist ein Setup, das wir nicht probiert haben.
  • Andere kleine Modelle. gemma4:e4b ist ein Ausweichmodell, das manche Anleitungen nutzen. Wir haben es nicht laufen lassen.
  • Ein echter Benchmark. Zwei Aufgaben an einem Paket zeigen ein Muster, keine Rangliste. Um die Regel zu erweitern, führe eigene Aufgaben mit run-task.sh aus und pflege eine Tabelle wie die oben.

FAQ

Ändert sich das normale claude, wenn ich den Alias hinzufüge? Nein. Die Variablen stehen in der Alias-Zeile, also spricht nur claude-alt mit Ollama.

Warum setzt der Alias ANTHROPIC_API_KEY=ollama und keinen leeren Key? Unter --bare liest Claude Code seinen Key nur aus ANTHROPIC_API_KEY oder apiKeyHelper. Unser Alias mit ollama als Key funktionierte. Einen leeren Key unter --bare haben wir nicht bis zum Ende getestet.

Wird das von Anthropic unterstützt? Nein. Die Doku von Anthropic sagt, dass das Routing von Claude Code auf Modelle, die nicht von Claude stammen, über kein Gateway unterstützt wird s4.

Kann ich einem grünen Testlauf des lokalen Modells vertrauen? Nur für das, was die Tests abdecken. In Aufgabe B bestanden die Tests, während ein Import kaputt war, weil nichts den alten Importpfad testete. Lies den Diff und importiere die alten Namen von Hand.

Wird es so schnell sein wie der Plan? Nicht in unseren Läufen. Aufgabe B dauerte auf dem Plan 38 s und auf dem Alias 142 s bis 464 s, und sie brach trotzdem.

Dateien