Mon 2026.11.02
OmniDiff: comparing files by their content
Today's pick: OmniDiff
OmniDiff is a product that compares changes according to the kind of file. It compares code by its syntax. It compares images pixel by pixel and PDFs page by page.
It is today’s pick because it lets you review changes in files that Git treats as binary.
- Found on
- Show HN
- Built with
- Rust, tree-sitter, Ratatui
The problem
In code review, people read changes as diffs. When a change touches only part of a line, or the file is not text, a line-based diff makes it hard to see what changed.
In the README, the maker shows the same code changes side by side in GNU diff and OmniDiff. Even when only part of a line changes, GNU diff marks the whole line as deleted and added again. According to the official Git documentation, even --word-diff looks for word changes only inside the lines that the line-based diff marked as changed. When git diff judges files to be binary, it prints only "Binary files … differ". To compare their content, you have to set a textconv program that turns the file into text. The same documentation says this conversion loses some information.
How it solves it
OmniDiff was posted on Hacker News as a Show HN on November 1, 2026. It identifies the file type, then chooses how to compare it. For code, it picks the language from the file extension. It parses code in 25 languages into an ASTAbstract syntax tree: a tree that shows the structure of source code. Compilers and analysis tools build it to read code. and compares the structure. It recognizes files that are not text by their bytes, not their names. OmniDiff compares images pixel by pixel. It compares archives file by file, fonts glyph by glyph and PDFs page by page.
You can see the result in an interactive terminal UI, as plain text or as JSON. When you connect it to Git with the GIT_EXTERNAL_DIFF environment variable, Git shows OmniDiff’s output in place of its own. With git difftool, OmniDiff opens its terminal UI for each file.
What is different
The first difference is how code changes are marked. OmniDiff compares the code as an AST and marks only the parts that changed inside a line, not the whole line. It also marks moved code as moved. The maker measured accuracy byte by byte against labels the maker added by hand. According to the README, 1,419 cases have such labels. OmniDiff’s marks match the labels exactly in 60.0 percent of them with --full and in 69.6 percent with --minimal, which highlights less. The goal is 90 percent.
The second difference is how OmniDiff handles files that are not text. OmniDiff reports how much of an image changed and where. It also lists the glyphs that changed in a font. The tradeoff is time, because it unpacks and renders the files to compare them. According to the README, 57 percent of PDF comparisons finish in under 100 ms. For archives, the p99The 99th percentile: the value below which 99 percent of measurements fall. Out of 100 requests, all but the slowest one finish within it. is 1,938 ms, over the one-second goal.
How it was built
- The repository has 1,514 commits from February 11 to November 1, 2026. Of these, 795 have a Co-authored-by trailer for Claude.
- In the README’s AI policy, the maker says the project is built with substantial help from Claude Code.
- The maker chose about 7,500 open-source repositories from Gentoo Linux’s package list and tested whether comparisons finish without failing. According to the README, 99.95 percent of 442,530 code file changes finished within 120 seconds and 6 GB of memory each. The rest went over the time or memory limit.
Running it
I built the repository with Rust 1.97 and ran it on a 4-core virtual machine in --headless mode, which prints the result as text.
- Build.
cargo build --release --lockedtook 6 minutes and 1 second. The binary was 54 MB. - Images. I compared two 200×120 PNG files with one rectangle changed. OmniDiff reported that 12.96 percent of the pixels changed. It printed the changed region’s size (61×51) and position. These matched the region I changed. Renaming both files to .txt gave the same result.
- Git. I committed a PNG file and a Python file in a new repository, then changed them. git diff printed only "Binary files … differ" for the PNG file. I set OmniDiff as
GIT_EXTERNAL_DIFF, and it reported the share and region of changed pixels in the PNG file. For the Python file, it showedtotalchanged tosum(numbers)and marked thereturnline as moved from line 5 to line 2. - Exit codes. With
--exit-code, identical files returned 0, different files 1 and a missing file 2. - Speed. I compared the 2,302 test file pairs in the repository one at a time. The median was 26.5 ms and the p99 was 858 ms. Of the 2,302 pairs, 16 took over a second. The README reports a median of 4.2 ms and a p99 of 177 ms for the same pairs on a laptop. No pair took over a second there. It says the maker’s Xeon server takes about 2.5 times as long as the laptop. Today I started a new process for each pair. Starting the binary took about 3 ms. I did not check whether the README’s numbers include start-up time.
Picture logo.png: PNG 200x120 RGB8, 419 bytes -> PNG 200x120 RGB8, 453 bytes
12.96% of pixels changed (3111 of 24000), in 1 region:
61x51 at (120, 30)
=== after: stats.py ===
1 def mean(numbers):
Moved from line 5
2 |~ return sum(numbers) / len(numbers)
Not checked
- The terminal UI. Check that a terminal with graphics support, such as kitty, shows images as pictures.
- PDFs and fonts. Change the label of one box in a PDF diagram, as in the README’s example, and compare the files. Then change the shape of one glyph in a font and compare.
Verdict
It works. It found the exact position and size of the changed region, even in PNG files renamed to .txt. But on a 4-core virtual machine, the median comparison time was about six times the maker’s laptop figure in the README. It is worth trying if you also review changes to binary files such as images.
Getting started
cargo install --locked omnidiffomnidiff --headless before.py after.pygit config difftool.omnidiff.cmd 'omnidiff "$LOCAL" "$REMOTE"'
- You need
- Rust 1.92 or later and a C compiler. The first build took 6 minutes on a 4-core virtual machine
- Cost
- Free under AGPL-3.0. A company that does not want the AGPL’s source-sharing terms can get a commercial license through a monthly GitHub Sponsors tier.
According to the maker, outside contributions are not accepted for now.
Steps select 1 ran.
Progress
- Day 3Upcoming
- Day 7Upcoming
- Day 15Upcoming
- Day 30Upcoming
- Day 90Upcoming
- Day 180Upcoming
- Day 365Upcoming