diffr
Structural diffs with a streaming API and an interactive terminal frontend.
diffr is derived from difftastic
(MIT, Wilfred Hughes) and its terminal UI from
hunk (MIT, Modem Labs). See NOTICE
for every upstream and its license.
Installation
The CLI, from crates.io (prebuilt via cargo-binstall, or compiled):
The terminal UI is not yet published. From a checkout, with Rust and
Bun installed, cargo xtask install builds and installs
both the CLI and the UI.
Configuration
To turn on semantic diff summarization:
- Run
diffr config - Search for 'summarization'
- Enable in the dropdown
- Add your API key for Gemini if you don't already have on your path
Usage
diffr accepts the exact same arguments that git diff does.
You can also use diffr in streaming mode, which is useful for TUI or GUI applications:
Architecture
When you run diffr ${commit_range_exp}, the following happens:
- Commits loaded from git
- Plugins (explained in more detail later) load
- Each file is parsed via tree-sitter & diffed using difftastic's ast/ast diffing algorithm
- This produces an alignment of file / file
- Note: because of known upstream limitations, the diffing algorithm is quite CPU/Mem intensive. We fall back to a textual diffing algorithm in case of issue
- Plugins define which AST nodes are present in the API + folded by default.
Plugin API
diffr has a powerful, wasm-based plugin API which customizes how it presents changed files.
For example, the following are all implemented as plugins:
- Context Folding: showing relevant context, like a function signature + closing brace (if applicable)
- Algorithm Summarization: using an LLM to summarize long algorithms into pseudocode
- Comment collapsing: collapsing long LLM comments + function bodies & expanding both at once
- Collapsing tests by default
The Rust SDK's Plugin trait exposes
four important methods:
// rust bindings of underlying WASM plugin API
use ;
sequenceDiagram
participant D as diffr
participant P as Plugins
participant G as Git
participant E as Diff engine
participant C as UI / API consumer
D->>P: new(options), queries()
P-->>D: Plugin instances and query sources
D->>G: Load changed files for comparison
G-->>D: Before and after versions
loop Each changed file
D->>P: classify(file)
P-->>D: File tags
D->>E: Compare versions using tags and queries
alt Structural comparison available
E->>E: Parse with tree-sitter and diff with difftastic
else Generated file or structural fallback
E->>E: Compute line diff
end
E-->>D: Aligned regions and folds
loop Each enabled plugin in order
D->>P: mutate(file, sides)
P-->>D: Presentation moves
D->>D: Apply moves to regions and fold state
end
D-->>C: Diff with initial fold state
end
The WASM interface is defined in wit/plugin.wit.
The SDK's export! macro and
guest adapter expose a Rust plugin
as a WASM component; the Wasmtime runner loads and
calls it. See the context plugin and its
Rust query for a concrete implementation,
or Writing plugins for the full guide.
License
MIT. See LICENSE for the terms and NOTICE for the third-party work
diffr builds on, starting with the lovely
difftastic.