JSONL (JSON Lines)
Kurz: Ein Dateiformat, bei dem jede Zeile für sich ein vollständiges, gültiges JSON-Objekt ist – anders als eine normale JSON-Datei, die als Ganzes ein einziges Objekt oder Array sein muss.
Genauer: Praktisch für Logs und Streams, weil man Zeile für Zeile lesen und schreiben kann, ohne die ganze Datei zu parsen, und weil sich neue Einträge einfach anhängen lassen.
Kontext bei uns: Claude Code speichert Session-Transkripte als JSONL (eine Zeile pro Ereignis: User-Nachricht, Assistant-Antwort, Tool-Aufruf, …) unter ~/.claude/projects/<projekt>/<session-id>.jsonl. Darauf griff der inzwischen wieder entfernte Stop-Hook zu.
Im Detail
Anhängen statt Neuschreiben
Der Vorteil von JSONL gegenüber einer einzelnen großen JSON-Datei zeigt sich besonders bei sehr langen oder wachsenden Datenströmen: Ein Log-Schreiber kann jede neue Zeile einfach ans Dateiende anhängen (fs.appendFile), ohne die komplette bisherige Datei einlesen, parsen, verändern und neu schreiben zu müssen — bei einer normalen JSON-Datei (die als Ganzes ein gültiges Array/Objekt sein muss) wäre das nötig, um z. B. ein neues Element ans Ende eines Arrays anzuhängen. Bei einer mehrere Gigabyte großen Log-Datei ist dieser Unterschied nicht nur unbequem, sondern praktisch relevant: Ein komplettes Neuschreiben bei jedem einzelnen neuen Eintrag wäre bei wachsender Dateigröße immer langsamer, während Anhängen konstant schnell bleibt, unabhängig von der bereits vorhandenen Dateigröße.
Zeilenweise Verarbeitung ohne vollständiges Laden
Zeilenweises Verarbeiten (statt alles auf einmal in den Speicher zu laden) ist ebenfalls einfacher:
const readline = require("readline");
const stream = readline.createInterface({ input: fs.createReadStream("session.jsonl") });
for await (const line of stream) {
const event = JSON.parse(line);
// ... Zeile für Zeile verarbeiten, ohne die ganze Datei im Speicher zu halten
}Das ist besonders wichtig bei Dateien, die größer als der verfügbare Arbeitsspeicher werden könnten — ein JSON.parse() einer gesamten mehrere Gigabyte großen Datei würde entweder sehr lange dauern oder direkt mit einem Speicherfehler abbrechen, während das zeilenweise Verarbeiten konstant wenig Speicher benötigt, unabhängig von der Gesamtgröße der Datei.
Fehlertoleranz
Ein Nachteil klassischer JSON-Dateien in diesem Kontext: Eine einzelne beschädigte Zeile (z. B. durch einen abgebrochenen Schreibvorgang, etwa weil der Prozess mitten im Schreiben abstürzte) lässt sich bei JSONL isoliert überspringen, ohne die ganze Datei unlesbar zu machen — bei einer klassischen JSON-Datei würde ein einziges kaputtes Zeichen irgendwo mitten drin das gesamte Parsen der Datei zum Scheitern bringen, selbst wenn 99% des Inhalts eigentlich intakt wären. Diese Eigenschaft macht JSONL besonders robust für Anwendungsfälle, bei denen Schreibvorgänge unterbrochen werden könnten (z. B. bei einem Systemabsturz oder abruptem Prozessende).
Verbreitete Einsatzgebiete
Neben Session-Transkripten wird JSONL häufig für Trainingsdaten im Machine-Learning-Bereich verwendet (jede Zeile ein Trainingsbeispiel), für Log-Aggregation (jede Zeile ein Log-Event, oft mit einheitlichen Feldern wie Zeitstempel und Log-Level) und für den Datenaustausch zwischen Systemen, bei denen Datensätze einzeln und unabhängig voneinander verarbeitet werden sollen — z. B. beim Streamen von Datenbank-Exports, wo jede Zeile einen einzelnen Datensatz repräsentiert.
Siehe auch: Claude Code Hooks, JSON