nasindex Dokumentation
nasindex macht ein Bauprojektarchiv auf dem NAS für Claude durchsuchbar, ohne dort etwas zu verändern. Diese Seite beschreibt, wie es arbeitet, wie man es einrichtet und betreibt, und wo seine Grenzen liegen.
Ein Findmittel, kein Wissensspeicher
Der Index bringt Claude zu den richtigen fünf Dokumenten. Danach liest Claude das vollständige Original mit intakten Tabellen. So entstehen keine aus dem Zusammenhang gerissenen Zahlen, die plausibel klingen und falsch sind.
Nur lesend
Das Archiv wird nie beschrieben. Der Zugriff läuft über einen Ordnerpfad auf dem NAS selbst oder über einen NAS-Benutzer, der nur lesen darf.
Die Ordner tragen das Wissen
Projekt, Phase, BKP-Code, Arbeitsgattung, Vergabestufe und Dokumentklasse liest nasindex aus dem Pfad, bevor es eine Datei öffnet.
Claude zitiert das Original
Antworten mit Zahlen stützen sich immer auf das gelesene Dokument, nie auf einen Suchausschnitt.
Vom Archiv zur Antwort
Ein Container erledigt beides: Er indexiert das Archiv in einer Dauerschleife und beantwortet die Anfragen von Claude. Der Index liegt im Container auf einem eigenen Datenträger, nie auf dem Archiv.
Ein Indexierungszyklus
| Schritt | Was passiert |
|---|---|
| Vorlage-Katalog einspielen | Nur beim ersten Start und nur, wenn ein Katalog von einem anderen Rechner bereitliegt (Seed). |
| Dateien suchen | Das Archiv wird durchlaufen. Aus jedem Pfad entstehen die Metadaten. |
| Texterkennung prüfen | Einmalige Kalibrierung des Text-Extraktors an Beispieldateien. |
| Dateien abgleichen | Neu, geändert oder verschwunden? Erkannt über Grösse und Änderungsdatum. |
| Prüfsummen bilden | SHA-256 je Datei, für Änderungen und Duplikate. |
| Texte auslesen | Volltext aus PDF, Office und Scans. Scans laufen durch die Texterkennung (OCR, Deutsch). |
| Volltextindex aufbauen | Suchindex über Dateiname, Pfad, Gattung und Inhalt. |
| Katalog exportieren | Ein Abbild des Index, aus dem ein anderer Rechner seinen Index aufbauen kann. |
Der erste Zyklus über ein grosses Archiv dauert Stunden. Danach dauert ein Zyklus über ein unverändertes Archiv nur noch Sekunden bis Minuten.
Was der Pfad verrät
Aus 21099-XXX / 1 Aufträge / 32162_Falttor Anlieferung / 2 Vergabe / 1 Angebote / Offerte_240813.pdf liest nasindex:
21099-XXX
1 Aufträge
32162 · Falttor Anlieferung
2 Vergabe
Angebot
2024
Duplikate führt nasindex über den Inhalt zusammen. Es gewinnt die Kopie mit Dokumentklasse, dann mit Gattung, dann die ausserhalb von Sicherungs-, Kopie- oder Versandordnern, dann der kürzere Pfad. Das Jahr stammt aus Pfad oder Dateiname, sonst aus dem Dateidatum. Es taugt für Zeitraumfilter, nicht für Aussagen wie «im Jahr X vergeben».
Drei Wege, ein Assistent
nasindex kommt als Paket nasindex-<version>.zip mit dem Programm für Intel/AMD und ARM. Das Installationsskript lädt das passende Programm, startet den Einrichtungs-Assistenten, prüft den Zugriff aufs Archiv und startet nasindex. Die Schritt-für-Schritt-Anleitung liegt als ANLEITUNG.md im Paket.
| Weg | Wann | Archivzugriff |
|---|---|---|
| Direkt auf dem NAS | Dauerbetrieb, wenn das NAS Docker kann (Synology Container Manager) | bind: der Ordnerpfad der Freigabe, z. B. /volume1/Projekte |
| Auf einem anderen Rechner | Ein Linux-Rechner, der dauernd läuft, oder ein Mac mit Docker Desktop | cifs: der Container verbindet sich selbst mit der Freigabe, mit einem Lese-Benutzer |
| Mac zuerst, dann NAS | Grosses Archiv, schwaches NAS: der Mac liest einmal alles aus, das NAS übernimmt | erst cifs auf dem Mac, dann bind auf dem NAS mit dem Katalog des Mac |
Voraussetzungen
- Docker mit Docker Compose v2. Prüfen mit
docker compose version. - Mindestens 5 GB frei im Installationsordner, dazu Platz für den Index, rund ein Zehntel der Archivgrösse.
- Tailscale auf dem Rechner mit nasindex und auf jedem Arbeitsplatz mit Claude.
- Auf den Arbeitsplätzen Claude Desktop mit Node.js, oder Claude Code.
- Im Modus
cifs: ein NAS-Benutzer mit nur Leserecht auf die Archiv-Freigabe. Ein Administrator-Konto braucht nasindex nie.
Starten
Paket entpacken, den Ordner nasindex nicht umbenennen oder verschieben, dann darin:
sh installieren.sh
Auf dem Mac geht auch ein Doppelklick auf Installieren.command. Braucht Docker Administratorrechte, wie auf dem Synology-NAS üblich, fragt das Skript selbst nach dem Passwort.
Seed: Katalog von einem anderen Rechner
Ein stärkerer Rechner baut den Index einmal komplett. Sein Katalog besteht aus vier Einträgen: catalog.jsonl.gz, catalog.json, text/ und meta/. Im Container liegen sie unter /daten:
mkdir nasindex-katalog
docker cp nasindex:/daten/catalog.jsonl.gz nasindex-katalog/
docker cp nasindex:/daten/catalog.json nasindex-katalog/
docker cp nasindex:/daten/text nasindex-katalog/
docker cp nasindex:/daten/meta nasindex-katalog/
Den Ordner aufs Zielsystem kopieren und dem Assistenten bei der Frage nach dem Seed-Pfad angeben. Beim ersten Start spielt nasindex ihn ein, im Log als Zeile seed: …. Danach meldet der Abgleich meist «0 neu, 0 geändert».
Fragen, Dateien, Prüfungen
Der Assistent ist in nummerierte Abschnitte gegliedert: Voraussetzungen, Archivzugang, Startdaten, Netzwerk, Feldextraktion, Dateien schreiben, Start und Erstindexierung, Abschluss. Bevor er etwas schreibt, zeigt er die Voraussetzungen mit Prüfergebnis.
| Frage | Bedeutung |
|---|---|
| Läuft der Container auf dem NAS selbst? | Ja: Modus bind, danach der Archivpfad. Nein: Modus cifs, danach SMB-Server, Freigabe, Lese-Benutzer, Domäne (optional) und Passwort. |
| Katalog von einem anderen Rechner (Seed-Pfad) | Leer: Erstindexierung hier. Sonst der Ordner mit dem Katalog. |
| Tailscale-IP-Adresse | Der Vorschlag kommt von tailscale ip -4. Nur eine IP-Adresse, kein Hostname. 0.0.0.0 lehnt der Assistent ab. lokal bindet nur an 127.0.0.1. |
| Port | Standard 8765. |
| Feldextraktion | Anbieter, Modell, optional Auftraggeber, Schlüssel und Freigabe. Standard: anthropic, kein Schlüssel, keine Freigabe. Siehe Feldextraktion. |
Was entsteht
| Datei | Inhalt |
|---|---|
.env | Modus, Compose-Dateien, Adresse und Port, Werte der Feldextraktion. Keine Zugangsdaten. |
docker/mcp.token | Der Zugangsschlüssel für Claude, zufällig erzeugt. |
docker/smb.cred | Nur im Modus cifs: Lese-Benutzer und Passwort. |
docker/llm.key | Optional: API-Schlüssel für die Feldextraktion. |
Alle Dateien haben die Rechte 600, nur der Besitzer kann sie lesen. Bestehende Dateien überschreibt der Assistent nur nach Rückfrage. Im Modus cifs prüft er die Zugangsdaten am NAS, bevor er startet, und fragt bei einem Fehler bis zu drei Mal neu.
Fortschritt und erneuter Aufruf
Nach dem Start zeigt der Assistent den ersten Zyklus live, zum Beispiel Schritt 5 von 7: Texte auslesen - 1234 von 20000 (6 %), noch ~3 h 10 min. Ctrl-C beendet nur die Anzeige, die Indexierung läuft weiter. Den Stand später wieder ansehen:
sh installieren.sh
Das Skript fragt dann «Die Fragen neu beantworten?». Enter heisst nein: es prüft nur und zeigt den Stand.
Arbeitsplätze verbinden
Am Ende druckt der Assistent beide Rezepte mit Adresse und Port. Den Schlüssel lesen Sie aus docker/mcp.token. Er gibt vollen Lesezugriff auf das indexierte Archiv: wie ein Passwort behandeln.
Claude Desktop
In claude_desktop_config.json ergänzen, danach Claude Desktop ganz beenden und neu starten. --allow-http ist richtig so, die Verschlüsselung übernimmt Tailscale.
{
"mcpServers": {
"archiv": {
"command": "npx",
"args": ["-y", "mcp-remote", "http://<tailscale-ip>:8765/mcp", "--allow-http",
"--header", "Authorization: Bearer <schluessel>"]
}
}
}Claude Code
claude mcp add --transport http archiv http://<tailscale-ip>:8765/mcp --header "Authorization: Bearer <schluessel>"Skill
In Claude unter Einstellungen → Fähigkeiten die Datei claude/archiv-skill.zip aus dem Paket hochladen. Der Skill sagt Claude, wann welches Werkzeug dran ist, dass Zahlen aus dem Original kommen und wie Fundstellen angegeben werden. Test: «Wie ist der Stand des Archivs?»
Suchen findet, Lesen belegt
| Werkzeug | Wofür |
|---|---|
archiv_suche | Volltext mit Filtern auf Projekt, Dokumentklasse, Gattung, BKP und Jahr. |
archiv_lesen | Das ganze Dokument aus dem Index, mit Tabellen. Hier kommen Zahlen und Daten her. |
archiv_datei | Die Originaldatei direkt in den Chat: PDF und Bilder (png, jpg, gif, webp) bis 10 MB. Sonst Pfad, Grösse und der Grund. |
archiv_sql | Eine einzelne lesende SQL-Abfrage. Zählen, gruppieren, Lücken finden. |
archiv_status | Was im Index steckt, wie aktuell er ist, ob das Archiv erreichbar ist. |
Fragen, die damit gehen
| Frage | Weg |
|---|---|
| Was wurde beim Falttor Anlieferung offeriert? | Suche mit Dokumentklasse Angebot, dann lesen |
| Wie viele Angebote haben wir pro Gattung? | SQL mit GROUP BY gattung |
| Welche Gattungen haben Rechnungen, aber keinen Werkvertrag? | SQL mit HAVING |
| Wo taucht Firma X sonst noch auf? | Suche ohne Filter über alle Projekte |
| Alle Werkverträge über CHF 50'000 | SQL auf die Tabelle felder, wenn die Feldextraktion gelaufen ist |
Was archiv_sql sieht
Für Zähl- und Vergleichsfragen. Die Abfrage ist nur lesend, ein einzelnes SELECT.
Tabelle docs
Eine Zeile je Datei. Die wichtigsten Spalten:
rel,filename,ext,size: Pfad im Archiv, Name, Endung, Grösseprojekt,phase,bkp,gattung,stufe,dokklasse,jahr: aus dem Pfaddup_of: gesetzt bei einem Duplikat, zeigt auf das Originalchars,page_count,table_count,ocr_used: zum ausgelesenen Textextract_status:ok,meta_only,duplicate,pending,error,missing
Tabelle felder
Eine Zeile je verarbeitetem Werkvertrag, verknüpfbar über rel:
auftragnehmer,gegenstand,vertragsdatum,vertragsnummernetto,bruttoals Zahl,waehrungunterzeichner_ag,unterzeichner_an,sachbearbeiter,telefon,emailstatusje Dokument:ok,leer,zu_gross,fehler<feld>_statusje Feld:wert,nicht_im_dokument,nicht_extrahiert
meta_only heisst: kein Volltext, etwa bei CAD-Plänen und Bildern. Sie sind über Pfad und Dateiname trotzdem auffindbar. missing heisst: die Datei ist aus dem Archiv verschwunden.
Was von allein läuft, was Sie tun
nasindex startet nach jedem Neustart des Rechners selbst und prüft das Archiv jede Stunde auf Neues und Geändertes. Alle Befehle laufen im Ordner nasindex. Auf dem Synology-NAS sudo voranstellen.
| Sie wollen | Befehl |
|---|---|
| Sehen, ob es läuft | docker compose ps |
| Die letzten Meldungen sehen | docker compose logs --tail 200 nasindex |
| Fortschritt und Stand sehen | sh installieren.sh, dann Enter |
| Wissen, wie viel im Index steckt | docker exec nasindex python3 /app/nasindex.py stats |
| Sofort indexieren statt auf die Stunde zu warten | docker exec nasindex python3 /app/docker/entrypoint.py build |
| Den Server ohne Claude prüfen | docker exec nasindex python3 /app/docker/entrypoint.py selbsttest |
Die NAS-Zugangsdaten prüfen (cifs) | docker compose run --rm --no-deps nasindex smb-pruefen |
| Neu starten | docker compose restart |
| Anhalten und wieder starten | docker compose stop und docker compose up -d |
| Schlüssel für Claude wechseln | Neuen Wert in docker/mcp.token (mindestens 32 Zeichen), dann docker compose restart. Arbeitsplätze neu eintragen. |
Aktualisieren
Ein Update ist ein neues Paket. Am selben Ort entpacken und vorhandene Dateien überschreiben lassen. .env und die Zugangsdaten sind nicht im Paket und bleiben. Dann sh installieren.sh und «Die Fragen neu beantworten?» mit Enter verneinen. Der Index bleibt erhalten.
Beträge aus Werkverträgen
Volltextsuche findet Dokumente, kann aber nicht rechnen. Für Schwellen und Summen liest felder zwölf Felder aus jedem Werkvertrag und schreibt sie in die Tabelle felder. Dafür geht der Vertragstext an ein Sprachmodell. Das ist der einzige Netzaufruf nach aussen in nasindex.
Nie automatisch
Der Container startet felder nie selbst. Es läuft nur auf Ihren Befehl.
Nur mit Freigabe
Ohne Freigabe verweigert felder jeden Lauf, auch den Trockenlauf. Der Assistent fragt danach, Standard ist nein.
Zitiert wird das Original
Beträge werden nie berechnet oder umgerechnet, nur übernommen, wenn sie so im Dokument stehen.
Anbieter
| Anbieter | Adresse | Modell | Schlüssel |
|---|---|---|---|
anthropic | fest, api.anthropic.com | optional, Standard claude-sonnet-5 | Pflicht, beginnt mit sk-ant- |
openai | fest, api.openai.com | Pflicht | Pflicht, beginnt mit sk- |
eigener | Pflicht, ein OpenAI-kompatibler Endpunkt wie vLLM, llama.cpp oder OpenRouter. http:// nur im Tailnet. | Pflicht | optional |
Geprüft hat Digital Apes nur anthropic mit dem Standardmodell. Bei openai und eigener muss das Modell ein JSON-Schema einhalten und Dokumente bis 500'000 Zeichen fassen, etwa 125'000 Token.
Ablauf
docker compose exec nasindex python3 /app/nasindex.py felder --trockenlauf
docker compose exec nasindex python3 /app/nasindex.py felder --limit 15
docker compose exec nasindex python3 /app/nasindex.py felder
Der Trockenlauf zeigt Anzahl, Zeichen und bei anthropic die geschätzten Kosten, ohne ein Dokument zu senden. Richtwert: 541 Werkverträge mit 14,7 Mio. Zeichen kosten rund 13 bis 15 US-Dollar. --limit 15 gibt ein kleines Set zum Gegenlesen. Ein abgebrochener Lauf macht beim nächsten Aufruf weiter. Nicht parallel zu einem laufenden Indexierungszyklus starten.
Vortest bei eigenem Modell
Vor jedem Lauf fragt nasindex den Server nach der Kontextgrösse und schickt eine Probe mit einem erfundenen Mini-Vertrag. So zeigt sich vorab, ob das Modell das Format einhält. Zu grosse Dokumente bleiben für ein Modell mit mehr Kontext liegen. Meldet der Server keine Kontextgrösse (Ollama, LM Studio, llama.cpp), setzen Sie sie im Assistenten oder als EXTRAKTION_KONTEXT. Ollama kürzt zu lange Eingaben still.
Feldregeln
- Vertragsnummer nur, wenn das Dokument sie als Vertrags-, Auftrags-, Bestell-, Nachtrags- oder Mehrkostennummer bezeichnet. Projekt-, Objekt-, Kostenstellen- und BKP-Nummern nie.
- Auftragnehmer sind nie Architekt, Fachplaner, Bauleitung oder Ingenieurbüro, ausser im eigenen Planervertrag. Auch nicht eine Liefer- oder Rechnungsadresse.
- Unterzeichner AN nur aus der Auftragnehmerfirma.
- Währung nur bei genanntem Betrag, nie aus einer IBAN.
- Telefon und E-Mail nur, wenn sie eindeutig zum Auftragnehmer gehören.
- Optional ein Auftraggeber: der Name gilt dann nie als Auftragnehmer.
Eine Regeländerung wirkt nur auf neu ausgelesene Verträge. felder --force liest alle neu und kostet wie ein voller Lauf.
EXTRAKTION_FREIGABE= in .env leeren, dann docker compose up -d. Den Stand zeigt docker compose logs nasindex | grep felder:.Einstellungen
Der Assistent schreibt die .env. Die übrigen Werte stehen im Abschnitt environment der Compose-Datei, compose.bind.yml oder compose.cifs.yml. Nach einer Änderung docker compose up -d. Zugangsdaten gehören nie in diese Dateien, nur in die Dateien unter docker/.
| Einstellung | Standard | Bedeutung |
|---|---|---|
INDEX_INTERVALL | 3600 | Sekunden zwischen zwei Zyklen, mindestens 60 |
ARCHIV_PROJEKTE | leer = alle | Projekte, kommagetrennt |
OCR | an | aus schaltet die Texterkennung für Scans ab |
OCR_SPRACHE | deu | Sprache der Texterkennung |
EXTRAKT_JOBS | 2 | Dateien, die gleichzeitig ausgelesen werden |
EXTRAKT_TIMEOUT | 600 | Sekunden je Datei, bevor abgebrochen wird |
XBERG_THREADS | 2 | Threads je Auslesevorgang |
MCP_HOST_ADRESSE | 127.0.0.1 | Adresse, an die der Port gebunden wird. Die Tailscale-IP, nie 0.0.0.0 |
MCP_PORT | 8765 | Port für Claude |
EXTRAKTION_FREIGABE | leer | ja gibt die Feldextraktion frei |
EXTRAKTION_ANBIETER | anthropic | anthropic, openai oder eigener |
EXTRAKTION_MODELL | bei anthropic: claude-sonnet-5 | Modell, bei openai und eigener Pflicht |
EXTRAKTION_BASIS_URL | leer | Adresse des eigenen Endpunkts, nur bei eigener |
EXTRAKTION_KONTEXT | leer | Kontextgrösse des eigenen Modells in Token |
EXTRAKTION_AUFTRAGGEBER | leer | Name des Auftraggebers für den Prompt |
Ressourcen: Die Compose-Dateien setzen 4 CPUs und 4 GB Arbeitsspeicher. Richtwert: 1 GB je gleichzeitig ausgelesener Datei plus 1 GB Grundlast. Ein ungültiger Wert bricht den Start mit einer Meldung ab, die nur den Namen der Einstellung nennt.
Was geschützt ist, und wodurch
Archiv nur lesend
Im Modus bind ist der Ordner nur lesend eingebunden. Im Modus cifs verbindet sich der Container mit fest verdrahteten Optionen nur lesend, ohne Ausführen. Der Lese-Benutzer hat ohnehin keine Schreibrechte.
Zugriff nur im Tailnet
Der Server spricht HTTP ohne eigenes TLS. Die Verschlüsselung kommt von Tailscale. Der Port wird nur an die Tailscale-Adresse gebunden, nie an 0.0.0.0. Öffentlich erreichbar ist er nicht vorgesehen.
Der Schlüssel ist Vollzugriff
Wer docker/mcp.token kennt, kann suchen, lesen und Originaldateien abrufen. Nicht per Mail oder Chat weitergeben. Ein Wechsel wirkt nach einem Neustart.
Zugangsdaten als Dateien
Passwort, Token und API-Schlüssel liegen in Dateien mit Rechten 600, nie in Umgebungsvariablen und nie im Programm. Meldungen nennen nie einen Schlüssel oder ein Passwort.
Ein einziger Weg nach aussen
Nur die Feldextraktion sendet Text an einen Anbieter, nur mit Freigabe und nur auf Befehl. Ein Schlüssel geht nur an die konfigurierte Adresse, nie an ein Umleitungsziel.
Zwei Adressen
POST /mcp verlangt den Schlüssel. GET /gesundheit antwortet ohne Schlüssel nur mit ok oder nicht ok. Jeder andere Pfad ergibt 404.
Was nasindex nicht kann
- CAD-Pläne und Bilder haben keinen Volltext. Sie sind über Pfad und Dateiname auffindbar.
- Das Jahr ist eine Näherung aus Pfad, Dateiname oder Dateidatum.
- Beträge sind im Volltext keine Zahlen. Schwellen und Summen gehen nur über die Tabelle
felder, heute für Werkverträge. - Neue Dateien erscheinen mit dem nächsten Zyklus, also spätestens nach einer Stunde.
- Eigene Modelle für die Feldextraktion sind ungeprüft. Die Qualität gilt pro Modell.
- Der Container läuft als root, im Modus
cifsmit dem Recht, Freigaben einzubinden. - Windows mit Docker Desktop ist im Modus
cifsungetestet. Ein Mac mit einem Netzlaufwerk alsbindist nicht unterstützt, dortcifsverwenden.
Wenn etwas hakt
Fällt das Archiv aus, funktioniert die Suche weiter. Der Index liegt im Container. Es fehlen nur neue Dateien und das Lesen von Originalen.
| Was Sie sehen | Was hilft |
|---|---|
| «nasindex erreicht das Archiv nicht» | Pfad, Server, Freigabe, Benutzer oder Passwort stimmen nicht. Assistent neu starten und die Fragen neu beantworten. |
| Claude findet den Server nicht | Tailscale auf beiden Geräten aktiv? Adresse, Port und Schlüssel richtig? Claude Desktop ganz neu gestartet? |
| Claude findet eine neue Datei nicht | Der nächste Zyklus nimmt sie auf. Sofort: entrypoint.py build, siehe Betrieb. |
scan: missing-Abgleich uebersprungen | Eine Schutzwache hat ausgelöst, weil auf einmal viele Dateien fehlen. Nichts ist verloren. Wurde wirklich ein Ordner entfernt, siehe unten. |
felder: Konfiguration unvollstaendig (…) | Die genannte Einstellung der Feldextraktion fehlt oder ist ungültig. Assistent neu starten. |
Kein Dokument passt in den Kontext | Kein Fehler des Laufs. Modell mit mehr Kontext wählen oder die Kontextgrösse richtig setzen. |
Ordner absichtlich entfernt
Die Schutzwache verhindert, dass ein kurz fehlendes Netzlaufwerk den Index leert. Ist der Rückgang gewollt, einmal bestätigen:
docker exec nasindex python3 /app/nasindex.py scan --verschwunden-ok --root /archiv --index /daten --cache /daten --rolle indexer
Meldungen von archiv_status
| Code | Bedeutung |
|---|---|
erreichbar | Das Archiv ist da und hat Inhalt. |
leer | Der Ordner ist leer, meist ein falscher Pfad. |
fehlt | Der Ordner existiert nicht, oder es fehlt das Leserecht. |
haengt | Keine Antwort in der Zeit, vermutlich eine hängende Verbindung zum NAS. |
Rückgabewerte von build
| Code | Bedeutung |
|---|---|
0 | Erfolg, auch «nichts zu tun» |
1 | Konfigurationsfehler oder Archiv nicht erreichbar, die Meldung nennt den Grund |
75 | Archivquelle nicht erreichbar, oder eine Schutzwache hat ausgelöst |
130 | Lauf durch einen Stopp abgebrochen |
137 | Von aussen beendet, oft zu wenig Arbeitsspeicher |
Bei Fragen schicken Sie Digital Apes die Ausgabe von docker compose logs --tail 200 nasindex. Sie enthält keine Zugangsdaten.