Wenn Claude Code den Haussegen gerade rückt
Diesen Beitrag gibt es auch auf Englisch: When Claude Code Restores the Peace at Home
Die Kamera war ein Geschenk von den Großeltern, eine dieser Kinderkameras aus der 19,99-Euro-Kategorie mit einer 32-GB-microSD-Karte drin, und eines Tages hat bei uns jemand auf „Alles löschen“ gedrückt. Mehr als ein Jahr Fotos war mit einem Klick vom kleinen Display verschwunden. Meine Frau war richtig grantig, und ich hab an dem Tag gelernt, dass eine Diskussion über Backup-Strategie, und wessen Aufgabe die gewesen wäre, in so einem Moment niemandem hilft. Zuversichtlich, dass ich das wieder hinkrieg, war ich auch nicht. Ich wusste nur, dass gelöschte Dateien unter gewissen Voraussetzungen zurückkommen können, weil ein Dateisystem beim Löschen meistens nichts wegwischt, sondern den Platz nur als frei markiert, und die Daten so lange auf der Karte bleiben, bis etwas Neues drübergeschrieben wird. Mir war auch klar, dass es dafür Spezialsoftware gibt und lokale Anbieter, die einem das abnehmen, aber mit der Karte irgendwo hinzufahren oder irgendein Tool runterzuladen, von dem ich noch nie gehört hatte, war mir viel zu mühsam. Ob die Voraussetzungen bei dieser Karte erfüllt waren, hatte ich keine Ahnung. Womit ich nicht gerechnet hab: Die eigentliche Rettung hat zehn Minuten gedauert, und spannend war alles danach.
Also hab ich Claude Code im Terminal auf meinem Mac aufgemacht und das Ganze dort erledigt, im Dialog. Claude hat die Befehle ausgeführt, ich hab Fragen beantwortet und dort das Go gegeben, wo es eins gebraucht hat. Mit allen Fehlversuchen waren es rund eineinhalb Stunden, und jedes Werkzeug dabei war entweder Open Source oder schon Teil von macOS.
Damit allen klar ist, was da auf dem Spiel stand, das hier ist Foto 734 von 744. Aufgenommen an einem Dienstagnachmittag im Mai, zu sehen ist der Fernseher, und für die Fotografin oder den Fotografen zählt es genauso viel wie die anderen 743.

Erst ein Image, dann carven
Der erste Rat war gleich der richtige. Die Kamera nicht mehr verwenden, kein einziges neues Foto machen, nicht formatieren und vor allem macOS die Karte nicht „reparieren“ lassen. Dann ein Eins-zu-eins-Image der Karte ziehen und das Original nie wieder anfassen. Claude hat die Karte als /dev/disk4 gefunden (31,3 GB, FAT32), PhotoRec über Homebrew installiert, geprüft, ob genug Platz für ein Image mit 29 GiB frei ist, und die Karte ausgehängt.
Das Image selbst hat dann drei Anläufe gebraucht. Der dd-Befehl, den Claude vorbereitet hatte, ist erst gelaufen, als ich ihn selbst in ein normales Terminal-Fenster kopiert hab, und der Grund dafür war am Ende der interessanteste Fehlschlag der ganzen Session.
Mit dem Image auf der Platte hat PhotoRec gemacht, was PhotoRec eben macht. Es durchsucht die Rohdaten nach Dateisignaturen (File Carving) und braucht dafür überhaupt kein Dateisystem. Ich hab nach JPEG, AVI, MOV und MP4 gefragt, und nach ein paar Sekunden hatte es rund 1.500 Dateien gefunden. Nach ein paar Minuten war es fertig, mit 1.490 JPEGs und keinem einzigen Video. Claude hat sie nach Auflösung sortiert. Dabei kamen 745 Fotos in voller Größe mit 5344×4000 heraus, 744 kleine Vorschaubilder mit 640×480, die die Kamera zu jedem Bild mitspeichert, und ein Ausreißer. Die Nummerierung folgt der Reihenfolge auf der Karte, und die entspricht ungefähr der Reihenfolge, in der die Fotos gemacht wurden.
Eine Kamera, die kein Datum schreibt
Die Kamera schreibt kein EXIF. In den Dateien steht kein Aufnahmedatum und auch kein Kameramodell. Importiert man 745 solche Dateien in Apple Fotos, hat man 745 Fotos mit dem Datum des Imports, alle auf einem Haufen an einer Stelle der Mediathek, wo man nach Datum nichts mehr findet.
Was die Kamera sehr wohl macht: Sie brennt Datum und Uhrzeit gelb in die linke untere Ecke jedes Bildes, etwa 2025/05/19 07:22:29. Das Datum war also da, nur als Pixel. Claude hat vorgeschlagen, es per OCR zurückzulesen und als echtes Aufnahmedatum in die Dateien zu schreiben, und weil es für genau das kein Werkzeug gibt, hat es eins geschrieben. Das ist ein kleines Swift-Programm auf dem Vision-Framework, das mit macOS mitkommt, also hat nichts den Rechner verlassen.
Der erste Lauf hat überhaupt keinen Text gefunden. Die zweite Version hat alles ausgefiltert, was nicht kräftig gelb war, und Vision stattdessen schwarzen Text auf weißem Grund gegeben, und auch die hat nichts gefunden. Dann hat Claude gemacht, was ich auch gemacht hätte, nur schneller, und die Zwischenbilder gespeichert, um sie sich anzuschauen. Der ausgeschnittene Bereich war flächig grau, jedes einzelne Pixel.
Flächiges Grau bekommt man, wenn ein JPEG abgeschnitten ist und der Decoder die fehlenden Zeilen auffüllt, also lag kurz der Verdacht nahe, PhotoRec hätte unvollständige Dateien gecarvt. Claude hat das mit einem zweiten kleinen Programm geprüft, das jedes JPEG in voller Auflösung dekodiert und von der untersten Zeile nach oben geht, bis es eine Zeile findet, die nicht Decoder-Grau ist, und die Fotos waren vollständig. Die eigentliche Ursache war viel banaler. Hat man das Bild so ausgeschnitten, wie es aus ImageIO kommt, also noch nicht dekodiert, kam Grau heraus. Hat man es zuerst in einen Bitmap-Kontext gezeichnet und dann ausgeschnitten, kam der Zeitstempel heraus.
// Cropping the lazily decoded JPEG straight from ImageIO yields flat gray, so force a full decode first.
func decoded(_ img: CGImage) -> CGImage? {
guard let ctx = CGContext(data: nil, width: img.width, height: img.height, bitsPerComponent: 8, bytesPerRow: 0,
space: CGColorSpaceCreateDeviceRGB(),
bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue) else { return nil }
ctx.draw(img, in: CGRect(x: 0, y: 0, width: img.width, height: img.height))
return ctx.makeImage()
}
Der Gelbfilter ist übrigens drin geblieben. Das Programm liest die unteren 10 Prozent der linken 40 Prozent des Bildes zweimal, einmal maskiert und einmal so, wie es ist, und behält jede Lesung, die zu einem Datumsmuster passt.
// The stamp is saturated yellow; render it as black on white so OCR ignores the background.
if r > 170 && g > 170 && r - b > 90 && g - b > 90 { gray[i] = 0 }
Die Nachbarn fragen
Vision hat auf 731 der 745 Fotos einen Zeitstempel gelesen. Am Ende waren 47 dieser Lesungen falsch, und in 40 davon war eine einzelne 3 in dieser winzigen gelben Schrift schuld, gelesen als 8, 9 oder 1. Je nachdem, wo die 3 stand, hat das ein Foto um fünf Sekunden, zwanzig Minuten oder sechs Tage verschoben, und jedes dieser Daten schaut für sich allein völlig plausibel aus.

Das ist der Teil, der mir am besten gefallen hat, und den würde ich aus der Geschichte für jede OCR-Aufgabe mitnehmen. Ein einzelnes Foto kann dir nicht sagen, ob sein Datum stimmt, seine Nachbarn können es sehr wohl. Die Reihenfolge auf der Karte entspricht ungefähr der Aufnahmereihenfolge, und Fotos nebeneinander liegen meistens Sekunden auseinander. Das Swift-Programm liefert deshalb nicht eine Lesung pro Foto. Es fragt Vision nach den zehn besten Kandidaten pro erkanntem Text, kombiniert sie und gibt jedes unterschiedliche Datum zurück, das es parsen kann. Ein kurzes Python-Skript nimmt dann für jedes Foto den Kandidaten, der dem Median seiner Nachbarn am nächsten liegt, fünf auf jeder Seite, und wiederholt das dreimal, damit sich die Korrekturen setzen.
times = [c[0] if c else None for c in cands]
for _ in range(3):
for i, c in enumerate(cands):
m = neighbour_median(times, i)
if c and m is not None:
times[i] = min(c, key=lambda t: abs(t.timestamp() - m))
Fotos ganz ohne lesbaren Zeitstempel (gelber Text auf knallgelbem Hintergrund gibt es wirklich) haben ein Datum genau zwischen ihren Nachbarn bekommen. Was danach im Vergleich zur Umgebung noch komisch ausgeschaut hat, hat das Skript ausgegeben, und Claude hat diese Bilder aufgemacht, den Stempel selbst gelesen und sie von Hand korrigiert. Übrig blieben 694 direkt gelesene Daten, 43 automatisch über die Nachbarn korrigierte, 4 von Hand korrigierte und 3, die zwischen den Nachbarn aufgefüllt wurden, und danach war der ganze Satz chronologisch geordnet, ohne einen einzigen Sprung.
Foto Nummer eins ist übrigens vom 12. Dezember 2024 und zeigt zwei Kameras auf einem Fließband. Es ist ein Testbild aus der Fabrik, und es ist das einzige Bild von dieser Karte, das ich in einen Blog stellen würde.

Ab in Fotos, und ab in die Familie
exiftool hat das Aufnahmedatum in jede Datei geschrieben, ins EXIF und als Änderungsdatum der Datei. Ein AppleScript hat sie direkt in ein neues Album in der Fotos-App importiert, 744 Fotos vom 3. Februar 2025 bis zum 23. Mai 2026, und als ich nachgeschaut hab, hatte kein einziges das Importdatum.
Dann die Frage, wie wir teilen, und dabei hat Claude mir etwas erklärt, das ich nur halb gewusst hab. Ein geteilter iCloud-Speicherplan heißt noch lange nicht geteilte Fotos. Entweder man nimmt eine geteilte Mediathek (volle Qualität) oder ein geteiltes Album, das die Bilder auf rund 2048 Pixel verkleinert. Wir haben uns fürs Album entschieden, und bei dieser Kamera geht dabei praktisch nichts verloren, weil sie auf 5344×4000 hochrechnet, aus einem Sensor, der ungefähr 2 Megapixel liefert. Ein geteiltes Album zählt außerdem bei niemandem zum iCloud-Speicher. Das Image mit 29 GB wurde am Schluss gelöscht, weil ich darum gebeten hab.
Root hat nicht gereicht
Zurück zur Wand. Claudes erster Versuch, die Karte zu imagen, war sudo dd über die !-Shell in Claude Code. Das scheitert sofort, weil sudo dort kein Terminal bekommt und nicht nach dem Passwort fragen kann. Der zweite Versuch ging über den Passwortdialog von macOS mit osascript … with administrator privileges. Ich hab mein Passwort eingegeben, macOS hat es akzeptiert, und dd hat trotzdem mit „Operation not permitted“ geantwortet.
Das ist TCC, die Datenschutzschicht von macOS. Root bringt dich da nicht vorbei, weil TCC darauf schaut, zu welcher App ein Prozess gehört und was diese App anfassen darf, und ein Prozess aus der Claude-Session durfte die rohe Wechseldisk nicht lesen. Genau derselbe Befehl, von mir in ein normales Terminal-Fenster kopiert, ist durchgelaufen und hat das ganze Image erzeugt.
Gefallen hat mir, dass Claude beide Fehlschläge benannt, erklärt und mir den Befehl zum selbst Ausführen gegeben hat, statt dasselbe ein drittes Mal mit anderen Flags zu probieren. Und im Rückblick auf die ganze Session war die Aufteilung zwischen uns sauberer, als ich es geplant hatte. Ich hab die Entscheidungen getroffen und die Schritte gemacht, die Rechte oder einen Klick in einer Oberfläche gebraucht haben, vom Passworteintippen bis zu den Freigabe-Einstellungen in Fotos. Claude hat den Rest gemacht, inklusive drei kleiner Programme, die ich nie wieder brauchen werde.
Für mich ist das die eigentliche Erkenntnis für alle, die Coding Agents auf dem eigenen Rechner laufen lassen. Die Grenze zwischen dem, was der Agent macht, und dem, was du machst, zieht nicht der Prompt und auch nicht, wie sehr du dem Modell vertraust. Hier hat sie das Betriebssystem gezogen, und zwar genau an der Stelle, an der ein Fehler teuer geworden wäre, beim rohen Schreibzugriff auf eine Disk. Es ist verlockend, das als Reibung abzutun und der App, in der der Agent läuft, jede Berechtigung zu geben, damit es aufhört. Ich würde die Wand stehen lassen. Einen Befehl selbst einzufügen hat mich zehn Sekunden gekostet, und ich wusste genau, was ich da ausführe.
Und falls dir das einmal passiert, hör sofort auf, die Karte zu verwenden, wenn du es merkst. Jedes neue Foto kann auf einem alten landen.
Zu Hause sind übrigens alle wieder happy. Eine Backup-Strategie haben wir trotzdem immer noch keine, denn Claude kann Dateien von einer Karte carven und Daten aus Pixeln lesen, aber die Prozessthemen löst es auch nicht magisch, nicht einmal zu Hause.
Gefällt dir der Beitrag? Lass uns auf LinkedIn weiterreden.
Auf LinkedIn folgen




