Zum Inhalt springen

OpenClaw Diffs Plugin: Änderungen in Sekunden visualisieren

Kennst du das? Du versuchst zu verstehen, was sich in einer Datei geändert hat, aber die reine Textausgabe ist einfach zu unübersichtlich. Es ist frustrierend, wenn man mühsam Zeile für Zeile vergleichen muss, anstatt die Änderungen sofort visuell zu erfassen.

Das diffs Plugin löst genau dieses Problem. Es ist ein optionales Tool mit einer integrierten System-Guidance und einem Skill, der Änderungen in ein schreibgeschütztes Diff-Artefakt für Agents verwandelt.

Das Tool akzeptiert entweder:

  • before und after Text
  • einen unified patch

Es kann folgendes zurückgeben:

  • Eine Gateway-Viewer-URL für die Darstellung im Canvas
  • Einen gerenderten Dateipfad (PNG oder PDF) für die Zustellung von Nachrichten
  • Beide Ausgaben in einem einzigen Aufruf

Wenn das Plugin aktiviert ist, stellt es eine kurze Anleitung im System-Prompt bereit und bietet einen detaillierten Skill an, falls der Agent genauere Anweisungen benötigt.

  1. Aktiviere das Plugin.
  2. Rufe diffs mit mode: "view" für Canvas-first Flows auf.
  3. Nutze diffs mit mode: "file" für die Zustellung von Dateien im Chat.
  4. Verwende diffs mit mode: "both", wenn du beide Artefakte benötigst.
{
plugins: {
entries: {
diffs: {
enabled: true,
},
},
},
}

Wenn du das diffs Tool aktiviert lassen, aber die integrierte System-Prompt-Guidance deaktivieren möchtest, setze plugins.entries.diffs.hooks.allowPromptInjection auf false:

{
plugins: {
entries: {
diffs: {
enabled: true,
hooks: {
allowPromptInjection: false,
},
},
},
},
}

Dies blockiert den before_prompt_build Hook des Plugins, während das Plugin, das Tool und der Skill weiterhin verfügbar bleiben. Wenn du sowohl die Guidance als auch das Tool deaktivieren willst, schalte stattdessen das gesamte Plugin aus.

  1. Der Agent ruft diffs auf und liest die details Felder aus.
  2. Der Agent öffnet entweder details.viewerUrl mit canvas present oder sendet details.filePath mit einer message über path bzw. filePath.

Vorher und Nachher:

{
"before": "# Hello\n\nOne",
"after": "# Hello\n\nTwo",
"path": "docs/example.md",
"mode": "view"
}

Patch:

{
"patch": "diff --git a/src/example.ts b/src/example.ts\n--- a/src/example.ts\n+++ b/src/example.ts\n@@ -1 +1 @@\n-const x = 1;\n+const x = 2;\n",
"mode": "both"
}

Alle Felder sind optional, sofern nicht anders angegeben:

  • before (string): Originaltext. Erforderlich zusammen mit after, wenn patch fehlt.
  • after (string): Aktualisierter Text. Erforderlich zusammen mit before, wenn patch fehlt.
  • patch (string): Unified Diff Text. Schließt sich gegenseitig mit before und after aus.
  • path (string): Angezeigter Dateiname für den Vorher-Nachher-Modus.
  • lang (string): Hinweis zur Sprachüberschreibung für den Vorher-Nachher-Modus. Unbekannte Werte fallen auf Plain Text zurück.
  • title (string): Überschreibung des Viewer-Titels.
  • mode ("view" | "file" | "both"): Ausgabemodus. Standardwert ist der Plugin-Standard defaults.mode. Der veraltete Alias "image" verhält sich wie "file".
  • theme ("light" | "dark"): Viewer-Theme. Standardwert ist defaults.theme.
  • layout ("unified" | "split"): Diff-Layout. Standardwert ist defaults.layout.
  • expandUnchanged (boolean): Erweitert unveränderte Abschnitte, wenn der volle Kontext verfügbar ist. Nur als Option pro Aufruf verfügbar.
  • fileFormat ("png" | "pdf"): Format der gerenderten Datei. Standardwert ist defaults.fileFormat.
  • fileQuality ("standard" | "hq" | "print"): Qualitätseinstellung für PNG- oder PDF-Rendering.
  • fileScale (number): Überschreibung der Geräteskalierung (1-4).
  • fileMaxWidth (number): Maximale Renderbreite in CSS-Pixeln (640-2400).
  • ttlSeconds (number): TTL des Viewer-Artefakts in Sekunden. Standard 1800, Maximum 21600.
  • baseUrl (string): Überschreibung des Viewer-URL-Origins. Muss http oder https sein, ohne Query/Hash.

Validierung und Limits:

  • before und after jeweils max. 512 KiB.
  • patch max. 2 MiB.
  • path max. 2048 Bytes.
  • lang max. 128 Bytes.
  • title max. 1024 Bytes.
  • Patch-Komplexitätslimit: max. 128 Dateien und 120.000 Zeilen insgesamt.
  • patch zusammen mit before oder after wird abgelehnt.
  • Sicherheitslimits für gerenderte Dateien (PNG und PDF):
    • fileQuality: "standard": max. 8 MP.
    • fileQuality: "hq": max. 14 MP.
    • fileQuality: "print": max. 24 MP.
    • PDFs sind auf maximal 50 Seiten begrenzt.

Das Tool gibt strukturierte Metadaten unter details zurück.

Gemeinsame Felder für Modi, die einen Viewer erstellen:

  • artifactId
  • viewerUrl
  • viewerPath
  • title
  • expiresAt
  • inputKind
  • fileCount
  • mode
  • context (agentId, sessionId, messageChannel, agentAccountId, sofern verfügbar)

Dateifelder, wenn PNG oder PDF gerendert wird:

  • artifactId
  • expiresAt
  • filePath
  • path (gleicher Wert wie filePath, für Kompatibilität mit Message-Tools)
  • fileBytes
  • fileFormat
  • fileQuality
  • fileScale
  • fileMaxWidth

Zusammenfassung des Modus-Verhaltens:

  • mode: "view": Nur Viewer-Felder.
  • mode: "file": Nur Dateifelder, kein Viewer-Artefakt.
  • mode: "both": Viewer-Felder plus Dateifelder. Falls das Rendering fehlschlägt, wird der Viewer dennoch mit einem fileError zurückgegeben.
  • Der Viewer kann Zeilen wie N unmodified lines anzeigen.
  • Steuerelemente zum Ausklappen dieser Zeilen sind konditional und nicht für jede Eingabeart garantiert.
  • Diese Steuerelemente erscheinen, wenn das gerenderte Diff erweiterbare Kontextdaten enthält (typisch bei Vorher-Nachher-Eingaben).
  • Bei vielen Unified-Patch-Eingaben sind weggelassene Kontext-Bodys nicht in den Parsed Patch Hunks verfügbar. In diesem Fall erscheint die Zeile ohne Ausklapp-Option. Das ist das erwartete Verhalten.
  • expandUnchanged greift nur, wenn erweiterbarer Kontext existiert.

Du kannst plugin-weite Standardwerte in ~/.openclaw/openclaw.json festlegen:

{
plugins: {
entries: {
diffs: {
enabled: true,
config: {
defaults: {
fontFamily: "Fira Code",
fontSize: 15,
lineSpacing: 1.6,
layout: "unified",
showLineNumbers: true,
diffIndicators: "bars",
wordWrap: true,
background: true,
theme: "dark",
fileFormat: "png",
fileQuality: "standard",
fileScale: 2,
fileMaxWidth: 960,
mode: "both",
},
},
},
},
},
}

Unterstützte Standardwerte sind: fontFamily, fontSize, lineSpacing, layout, showLineNumbers, diffIndicators, wordWrap, background, theme, fileFormat, fileQuality, fileScale, fileMaxWidth und mode. Explizite Tool-Parameter überschreiben diese Werte.

  • security.allowRemoteViewer (boolean, Standard false)
    • false: Anfragen an Viewer-Routes, die nicht über Loopback kommen, werden abgelehnt.
    • true: Remote-Viewer sind erlaubt, wenn der tokenisierte Pfad gültig ist.

Beispiel:

{
plugins: {
entries: {
diffs: {
enabled: true,
config: {
security: {
allowRemoteViewer: false,
},
},
},
},
},
}
  • Artefakte werden im temporären Unterordner $TMPDIR/openclaw-diffs gespeichert.
  • Die Metadaten der Viewer-Artefakte enthalten eine zufällige Artefakt-ID (20 Hex-Zeichen), ein zufälliges Token (48 Hex-Zeichen), createdAt, expiresAt sowie den gespeicherten viewer.html Pfad.
  • Die Standard-TTL für den Viewer beträgt 30 Minuten, falls nichts anderes angegeben ist.
  • Die maximal akzeptierte TTL beträgt 6 Stunden.
  • Bereinigungen laufen opportunistisch nach der Erstellung von Artefakten ab. Abgelaufene Artefakte werden gelöscht. Eine Fallback-Bereinigung entfernt Ordner, die älter als 24 Stunden sind, falls Metadaten fehlen.

Viewer-Route:

  • /plugins/diffs/view/{artifactId}/{token}

Viewer-Assets:

  • /plugins/diffs/assets/viewer.js
  • /plugins/diffs/assets/viewer-runtime.js

Das Viewer-Dokument löst diese Assets relativ zur Viewer-URL auf. Ein optionaler baseUrl Pfad-Präfix bleibt also auch für Asset-Anfragen erhalten.

Verhalten bei der URL-Konstruktion:

  • Falls baseUrl angegeben ist, wird diese nach einer strengen Validierung verwendet.
  • Ohne baseUrl fällt die Viewer-URL auf den Loopback 127.0.0.1 zurück.
  • Wenn der Gateway-Bind-Modus auf custom steht und gateway.customBindHost gesetzt ist, wird dieser Host verwendet.

Regeln für baseUrl:

  • Muss http:// oder https:// sein.
  • Query und Hash werden abgelehnt.
  • Origin plus optionaler Basispfad ist erlaubt.

Härtung des Viewers:

  • Standardmäßig nur Loopback-Zugriff.
  • Tokenisierte Viewer-Pfade mit strenger ID- und Token-Validierung.
  • CSP (Content Security Policy) für Viewer-Antworten: default-src 'none', Scripte/Assets nur von self, kein ausgehender connect-src.
  • Throttling bei Fehlversuchen (wenn Remote-Zugriff aktiviert ist): 40 Fehler pro 60 Sekunden führen zu einer 60-sekündigen Sperre (429 Too Many Requests).

Härtung des Datei-Renderings:

  • Routing-Anfragen des Screenshot-Browsers sind standardmäßig deaktiviert.
  • Nur lokale Viewer-Assets von http://127.0.0.1/plugins/diffs/assets/* sind erlaubt.
  • Externe Netzwerkanfragen werden blockiert.

Für mode: "file" und mode: "both" benötigst du einen Chromium-kompatiblen Browser.

Reihenfolge der Auflösung:

  1. browser.executablePath in der OpenClaw-Konfiguration.
  2. Umgebungsvariablen: OPENCLAW_BROWSER_EXECUTABLE_PATH, BROWSER_EXECUTABLE_PATH oder PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH.
  3. Fallback über die Befehls-/Pfadsuche des Betriebssystems.

Häufiger Fehlertext:

  • Diff PNG/PDF rendering requires a Chromium-compatible browser...

Lösung: Installiere Chrome, Chromium, Edge oder Brave oder setze eine der oben genannten Pfad-Optionen.

Validierungsfehler bei der Eingabe:

  • Provide patch or both before and after text. -> Füge sowohl before als auch after hinzu oder liefere einen patch.
  • Provide either patch or before/after input, not both. -> Mische die Eingabemodi nicht.
  • Invalid baseUrl: ... -> Nutze einen http(s) Origin mit optionalem Pfad, ohne Query/Hash.
  • {field} exceeds maximum size (...) -> Reduziere die Größe der Nutzlast.
  • Ablehnung großer Patches -> Reduziere die Anzahl der Dateien oder die Gesamtzeilen im Patch.

Probleme mit der Viewer-Erreichbarkeit:

  • Die Viewer-URL wird standardmäßig auf 127.0.0.1 aufgelöst.
  • Für Remote-Szenarien: Übergib baseUrl pro Tool-Aufruf oder nutze gateway.bind=custom mit gateway.customBindHost.
  • Aktiviere security.allowRemoteViewer nur, wenn du externen Zugriff wirklich benötigst.

Kein Expand-Button bei unveränderten Zeilen:

  • Dies kann bei Patch-Eingaben passieren, wenn der Patch keinen erweiterbaren Kontext enthält. Das ist kein Fehler des Viewers.

Artefakt nicht gefunden:

  • Das Artefakt ist aufgrund der TTL abgelaufen, das Token/der Pfad hat sich geändert oder die Bereinigung hat die Daten entfernt.
  • Nutze bevorzugt mode: "view" für interaktive Reviews im Canvas.
  • Verwende mode: "file" für externe Chat-Kanäle, die einen Anhang benötigen.
  • Lass allowRemoteViewer deaktiviert, außer deine Umgebung erfordert Remote-URLs.
  • Setze explizit kurze ttlSeconds für sensible Diffs.
  • Vermeide es, Secrets in Diff-Eingaben zu senden, wenn es nicht unbedingt nötig ist.
  • Falls dein Kanal Bilder stark komprimiert (z. B. Telegram oder WhatsApp), nutze lieber die PDF-Ausgabe (fileFormat: "pdf").

Die Diff-Rendering-Engine basiert auf Diffs.

AI Setup Assistant

OpenClaw

OpenClaw Expert

Noch festgefahren?

Wenn diese Seite nicht hilft, frage OpenClaw Expert nach Schritt-fuer-Schritt-Loesungen.