// install

Three commands, no dependencies.

ScrubPony is a single C99 program with no configure step and nothing to link but libc. If you have a compiler and make, you have everything.

Build from source

This is the supported path today, on macOS and on Linux.

build and install
$ git clone https://github.com/norsehorse-dev/ScrubPony.git
$ cd ScrubPony
$ make
$ sudo make install

make alone builds ./scrubpony in the working tree, which is enough to try it without installing anything. make install honours PREFIX (default /usr/local) and DESTDIR, so a user-local install needs no sudo:

make PREFIX=$HOME/.local install

// check it works

scrubpony --version should print scrubpony 1.0.0. Then point -n at a photo you know has GPS in it and read the list before you remove anything.

Homebrew

There is no tap yet. It is the single biggest usability win left and it is on the roadmap — but this page will not print a brew install line before there is one to run. Building from source takes about thirty seconds and needs nothing that is not already on a developer machine.

What you need

RequirementDetail
A C99 compilergcc or clang. Nothing exotic is used and nothing is assumed beyond the standard.
makeGNU Make or BSD make. Apple's bundled GNU Make 3.81 is fine.
POSIX.1-2008The safety guarantees rest on O_NOFOLLOW, POSIX permission bits, and rename-over-an-existing-file.
Optional: exiftoolOnly for the golden cross-check tests. They skip cleanly without it.
Optional: Python 3 + PillowOnly for tests/verify_scrub.py and regenerating the synthetic fixtures.

Make targets

TargetWhat it does
makeBuild ./scrubpony.
make testUnit tests under AddressSanitizer and UndefinedBehaviorSanitizer.
make checkThe full suite: unit tests plus eight further suites.
make asanBuild the binary itself with sanitizers.
make fuzzlibFuzzer target. Needs a clang that ships compiler-rt.
make fuzz-dumbSelf-contained mutation fuzzer. No dependencies at all.
make installInstall to $PREFIX/bin. Honours DESTDIR.

Verified on

PlatformCompilerResult
macOS 26.5.2, arm64Apple clang 21, GNU Make 3.81741 checks, 8/8 suites, 0 warnings
Linux, aarch64 and x86-64gcc 11–13, clang 18741 checks, 8/8 suites, 0 warnings

Both under -Wall -Wextra -Wpedantic -Wconversion with AddressSanitizer and UndefinedBehaviorSanitizer on every test binary. CI runs the full suite on both platforms with both compilers on every push, plus a timed libFuzzer job.

The BSDs should work untouched — the same POSIX surface — but they are untested, which is not the same as unsupported. If you run one, a report either way is useful.

Windows is out of scope. O_NOFOLLOW, POSIX permission bits and rename-over-an-existing-file all behave differently there, and those are exactly the things the safety guarantees rest on.

Toolchains that need a flag

make SAN= check runs the whole suite without sanitizers, for toolchains that cannot provide them — Homebrew GCC on macOS, for instance, where AddressSanitizer belongs to Apple's runtime rather than GCC's. LeakSanitizer does not exist on macOS either, so make check there runs ASan and UBSan without it.

On macOS make fuzz needs a clang that ships libFuzzer, and Apple's does not:

brew install llvm make fuzz CC=$(brew --prefix llvm)/bin/clang

Or use make fuzz-dumb, which needs nothing. It finds less than libFuzzer and it finds it without ceremony; a 20,000-iteration run is part of make check so the harness cannot quietly rot.

First run

Read before you remove. -n writes nothing:

scrubpony -n ~/Pictures/IMG_4471.jpg

Then scrub a whole folder into a clean copy, leaving the originals alone:

scrubpony -r -d ~/clean ~/Pictures/to-upload

The guides walk through the four modes in order, and the documentation has every flag and exit code.

Uninstall

# if you used the default prefix sudo rm /usr/local/bin/scrubpony

There is nothing else. No config file, no state directory, no daemon, no cache.

Common questions.

Do I need any libraries?
No. ScrubPony is C99 against POSIX.1-2008 and links nothing but libc. There is no configure step and no package tree. exiftool and Python are optional and used only by parts of the test suite, which skip cleanly without them.
Where does make install put it?
PREFIX defaults to /usr/local, so the binary lands at /usr/local/bin/scrubpony. Both PREFIX and DESTDIR are honoured, so make PREFIX=$HOME/.local install works without sudo.
Is there a Homebrew formula?
Not yet. A tap is the single biggest usability win left and is on the roadmap, but nothing is published today and this page will not print a command that would fail. Building from source takes about thirty seconds.
Why does make fuzz fail on my Mac?
Apple's clang does not ship libFuzzer. Either brew install llvm and build with make fuzz CC=$(brew --prefix llvm)/bin/clang, or use make fuzz-dumb, which is a self-contained mutation fuzzer that needs nothing but a C compiler.
My toolchain has no sanitizers.
Run make SAN= check. Homebrew GCC on macOS is the usual case — AddressSanitizer there belongs to Apple's runtime rather than GCC's. LeakSanitizer does not exist on macOS at all, so make check on a Mac runs ASan and UBSan without it.