CommunityBildgithub.com

darkhipo/sharethought

Schichte Daten in eine PNG-Datei ein. Das Bild zeigt die gerenderte SVG-Oberfläche; die SVG-Quelle und ein Markdown-Dokument reisen in iTXt-Chunks und einem grep-fähigen Trailer nach IEND mit.

Was ist sharethought?

Diese Fähigkeit (Skill) ermöglicht es, strukturierte Textdaten wie SVG-Quellcode und Markdown-Dokumente unsichtbar in eine PNG-Datei einzubetten. Das resultierende „Sharethought“-File ist ein selbstenthaltendes Artefakt: Menschen sehen das gerenderte Bild, während ein KI-Agent (z. B. Claude Code, Cursor oder Codex) die versteckten Ebenen auslesen kann. Die Daten werden entweder als `iTXt`-Chunks im PNG-Stream (überlebt Bildpipelines) oder als Text-Trailer nach dem IEND-Chunk (für byte-exakte Übertragung) transportiert – die Referenzimplementierung `sharethought.py` schreibt beide Varianten auf einmal, sodass sie garantiert übereinstimmen. Der Anwendungsfall ist die kollaborative Kommunikation zwischen Mensch und LLM: Der Mensch beschreibt oder zeigt das Bild, der Agent extrahiert die vollständige SVG-Quelle und die dazugehörigen Notizen, um den Kontext umfassend zu verstehen und Änderungen vorzunehmen.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/darkhipo/sharethought/tree/HEAD

Installed? Explore more Bild skills: steipete/songsee, affaan-m/frontend-design, mattpocock/improve-codebase-architecture · View all 6 →

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Was macht sharethought?

Eine Sharethought-Datei ist eine gültige PNG-Datei, die Textabschnitte neben dem Bild transportiert. Sie öffnet und rendert überall wie ein normales Bild. Hinter dem Bild verbergen sich: die SVG-Quelle, aus der es gerendert wurde, und ein Markdown-Dokument. Ein Manifest am Anfang der transportierten Daten indexiert alles und trägt die Entpack-/Neupackanweisungen innerhalb der Datei selbst.

Die Abschnitte können in einem von zwei Trägern reisen: angehängt nach dem IEND-Chunk (einfach, nur byte-exakte Transporte) oder innerhalb von PNG-Ancillary-Chunks (überlebt Bildpipelines). Siehe Träger.

Verwenden Sie die Referenzimplementierung

sharethought.py in diesem Repository ist die getestete, stdlib-only Implementierung. Bevorzugen Sie sie gegenüber handgestrickten Parsern – jede Neuimplementierung ist eine neue Fehlerquelle.

python3 sharethought.py pack   --png base.png --svg s.svg --doc d.md -o out.png --what "eine Zeile"
python3 sharethought.py unpack out.png [--out-dir VERZ]
python3 sharethought.py repack --text out.png --set doc=neu.md -o out2.png
python3 sharethought.py verify out.png
python3 -m unittest -q test_sharethought    # die Testsuite

pack schreibt beide Träger aus einem Build (sie können nicht auseinanderlaufen). unpack bevorzugt Chunks, fällt auf den Trailer zurück und meldet Fehler, wenn beide Träger vorhanden sind, aber nicht übereinstimmen – pack kann das nicht erzeugen, also bedeutet Uneinigkeit externe Manipulation. verify prüft Signatur, IEND, beide Träger, Abschnittsnamensgrammatik und Manifest↔Abschnitt-Konsistenz.

Format (exakt)

[ PNG-Bytes ... IEND-Chunk ]
SHARETHOUGHT-v1\n
[ JSON-Manifest – ein UTF-8-Objekt, siehe Schema ]\n
<<<SECTION:name>>>\n
[ Abschnitts-Inhalt – standardmäßig UTF-8, base64 wenn "enc":"base64" ]\n
<<<END:name>>>\n
... (weitere Abschnitte, gleicher Rahmen)

Der Marker SHARETHOUGHT-v1 beginnt unmittelbar nach dem IEND-Chunk der PNG und wird durch einen Zeilenumbruch abgeschlossen. (Das Byte davor ist der CRC-Tail des IEND-Chunks, kein Zeilenumbruch – also finden Sie ihn byteweise, nicht zeilenweise.) Alles vom Marker bis EOF ist der Trailer. Standardabschnitte: svg (die Bildquelle, image/svg+xml) und doc (Markdown, text/markdown). Beliebige zusätzliche Abschnitte sind erlaubt – jeder Texttyp.

Abschnittsnamen müssen dem Muster [A-Za-z0-9_]+ entsprechen. Namen außerhalb dieser Grammatik werden beim Packen zurückgewiesen und beim Entpacken mit einem benannten Fehler gekennzeichnet – sie verschwinden nie stillschweigend.

Träger

Das gleiche Manifest und die gleichen Abschnitte können auf zwei Arten transportiert werden. Wählen Sie je nach Transportweg.

A. Trailer – angehängt nach dem IEND-Chunk (die Standardmethode oben).

  • Trivial von Hand zu schreiben: cat trailer.txt >> datei.png. Keine CRC, kein Chunk-Rahmen, keine Bibliothek.
  • Überlebt nur byte-exakte Transporte: git, zip, curl -O, direkte Dateikopie.
  • Überlebt nicht irgendeine Pipeline, die das Bild neu serialisiert oder neu kodiert. Eine PNG→JPEG-Transkodierung entfernt es vollständig. Eine Neuordnung auf Chunk-Ebene – wie sie viele Chat- und Drive-Pipelines durchführen – behält jedes IDAT-Byte und verwirft alles nach IEND.

B. Ancillary-Chunks – iTXt innerhalb des PNG-Chunk-Streams.

  • Lebt innerhalb der Chunk-Liste, überlebt also Neuordnungen auf Chunk-Ebene und Bildpipelines, die PNG beibehalten.
  • Kostet eine CRC und Chunk-Rahmen, und große Abschnitte wollen komprimiert werden.
  • Überlebt nicht eine PNG→JPEG-Transkodierung – nichts überlebt das außer den Pixeln.

Empfehlung: Schreiben Sie beide (pack macht das). Gleiche Nutzlast, ein Build, keine Abweichung möglich. Ein Leser sucht zuerst nach Chunks und fällt auf den Trailer zurück, sodass die Datei sowohl in Chat-Pipelines als auch bei byte-exakten Transporten funktioniert. Der Preis ist ungefähr eine zusätzliche Kopie der Nutzlast.

Chunk-Layout:

[ IHDR ] [ IDAT ... ] [ iTXt sharethought:manifest ] [ iTXt sharethought:<name> ] ... [ IEND ]

Ein iTXt pro Abschnitt: Schlüsselwort sharethought:manifest für das Manifest, sharethought:<name> für den Inhalt jedes Abschnitts (roher Inhalt, keine Trennzeichen). Standard iTXt-Rahmen – Schlüsselwort \0, Komprimierungsflag (1 Byte, 1 = zlib), Komprimierungsmethode (0), Sprach-Tag \0, übersetztes Schlüsselwort \0, dann der Text.

Manifest-Schema

{
  "v": 1,
  "what": "Einzeiler, der dieses Artefakt beschreibt",
  "how": {
    "unpack": "Lesen Sie die iTXt-Chunks mit Namen sharethought:* falls vorhanden (das Manifest ist sharethought:manifest); andernfalls lesen Sie Bytes vom SHARETHOUGHT-v1-Marker bis EOF. Parsen Sie das JSON-Manifest, dann jeden Abschnitt zwischen seinen <<<SECTION:name>>> und <<<END:name>>>-Trennzeichen. Dekodieren Sie base64-Abschnitte.",
    "repack_text_only": "Behalten Sie die ursprünglichen PNG-Bytes bis zum Marker, dann überschreiben Sie den Trailer mit aktualisiertem Manifest und Abschnitten. Kein Neurendern nötig. Oder führen Sie aus: python3 sharethought.py repack --text DATEI --set doc=neu.md",
    "repack_visual": "Um das Bild zu ändern: Bearbeiten Sie den svg-Abschnitt, rendern Sie ihn nach PNG (rsvg-convert -w 1200 in.svg > out.png, oder cairosvg, oder resvg, oder ein Headless-Browser wie Chromium via Playwright), dann packen Sie erneut."
  },
  "sections": [
    { "name": "svg",  "type": "image/svg+xml", "enc": "utf8",    "summary": "einzeilige Beschreibung des Bildes" },
    { "name": "doc",  "type": "text/markdown", "enc": "utf8",    "summary": "einzeilige Beschreibung des Dokuments" }
  ]
}

Das how-Feld ist obligatorisch und muss funktionierende Anweisungen enthalten – die Datei lehrt jeden kalten Leser, sie zu öffnen.

Entpacken

Am besten: python3 sharethought.py unpack datei.png. Manuell, Trailer-Träger:

raw = open("datei.png", "rb").read()
# Die PNG-Chunks bis zum echten IEND durchgehen – niemals raw.index() auf den Marker,
# komprimierte IDAT-Bytes können ihn zufällig enthalten.
off = 8
while True:
    import struct
    ln, typ = struct.unpack(">I", raw[off:off+4])[0], raw[off+4:off+8]
    if typ == b"IEND": break
    off += 12 + ln
trailer = raw[off + 12:].decode("utf-8")
import json
manifest, _ = json.JSONDecoder().raw_decode(trailer[trailer.index("\n")+1:])
import re
for m in re.finditer(r"<<<SECTION:(\w+)>>>\n(.*?)\n<<<END:\1>>>", trailer, re.DOTALL):
    name, body = m.group(1), m.group(2)
    # wenn enc base64 ist: import base64; body = base64.b64decode(body)

Manuell, Chunk-Träger (zuerst geprüft):

import struct, zlib, json
raw = open("datei.png", "rb").read()
off, chunks = 8, {}
while off + 8 <= len(raw):
    ln = struct.unpack(">I", raw[off:off+4])[0]
    typ = raw[off+4:off+8]
    data = raw[off+8:off+8+ln]
    if typ == b"IEND": break
    if typ == b"iTXt":
        key, _, rest = data.partition(b"\x00")
        flag = rest[0]
        rest = rest[2:]
        _, _, rest = rest.partition(b"\x00")   # Sprach-Tag
        _, _, rest = rest.partition(b"\x00")   # übersetztes Schlüsselwort
        if flag == 1:
            rest = zlib.decompress(rest)
        chunks[key.decode()] = rest.decode("utf-8")
    off += 12 + ln
manifest = json.loads(chunks["sharethought:manifest"])
sections = {k[len("sharethought:"):]: v
            for k, v in chunks.items()
            if k.startswith("sharethought:") and k != "sharethought:manifest"}

Nur mit Shell: tail -c +$(( $(grep -abo 'SHARETHOUGHT-v1' datei.png | head -1 | cut -d: -f1) + 1 )) datei.png gibt den Trailer als Text aus (funktioniert nur, wenn der Trailer den Transport überlebt hat).

Erstellen

Am besten: SVG rendern, dann python3 sharethought.py pack --png out.png --svg diagramm.svg --doc notizen.md -o artefakt.png. Manuell:

  1. Schreiben Sie das SVG (das menchenlesbare Bild oder Diagramm).
  2. Rendern Sie nach PNG: rsvg-convert -w 1200 diagramm.svg > out.png (oder cairosvg diagramm.svg -o out.png, oder resvg diagramm.svg out.png, oder ein Headless-Browser – Chromium via Playwright – was oft der einzige installierte SVG-Renderer ist).
  3. Schreiben Sie das Markdown-Dokument.
  4. Hängen Sie den Trailer an (Form cat trailer.txt >> datei.png) und schreiben Sie besser auch die iTXt-Chunks – pack macht beides aus einem Build.

Die Ausgabe rendert wie ein normales PNG. Überprüfen: Öffnen Sie es in einem beliebigen Bildbetrachter (zeigt das Bild), dann strings artefakt.png | grep SHARETHOUGHT (zeigt, dass der Trailer existiert), oder python3 sharethought.py verify artefakt.png (prüft alles, einschließlich der Übereinstimmung beider Träger).

Neupacken

Am besten: python3 sharethought.py repack --text artefakt.png --set doc=neu.md -o out.png – überschreibt beide Träger, kein Renderer nötig.

Nur-Text-Bearbeitung (doc geändert, Bild unverändert): Verwenden Sie die ursprünglichen PNG-Bytes (alles vor SHARETHOUGHT-v1) wieder, schreiben Sie einen neuen Trailer mit dem bearbeiteten Abschnitt und aktualisierten Manifest-Zusammenfassungen. Wenn die Datei auch Chunks trägt, schreiben Sie auch diese neu – die Referenzimplementierung baut beide aus einer Quelle neu auf, was der einzige sichere Weg ist, sie in Übereinstimmung zu halten.

Visuelle Bearbeitung (svg geändert): Rendern Sie das modifizierte SVG in ein neues PNG, dann packen Sie erneut mit dem neuen svg-Abschnitt + doc + Manifest. Jeder SVG-Renderer funktioniert, auch ein Headless-Browser.

Round-Trip-Regel: Eine neu gepackte Datei ist eine Sharethought-Datei. Gleiches Format, gleicher Marker, aktualisiertes Manifest.

Sicherheit der Trennzeichen

Abschnitts-Trennzeichen sind <<<SECTION:name>>> und <<<END:name>>> in eigenen Zeilen. Wenn der Inhalt eine solche Zeile enthalten könnte, setzen Sie "enc":"base64" im Manifest für diesen Abschnitt und base64-kodieren Sie den Inhalt – pack macht das automatisch, wenn ein Inhalt sein eigenes schließendes Trennzeichen oder die Markerzeichenkette enthält.

Welche Kollision tatsächlich bricht: Ein Inhalt, der die Trennzeichen eines anderen Abschnitts enthält, ist harmlos. Ein Inhalt, der seine eigene <<<END:name>>>-Zeile enthält, wird von einer nicht-gierigen Regex abgeschnitten – alles nach dieser Zeile wird verwaist. Die Referenzimplementierung erkennt dies (Fehler für verwaisten Inhalt und unausgeglichene Trennzeichen), anstatt stillschweigend zu kürzen. Im Zweifelsfall base64.

Die Nutzlast am Leben halten

Die Nutzlast ist nicht Teil der PNG-Pixeldaten, sodass jedes Werkzeug, das das Bild neu kodiert, sie stillschweigend entfernen kann und eine perfekt normal aussehende PNG ohne Tiefe hinterlässt. Dazu gehören Image.open(f).save(g) in Pillow, Bildeditoren und CDN-Optimierer. Packen Sie aus den ursprünglichen Bytes neu, anstatt die gerenderte Datei erneut zu speichern.

Trailer nach IEND überleben nur byte-exakte Transporte. Wenn die Datei durch eine Bildpipeline reisen muss – ein Chat-Anhang, ein Thumbnailer, ein Transkoder – verwenden Sie den Chunk-Träger (pack macht das), und laden Sie sie als Datei hoch, nicht als Inline-Bild, damit das PNG nicht nach JPEG transcodiert wird.

Zusammenarbeit mit einem Menschen

Der Mensch sieht die PNG – die vereinfachte, visuelle Ebene. Die gesamte Tiefe (SVG-Quelle, doc, Manifest) ist für beiläufige Betrachter unsichtbar, aber für Sie vollständig vorhanden. Wenn der Mensch nach dem Bild fragt, entpacken und lesen Sie das doc für den Kontext. Wenn der Mensch eine Änderung des Bildes wünscht, bearbeiten Sie das svg und packen Sie visuell neu. Wenn der Mensch zusätzliche Tiefe wünscht, bearbeiten Sie das doc und packen Sie nur-Text neu. Die Datei ist der gesamte Austausch – ein Artefakt, beide Modalitäten, keine Seitenkanäle.

Verwandte Skills