Images, binaries, URLs — and text, of course.
Do they differ, and where.

Images, binaries, URLs, the clipboard, a deployed site, a directory over SSH. One command, and the same two answers for all of them: do they differ, and where. It never opens a window.

One command, every kind of file macOS · one brew install · no dependencies MIT licensed — free
$ mrdiff before.png after.png
Images differ — 12,481 of 390,000 pixels (3.2%)
First difference at (412, 88)
  largest per-channel gap: 41 — --tolerance=41 would call these the same

$ mrdiff firmware-v1.bin firmware-v2.bin
Binary files differ — 47 regions, first at 0x1A3F
  158 of 2,000,000 bytes differ

$ mrdiff --ssh ./site deploy@host:/var/www
changed   config/app.yml
only local (not deployed)   pages/new.html
only on remote (left over?)   backups/customers.sql
1 changed, 1 only local, 1 only on remote

An image, a binary, a server — the answer has the same shape. In the terminal you are already in.

Do these differ, and where?

Those two, and on purpose nothing more. MrDiff does not show a difference. In return it answers the same question, in the same shape, for text, an image, a binary, a live site, or a 10 GB log where you only care whether anything moved — so there is no separate tool to learn per kind of file.

One command, every kind of file

Which comparison runs is decided by content, not by extension. A PNG named .bin is still an image.

Images

Do they differ, what fraction of pixels, and where the first one is. Pixels are counted, so a one-pixel change is never rounded to “0.0%”. --tolerance=N lets small value drift count as the same; when it is on, the output says so — “identical” on its own always means byte-identical.

$ mrdiff --tolerance=2 a.png b.jpg
Images differ — 1,560 of 390,000 pixels (0.4%)
  compared with ±2 per channel
  largest per-channel gap: 5 — --tolerance=5 would call these the same

Binaries

How many regions differ and the offset of the first, in hex. Adjacent bytes are one region, not forty. If the lengths differ, the common part is compared and the rest is reported as the rest — an inserted byte does not turn into “everything after it changed”.

$ mrdiff v1.bin v2.bin
Binary files differ — 47 regions, first at 0x6BDF
  158 of 2,000,000 bytes differ

Text and source

A line diff with a character-level highlight, so the one character that moved is marked — painting the whole line red is not enough. Two line-number columns, left and right: a deleted line 7 and an added line 7 are not the same line.

URLs and the clipboard

mrdiff https://a https://b fetches both and compares what the server returned. --clipboard compares what you just copied — text, or a screenshot if there is no text — against a file or a URL. “Is this the same as before?” without saving anything first.

A deployed site vs the folder it came from

--site walks the git-tracked files in a folder, fetches each one from the live site, and tells you what does not match: changed, or not on the site at all. git ls-files is what defines “the files that are meant to be there”, so build junk and .DS_Store are not yours. “Did I forget to deploy this?” becomes a CI check.

$ mrdiff --site https://example.com ./site
changed   index.html
not on site   pricing.html
1 changed, 1 not deployed, 0 could not be checked
  note: files on the site that are not in git cannot be found this way (HTTP has no directory listing)

A local directory vs a server, over SSH

host:/path works as a file; --ssh walks a whole tree, both ways. So it reports the third thing a deploy check usually cannot: a file on the server that is not in your repo — an old export, a forgotten backup. Authentication is your ssh's: keys, ~/.ssh/config, agent. It never asks for a password.

Built to sit in a pipeline

What it will not tell you

Every one of these is printed by the tool itself, every time, rather than left for you to discover.

It does not show the difference

It answers whether and where. Seeing how two images or two firmware images differ is a different tool's job, and MrDiff does not pretend to be one.

A URL is what the server sent

No JavaScript is run and nothing is rendered, so the answer can differ from what a browser shows. Pretending otherwise would make a tool that claims differences where there are none.

Markdown and JSON are compared as text

Line by line. Reformatting counts as a change. Saying that **bold** removed, or keys reordered, is “the same” is outside what this version does.

--site cannot see files that are not in git

HTTP has no directory listing. A left-over customers.xlsx on the server is invisible to it, and it says so on every run rather than implying the site is clean. Over SSH the remote side can be listed, so there it is reported.

Install

One brew install. Nothing else to set up.

$ brew install mr-tabata/tap/mrdiff

# then
$ mrdiff a.png b.png
$ mrdiff a.bin b.bin
$ mrdiff https://example.com/a https://example.com/b
$ mrdiff --clipboard notes.md
$ mrdiff --site https://example.com ./site
$ mrdiff local.conf host:/etc/app.conf
$ mrdiff --ssh ./site host:/var/www

$ mrdiff --exit-code a.png b.png     # exit 1 if they differ
$ mrdiff --json a.bin b.bin          # machine readable

macOS. Written in Swift; image decoding uses the system's ImageIO, which is why it is macOS only. Output is English by default; MRDIFF_LANG=ja switches the human-readable lines to Japanese. JSON and exit codes never change.