2026-02-28 18:38:00 -05:00
# @openclaw/diffs
Read-only diff viewer plugin for **OpenClaw** agents.
It gives agents one tool, `diffs` , that can:
- render a gateway-hosted diff viewer for canvas use
2026-03-02 04:38:50 -05:00
- render the same diff to a file (PNG or PDF)
- accept either arbitrary `before` and `after` text or a unified patch
2026-02-28 18:38:00 -05:00
## What Agents Get
The tool can return:
- `details.viewerUrl` : a gateway URL that can be opened in the canvas
2026-03-02 04:38:50 -05:00
- `details.filePath` : a local rendered artifact path when file rendering is requested
- `details.fileFormat` : the rendered file format (`png` or `pdf` )
2026-02-28 18:38:00 -05:00
2026-03-03 16:50:59 +10:00
When the plugin is enabled, it also ships a companion skill from `skills/` that guides when to use `diffs` . This guidance is delivered through normal skill loading, not unconditional prompt-hook injection on every turn.
2026-02-28 18:38:00 -05:00
This means an agent can:
- call `diffs` with `mode=view` , then pass `details.viewerUrl` to `canvas present`
2026-03-02 04:38:50 -05:00
- call `diffs` with `mode=file` , then send the file through the normal `message` tool using `path` or `filePath`
2026-02-28 18:38:00 -05:00
- call `diffs` with `mode=both` when it wants both outputs
## Tool Inputs
2026-03-02 04:38:50 -05:00
Before and after:
2026-02-28 18:38:00 -05:00
```json
{
"before": "# Hello\n\nOne",
"after": "# Hello\n\nTwo",
"path": "docs/example.md",
"mode": "view"
}
```
Patch:
```json
{
"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"
}
```
Useful options:
2026-03-02 04:38:50 -05:00
- `mode` : `view` , `file` , or `both`
2026-02-28 18:38:00 -05:00
- `layout` : `unified` or `split`
- `theme` : `light` or `dark` (default: `dark` )
2026-03-02 04:38:50 -05:00
- `fileFormat` : `png` or `pdf` (default: `png` )
- `fileQuality` : `standard` , `hq` , or `print`
- `fileScale` : device scale override (`1` -`4` )
- `fileMaxWidth` : max width override in CSS pixels (`640` -`2400` )
- `expandUnchanged` : expand unchanged sections (per-call option only, not a plugin default key)
- `path` : display name for before and after input
2026-02-28 18:38:00 -05:00
- `title` : explicit viewer title
- `ttlSeconds` : artifact lifetime
2026-03-02 05:07:04 +00:00
- `baseUrl` : override the gateway base URL used in the returned viewer link (origin or origin+base path only; no query/hash)
Input safety limits:
2026-03-02 04:38:50 -05:00
- `before` and `after` : max 512 KiB each
2026-03-02 05:07:04 +00:00
- `patch` : max 2 MiB
- patch rendering cap: max 128 files / 120,000 lines
2026-02-28 18:38:00 -05:00
2026-02-28 19:20:07 -05:00
## Plugin Defaults
Set plugin-wide defaults in `~/.openclaw/openclaw.json` :
```json5
{
plugins: {
entries: {
diffs: {
enabled: true,
config: {
defaults: {
fontFamily: "Fira Code",
fontSize: 15,
2026-03-01 22:06:50 -05:00
lineSpacing: 1.6,
2026-02-28 19:20:07 -05:00
layout: "unified",
2026-03-01 22:06:50 -05:00
showLineNumbers: true,
diffIndicators: "bars",
2026-02-28 19:20:07 -05:00
wordWrap: true,
background: true,
theme: "dark",
2026-03-02 04:38:50 -05:00
fileFormat: "png",
fileQuality: "standard",
fileScale: 2,
fileMaxWidth: 960,
2026-02-28 19:20:07 -05:00
mode: "both",
},
},
},
},
},
}
```
Explicit tool parameters still win over these defaults.
2026-03-02 05:07:04 +00:00
Security options:
- `security.allowRemoteViewer` (default `false` ): allows non-loopback access to `/plugins/diffs/view/...` token URLs
2026-02-28 18:38:00 -05:00
## Example Agent Prompts
Open in canvas:
```text
2026-03-02 04:38:50 -05:00
Use the `diffs` tool in `view` mode for this before and after content, then open the returned viewer URL in the canvas.
2026-02-28 18:38:00 -05:00
Path: docs/example.md
Before:
# Hello
This is version one.
After:
# Hello
This is version two.
```
2026-03-02 04:38:50 -05:00
Render a file (PNG or PDF):
2026-02-28 18:38:00 -05:00
```text
2026-03-02 04:38:50 -05:00
Use the `diffs` tool in `file` mode for this before and after input. After it returns `details.filePath` , use the `message` tool with `path` or `filePath` to send me the rendered diff file.
2026-02-28 18:38:00 -05:00
Path: README.md
Before:
OpenClaw supports plugins.
After:
OpenClaw supports plugins and hosted diff views.
```
Do both:
```text
2026-03-02 04:38:50 -05:00
Use the `diffs` tool in `both` mode for this diff. Open the viewer in the canvas and then send the rendered file by passing `details.filePath` to the `message` tool.
2026-02-28 18:38:00 -05:00
Path: src/demo.ts
Before:
const status = "old";
After:
const status = "new";
```
Patch input:
```text
Use the `diffs` tool with this unified patch in `view` mode. After it returns the viewer URL, present it in the canvas.
diff --git a/src/example.ts b/src/example.ts
--- a/src/example.ts
+++ b/src/example.ts
@@ -1,3 +1,3 @@
export function add(a: number, b: number) {
- return a + b;
+ return a + b + 1;
}
```
## Notes
- The viewer is hosted locally through the gateway under `/plugins/diffs/...` .
2026-03-02 05:07:04 +00:00
- Artifacts are ephemeral and stored in the plugin temp subfolder (`$TMPDIR/openclaw-diffs` ).
- Default viewer URLs use loopback (`127.0.0.1` ) unless you set `baseUrl` (or use `gateway.bind=custom` + `gateway.customBindHost` ).
- Remote viewer misses are throttled to reduce token-guess abuse.
2026-03-02 04:38:50 -05:00
- PNG or PDF rendering requires a Chromium-compatible browser. Set `browser.executablePath` if auto-detection is not enough.
- If your delivery channel compresses images heavily (for example Telegram or WhatsApp), prefer `fileFormat: "pdf"` to preserve readability.
- `N unmodified lines` rows may not always include expand controls for patch input, because many patch hunks do not carry full expandable context data.
2026-02-28 20:40:30 -05:00
- Diff rendering is powered by [Diffs ](https://diffs.com ).