Claude Context offline — Ollama, lokalny Milvus, zero ruchu na zewnątrz
Konfiguracja Claude Context bez OpenAI i bez Zilliz Cloud. Lokalne embeddingi przez Ollamę, Milvus w Dockerze, pełna prywatność kodu. Krok po kroku.
Claude Context domyślnie kieruje cię do OpenAI za embeddingi i Zilliz Cloud jako magazyn wektorów. Dla firm z wymaganiami zgodności albo po prostu z awersją do wysyłania kodu na zewnątrz — obie decyzje da się cofnąć. Tu opisuję pełną konfigurację offline: Ollama lokalnie, Milvus w Dockerze, żadnych kluczy API.
Wracamy do głównego artykułu: Claude Code — jak przestać palić tokeny.
Dlaczego offline
Kod, który indeksujesz Claude Contextem, idzie do modelu embeddingów. Domyślnie to OpenAI (text-embedding-3-small albo -large), który:
- Wysyła fragmenty twojego kodu poza sieć firmową
- Wymaga klucza API, który musi być rotowany
- Kosztuje (niedużo, ale notuje zużycie)
- Podlega polityce retencji OpenAI (30 dni logów domyślnie)
Dla wielu kontraktów (health, finance, defense, public sector) to wyklucza taki przypadek użycia. Konfiguracja offline rozwiązuje wszystkie cztery problemy naraz.
Architektura stosu offline
Trzy komponenty, wszystkie lokalne. Ruch sieciowy = zero (po jednorazowym pobraniu obrazu Dockera i modelu Ollama).
Krok 1 — Ollama i model embeddingów
Instalacja
# macOS:
brew install ollama
brew services start ollama
# Linux:
curl -fsSL https://ollama.com/install.sh | sh
systemctl --user enable --now ollama
# Weryfikacja:
curl http://localhost:11434/api/tags
# powinno zwrócić {"models": []}
Wybór modelu
Ollama serwuje kilka modeli embeddingów. Dla Claude Context rekomendowane:
| Model | Wymiar | Rozmiar | Jakość | Komenda pull |
|---|---|---|---|---|
nomic-embed-text | 768 | 274 MB | dobra | ollama pull nomic-embed-text |
mxbai-embed-large | 1024 | 670 MB | bardzo dobra | ollama pull mxbai-embed-large |
bge-m3 | 1024 | 1,2 GB | flagship | ollama pull bge-m3 |
Domyślnie wybieram nomic-embed-text — najlepszy kompromis jakości do rozmiaru, trzyma się <300 MB. mxbai-embed-large bierzesz, gdy masz dużą bazę kodu (>10k plików) i zależy ci na semantyce.
ollama pull nomic-embed-text
# Weryfikacja że działa:
curl http://localhost:11434/api/embed \
-d '{"model": "nomic-embed-text", "input": "test embedding"}'
# powinno zwrócić {"embeddings": [[...768 liczb...]]}
Krok 2 — Milvus w Dockerze
Milvus to ten sam silnik co w Zilliz Cloud, tylko lokalnie. Najprostsza konfiguracja to tryb standalone przez docker-compose.
Pobranie i uruchomienie
mkdir -p ~/milvus && cd ~/milvus
curl -L https://github.com/milvus-io/milvus/releases/download/v2.4.15/milvus-standalone-docker-compose.yml -o docker-compose.yml
docker compose up -d
Standalone startuje trzy kontenery: milvus-standalone, milvus-etcd, milvus-minio. Razem ~2 GB pamięci w spoczynku, ~500 MB dysku per 100k embeddingów.
Weryfikacja
# Health check:
curl http://localhost:9091/healthz
# powinno zwrócić 200 OK
# Port 19530 — główne API gRPC
docker compose ps
# wszystkie trzy powinny być (healthy)
Utrwalenie danych
Domyślny docker-compose.yml trzyma dane w volumie. Jeśli skasujesz kontenery, dane zostają. Jeśli chcesz reset:
docker compose down -v # -v usuwa też volumes
Krok 3 — Claude Context z lokalnym backendem
Instalacja
claude mcp add claude-context \
-e EMBEDDING_PROVIDER=ollama \
-e EMBEDDING_MODEL=nomic-embed-text \
-e OLLAMA_HOST=http://localhost:11434 \
-e MILVUS_ADDRESS=localhost:19530 \
-e MILVUS_TOKEN= \
-e HYBRID_MODE=true \
-- npx @zilliz/claude-context-mcp@latest
Kluczowe zmienne:
EMBEDDING_PROVIDER=ollama— wyłącza domyślne OpenAIEMBEDDING_MODEL=nomic-embed-text— musi być modelem, któryollama pullściągnąłOLLAMA_HOST— domyślniehttp://localhost:11434, ale warto ustawić jawnieMILVUS_ADDRESS=localhost:19530— lokalny port MilvusaMILVUS_TOKEN=— pusty (lokalny Milvus nie wymaga tokena)HYBRID_MODE=true— włącza BM25 + vector zamiast samego vectora
Globalny config (alternatywa)
Zmienne można trzymać w ~/.context/.env zamiast w linii komend:
EMBEDDING_PROVIDER=ollama
EMBEDDING_MODEL=nomic-embed-text
OLLAMA_HOST=http://localhost:11434
MILVUS_ADDRESS=localhost:19530
MILVUS_TOKEN=
HYBRID_MODE=true
CUSTOM_IGNORE_PATTERNS=node_modules,dist,build,.planning,archives,.next,target
SPLITTER_TYPE=ast
CUSTOM_IGNORE_PATTERNS to ważne — domyślnie Claude Context indeksuje wszystko. Wyklucz katalogi, które nie mają wartości semantycznej (artefakty builda, cache, archiwa).
Krok 4 — pierwsze indeksowanie
W sesji Claude Code:
Zaindeksuj tę bazę kodu używając claude-context.
Claude wywoła index_codebase przez MCP. W zależności od wielkości repo to od kilku minut do pół godziny. Postęp można śledzić:
# W drugim terminalu:
docker compose -f ~/milvus/docker-compose.yml logs -f milvus-standalone | grep -i "inserted"
Dla kontekstu: 5000 plików TypeScript indeksuje się u mnie ~8 minut na M2, głównie czeka na Ollamę (embedding jest wąskim gardłem, nie Milvus).
Po zakończeniu weryfikacja:
Jaki jest status indeksowania?
Albo bezpośredni test:
Znajdź funkcje, które obsługują uwierzytelnianie użytkownika.
Jeśli semantyka działa — zwróci trafne fragmenty kodu bez czytania plików. To ten moment, kiedy widzisz oszczędność tokenów w akcji.
Troubleshooting
DEADLINE_EXCEEDED na gRPC
Najczęściej w trybie Zilliz Cloud Free tier (mamy opcję offline, więc nie dotyczy). Ale jeśli trafisz lokalnie — Milvus nie wstał do końca. Sprawdź:
docker compose logs milvus-standalone | tail -50
Typowa przyczyna: kontener jeszcze się inicjalizuje (pierwszy start trwa do 2 minut). Odczekaj.
Orphaned merkle files
Merkle trees służą do inkrementalnego reindexowania. Jeśli skasujesz kolekcję w Milvusie ręcznie, zostają puste pliki śledzące. Fix:
rm -rf ~/.context/merkle/<nazwa-projektu>/
# w sesji Claude:
# "Zaindeksuj tę bazę kodu od zera"
Ollama timeout podczas indeksowania
Duże pliki (>100 KB) bywają za ciężkie dla Ollamy w jednym requeście. W ~/.context/.env:
SPLITTER_MAX_CHUNK_SIZE=2000
SPLITTER_CHUNK_OVERLAP=200
To wymusza mniejsze chunki (2000 chars z 200 overlappingu). Ollama radzi sobie z tym od ręki.
Niekompatybilny Node.js
Claude Context wymaga Node.js 20.x lub 22.x. Nie 24.0.0+ — pakiet @zilliz/claude-context-mcp nie kompiluje się na 24. Jeśli masz nvm:
nvm install 22
nvm use 22
claude mcp add ... # świeża rejestracja
Benchmark jakości — offline vs OpenAI
Claude Context oficjalnie benchmarkował konfigurację z OpenAI. Z Ollamą nomic-embed-text otrzymasz:
- Retrieval F1 niższe o ~5-10% (ale wciąż w zakresie użyteczności)
- Embeddingi szybsze lokalnie (brak dodatkowego opóźnienia sieciowego)
- Większy zimny start (pierwszy embedding ~2 s na Apple Silicon, potem ~50-100 ms)
Dla większości zastosowań różnica jakości jest niezauważalna. Jeśli widzisz, że Claude często nie znajduje funkcji, które powinien — przesiądź się na mxbai-embed-large, to wyraźnie lepszy model (kosztem 670 MB dysku).
Monitorowanie i konserwacja
Miejsce na dysku
Milvus lokalnie trzyma dane w ~/milvus/volumes/ (domyślnie). Dla średniego projektu:
- 1000 plików ≈ 50 MB
- 10 000 plików ≈ 500 MB
- 100 000 plików ≈ 5 GB
Sprawdzenie:
du -sh ~/milvus/volumes/
Czyszczenie starych kolekcji
Każdy projekt robi osobną kolekcję. Jeśli skończyłeś z jakimś repo:
docker exec milvus-standalone attu-cli --help
# lub wejście do Python API:
python -c "from pymilvus import connections, utility; connections.connect('default', host='localhost', port='19530'); print(utility.list_collections())"
Aktualizacje Ollamy i modeli
ollama pull nomic-embed-text # zaktualizuje jeśli jest nowsza wersja
brew upgrade ollama # update samej Ollamy
Po update modelu trzeba reindex — stare embeddingi nie są kompatybilne z nową wersją (inna skala, często inny wymiar).
Kiedy ta konfiguracja się nie opłaca
Offline ma koszt stały:
- ~2 GB RAM dla Milvusa
- ~300 MB-1 GB dla Ollamy (zależnie od modelu)
- Docker Desktop / Docker Engine
Jeśli pracujesz na małym projekcie (<500 plików), hobbystycznie, bez wymagań zgodności — prostsza konfiguracja z OpenAI + Zilliz Cloud Free tier działa od razu w 2 minuty i kosztuje cię ~$0 miesięcznie. Offline to decyzja dla kontekstu firmowego albo mocnego przywiązania do prywatności.
Wracając do głównego artykułu: Claude Code — jak przestać palić tokeny. Dla terminala zamiast bazy kodu: RTK — pełna konfiguracja.