OmniDiff, an open-source Rust difftool, diffs files by content type

OmniDiff, an open-source Rust difftool, diffs files by content type

OmniDiff is a content-aware diff tool written in Rust by Marko Ivankovic, published on GitHub and shown on Hacker News. The README sells it on three words: fast, robust, accurate. Its two headline claims are that it can diff 99.95% of code changes, and that 98.8% of changes are diffed with content-specific algorithms.

The tool chooses its method by file type. The language is detected from the file extension, and 25 languages are parsed with a tree-sitter grammar and diffed structurally. Some formats are recognised by extension but diffed as plain text because no grammar is compiled in: Bazel, Dart, Emacs Lisp, Markdown, Protocol Buffers and SQL. A file with an unknown extension is diffed as plain text, line by line, so nothing is refused. Files that are not text are recognised by their bytes, never by their names, and diffed by what they hold. Only the members that changed are opened, so a font with two edited glyphs shows two glyphs. Each change is also labelled by how much of it a reader would see: invisible, imperceptible, artifacts, edited, redrawn or replaced. The README's examples include a PDF diagram with one box renamed and a web font with twenty icons redrawn. Any other binary file gets a one-line "Binary file differs" notice.

There are several ways to run it. omnidiff BEFORE AFTER opens a terminal viewer (TUI) on two files; the TUI shows pictures as pictures, using the kitty, sixel or iTerm2 graphics protocols where available and Unicode half blocks elsewhere. omnidiff --headless BEFORE AFTER (synonym --batch) prints plain text with optional color, and this mode starts automatically whenever stdout is not a terminal, so piping into less works. --mode json prints the diff as one JSON object described by a JSON Schema in the repository. Long runs of unchanged lines are collapsed, keeping 3 lines of context on each side of a change by default (--context N overrides it), and each hunk is prefixed with the nearest enclosing function, class or struct line when that line is not otherwise visible.

For version control, omnidiff git configure runs a setup wizard, and git difftool --tool=omnidiff opens the interactive viewer. Plain git diff and git log -p pipe through a pager, so OmniDiff falls back to plain text there; GIT_EXTERNAL_DIFF=omnidiff git diff works without any difftool config. jj needs its own setup (omnidiff jj configure), because it does not read git's difftool settings, and it requires diff-invocation-mode = "file-by-file" since OmniDiff diffs two files rather than two directory trees. Exit code is 0 on success and 2 on error; 1 for differing files appears only with --exit-code, because git and jj read a non-zero exit as a tool failure.

On speed, the stated goals are a median diff in 100ms or less and a 99th-percentile diff in 1000ms or less, and the README says both are met. Across the 2,302 fixtures in src/test/data/diffs/, measured on 2026-10-31 on a laptop with an Intel Core i7-1370P (6 performance and 8 efficiency cores, 20 threads) and 32 GB RAM, the p50 is 4.2ms, p90 35.1ms, p99 177ms and the slowest 482ms. The 100ms mark is the 97.6th percentile: 55 fixtures take longer, and none takes longer than a second. An Intel Xeon E3-1275 v5 server takes about 2.5 times as long per fixture. Other content was timed separately on 2026-10-17: archives miss the 99th-percentile goal because the slowest hold thousands of changed members, while PDFs meet both goals, though only 57% of them take under 100ms since a PDF draws every changed page.

The robustness figure comes from a large corpus. The test dataset holds the git history of about 7,500 open-source repositories, with the list taken from the Gentoo Linux distribution. The author diffed every modified code file in the most recent 50 commits of each: 442,530 readable before/after pairs in 25 languages, with no size cap, under a 120-second budget and a 6 GB memory cap per process. Of these, 442,322 (99.95%) completed successfully; 96 pairs ran past the time budget and 112 past the memory cap. The README states the goal as processing 100% of all commits.

Installation options: cargo install --locked omnidiff (needs a C compiler and rustc 1.92 or later; the first build takes a few minutes), prebuilt binaries for Linux, macOS (Intel and Apple Silicon) and Windows attached to each GitHub release, Homebrew, a signed apt repository with .deb packages for amd64 and arm64, and Nix. Arch and Gentoo recipes live in the repository. There is a VS Code extension and a Neovim plugin, but VS Code does not yet let an extension replace its built-in diff view; the API is implemented upstream but unreleased, so the extension will adopt it when it ships.

The code is under the GNU AGPL v3. A commercial license is offered as a monthly subscription through GitHub Sponsors, covering internal use by an organisation without the AGPL's source-disclosure obligations; the terms are in LICENSE-COMMERCIAL.

Key facts

  • OmniDiff is a Rust diff tool with a terminal viewer, a headless mode, JSON output and integration with git (difftool and GIT_EXTERNAL_DIFF) and jj.
  • 25 languages are parsed with tree-sitter and diffed structurally; pictures, fonts, archives and PDFs get content-aware reports, and unknown extensions fall back to line-by-line text.
  • On 2,302 fixtures, measured on the author's Core i7-1370P laptop, the median diff takes 4.2ms, p99 177ms and the slowest 482ms; a Xeon E3-1275 v5 server takes about 2.5 times as long.
  • Of 442,530 before/after pairs from about 7,500 open-source repositories, 442,322 (99.95%) finished within a 120-second budget and a 6 GB memory cap; 96 ran past the budget and 112 past the memory cap.
  • Licensed under AGPL-3.0, with a commercial license sold as a monthly subscription through GitHub Sponsors.

Why it matters

Most diff tools treat every file as lines of text. OmniDiff tries to read what a file is: code is parsed with tree-sitter grammars, and non-text content such as fonts, archives, pictures and PDFs is opened and compared member by member. The README reports that 98.8% of changes in its test corpus were diffed with content-specific algorithms. It also aims to slot into existing workflows rather than replace them, working behind git difftool, GIT_EXTERNAL_DIFF and jj.

Who it affects

Developers who read diffs in the terminal with git or jj are the main audience. VS Code, VSCodium, Cursor and Windsurf users can install the extension, and Neovim users have a plugin, though in VS Code the tool cannot yet replace the built-in diff view. Teams that want to use it internally need to weigh the AGPL against the paid commercial license.

How to use it

Install with cargo install --locked omnidiff, Homebrew (brew install ivankovic/omnidiff/omnidiff), the signed apt repository, Nix (nix run github:ivankovic/omnidiff) or a prebuilt binary from the GitHub releases. For git, run omnidiff git configure, then git difftool --tool=omnidiff; use GIT_EXTERNAL_DIFF=omnidiff git diff for plain-text output with no config. For jj, run omnidiff jj configure, which sets file-by-file invocation mode. In scripts and CI use --headless, or --mode json for structured output, and add --exit-code if you need exit code 1 when files differ. Licensing: AGPL-3.0, or a commercial license as a monthly GitHub Sponsors subscription; the source gives no price.

How solid is it

The numbers come from the author's own README, and the speed figures are from one laptop, an Intel Core i7-1370P, with the author noting that times belong to the machine that measured them. The 99.95% figure is the share of 442,530 pairs that completed under a 120-second budget and a 6 GB memory cap; it is a completion rate across a large real-world corpus of about 7,500 repositories, not a correctness score. The README states that PDF accuracy rests on fewer than ten judged test cases. The visible text names no release version and gives no timing comparison against other diff tools.

Risks and caveats

Archives miss the 99th-percentile speed goal, and only 57% of PDF diffs finish under 100ms. In the corpus run, 96 pairs ran past the time budget and 112 past the memory cap. Markdown, SQL, Dart, Protocol Buffers, Bazel and Emacs Lisp files are diffed as plain text for now. The companion browser review tool, codereview, is at v0.0.0, and the README says to use it at your own risk. The AGPL's source-disclosure terms may rule out internal use at some organisations without the paid license. The first build from source compiles every tree-sitter grammar from C and takes a few minutes.

“OmniDiff's goal is to process 100% of all commits.”

— OmniDiff README