Lokale Pseudonymisierung personenbezogener Daten, bevor sie an Cloud-LLMs gehen - als Proxy vor anderen MCP-Servern, als MCP-Server und als CLI/Library.
Kuckuck erkennt personenbezogene Daten (E-Mail-Adressen, Telefonnummern, Jira-/Confluence-Handles, optional Personennamen), ersetzt sie durch deterministische Token ([[EMAIL_a7f3b2c1]]) und legt die Zuordnung in einem lokalen, AES-GCM-verschlüsselten Mapping ab.
Das LLM sieht nur die Token; mit dem Master-Key führst du sie lokal wieder auf die Originale zurück.
Derselbe Wert bekommt - über Dokumente, Tool-Calls und Teammitglieder mit gleichem Key hinweg - immer denselben Token.
Der Master-Key bleibt lokal, das Mapping ist ohne ihn kryptographisch unlesbar - siehe Abschnitt "Umkehrbarkeit".
| Modus | Wofür | Einstieg |
|---|---|---|
| MCP-Proxy | Du nutzt einen fremden MCP-Server (Jira, ein Server vor einer Kunden-REST-API), der selbst PII zurückgibt, und willst sie pseudonymisieren, bevor sie das LLM erreichen | MCP-Proxy |
| MCP-Server | Dein Coding-Assistent soll Dateien aktiv über native MCP-Tools (kuckuck_pseudonymize) pseudonymisieren |
MCP-Server |
| CLI & Library | Du pseudonymisierst Dateien oder Text direkt - im Terminal oder aus Python | Dateien & Text |
Was Kuckuck ist:
- Ein lokales Tool - MCP-Proxy, MCP-Server, CLI und Python-Library. Keine Cloud, keine Telemetrie.
- Ein einfacher Weg, personenbezogene Daten aus E-Mails, Tickets, Wiki-Exporten und fremden MCP-Servern zu pseudonymisieren, bevor du sie an Claude, ChatGPT oder ein anderes Cloud-LLM gibst.
- Deterministisch: derselbe Wert bekommt - über Dokumente und zwischen Teammitgliedern mit gleichem Key - denselben Token.
Was Kuckuck nicht ist:
- Keine DSGVO-Anonymisierung im Sinne von Erwägungsgrund 26. Pseudonymisierte Daten bleiben personenbezogen. Kläre den Einsatz mit deinem DSB ab, bevor du Kuckuck produktiv benutzt.
- Kein Ersatz für Datenminimierung. Kontextuelle Re-Identifikation (Rolle + Ort + Datum) ist möglich und nicht Aufgabe des Tools.
Nur mit dem passenden
.kuckuck-keylässt sich die Pseudonymisierung rückgängig machen. Ohne Key ist der Output wie ein Einweg-Hash: der Mapping-Sidecar (*.kuckuck-map.enc) ist AES-GCM-verschlüsselt und ohne Masterkey kryptographisch unlesbar.
Das heißt konkret:
- Wer den Key hat, kann jedes Mapping entschlüsseln und jeden Token zurück auf das Original führen.
- Wer den Key verloren hat, hat auch den Zugriff auf die Originalnamen unwiderruflich verloren.
- Wer den Key weitergibt, gibt damit die Fähigkeit weiter, alle bisher pseudonymisierten Dokumente zu deanonymisieren.
Lege den Key deshalb wie ein Passwort an und teile ihn nur über einen sicheren Kanal (Passwort-Manager wie 1Password/Bitwarden).
Jein - die ehrliche Antwort ist: es kommt auf drei Bedingungen an.
Kuckuck ist per Definition ein Pseudonymisierungs-Tool nach DSGVO Art. 4 Nr. 5. Pseudonymisierte Daten bleiben personenbezogene Daten, solange die Zuordnung wiederherstellbar ist. Damit der pseudonymisierte Output als anonymisiert im Sinne von Erwägungsgrund 26 gelten kann, müssen alle drei folgenden Punkte erfüllt sein:
- Alle Kopien des Keys sind zerstört - im Passwort-Manager, in allen Backups, in allen Teammitglieder-Kopien, in allen CI-Caches. Solange irgendwo eine Kopie existiert, bleibt die Rückführung möglich und der Output bleibt pseudonymisiert, nicht anonymisiert.
- Alle Kopien des Mappings sind zerstört - oder zumindest alle Kopien der Originaldokumente, aus denen die Mappings rekonstruiert werden könnten. Wer die Original-E-Mail noch hat, kann per re-Pseudonymisierung die Zuordnung rekonstruieren.
- Kontextuelle Re-Identifikation ist praktisch nicht möglich - der pseudonymisierte Text enthält keine Kombinationen aus Rolle, Ort, Datum, Projektnamen, die eine Einzelperson eindeutig identifizieren. Kurze, generische Texte sind hier sicherer als lange, kontextreiche.
Nur wenn alle drei Bedingungen zusammen erfüllt sind, ist der verbleibende Text nach DSGVO-Maßstab anonymisiert. In der Praxis ist Bedingung 3 die schwierigste: „der Geschäftsführer eines mittelständischen Bäckereibetriebs in 49716 Meppen" ist nach Weggabe des Keys zwar ohne Mapping nicht mehr über den Token rückführbar, aber weiterhin einer realen Person zuordenbar.
Kurz: Den Key wegzuwerfen reicht in den meisten realistischen Szenarien nicht aus, um aus Pseudonymisierung eine Anonymisierung zu machen. Behandle den pseudonymisierten Output deshalb weiterhin als personenbezogenes Datum, bis dein DSB für dein konkretes Szenario etwas anderes feststellt.
| Entitätstyp | Erkennung |
|---|---|
| E-Mail-Adressen | Regex + email-validator für Vetting |
| Telefonnummern | phonenumbers (Default-Region: DE) |
| Jira-/Confluence-Handles | Regex - @user.name, [~accountid:...], [~user] |
| Denylist-Einträge | Kunden-/Projektnamen aus einer Datei |
| Personen-Namen | Optional via GLiNER (urchade/gliner_multi-v2.1), Opt-in per --ner |
Die Regex-Detektoren decken die häufigsten Datenquellen (Mail-Signaturen, Jira-Reporter, Confluence-Mentions, API-Felder) ohne ML ab. Klarnamen ohne Handle werden erst beim Opt-in zum NER-Detektor erfasst.
# Library-Nutzung
pip install kuckuck
# Zusätzlich die CLI installieren
pip install "kuckuck[cli]"
# MCP-Server und MCP-Proxy
pip install "kuckuck[mcp]"
# CLI plus optionaler GLiNER-Personen-Detektor (zieht torch + gliner)
pip install "kuckuck[cli,ner]"Lade dir die plattformspezifische Binary von der Releases-Seite. Ein Binary pro Plattform - es enthält CLI, MCP-Server, MCP-Proxy und PERSON-Namen-Erkennung (NER) in einem:
| Plattform | Dateiname | Größe |
|---|---|---|
| Windows | kuckuck_windows_<ver>.exe |
~ 300 MB |
| macOS Apple Silicon | kuckuck_macos_arm64_<ver> |
~ 300 MB |
Das Binary startest du als CLI mit kuckuck <file>, als MCP-Server mit kuckuck mcp serve und als MCP-Proxy mit kuckuck mcp proxy - MCP-Clients (Claude Code, opencode, Claude Desktop) bekommen in der Config command: "kuckuck", args: ["mcp", "serve"].
Siehe integrations/mcp/README.md für die Setup-Anleitung pro Client.
Das NER-Modell selbst (~ 1.1 GB) wird einmalig via kuckuck fetch-model oder das kuckuck_fetch_model MCP-Tool nachgeladen.
Nach dem Download umbenennen (optional) und Quarantäne-Attribut entfernen:
# macOS
mv kuckuck_macos_arm64_v0.1.0 kuckuck
xattr -c kuckuck
chmod +x kuckuckKuckuck pseudonymisiert mit einem geheimen Master-Key, aus dem HMAC- und Verschlüsselungs-Subkeys abgeleitet werden. Lege ihn einmalig an:
kuckuck init-key # schreibt ~/.config/kuckuck/key (User-scoped)
kuckuck init-key --project # alternativ ein Key pro Projekt: ./.kuckuck-keyKopiere den Inhalt in euren Passwort-Manager (1Password, Bitwarden, …) und verteile ihn dort. Mit dem gleichen Key bekommt derselbe Name bei jedem Teammitglied denselben Token - ihr könnt pseudonymisierte Dokumente untereinander diskutieren.
- CLI-Flag
--key-file PATH - Env-Var
KUCKUCK_KEY_FILE(auch aus.env) $PWD/.kuckuck-key~/.config/kuckuck/key
Key-Datei und Mapping-Sidecar dürfen niemals in ein Repo committet werden.
Füge diese Zeilen in deine .gitignore ein:
# Kuckuck - Schlüssel und verschlüsseltes Mapping (nie committen!)
.kuckuck-key
*.kuckuck-key
*.kuckuck-map.enc
# Optional: pseudonymisierte Dateien, wenn du nur das Original im Repo willst
*.pseudonymized.**.kuckuck-map.enc ist zwar AES-GCM-verschlüsselt, ein Commit ins Repo würde aber den Blast-Radius eines versehentlich geleakten Keys massiv vergrößern - besser gar nicht erst committen.
Der häufigste Einsatz: ein LLM-Client (Claude Code, Cursor, Claude Desktop, opencode, …) soll personenbezogene Daten nie im Klartext zu sehen bekommen. Je nach Quelle der Daten gibt es zwei Hauptwege - den MCP-Proxy für Daten, die aus anderen MCP-Servern kommen, und den MCP-Server für Dateien in deinem Workspace - plus einen Hook und eine reine Konventions-Ebene als Fallback.
| Stufe | Mechanismus | Client-Support | Wann sinnvoll |
|---|---|---|---|
| 1 | Konvention via AGENTS.md / CLAUDE.md |
alle | Minimal-Setup, wenn nichts weiter geht |
| 2 | Claude-Code-Hook (dieses Repo) | nur Claude Code | Defense-in-Depth: blockt Read(*.eml) auch ohne MCP |
| 3 | MCP-Server (dieses Repo) | Claude Code, Cursor, Cline, Zed, opencode, Claude Desktop | Dateien aktiv über kuckuck_pseudonymize pseudonymisieren |
| 4 | MCP-Proxy (dieses Repo) | jeder MCP-Client | PII aus fremden MCP-Servern pseudonymisieren, bevor sie das LLM erreichen |
Wenn du einen MCP-Server benutzt, der selbst personenbezogene Daten zurückgibt - z. B. ein Jira-MCP oder ein hausinterner Server, der eine Kunden-REST-API kapselt - dann willst du diese Daten pseudonymisieren, bevor sie überhaupt beim LLM ankommen. Genau das macht der MCP-Proxy: er legt sich als Wrapper vor den fremden Server und schreibt jede Antwort um.
sequenceDiagram
actor LLM as LLM-Client<br/>(Claude, ...)
participant Proxy as Kuckuck-Proxy<br/>(Middleware)
participant Map as Mapping-Sidecar<br/>(verschlüsselt)
participant MCP as Fremder MCP-Server<br/>(Jira, Kunden-API)
Note over LLM,MCP: Antwort: Backend -> Modell (immer pseudonymisiert)
LLM->>Proxy: tools/call get_customer
Proxy->>MCP: unveränderte Anfrage weiterleiten
MCP-->>Proxy: { email: "max@firma.de" }
Proxy->>Map: Original speichern, Token vergeben
Proxy-->>LLM: { email: "[[EMAIL_a7f3]]" }
Note over LLM,MCP: Anfrage: Modell -> Backend (Restore nur mit --trusted)
LLM->>Proxy: tools/call notify(to: "[[EMAIL_a7f3]]")
Proxy->>Map: Token -> Original (nur trusted backend)
Proxy->>MCP: notify(to: "max@firma.de")
MCP-->>Proxy: ok
Proxy-->>LLM: ok (Antwort wieder pseudonymisiert)
Der Master-Key und der Mapping-Sidecar bleiben lokal - im Modell-Kontext landen nur Token.
# einen einzelnen Backend-Server (HTTP/SSE-URL oder lokales Server-Script) wrappen
kuckuck mcp proxy --backend https://jira.example/mcp --sidecar ./team.kuckuck-map.enc
# stdio- oder Multi-Server-Backends via MCPConfig-JSON (mcpServers-Objekt)
kuckuck mcp proxy --config ./backend.mcp.json --sidecar ./team.kuckuck-map.encIm MCP-Client trägst du dann den Proxy statt des Original-Servers ein (command: "kuckuck", args: ["mcp", "proxy", "--backend", "..."]).
Zwei Richtungen:
- Antwort (Backend -> Modell): PII in Tool-Ergebnissen und in Resource-Inhalten wird zu Token (
[[EMAIL_...]],[[PERSON_...]], ...), bevor das Modell sie sieht. Das ist die Kern-Garantie - im Modell-Kontext landet kein Klartext. (Resources sind wichtig, weil Jira-/Confluence-MCP-Server ihre Inhalte oft als Resource statt als Tool-Result ausliefern.) - Anfrage (Modell -> Backend): Nur mit
--trustedwerden Token, die das Modell in Tool-Argumenten mitschickt, vor dem Weiterreichen wieder zu echtem Klartext aufgelöst. Damit kann das Modell auf echten Datensätzen handeln (ein Jira-Kommentar schreiben, einen Datensatz aktualisieren), ohne die PII je gesehen zu haben.
Prompts (on_get_prompt) werden bewusst nicht pseudonymisiert - ein Prompt-Template ist autoren-kontrolliert und trägt erwartungsgemäß kein Kunden-PII.
Binär-Inhalte (Bild/Audio/Blob) haben keinen erkennbaren Text.
Ja - der Proxy reicht die Signatur des Original-Servers unverändert durch (create_proxy exponiert dieselben Tool- und Output-Schemata), und die Pseudonymisierung ersetzt nur String-Werte durch String-Token.
Die JSON-Struktur, Feldnamen und Nicht-String-Typen (int, bool, verschachtelte Objekte) bleiben exakt erhalten, sodass die Antwort weiterhin demselben Schema genügt.
Ein streng typisiertes pydantic-Model als Return-Type funktioniert also weiter; nur der String-Inhalt eines Feldes wird zum Token.
Eine Einschränkung gibt es bei String-Feldern mit einem Wert-Constraint (z. B. EmailStr, also format: email, oder ein pattern):
ein Token wie [[EMAIL_a7f3]] ist kein gültiger Wert für format: email.
Das Token wird trotzdem ausgeliefert (kein Leak, kein Tool-Crash), aber ein Client, der das structured_content strikt gegen das Schema in das typisierte Model zurückparst, bekommt für dieses Feld kein Objekt (.data bleibt leer).
Das ist prinzipbedingt - man kann eine E-Mail nicht gleichzeitig verbergen und format: email erfüllen.
--trustedschickt echtes PII an das Backend. Setze es nur für lokale / vertrauenswürdige Server - niemals für ein Backend, das selbst wieder in eine Cloud schreibt. Ohne--trustedbekommt das Backend das Token wörtlich, nicht den Klartext.
Default ist fail-closed: scheitert die Pseudonymisierung einer Antwort, wird der Tool-Call blockiert statt Klartext durchzulassen (Notausgang KUCKUCK_PROXY_FAIL_OPEN=1 bzw. --fail-open, dokumentiert UNSICHER).
Das Token-Mapping teilt sich der Proxy über den verschlüsselten --sidecar mit dem datei-basierten CLI - dieselben Token, stabil über Neustarts und kompatibel mit kuckuck restore.
Stand heute wrappt der Proxy einen einzelnen Backend-Server mit einer Trust-Einstellung; per-Backend-Trust über eine Multi-Server-Config ist ein Folge-Issue.
Kuckuck kann sich als Model Context Protocol Server registrieren.
Damit ruft der Assistent kuckuck_pseudonymize und kuckuck_restore als native MCP-Tools auf, ohne pro-Client-Hook und ohne dass du dich auf AGENTS.md-Konventionen verlassen musst.
pip install "kuckuck[mcp]"
# danach den MCP-Server in deinem Client eintragenSetup-Anleitungen für Claude Code, opencode und Claude Desktop: siehe integrations/mcp/README.md.
Beispiel-Configs liegen daneben.
Zusätzlich zum MCP-Server kann Claude Code einen PreToolUse-Hook aufrufen, der Read, Edit und Grep auf *.eml/*.msg-Dateien abfängt und sie vorher durch Kuckuck schickt.
Der Hook ist Defense-in-Depth: auch wenn das Modell vergisst, das kuckuck_pseudonymize MCP-Tool aufzurufen, landet kein Klartext-PII im Claude-Kontext.
pip install "kuckuck[cli]"
apt install jq # bzw. 'brew install jq', 'winget install jqlang.jq'
kuckuck install-claude-hookDas CLI-Kommando legt das Shell-Script (oder .ps1 unter Windows) unter .claude/hooks/kuckuck-pseudo.sh ab und merged den Hook-Eintrag idempotent in .claude/settings.json.
Setup, Fail-Closed-Semantik und Troubleshooting: siehe integrations/claude-code/README.md.
Füge folgenden Abschnitt in deine AGENTS.md oder CLAUDE.md ein:
## PII-Schutz für E-Mails, Tickets und Wiki-Exporte
Dateien mit personenbezogenen Daten (E-Mails, exportierte Jira-Tickets, Confluence-Seiten, Chat-Logs) dürfen **nicht im Original** gelesen oder an externe Modelle gesendet werden.
Vor der Analyse immer durch Kuckuck pseudonymisieren:
```bash
kuckuck <file> # ersetzt die Datei in-place
kuckuck restore <file> # Original wiederherstellen, nachdem die
# Analyse abgeschlossen ist
```
Erkennung:
- `[[EMAIL_...]]` - E-Mail-Adresse
- `[[PHONE_...]]` - Telefonnummer
- `[[HANDLE_...]]` - Jira-/Confluence-Mention
- `[[TERM_...]]` - Eintrag aus `denylist.txt` (Kunden/Projekte)
- `[[PERSON_...]]` - Personenname (nur mit `kuckuck --ner`, vorher `kuckuck fetch-model` einmalig)
Eingabeformate, die Kuckuck strukturiert erkennt:
- `.eml` (E-Mail mit Headern + Body, Signatur-Trigger werden separiert)
- `.msg` (Outlook, HTML > RTF > Plain Body, Anhänge bleiben aussen vor)
- `.md` (Markdown, Code-Blocks und YAML-Frontmatter bleiben unangetastet)
- `.xml` / `.html` (Tag-Struktur bleibt, Text und Attribute gehen durch)
- alles andere als Plain-Text
Gleiche Namen bekommen den gleichen Token, auch dokumentübergreifend.
Du (Assistent) darfst bei der Analyse annehmen, dass `[[HANDLE_abc]]` mit gleichem Suffix in mehreren Dokumenten dieselbe Entität ist - ohne den Klartext zu benötigen.
Regeln:
1. Vor dem ersten Read einer `.eml` / `.msg` / exportierten Jira-/Confluence-Datei: `kuckuck <file>` aufrufen.
2. In Commits niemals die `*.kuckuck-map.enc`-Dateien oder `.kuckuck-key` mit-committen (sind in `.gitignore`).
3. Tokens in deinen Antworten **nicht** auflösen - der Nutzer führt den Restore-Schritt lokal aus.Wenn du pseudonymisierten Text per API an Claude, GPT oder Gemini schickst, ergänze deinen System-Prompt:
Im Benutzertext erscheinen Platzhalter der Form
[[TYP_hash]], z.B.[[EMAIL_a7f3b2c1]]oder[[HANDLE_b1e2c3d4]]. Diese Token sind pseudonymisierte personenbezogene Daten. Übernimm sie wörtlich und unverändert in deine Antwort. Flektiere sie nicht (kein Genitiv-s anhängen, keine Kleinschreibung, keine Umbenennung). Gleiche Token-IDs im gesamten Text beziehen sich auf dieselbe Entität.
Für Dateien im Terminal: derselbe Master-Key, dasselbe Token-Mapping wie beim MCP-Proxy.
kuckuck brief.txt
# -> brief.txt enthält jetzt [[EMAIL_a7f3b2c1]] statt max@firma.de
# -> brief.txt.kuckuck-map.enc liegt daneben (verschlüsseltes Mapping)
kuckuck restore brief.txt # Rückführung nach dem LLM-Roundtrip
kuckuck docs/*.md # Batch
kuckuck brief.txt --output-dir out/ # Original behalten
kuckuck brief.txt --dry-run # Vorschau, nichts schreibenMit Denylist für Kunden-/Projektnamen und NER-Detektor für Personennamen:
kuckuck brief.txt --denylist denylist.txt # eine Zeile pro Eintrag, # = Kommentar
# NER einmalig vorbereiten (zieht torch, lädt ~ 1.1 GB ins ~/.cache/kuckuck/models/)
pip install "kuckuck[ner]"
kuckuck fetch-model
kuckuck brief.txt --ner # "Max Mustermann" -> [[PERSON_a7f3b2c1]]Der NER-Detektor läuft nur mit --ner, damit die Default-Pipeline kein torch laden muss.
Ohne kuckuck[ner]-Extra oder lokales Modell beendet sich kuckuck --ner mit Exit-Code 7 und einem Hinweis.
sequenceDiagram
actor User
participant Kuckuck
participant Mapping as Mapping-Sidecar<br/>(verschlüsselt)
participant LLM as Cloud-LLM<br/>(Claude, GPT, ...)
User->>Kuckuck: kuckuck brief.eml (mit max@firma.de, Anna)
Kuckuck->>Mapping: speichert Originale,<br/>vergibt Token
Kuckuck-->>User: brief.eml mit [[EMAIL_...]], [[PERSON_...]]
User->>LLM: pseudonymisierten Text
LLM-->>User: Antwort mit den gleichen Token
User->>Kuckuck: kuckuck restore brief.eml
Kuckuck->>Mapping: liest Originale
Kuckuck-->>User: Antwort mit echten Namen
Kuckuck wählt das Format automatisch über die Datei-Endung (--format setzt es explizit) und lässt strukturelle Teile in Ruhe:
| Format | Endung | Was bleibt unangetastet |
|---|---|---|
| Plain Text | alles ohne Match | - (ganzer Inhalt geht durch) |
.eml |
Header; nur der Body wird verarbeitet | |
| Outlook | .msg |
Anhänge (Body: HTML > RTF > Plain, kein byte-faithful Round-Trip) |
| Markdown | .md / .markdown |
YAML-Frontmatter, Code-Blocks, Inline-Code |
| XML / HTML | .xml / .html |
Tag-Struktur, Namespaces, CDATA |
kuckuck mail.eml --format eml # --format nur nötig, wenn die Endung nicht passt
kuckuck brief.txt --sequential-tokens # [[EMAIL_1]], [[EMAIL_2]] pro Dokument (nicht cross-doc-stabil)
kuckuck inspect brief.txt.kuckuck-map.enc # Mapping als Klartext dumpen (Debugging)Alle Subkommandos:
kuckuck <file>... Pseudonymisieren (Default)
kuckuck run <file>... Explizit (identisch zur Default-Form), nimmt --ner
kuckuck restore <file>... Mapping anwenden, Original wiederherstellen
kuckuck mcp serve MCP-Server starten
kuckuck mcp proxy Pseudonymisierenden MCP-Proxy vor einen anderen Server starten
kuckuck init-key Neuen Master-Key generieren
kuckuck fetch-model GLiNER-Modell laden (nur mit kuckuck[ner])
kuckuck install-claude-hook Claude-Code-PreToolUse-Hook installieren
kuckuck inspect <map> Verschlüsseltes Mapping als Klartext dumpen
kuckuck list-detectors Alle registrierten Detektoren zeigen
kuckuck version Version ausgeben
Die Standalone-Binaries verhalten sich identisch zur pip-installierten CLI (./kuckuck_macos_arm64 init-key, .\kuckuck_windows.exe brief.txt, …).
from pathlib import Path
from kuckuck import (
Mapping,
build_default_detectors,
load_default_key,
load_mapping,
pseudonymize_text,
restore_text,
save_mapping,
)
key = load_default_key()
detectors = build_default_detectors(denylist=["Kunde Alpha GmbH"])
source = Path("brief.eml")
text = source.read_text(encoding="utf-8")
# Bei vorhandenem Mapping merge-reload, sonst leer starten
map_path = source.with_suffix(source.suffix + ".kuckuck-map.enc")
mapping = load_mapping(key, map_path) if map_path.is_file() else Mapping()
result = pseudonymize_text(text, key, detectors, mapping=mapping)
source.write_text(result.text, encoding="utf-8")
save_mapping(key, result.mapping, map_path)
# Später: restore
restored = restore_text(source.read_text(encoding="utf-8"), result.mapping)- Kontextuelle Re-Identifikation: „Der Geschäftsführer eines mittelständischen Bäckereibetriebs in 49716 Meppen" ist praktisch eindeutig - Kuckuck ersetzt Namen, nicht Kontexte. Kurze Texte sind sicherer als lange.
- Seltene Namen / Initialen: Die Regex-Pipeline kennt keine Namen.
Klarnamen ohne Handle landen nur dann im Mapping, wenn der NER-Detektor (
--ner) aktiviert ist - GLiNER ist multilingual und auf deutsche Personennamen vortrainiert, hat aber bei sehr kurzen oder seltenen Vornamen Recall-Lücken. - Formate: Plain-Text plus format-aware Verarbeitung für
.eml,.msg, Markdown und XML/HTML (siehe Tabelle oben). Outlook-.msg-Dateien geben keinen byte-faithful Round-Trip zurück - nur den pseudonymisierten Body als Plain-Text, weil das compound-document Re-Roundtrippen nicht das Ziel ist. Anhänge in.msgwerden nicht angefasst. - Linkage-Risiko: Durch die Cross-Document-Konsistenz kann ein Cloud-LLM-Provider - wenn er Logs speichert - Tokens über Sessions verketten. Für Anthropic/OpenAI B2B mit ausgeschalteter Trainings-Nutzung in der Praxis irrelevant, im eigenen Compliance-Kontext aber evaluieren.
Das Repo folgt dem Hochfrequenz-Python-Template. Tox orchestriert alle Entwickler-Workflows:
tox -e dev # komplettes Dev-Environment erzeugen
tox -e tests # Unit- und Integrationstests (pytest + syrupy + hypothesis)
tox -e snapshots # Snapshots regenerieren (--snapshot-update)
tox -e linting # pylint (10/10 nötig)
tox -e type_check # mypy --strict
tox -e coverage # Coverage-Report (>= 80 %)
tox -e build_executable # PyInstaller Windows/Linux
tox -e build_executable_macos # PyInstaller macOS + ad-hoc codesignDie Dev-Environment-Einrichtung und PyCharm/VS-Code-Integration sind im Template-README dokumentiert.
MIT - siehe das LICENSE-File bei Inklusion im Release.