I changed qty * 10 to qty * 12, ran OmniDiff, and got exit code 0.
The diff was there. The command had succeeded. Those are separate questions, and a script needs to know which one it’s asking. 🙂
OmniDiff 0.3.0 is a content-aware diff tool with a terminal viewer, plain-text output and JSON output. I tried its official release binary on a tiny Python fixture. Here’s the part I’d check before putting it in a build job.
Original diagram of the executed file checks. These are return codes, not a speed comparison.
Get a useful result without changing Git settings 🧪
Download and extract the matching binary from the 0.3.0 release, then make omnidiff available on your PATH. The release has builds for several platforms. I used the prebuilt binary; this walkthrough doesn’t require compiling Rust.
Save this as check_diff.py and run python3 check_diff.py. It creates disposable input files, checks the actual process results, and removes the fixtures when it finishes.
from pathlib import Path import subprocess import tempfile with tempfile.TemporaryDirectory() as directory: root = Path(directory) (root / 'before.py').write_text('def price(qty):\n return qty * 10\n') (root / 'after.py').write_text('def price(qty):\n return qty * 12\n') cases = [ ('changed, default', [], 'before.py', 'after.py', 0), ('changed, opt-in', ['--exit-code'], 'before.py', 'after.py', 1), ('identical, opt-in', ['--exit-code'], 'before.py', 'before.py', 0), ('missing, opt-in', ['--exit-code'], 'before.py', 'missing.py', 2), ] for label, flags, before, after, expected in cases: result = subprocess.run( ['omnidiff', '--headless', '--color', 'never', *flags, before, after], cwd=root, capture_output=True, text=True, ) assert result.returncode == expected, result.stderr print(f'{label}: {result.returncode}') My output was:
changed, default: 0 changed, opt-in: 1 identical, opt-in: 0 missing, opt-in: 2 ✅ The missing-file case matters. A script that treats every nonzero return as “files changed” would put a read error in the same bucket as a valid diff.
Pick the process contract first
For a display tool, success means it could produce the comparison. That explains the default zero even when the files differ.
For a check, add --exit-code. Then handle the results explicitly: zero means identical, one means different, and two means an error.2
In Python, I’d inspect returncode before deciding whether to fail the job. Using check=True immediately would raise on a normal changed-file result too. That can be useful if any change must fail the job, but the error path still deserves its own message. ⚠️
There’s also a Git-specific boundary: OmniDiff ignores --exit-code in Git’s external-diff argument form. I checked that form with the same changed files and got zero. Git can treat a nonzero external-diff result as the tool failing, so don’t carry the direct-file assumption into that integration.2
JSON helps with a different problem 🔎
I also ran the fixture with --mode json --exit-code. It returned one and produced a JSON object with before and after sections, each containing an update range. The versioned schema describes those fields.3
That gives an editor structured locations to display. It doesn’t tell the editor whether changing the multiplier was correct. I’d keep the application test beside the prettier diff.
This was a small process-behavior check: Python text files, equality, a missing input, JSON output and the external-diff argument form. I didn’t measure performance or test its other content handlers.
References and asset credit
- OmniDiff 0.3.0 release, Marko Ivankovic.
- Versioned README: headless mode and exit-code contract.
- Versioned JSON output schema.
The figure is an original rendering of the executed checks. The fixture and Python wrapper are original examples.
AI disclosure
AI was used to draft the article.

