Wie mein Vault lernte, sich zu erinnern
In Teil 1 habe ich erzählt, wie der Vault entstanden ist: woher die Ideen kommen (Karpathy, Cole Medin, Julian Ivanov), wie ich ChatGPT als Vorarbeit genutzt habe, und wie am Ende von Tag eins ein solides Obsidian-Vault stand — mit Struktur, Kontext-Profil und importierten Chats. Was noch fehlte: ein Gedächtnis. Jede Session begann bei Null.
Jetzt wird es technisch. Nicht als Tutorial zum Abtippen, sondern als ehrlicher Blick unter die Haube: Was passiert bei jeder Session? Wie wird aus einem KI-Gespräch ein Wissensartikel der bei der nächsten Session automatisch zur Verfügung steht? Und wo habe ich Designentscheidungen getroffen, die man auch anders hätte treffen können?
Um Coles Implementierung in meinen Vault zu integrieren, musste ich zuerst verstehen wie sie funktioniert. Die wichtigste Erkenntnis: Das ganze System basiert auf drei automatischen Auslösern — sogenannten Hooks — die bei bestimmten Ereignissen in Claude Code feuern. Kein manuelles Starten, kein Cron-Job. Einfach Hooks, die im Hintergrund laufen.
Die drei Hooks
Was sind Hooks? In Claude Code sind Hooks kleine Scripts, die automatisch bei bestimmten Ereignissen ausgeführt werden — ähnlich wie Git-Hooks, die beim Commit oder Push feuern. Man konfiguriert sie in der Datei
.claude/settings.jsonund gibt dort an: Bei welchem Ereignis soll welches Script laufen? Claude Code kennt mehrere Hook-Zeitpunkte: wenn eine Session startet, wenn sie endet, und wenn der Kontext komprimiert wird. Die Scripts selbst können beliebige Dinge tun — Dateien lesen, Prozesse starten, Daten injizieren.
Das Herz meines Systems sind drei solche Hooks, die bei jeder Claude-Session im Hintergrund mitlaufen. Ich merke nichts davon — sie brauchen keine Eingabe von mir und zeigen keine Ausgabe. Aber sie sorgen dafür, dass keine Session-Erkenntnis verloren geht.
1. SessionStart: Der Wecker
Wenn eine neue Claude-Session startet, passieren zwei Dinge:
Kontext-Injektion: Der Hook liest den Knowledge-Base-Index — eine Markdown-Tabelle mit allen bisher kompilierten Wissensartikeln — und die letzte Daily Note. Beides wird als zusätzlicher Kontext in die Session injiziert, sodass Claude von Anfang an weiß, was in vergangenen Sessions passiert ist. Das ist der Moment, in dem die KI aufhört bei Null zu starten.
Compilation-Check: Gleichzeitig prüft der Hook, ob es Daily Notes gibt die noch nicht in Wissensartikel umgewandelt wurden — oder die sich seit der letzten Kompilierung verändert haben. Falls ja, startet er den Compiler im Hintergrund. Das ist eine bewusste Design-Entscheidung: Ursprünglich war die Kompilierung an eine feste Uhrzeit gebunden (18:00). Das Problem dabei ist offensichtlich — wenn der Rechner um 18:00 aus ist, passiert nichts. Jetzt wird bei jedem Session-Start nachgeholt, was offen ist.
def has_uncompiled_logs() -> bool:
for log_path in sorted(DAILY_DIR.glob("*.md")):
name = log_path.name
if name not in ingested:
return True # never compiled
stored_hash = ingested[name].get("hash", "")
current_hash = hashlib.sha256(log_path.read_bytes()).hexdigest()[:16]
if stored_hash != current_hash:
return True # changed since last compile
return False
Technisch sind das einfache Hash-Vergleiche — der Hook selbst braucht unter einer Sekunde, weil er keine API-Calls macht, sondern nur lokale Dateien liest.
2. SessionEnd: Das Gedächtnis
Wenn eine Session endet, passiert der eigentlich spannende Teil: Der Hook liest das Transkript der Konversation (Claude Code legt automatisch eine JSONL-Datei mit allen Turns an), extrahiert die letzten 30 Gesprächsrunden und schreibt sie in eine temporäre Datei. Dann startet er flush.py als eigenständigen Hintergrundprozess und beendet sich selbst.
Warum als Hintergrundprozess? Weil Hooks in Claude Code ein Timeout von 10 Sekunden haben. Die eigentliche Wissensextraktion braucht aber einen LLM-Call, und der dauert länger. Die Lösung ist ein elegantes Muster: Der Hook macht die schnelle Vorarbeit (Transkript lesen, Kontext extrahieren), startet den langsamen Prozess als eigenständige Instanz, und stirbt dann. flush.py läuft danach unabhängig weiter — selbst wenn Claude Code sich in der Zwischenzeit schon beendet hat.
subprocess.Popen(
cmd,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
start_new_session=True, # überlebt den Parent-Prozess
)
3. PreCompact: Das Sicherheitsnetz
Dieser Hook ist in der Praxis der wichtigste — obwohl er am wenigsten spektakulär klingt. Um zu verstehen warum, muss man wissen wie Claude Code mit langen Gesprächen umgeht: Es gibt ein begrenztes Kontextfenster, und wenn das voll wird, komprimiert Claude automatisch — ältere Teile des Gesprächs werden zusammengefasst und die Details gehen dabei verloren.
Der PreCompact-Hook feuert bevor diese Komprimierung passiert. Er macht genau das Gleiche wie der SessionEnd-Hook: Kontext extrahieren und flush.py im Hintergrund starten. So gehen auch bei langen Sessions, die mehrfach komprimiert werden, keine Erkenntnisse verloren.
Warum sage ich, das ist der wichtigere Hook? SessionEnd feuert einmal am Ende der Session. PreCompact feuert bei langen Sessions dagegen mehrfach zwischendurch — jedes Mal wenn das Kontextfenster voll wird. Bei Sessions die zwei Stunden dauern und drei Komprimierungen durchlaufen, ist PreCompact der Unterschied zwischen „alles erfasst“ und „die erste Stunde ist weg“.
flush.py: Der Extraktor
flush.py ist der eigentliche Denker im System. Es liest den Konversationskontext, den der Hook vorbereitet hat, und ruft das Claude Agent SDK auf — eine Python-Bibliothek, mit der man Claude programmatisch aufrufen kann, ohne das Chatfenster zu brauchen. Der Prompt ist bewusst präzise gehalten:
„Review the conversation context. Extract decisions made, lessons learned, key exchanges, and action items. Skip anything trivial.“
Die KI entscheidet dabei selbst, was es wert ist gespeichert zu werden. Das ist ein wichtiger Punkt: Es gibt keine starren Regeln, was „wichtig“ ist. Wenn eine Session nur aus „erstelle mir eine Datei“ und „fertig“ bestand, kommt FLUSH_OK zurück — nichts zu speichern. Wenn eine Session dagegen eine Architekturentscheidung enthielt, ein Debugging-Abenteuer oder eine unerwartete Erkenntnis, wird genau das extrahiert und in die Daily Note geschrieben.
So sieht das Ergebnis in der Praxis aus:
### Session Memory (14:30)
**Context:** Vault Knowledge Base System aufgebaut
**Decisions Made:**
- Karpathy + Cole's Memory Compiler adaptiert statt eigenes System
- Knowledge Base lebt in 04 Ressourcen/ (sichtbar im Vault)
- SessionStart statt Uhrzeit als Compilation-Trigger
**Lessons Learned:**
- SessionEnd-Hook feuert nicht zuverlässig beim Tab-Schließen
- PreCompact ist das wichtigere Sicherheitsnetz
- Python 3.9 zu alt für claude-agent-sdk, uv managed 3.12 automatisch
**Action Items:**
- [ ] System testen: Session schließen, neu öffnen, flush.log prüfen
Die Extraktion läuft schnell und verbraucht wenig Ressourcen, weil der Kontext kompakt ist und die Antwort kurz sein soll.
compile.py: Der Compiler
Wenn die Extraktion (flush.py) das Kurzzeitgedächtnis ist, dann ist die Kompilierung das Langzeitgedächtnis. compile.py nimmt eine Daily Note und verwandelt sie in vernetzte Wissensartikel, die dauerhaft in der Knowledge Base leben.
Dafür liest der Compiler die Daily Note zusammen mit dem aktuellen Knowledge-Base-Index, allen existierenden Artikeln und einem Schema, das die Struktur vorgibt. Dann instruiert er Claude:
„Lies diesen Daily Log. Extrahiere 3-7 Konzepte die einen eigenen Artikel verdienen. Aktualisiere existierende Artikel. Erstelle Querverbindungen. Aktualisiere den Index.“
Das Besondere: Claude bekommt für diesen Prozess Schreibrechte auf den Vault — es kann Dateien lesen, erstellen und bearbeiten. Es schreibt direkt Markdown-Dateien mit YAML-Frontmatter, Wikilinks zu verwandten Konzepten und Quellenverweisen zurück zur ursprünglichen Daily Note.
Ein konkretes Beispiel macht das greifbar: Aus meiner Daily Note vom 14.03.2025, die nur drei Tool-Namen enthielt (Traefik, Caddy, Nginx) und ein paar Stichpunkte dazu, hat der Compiler vier Artikel erstellt:
– concepts/traefik.md — Container-native Service Discovery
– concepts/caddy.md — Automatisches HTTPS
– concepts/nginx.md — Klassischer Reverse Proxy
– connections/traefik-caddy-nginx-vergleich.md — Ein Entscheidungsrahmen mit Vergleichstabelle
Aus drei Stichworten wurden vier vernetzte Wissensartikel, die Claude bei der nächsten Session automatisch als Kontext hat. Das ist die Kompilierung in Aktion — und der Grund, warum das System mit jeder Session klüger wird statt bei Null zu starten.
Warum kein RAG?
Das ist die Frage die jeder stellt, der sich mit KI-Systemen auskennt: Warum keine Vektordatenbank, kein Embedding, keine semantische Suche? Das ist doch der Standard-Ansatz, wenn man einer KI eigenes Wissen geben will?
Die kurze Antwort: Weil es bei meinem Maßstab nicht nötig ist — und der einfache Ansatz besser funktioniert. Karpathys Erkenntnis, die ich nach eigener Erfahrung bestätigen kann:
Bei persönlichem Maßstab (50-500 Artikel) schlägt ein LLM mit strukturiertem Index die Vektor-Suche. Der LLM versteht was du wirklich fragst. Cosine Similarity findet nur ähnliche Wörter.
Mein Index hat aktuell 52 Einträge. Claude liest den kompletten Index beim Session-Start — das sind vielleicht 3.000 Tokens, ein Bruchteil des verfügbaren Kontextfensters. Wenn ich frage „Wie war das mit dem SSH-Problem bei MCP?“, findet Claude den richtigen Artikel nicht über Vektor-Ähnlichkeit, sondern weil es den Index liest und versteht was ich meine. Das ist ein fundamentaler Unterschied: Verständnis statt Wortabgleich.
Natürlich wird das bei 2.000+ Artikeln irgendwann nicht mehr skalieren — dann braucht man eine Suchschicht. Aber bei 52 Artikeln, und selbst bei 500, passt der Index komplett ins Kontextfenster. Und das bedeutet: Kein Setup, keine zusätzlichen Dependencies, keine Infrastruktur-Wartung. Nur Markdown und ein Index.
Die Adaptation: Von Cole zum Vault
Coles System war als eigenständiges Projekt konzipiert — mit eigenen Verzeichnissen für Daily Logs, Knowledge-Artikel und Scripts. Wenn ich das einfach so übernommen hätte, wären es zwei getrennte Welten gewesen: meine Obsidian-Notizen in einem Vault und das Gedächtnis in einem separaten Ordner daneben. Doppelte Strukturen, keine Vernetzung — genau das was ich vermeiden wollte.
Die Adaptation war deshalb der kritische Schritt. Im Kern ging es darum, Coles Verzeichnisse auf meine bestehende Vault-Struktur abzubilden:
| Original (Cole) | Adaptation (Vault) | Warum |
|---|---|---|
daily/ | 05 Daily Notes/ | Nutzt bestehende Daily Notes statt eigene |
knowledge/ | 04 Ressourcen/Knowledge Base/ | Lebt im Vault, sichtbar in Obsidian |
scripts/ | .claude/kb-scripts/ | Unsichtbar, neben den anderen Claude-Skills |
hooks/ | .claude/kb-hooks/ | Eigener Ordner, saubere Trennung |
AGENTS.md | .claude/kb-schema.md | CLAUDE.md bleibt für Vault-Regeln |
| Timezone: Chicago | Timezone: Atlantic/Canary | Meine Zeitzone statt Illinois |
| Eigene Daily Logs | Append an bestehende Notes | Kein Überschreiben manueller Inhalte |
Die wichtigste Änderung in der ganzen Liste: flush.py erkennt ob eine Daily Note bereits existiert und hängt an statt zu überschreiben. Das klingt nach einem Detail, ist aber entscheidend — denn so können manuell geschriebene Notizen und automatische Session-Extrakte friedlich in der gleichen Datei koexistieren. Meine Daily Note ist eine Mischung aus dem, was ich selbst geschrieben habe, und dem, was das System automatisch extrahiert hat.
Die Grenzen
Kein System ist perfekt, und ich will hier ehrlich sein über die Stellen, die ich noch nicht gelöst habe:
1. Die Qualität hängt von der Qualität der Eingabe ab. Meine alten Daily Notes aus Logseq hatten manchmal nur einen einzigen Satz. Der Compiler hat trotzdem versucht, daraus einen Wissensartikel zu machen — mit entsprechend mäßigem Ergebnis. Das klassische Garbage-in-Garbage-out-Problem: Je reichhaltiger die Daily Notes sind, desto besser werden die kompilierten Artikel.
2. SessionEnd feuert nicht immer zuverlässig. In Claudian (dem Obsidian-Plugin) bin ich nicht sicher, ob der SessionEnd-Hook beim Schließen des Tabs zuverlässig feuert. PreCompact und SessionStart fangen das meiste auf — aber es gibt eine theoretische Lücke für kurze Sessions, die nie komprimiert werden und abrupt enden. In der Praxis ist mir dadurch noch nichts verloren gegangen, aber die Lücke existiert.
3. Die Knowledge Base ist für die KI geschrieben, nicht für mich. Die Artikel in der Knowledge Base sind lesbar, aber nicht schön — sie sind maschinenoptimiert. Kein Problem für den Anwendungsfall, aber es ist kein Zettelkasten den man gerne durchblättert. Im Moment nutze ich sie hauptsächlich, um zu prüfen ob das System korrekt arbeitet.
4. Keine Echtzeit-Aktualisierung. Die Kompilierung zu vernetzten Artikeln läuft beim nächsten Session-Start oder nach 18:00. Wenn ich um 10:00 etwas Wichtiges bespreche, ist es als Session-Extrakt sofort in der Daily Note verfügbar — aber der vernetzte Wissensartikel daraus existiert erst ab der nächsten Session.
Weiter in Teil 3
Das System erinnert sich jetzt. Aber es kann noch mehr — und der nächste Schritt war eine Erweiterung, die ich ursprünglich gar nicht geplant hatte. In Teil 3 zeige ich, wie der gleiche Flush-Prozess gleichzeitig bewertet, ob eine Session Content-Potenzial hat — und wenn ja, automatisch Ideen für Blog, LinkedIn, YouTube und Podcast in meinen Ideen-Backlog schreibt.
→ Teil 3: Die Content-Maschine — wenn dein Vault weiß was du erzählen solltest





