Communitygithub.com

shenmituzi/img-share

DSH-Fähigkeit: Browser-Screenshots / lokale Bilder im Chat teilen (Vorschaubild + Vollbild, vom Handy aus sichtbar)

Was ist img-share?

Die Fähigkeit **img-share** macht **Browser-Screenshots** oder **lokale Bilder** zu **anklickbaren Großbildern** im Chat (Vorschaubild + Vollbild beim Klick) und sorgt dafür, dass diese auch **vom Handy/anderen Geräten aus erreichbar** sind. Sie ist plattformübergreifend auf Linux, macOS, WSL und **nativ unter Windows** einsetzbar. Die Fähigkeit erkennt automatisch, ob der Host bereits öffentlich erreichbar ist (etwa via `dsh-trust-proxy`) und legt dann die Bilder unter demselben Host-Pfad ab – ohne zusätzlichen Tunnel. Falls der Host nur lokal läuft, wird der Benutzer gefragt, ob ein separater öffentlicher Tunnel (via Cloudflared) gelegt werden darf. Dazu wird ein Python-Skript (`serve.py`) genutzt, das das gewünschte Bild in ein temporäres Verzeichnis kopiert, einen lokalen Dateiserver startet, einen Cloudflared-Tunnel aufbaut und nach dem Teilen sofort wieder abbaut. Auch bei fehlender CDP/Chromium-Kapazität greift ein Cloud-Screenshot-Fallback (über Dienste wie thum.io). Fehler wie Port-Konflikte, fehlende Abhängigkeiten oder fehlschlagende Tunnel werden behandelt, und die Sicherheit wird durch strikte Dateiisolierung und automatische Zerstörung des Tunnels nach dem Teilen gewährleistet.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add shenmituzi/img-share

In Ihrer bevorzugten KI fragen

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

Dokumentation

img-share Skill

Mache Browser-Screenshots oder lokale Bilder zu anklickbaren Großbildern im Chat (Vorschaubild + Vollbild beim Klicken), die auch vom Handy/anderen Geräten aus erreichbar sind. Plattformübergreifend (Linux/macOS/WSL/Windows nativ).

whenToUse (Wann auslösen)

  • Der Benutzer möchte einen Screenshot einer bestimmten Website/Seite im Chat haben.
  • Ein Bild wird in den Chat eingefügt und soll „auch auf dem Handy sichtbar sein und zum Vergrößern klickbar“ sein.
  • Ein Arbeitsbereichsbild soll als klickbares, eingebettetes Großbild im Chat geteilt werden.

Abhängigkeiten

AbhängigkeitZweckBezug
web-access skillScreenshot (CDP-gesteuerter Browser)Muss installiert: https://github.com/eze-is/web-access
python3/pythonOrchestrierung (serve.py)Systemintegriert
cloudflaredÖffentlicher Tunnel als FallbackMac: brew install cloudflared; Win: winget install Cloudflare.cloudflared; Linux: siehe offizielles README; oder setze CLOUDFLARED=/Pfad
ffmpeg (optional)Mehrere Bilder zu einem Grid zusammenfügenSysteminstallation (wird von scripts/montage.sh genutzt)

Ausführungsschritte

  1. Host-Erreichbarkeitsprüfung (zwingend, zuerst) – Bestimmt die Basis-URL der Bilder und ob ein separater öffentlicher Tunnel nötig ist. Die Bildadresse muss der Host-Adresse folgen – es darf nicht eigenständig ein Tunnel mit anderer Herkunft als der Host geöffnet werden, nur weil es „funktioniert“.

    PrüfungErgebnis (Aktion)
    Host ist bereits getunnelt/öffentlich erreichbar (der Benutzer erreicht die Sitzung genau über diese Adresse) und der Host stellt einen statischen Bildpfad bereit (z. B. /img/*)Bild in das statische Host-Verzeichnis legen und mit der öffentlichen Host-Adresse einbetten. Keinen neuen Tunnel öffnen.
    Host öffentlich erreichbar, aber ohne statischen BildpfadNicht stillschweigend ausweichen: zuerst dem Benutzer mitteilen, dass der Host eine statische Bildzuordnung benötigt; nur mit ausdrücklicher Zustimmung des Benutzers den „expliziten unabhängigen Tunnel-Fallback“ verwenden.
    Host nur localhost (z. B. DSH_WEB_URL=http://127.0.0.1:*, kein öffentlicher Tunnel)Das Bild wäre nur lokal/lokalnetz erreichbar, das Handy erreicht die Sitzung ohnehin nicht. – Zuerst den Benutzer auffordern, DSH öffentlich zu machen, oder nach Zustimmung den expliziten Fallback verwenden. Es ist verboten, eine localhost-/127.0.0.1-Adresse einzubetten und zu behaupten, das Handy könne sie sehen.
    Keine Erkennung möglich / unsicherNicht raten, zuerst den Benutzer fragen: „Welche Adresse verwendest du auf deinem Handy, um auf diese Sitzung zuzugreifen (öffentliche Domain oder localhost)?“ Dann gemäß obiger Tabelle vorgehen.

    Erkennungsmethode: Umgebungsvariablen lesen (DSH_WEB_URL, DSH_PUBLIC_BASE, DSH_IMG_BASE usw.), statische Host-Routing-Konfiguration prüfen; falls nichts gefunden wird, gilt der Host als „nicht bereitgestellt“ – gemäß Tabelle „Benutzer fragen/hinweisen“, kein stillschweigendes Öffnen eines anderen Tunnels.

    Host-Vertrag (vorausschauende Vereinbarung, aktuell vom DSH-Host noch nicht bereitgestellt): Wenn der Host DSH_PUBLIC_BASE / DSH_IMG_BASE oder eine äquivalente statische Pfaddeklaration bereitstellt, muss der Agent die Bilder vorrangig unter der Host-Domain ablegen; falls nicht bereitgestellt, nicht annehmen, dass es existiert.

  2. Screenshot (falls nötig): Verwende die web-access-Fähigkeit, /screenshot, um die Seite als PNG zu rendern.

    • Falls CDP/Chromium in einer eingeschränkten Umgebung nicht startet (kein Netzwerkzugriff, Prozessabsturz), auf Cloud-Screenshot zurückfallen: thum.io / mshots / microlink usw. mit ?wait=N&width=W; nach Erhalt prüfen, ob „Anteil nicht-weißer Pixel > Schwellwert“ und „Farbcluster-Anzahl > N“; nur wenn nicht leer, verwenden.
  3. Bild speichern: In das Arbeitsverzeichnis legen (z. B. img/x.png; Dateiname ASCII/keine Leerzeichen).

  4. Teilen (je nach Schritt-0-Ergebnis eine von zwei Optionen):

    • Host-Pfad (wenn Schritt 0 ergibt, dass der Host wiederverwendet werden kann): Das Bild in das vom Host bereitgestellte statische Verzeichnis legen, einbetten als https://<Host-Domain>/img/x.png. Keinen unabhängigen Tunnel öffnen.
    • Expliziter Fallback (wenn Schritt 0 ergibt, dass ein Fallback nötig ist und der Benutzer zugestimmt hat): Nur diese eine Datei teilen, nicht das ganze Verzeichnis öffnen; Bildserver [nur Loopback] + öffentlicher Tunnel, End-to-End-Prüfung, Ausgabe von PUBLIC_BASE:
      bash <skill>/scripts/setup.sh <img>/x.png        # Unix/WSL
      python <skill>/scripts/serve.py --share <img>/x.png   # Windows nativ
      
  5. In Antwort einbetten (Vorschaubild = Original-URL, klicken öffnet Vollbild):

    [![Beschreibung](https://<Basis>/x.png)](https://<Basis>/x.png)
    

    Die Basis muss das Ergebnis von Schritt 0 sein (öffentliche Host-Adresse oder vom Benutzer zugestimmte explizite Tunneladresse). Es ist verboten, localhost/127.0.0.1 einzubetten und zu behaupten, das Handy könne es sehen. Teile dem Benutzer mit: Im Chat wird das Vorschaubild angezeigt, bei Klick wird das Original geöffnet; das Handy kann dieselbe öffentliche Adresse verwenden (DSH wurde getestet, um öffentliche Markdown-Bilder darzustellen).

  6. Nach dem Teilen → Tunnel abbauen (nur beim expliziten Fallback, um dauerhafte Offenlegung zu vermeiden):

    bash <skill>/scripts/teardown.sh                  # Bildserver+Tunnel+Reinigung stoppen
    

Fehlerbehandlung

  • Host-Erreichbarkeit nicht bestimmbar: Nicht raten, nicht stillschweigend einen anderen Tunnel öffnen; zuerst den Benutzer fragen, welche Adresse er auf dem Handy für die Sitzung verwendet (siehe Schritt 0).
  • Host öffentlich, aber kein statischer Bildpfad: Benutzer auffordern, eine statische Zuordnung zu konfigurieren, oder nach Zustimmung den expliziten Fallback verwenden und darauf hinweisen, dass dieser eine andere Herkunft als der Host hat.
  • Fehlende Abhängigkeiten: serve.py meldet „cloudflared/python fehlt“; installieren oder CLOUDFLARED setzen; fehlender Screenshot von web-access → Cloud-Screenshot-Fallback (siehe oben) oder Benutzer auffordern, das Bild selbst hochzuladen.
  • Port belegt: serve.py wählt automatisch einen freien Port.
  • Tunnel-Domain nicht abrufbar (langsames Netzwerk/Cloudflare-Verbindungsabbruch): serve.py wiederholt die Abfrage mit Polling; falls immer noch fehlschlägt, dem Benutzer mitteilen „Netzwerk kann keinen Tunnel aufbauen“, zurückfallen auf nur lokal/LAN (lokale Adresse angeben und erklären, dass für das Handy-Szenario der Host/Dienst zuerst öffentlich erreichbar sein muss).
  • End-to-End-Prüfung fehlgeschlagen: serve.py führt einen curl auf die tatsächliche Datei durch und prüft auf HTTP 200; bei Fehlschlag sofort abbauen, um eine „scheinbar live, aber tatsächlich 404“-Situation zu vermeiden.
  • Domain-Drift: Schnelltunnel ändern beim Neustart die Domain; alte eingebettete URLs werden ungültig; Host-Pfad hat dieses Problem nicht; für langlebige Stabilität im Fallback-Szenario benannte Tunnel/feste Domains verwenden.

Umgebungs-Selbstprüfung (Agent zuerst ausführen)

Vor Beginn prüfen: Kann auf das öffentliche Netz zugegriffen werden (curl auf eine öffentliche Adresse)? Kann ein Browser-Prozess gestartet werden (CDP)? Ist der Host öffentlich erreichbar (siehe Schritt 0)? Weder ausgehendes Netz noch CDP möglich → Cloud-Screenshot + Hinweis, dass höhere Berechtigungen nötig sind; nicht einfach ein Bild ausliefern, das „aussieht, als ob es funktioniert, aber in Wirklichkeit kaputt ist“.

Sicherheit (Standardaktionen, keine Hinweise)

  • Nur die angegebene Datei teilen: serve.py kopiert die zu teilende Datei in ein zufällig benanntes Unterverzeichnis und startet dann den Dienst – auf keinen Fall das gesamte img/-Verzeichnis öffnen (sonst könnte die Tunnel-URL alle Dateien in diesem Verzeichnis auflisten/herunterladen); beim Host-Pfad ebenfalls nur die zu teilende Datei ablegen.
  • Bildserver bindet nur an 127.0.0.1 (nicht direkt aus dem LAN erreichbar); öffentliche Tunnel-URL ohne Authentifizierung – nach dem Teilen sofort teardown.
  • Für höhere Sicherheit: der URL einen zufälligen Token hinzufügen / kurzlebige Tunnel verwenden; keine sensiblen Bilder teilen.
  • Nicht alle Bilder öffentlich machen: Nur das/die „diesmal zu teilende(n)“ Bild(er) in einem öffentlich zugänglichen Verzeichnis/Tunnel platzieren.

Host-Tunnel bevorzugen (siehe Schritt 0 der Ausführungsschritte)

  • Bildadresse folgt der Host-Adresse: Ist der Host bereits getunnelt/öffentlich, sollen die Bilder unter derselben Domain des Hosts abgelegt werden (z. B. statischer Pfad /img/*) – der Benutzer lädt sie auf dem Handy in der Sitzung, kein separater Tunnel mit anderer Herkunft nötig und sollte auch nicht geöffnet werden.
  • Wenn der Host über dsh-trust-proxy o. Ä. eine /img/-statische Regel bereitstellt, lautet die Bild-URL z. B. https://<DSH-Domain>/img/x.png – geräteübergreifend, ohne zusätzlichen Tunnel.
  • Der unabhängige cloudflared-Tunnel von serve.py ist nur ein tragbarer Fallback (läuft auf jedem Rechner): Nur in Schritt 0, wenn der Host nicht öffentlich wiederverwendbar ist und der Benutzer zugestimmt hat; dabei die Einschränkungen klar kommunizieren (andere Herkunft als der Host, Schnelltunnel ändern beim Neustart die Domain).

Randbedingungen

  • Prozess muss persistent/abbaubar sein: serve.py speichert die PID für teardown; in einer DSH-Sitzung muss der Dienst sitzungsübergreifend sein (mit verwaltetem Hintergrunddienst + explizitem teardown).
  • Dateiname: ASCII, keine Leerzeichen; Skripte prüfen auf Datei-Existenz; chinesische Zeichen/Leerzeichen werden durch URL-Kodierung behandelt, aber es wird empfohlen, sie zu vermeiden.
  • Unterschiedliche Arbeitsverzeichnisse: Verschiedene Sitzungen haben unterschiedliche Arbeitsverzeichnisse; das Teilen erfolgt relativ zum Sitzungspfad; serve.py verwendet das systemweite temporäre Verzeichnis, unabhängig vom Arbeitsverzeichnis.

Verwandte Skills