Spezifikation

Das Sidecar-Format von PaperPeace

Dieses Dokument beschreibt die Metadaten-Dateien, die PaperPeace in einem eigenen Ordner am Speicherort ablegt, getrennt von den Dokumenten, damit andere Programme, Skripte und Sprachmodelle sie lesen können. Es reicht aus, um eine Bibliothek zu lesen, ohne die App sonst zu kennen.

1. Was ein Sidecar ist

PaperPeace lässt die Originaldateien einer Bibliothek (PDFs, Bilder) unverändert in den eigenen Ordnern des Nutzers. Alles, was die App über ein Dokument weiß – Titel, Typ, Korrespondent, Schlagwörter, Status, Daten, Notiz –, steht in einer kleinen Markdown-Datei, dem Sidecar, in einem eigenen Ordner desselben Speicherorts. Zu jedem Dokument gibt es ein Sidecar. Es gibt keinen Server und keine Datenbank, die man fragen müsste: Die Sidecars sind die Metadaten.

Alle Sidecars sind reiner Text. Eine Bibliothek lässt sich mit grep, einem Texteditor oder einem Skript lesen.

2. Wo die Dateien liegen

Pfade gelten ab der Bibliothekswurzel, dem Ordner, den der Nutzer als Speicherort gewählt hat. Das Trennzeichen ist /.

<Bibliothekswurzel>/
  Rechnungen/2026/2026-03-14 Stromrechnung.pdf      das Original, in den Ordnern des Nutzers
  _Meta/
    Sidecars/
      6c2b0f7a-3e41-4b0e-9c55-2d9a1f0b7e33.md       das Sidecar
      6c2b0f7a-3e41-4b0e-9c55-2d9a1f0b7e33.ocr.json der erkannte Text (siehe Abschnitt 9)
      6c2b0f7a-3e41-4b0e-9c55-2d9a1f0b7e33.lock     intern, ignorieren
  _Deleted/
    6c2b0f7a-3e41-4b0e-9c55-2d9a1f0b7e33.pdf        ein Original, das der Nutzer in den Papierkorb gelegt hat
  • Alle Sidecars liegen in einem flachen Ordner, _Meta/Sidecars/. Nicht neben den Originalen und nicht in Unterordnern.
  • Der Dateiname eines Sidecars ist die Kennung des Dokuments plus .md. Die Kennung ist eine zufällige UUID in Kleinbuchstaben (zum Beispiel 6c2b0f7a-3e41-4b0e-9c55-2d9a1f0b7e33), die mit dem Dokument entsteht und sich nie ändert (nicht beim Umbenennen, Verschieben, Löschen oder Wiederherstellen). Sie hat keine Bedeutung, und man sortiert nicht nach ihr.
  • Das Kopffeld doc_id wiederholt die Kennung. Stimmen Dateiname und doc_id nicht überein, ist die Datei kein gültiges Sidecar und wird übergangen. Ein Dateiname mit Großbuchstaben ist ebenfalls kein Sidecar. Eine Kopie wie 6c2b0f7a-… (Konflikt).md, die ein Speicheranbieter anlegt, ist also kein zweites Dokument.
  • Eine .md-Datei an anderer Stelle, außerhalb von _Meta/Sidecars/, ist nie ein PaperPeace-Sidecar. Sie gehört dem Nutzer.
  • Welches Original zu einem Sidecar gehört: Das Kopffeld source_file enthält den Pfad des Originals ab der Bibliothekswurzel (Rechnungen/2026/2026-03-14 Stromrechnung.pdf). Ein Name ohne Ordner heißt: Das Original liegt in der Wurzel. Das ist die einzige Verbindung; Sidecars heißen nach der Kennung, nicht nach dem Original. Der Pfad ändert sich, wenn der Nutzer das Dokument umbenennt oder verschiebt, also immer aus dem aktuellen Sidecar lesen.
  • Papierkorb: Bei einem gelöschten Dokument steht das Feld deleted_at. Sein Original liegt dann unter _Deleted/<Kennung>.<Endung> (ohne Unterordner); das Sidecar bleibt, wo es ist. Ob ein Dokument gelöscht ist, sagt allein deleted_at, nicht der Ort des Originals.

3. Dateiformat

  • Kodierung: UTF-8, ohne Byte-Order-Mark. Eine Datei, die kein gültiges UTF-8 ist, lässt sich nicht lesen. Zeilen enden mit LF (\n); Leser sollten CRLF tolerieren.
  • Aufbau: ein Kopf (Frontmatter), danach ein Rumpf.
---
schlüssel: wert
schlüssel: wert
checksum: …
---

## Abschnitt

Text…
  • Die erste Zeile ist ---. Der Kopf reicht bis zur nächsten Zeile, die --- lautet. Alles danach ist der Rumpf. Fehlt eine der beiden Zeilen, lässt sich die Datei nicht lesen.
  • Jede Kopfzeile ist schlüssel: wert. Der Schlüssel ist alles vor dem ersten Doppelpunkt, der Wert alles danach, beide ohne Leerzeichen am Rand. Ein Doppelpunkt im Wert ist deshalb in Ordnung und wird nicht in Anführungszeichen gesetzt. Eine Zeile ohne Doppelpunkt wird übergangen. Steht ein Schlüssel zweimal, gilt die letzte Zeile.
  • Der Kopf ist flach: keine Verschachtelung, keine mehrzeiligen Werte, keine YAML-Funktionen. Er sieht aus wie YAML, wird aber nicht als YAML gelesen; ein YAML-Parser ist nicht geeignet (er machte etwa aus asn: 0042 oder einer 64-Bit-Zahl einen anderen Wert). Lies jeden Wert als Text und wandle ihn selbst um, wo du eine Zahl brauchst.
  • Ein Wert steht in einer Zeile. Schreibende entfernen aus jedem Wert Zeilenumbrüche und Steuerzeichen. Ein Wert darf leer sein (person:); ein leerer Wert und eine fehlende Zeile bedeuten dasselbe.
  • Listen stehen in eckigen Klammern, die Einträge durch Komma und Leerzeichen getrennt: tags: [Energie, Haushalt]. Listen sind nur tags, status, cases und Mehrfachauswahlen bei eigenen Feldern (Abschnitt 5). Ein Eintrag mit [, ], , oder " oder mit einem Leerzeichen am Anfang oder Ende steht in doppelten Anführungszeichen; darin steht \\ für einen Rückstrich, \" für ein Anführungszeichen und \n für einen Zeilenumbruch: tags: ["Haus, Hof", Steuer]. Leere Einträge entfallen.
  • Tage und Zeitpunkte stehen immer in UTC. Ein Tag ist JJJJ-MM-TT (2026-03-14). Ein Zeitpunkt ist Tag, ein T, die Uhrzeit, ein Z (2026-03-15T08:12:40Z). Ein Leser kann auf einen Sekundenbruchteil oder ein Leerzeichen statt T treffen und sollte beides annehmen.
  • Ja/Nein steht als true. Felder, die nur true sein können, fehlen sonst.
  • Reihenfolge: Schreibende geben die Schlüssel in dieser Reihenfolge aus: type, date, due_date, title, title_source, placement, placement_source, filing_rule, filing_rule_matched, correspondent, person, tags, status, cases, asn, reminder_date, reminder_note, deleted_at, archive_on, source_file, scanned_at, modified_at, version, edited_by, confirmed_by_user, file_hash, file_hash_basis, source_file_hash, text_simhash, original_filename, paperless_id, paperless_server, source, source_sender, source_subject, source_message_id, source_device, source_device_name, source_folder, analysis_state, done, password_protected, doc_id; dann die eigenen Felder field.<Kennung>, dann sync_vector, field_marks, dann die Schlüssel, die die App nicht kennt, und zuletzt checksum. Zeilen von Schlüsseln, zu denen es nichts zu sagen gibt, entfallen. Leser dürfen sich nicht auf die Reihenfolge verlassen.

4. Die Kopffelder

Um einen Kopf gegen das JSON Schema zu prüfen, wandelst du ihn zuerst in ein JSON-Objekt um: Jeder Wert ist ein String, außer tags, status und cases; sie sind Arrays von Strings. Ein eigenes Feld ist ein String; wer weiß, dass das Feld eine Mehrfachauswahl ist, darf einen Wert in eckigen Klammern wie in Abschnitt 3 zerlegen, und das Schema lässt beides zu.

„Immer“ heißt: Die App schreibt die Zeile in jedes Sidecar, gegebenenfalls mit leerem Wert. „Wenn gesetzt“ heißt: Die Zeile entfällt, wenn es nichts zu sagen gibt. Typen: Text ist eine Zeile; Tag und Zeitpunkt wie oben.

Inhalt, vom Nutzer oder von der Erkennung gesetzt

Schlüssel Typ Geschrieben Bedeutung
type Text immer Dokumenttyp, z. B. Rechnung.
date Tag immer Datum des Dokuments selbst (das Datum auf dem Brief).
due_date Tag wenn gesetzt Fälligkeit.
title Text immer Titel.
title_source Text immer Woher der Titel kommt: generated (aus der Vorlage), original (aus dem Dateinamen), custom (vom Nutzer eingegeben). Fehlt das Feld oder ist der Wert unbekannt: Herkunft des Titels unbekannt.
correspondent Text immer Absender oder Gegenüber, z. B. eine Firma. Ein Wert; ein Komma gehört zum Namen.
person Text immer Die Person, die das Dokument betrifft. Genau ein Wert; ein Komma gehört zum Namen (Müller, Anna).
tags Liste immer Schlagwörter.
status Liste immer Status, z. B. [Offen]. Der Verlauf steht im Rumpf (Abschnitt 6).
cases Liste wenn gesetzt Vorgänge: Namen, die zusammengehörige Dokumente bündeln, etwa Angebot, Lieferschein und Rechnung einer Bestellung. Ein Dokument kann zu mehreren gehören.
asn Text (Ziffern) wenn gesetzt Archivnummer, wie der Nutzer sie eingegeben hat.
reminder_date Zeitpunkt wenn gesetzt Wann erinnert wird.
reminder_note Text wenn gesetzt Text der Erinnerung.
done Ja/Nein nur true Abgehakt.
deleted_at Zeitpunkt wenn gelöscht Das Dokument liegt seit diesem Zeitpunkt im Papierkorb. Eine Zeile mit leerem Wert heißt: nicht gelöscht.
archive_on Tag wenn gesetzt Ab diesem Tag gilt das Dokument als archiviert (in den normalen Listen der App ausgeblendet). Am Stichtag wird nichts geschrieben; ob es archiviert ist, ergibt sich aus dem Datum.
field.<Kennung> Text oder Liste wenn gesetzt Eigene Felder, siehe Abschnitt 5.

Wo das Original liegt

Schlüssel Typ Geschrieben Bedeutung
source_file Text immer Pfad des Originals ab der Bibliothekswurzel (Abschnitt 2).
placement Text nur manual manual: Das Original bleibt, wo es ist, und wird nicht nach einer Regel einsortiert.
placement_source Text nur user user: Der Nutzer hat den Ort ausdrücklich festgelegt.
filing_rule Text wenn nicht die Standardregel Kennung der Ablageregel, nach der einsortiert wurde.
filing_rule_matched Text wenn die Bedingungen die Regel gewählt haben Dieselbe Kennung wie filing_rule, wenn die Regel durch ihre Bedingungen zugewiesen wurde und nicht von Hand.

Was die Erkennung weiß

Schlüssel Typ Geschrieben Bedeutung
analysis_state Text nach einer Analyse done oder failed. Fehlt die Zeile, ist kein Ergebnis bekannt. Der Wert pending kann in alten Dateien stehen und heißt dasselbe wie fehlend.
confirmed_by_user Ja/Nein immer (true/false) Ein Mensch hat die Werte geprüft.

Was die Originaldatei ausmacht

Schlüssel Typ Geschrieben Bedeutung
file_hash Text wenn bekannt SHA-256 des Originals, wie es jetzt liegt, kleingeschrieben hexadezimal.
source_file_hash Text wenn bekannt SHA-256 der Datei beim Import. Weicht von file_hash ab, wenn die App die Datei umgewandelt hat (ein Bild in ein PDF, ein PDF mit eingebetteter Textebene).
file_hash_basis Text nach neuen Bytes Zwei SHA-256-Werte, durch ein Leerzeichen getrennt: die neuen Bytes, dann die ersetzten.
text_simhash Text (Ziffern) wenn berechnet Fingerabdruck des Texts, um ähnliche Dokumente zu finden. Eine vorzeichenlose 64-Bit-Ganzzahl – als Text behandeln. 0 heißt: keiner.
original_filename Text wenn bekannt Dateiname beim Import.
password_protected Ja/Nein nur true Das Original ist kennwortgeschützt.

Woher das Dokument kam

Wird beim Import einmal geschrieben und nie geändert.

Schlüssel Typ Bedeutung
source Text Der Weg hinein: scan, photo, file, folder, share, shortcut, watched_folder, email, paperless, inbox, derived (aus anderen Dokumenten erstellt: zusammengeführt, aufgeteilt, ausgefüllt und unterschrieben, als neues Dokument gesichert). Ein unbekannter Wert gilt als fehlend.
source_device, source_device_name Text Kennung und Name (zu diesem Zeitpunkt) des importierenden Geräts.
source_folder Text Ganzer Pfad des Ordners, aus dem die Datei kam, wie ihn das importierende Gerät sah. Ein Pfad auf einem Gerät; auf einem anderen nicht auflösen.
source_sender, source_subject, source_message_id Text Absender, Betreff und Nachrichten-ID beim Import aus einer Mail.
paperless_id, paperless_server Text Kennung und Serveradresse beim Import aus paperless-ngx.

Verwaltung

Schlüssel Typ Geschrieben Bedeutung
doc_id Text (UUID) immer Die Kennung; gleich dem Dateinamen ohne .md.
scanned_at Zeitpunkt immer Seit wann das Dokument in der Bibliothek ist (Zeitpunkt des Imports).
modified_at Zeitpunkt immer Letzte Änderung durch den Nutzer. Automatische Arbeit (Erkennung, Verschieben einer Datei, Umbenennen eines Schlagworts für alle Dokumente) ändert ihn nicht.
version Text immer Fassung dieser Datei, eine ULID mit 26 Zeichen. Siehe Abschnitt 7.
edited_by Text immer Anzeigename des Geräts, das zuletzt geschrieben hat.
sync_vector, field_marks, checksum Text siehe Abschnitt 7 Buchführung für den Abgleich mehrerer Geräte. Nicht bearbeiten.

5. Eigene Felder

Nutzer können eigene Felder anlegen (zum Beispiel eine Vertragsnummer). Jeder Wert steht in einer Kopfzeile field.<Kennung>, hinter doc_id und vor sync_vector, nach <Kennung> Byte für Byte sortiert.

  • <Kennung> besteht aus ASCII-Buchstaben, Ziffern und _, höchstens 64 Zeichen; Groß und Klein sind verschieden. Sie ändert sich nie, auch wenn der Nutzer das Feld umbenennt. Der sichtbare Name und die Art des Felds stehen nicht im Sidecar (sie stehen in den Einstellungen der App); aus dem Sidecar allein ist also jeder Wert Text.
  • Werte stehen in einer festen, sprachunabhängigen Form: Text als eine Zeile; Zahl in der kürzesten Dezimalschreibweise (29.9, -1200, 0.05, kein Tausendertrenner, kein Exponent); Datum als JJJJ-MM-TT; Ja/Nein als true oder false; Einfachauswahl als gewählter Text; Mehrfachauswahl als Liste [A, B], nach Bytes sortiert. Ein leerer Wert wird nicht geschrieben.
  • Eine Zeile ist höchstens 1 KB lang, alle eigenen Felder zusammen höchstens 32 KB. Eine Zeile field.…, die diese Regeln verletzt, ist einfach ein unbekannter Schlüssel (Abschnitt 7).
  • Ein Wert, der nicht zu seinem Feld passt, gilt als Text und bleibt, wie er ist.

6. Die Abschnitte im Rumpf

Der Rumpf besteht aus Abschnitten, jeder beginnt mit einer Überschrift ## Name. In dieser Reihenfolge:

Überschrift Inhalt
## Status History Je Änderung eine Zeile, siehe unten.
## Note Die Notiz des Nutzers: freier Text über beliebig viele Zeilen. Das ist der einzige Teil eines Sidecars, der sich nicht aus der Originaldatei neu aufbauen lässt.
## OCR Text Nur in älteren Sidecars: der erkannte Text aus der Zeit, bevor er nach <Kennung>.ocr.json zog (Abschnitt 9). Gibt es beides, gilt die JSON-Datei.
## Summary Abgeschafft. Ignorieren.
  • Eine Zeile von ## Status History ist - <Zeitpunkt> | added | <Status> oder - <Zeitpunkt> | removed | <Status> (ein Bindestrich, ein Leerzeichen, dann drei Teile, getrennt durch |). Die App schreibt die neueste Zeile zuerst. Zwei gleiche Zeilen sind zwei Änderungen.
  • Ein Abschnitt, der leer wäre, entfällt.
  • Ein Abschnitt endet nur an einer der vier Überschriften oben. Jede andere Zeile ## … in einer Notiz ist einfach Text der Notiz (Nutzer schreiben solche Zeilen). Beginnt eine Zeile der Notiz selbst mit einer der vier Überschriften, rückt der Schreibende sie um ein Leerzeichen ein.
  • Hinter ## OCR Text beginnt jede weitere Zeile ## … einen eigenen Abschnitt. Ein solcher Abschnitt ist dir unbekannt und bleibt, wie er ist.
  • Text vor der ersten Überschrift bleibt ebenfalls, wie er ist.

7. Abgleichszeilen, Versionen und Unbekanntes

Mehrere Geräte arbeiten über den gemeinsamen Speicherordner an derselben Bibliothek. Vier Kopfzeilen sind die Buchführung, mit der sie ihre Arbeit zusammenführen. Ein Programm, das nur liest, kann sie ignorieren. Sie sind die eigene Buchführung der App; ändere sie nicht (Abschnitt 11).

  • version – eine ULID: 26 Zeichen aus dem Crockford-Alphabet (0-9A-HJKMNP-TV-Z), die ersten zehn kodieren den Entstehungszeitpunkt in Millisekunden, der Rest ist Zufall. Die App gibt jeder Änderung einen neuen, größeren Wert. Sie ist nicht die Version dieses Formats (siehe unten). Nach ihr werden Fassungen nicht sortiert.
  • sync_vector – @<version> <n>.<Zeitpunkt> <Gerät>=<Nummer>,…. Der Stempel hinter @ ist die version, mit der die Zeile geschrieben wurde; passt er nicht zur version der Datei, gilt die Zeile nicht (jemand hat die Datei ohne die App geändert). <n>.<Zeitpunkt> (zum Beispiel 7.2026-09-18T10:22:31.400Z) ist die Ordnung der Fassung: ein Zähler und der UTC-Zeitpunkt der Schreibung mit Millisekunden. Danach folgen Paare aus Gerätekennung und der Nummer der letzten Änderung dieses Geräts, die in der Datei enthalten ist.
  • field_marks – durch Komma getrennte Einträge Feld=Gerät:Nummer@Zeit, nach Feldname sortiert: welches Gerät welches Feld zuletzt geändert hat, in welcher seiner Änderungsnummern, und wann. Zeit sind Millisekunden seit 1970-01-01 UTC zur Basis 36, kleingeschrieben; sie kann fehlen. Listen tragen einen Eintrag je Wert: tags[Steuer]=18F00519:7@mu6t7tuw; % und , zwischen den Klammern stehen als %25 und %2C. Eigene Felder heißen field.<Kennung> bei einem Text und field.<Kennung>/<Wert> für jeden Wert einer Mehrfachauswahl.
  • checksum – die letzte Zeile des Kopfs. SHA-256, kleingeschrieben hexadezimal, über den vollständigen Dateitext, aus dem genau diese Zeile entfernt ist. Sie ist kein Schlüssel und unterschreibt nichts; sie zeigt nur, ob jemand die Datei ohne die App geändert hat. Eine fehlende Prüfsumme beweist nichts.

Es gibt keine Formatversion

Das Sidecar trägt keine Versionsnummer seines Formats, und es wird keine erfunden. Das Format wächst nur durch Ergänzungen: neue Kopfschlüssel und neue Rumpfabschnitte. Deshalb gilt:

  • Ein Leser übergeht Kopfschlüssel und Abschnitte, die er nicht kennt, und behandelt sie nicht als Fehler.
  • Ein Leser behandelt einen unbekannten Wert eines bekannten Felds (zum Beispiel ein neues source) wie einen fehlenden Wert.
  • Ein Schlüssel, den PaperPeace abgeschafft hat, bekommt nie eine neue Bedeutung. Alte Dateien können ihn noch enthalten; ignorieren: content_hash, ai_model, note, owner_device, ai_confidence, text_extractor_fingerprint, sync_conflicts.
  • Einen unbekannten Schlüssel, in welcher Datei auch immer, von einer neueren App oder einem anderen Programm geschrieben, bewahrt die App beim nächsten Schreiben auf – hinter den bekannten Schlüsseln, in der Reihenfolge der Zeilen, bis zu 8 KB insgesamt und 1 KB je Zeile.

8. Ein vollständiges Beispiel

So schreibt die App ein Sidecar (alle Namen sind erfunden). Die Zeile checksum stimmt für diesen Text.

---
type: Rechnung
date: 2026-03-14
due_date: 2026-04-01
title: Stromrechnung März
title_source: generated
correspondent: Stadtwerke Musterstadt
person: Anna Musterfrau
tags: [Energie, Haushalt]
status: [Offen]
cases: [Wohnung 2026]
asn: 1042
source_file: Rechnungen/2026/2026-03-14 Stromrechnung.pdf
scanned_at: 2026-03-14T18:01:52Z
modified_at: 2026-09-18T10:22:31Z
version: 01M2T0M1Z88Q4M7V1C9TXB5HNA
edited_by: iPhone von Anna
confirmed_by_user: true
file_hash: 9f2c61a4e5803b1d7a64c0e2b9d85f3a1c7e40b6d2a98f5e3b1c60d4a7e2f815
source_file_hash: 9f2c61a4e5803b1d7a64c0e2b9d85f3a1c7e40b6d2a98f5e3b1c60d4a7e2f815
text_simhash: 965656484482950027
original_filename: Scan 14.03.2026.pdf
source: scan
source_device: 7CCA58C8
source_device_name: iPhone von Anna
analysis_state: done
doc_id: 6c2b0f7a-3e41-4b0e-9c55-2d9a1f0b7e33
field.contractNumber: K-2026-0042
sync_vector: @01M2T0M1Z88Q4M7V1C9TXB5HNA 7.2026-09-18T10:22:31.400Z 18F00519=7,7CCA58C8=41,C463FDD2=13
field_marks: field.contractNumber=C463FDD2:13@mu6t7tuw,person=7CCA58C8:41@mu6t4mo8,tags[Energie]=7CCA58C8:40@mu6t4mo8,tags[Haushalt]=18F00519:7@mu6t4mo8,title=C463FDD2:13@mu6t7tuw
checksum: a3ae1998a8635b7d6b0d44f8a19a231d8f0c133f15cdf62f6380ddee2d8f1465
---

## Status History

- 2026-03-15T08:12:40Z | added | Offen

## Note

Abschlag ab April angepasst.
Widerspruch bis 30.04. einlegen.

9. Der erkannte Text

Der Text, den die App aus dem Original gelesen hat (OCR), steht in _Meta/Sidecars/<Kennung>.ocr.json, einer JSON-Datei neben dem Sidecar, nicht im Sidecar. Sie enthält die Textblöcke mit ihrer Position auf der Seite und der Sicherheit der Erkennung. Ein "source": "manual" auf oberster Ebene kennzeichnet einen Text, den der Nutzer von Hand eingegeben hat; "source": "firstPage" einen Text, der nur von der ersten Seite gelesen wurde. Der innere Aufbau dieser Datei ist hier nicht festgelegt; um den Text einer Bibliothek zu durchsuchen, lies die Dateien als JSON und übergehe unbekannte Eigenschaften. Ältere Sidecars können den Text stattdessen unter ## OCR Text tragen.

10. Lesen – immer sicher

Lesen schadet einer Bibliothek nie, und kein Lesen kann sie ändern. Ein einfacher Leser:

  1. _Meta/Sidecars/*.md auflisten. Der Dateiname ohne .md ist die Kennung.
  2. Die Datei als UTF-8 lesen. Prüfen, dass die erste Zeile --- ist, und das schließende --- suchen.
  3. Jede Kopfzeile am ersten Doppelpunkt teilen, von jedem Schlüssel den letzten Wert behalten, Zeilen ohne Doppelpunkt und unbekannte Schlüssel übergehen.
  4. Listen (tags, status, cases) wie in Abschnitt 3 zerlegen. Alles andere als Text behalten.
  5. Die Datei verwerfen, wenn doc_id vorhanden ist und von der Kennung abweicht.
  6. Das Dokument als gelöscht ansehen, wenn deleted_at nicht leer ist. Das Original liegt unter source_file, bei einem gelöschten unter _Deleted/<Kennung>.<Endung>.
  7. Die Rumpfabschnitte lesen, die du brauchst (## Note, ## Status History).

Rechne mit: fehlenden Zeilen, leeren Werten, unbekannten Schlüsseln und Abschnitten, Werten, die du nicht kennst, und mit einer Bibliothek, in die gerade ein anderes Gerät schreibt (eine Datei kann sich zwischen zwei Lesevorgängen ändern).

11. Schreiben – bitte in der App

Lesen ist sicher. Änderungen macht man bitte in der App.

Eine Änderung, die ein anderes Programm an einem Sidecar vornimmt, übernimmt die App heute nicht. Sie liest die Datei neu, bemerkt, dass nicht die App sie geändert hat, und behält dann ihren eigenen letzten Stand des Eintrags. Die Änderung des anderen Programms ist danach nicht mehr in der Bibliothek, auch auf anderen Geräten nicht. Sonst nimmt die Bibliothek dadurch keinen Schaden.

Die Dateien gehören dem Nutzer, und nichts hindert ein Programm daran, sie zu beschreiben. Wer es trotzdem tut, muss damit rechnen, dass die Änderung nicht bleibt.

12. Zum Beispiel und zu Änderungen an diesem Dokument

Das Beispiel hat die App gelesen und unverändert, Byte für Byte, zurückgeschrieben. Bekommt das Format Felder, werden sie in die Tabelle in Abschnitt 4 aufgenommen, und das Datum der Änderung steht unten.

  • 2026-10: erste öffentliche Fassung.