Find out why things are on your computer.
$ why protobuf
protobuf 35.1
Location
/opt/homebrew/Cellar/protobuf/35.1 (likely)
Required by
onnx [Homebrew]
openai-whisper [Homebrew]
openvino [Homebrew]
pytorch [Homebrew]
qt [Homebrew]
qtgrpc [Homebrew]
Safe to remove?
No — 6 installed packages depend on it.
No brew uses, no dpkg -S, no lsof, no /proc spelunking. Just ask.
$ why python
python
Resolves to
/opt/homebrew/bin/python3.13
$ why 8080
Port 8080
Listening
node (PID 48192)
Started by
node server.js
$ why ~/.cache/huggingface
~/.cache/huggingface
Likely belongs to
huggingface_hub (possible)
why is an evidence engine, not an AI assistant. Every line it prints traces
back to something concrete on your machine — a PATH lookup, a package
manager's own metadata, /proc, sysinfo. When it isn't sure, it says so
("possible", "likely") instead of guessing with confidence.
Works on macOS and Linux, without a daemon, account, network connection, LLM, root access, or config file. Normal queries finish in well under 200ms.
| Query | What it explains |
|---|---|
why python / why command python |
Which executable PATH actually resolves to, its symlink chain, and what it shadows |
why protobuf / why package protobuf |
Which package manager installed it, its dependencies, and what would break if you removed it |
why 8080 / why port 8080 |
What's listening on a port and the process chain that started it |
why 48392 / why process 48392 |
A running process's command line, working directory, and parent chain |
why ~/.cache/huggingface / why file ~/.cache/huggingface |
A conservative guess at who owns a file or directory, and whether it looks safe to clean up |
why ollama / why service ollama |
A launchd/systemd service's executable, config file, and running process |
Ambiguous input (why 8080 could be a port or a PID) isn't guessed — why
checks which candidates actually exist and only asks you to disambiguate
when more than one real match is found.
Package managers: Homebrew, Cargo, npm/pnpm, pip/pipx, apt/dpkg. Service managers: launchd, systemd.
Add --json for machine-readable output (stable schema_version), or
--verbose to see the evidence behind every conclusion.
Requires Rust 1.85+ and ~/.cargo/bin on your PATH.
cargo install whyVerify:
why --helpBuild from source — for development or unreleased changes
git clone https://github.com/cesarferreira/why.git
cd why
cargo install --path . --locked
# or
make install-releaseDebug install (faster compile, larger binary):
make installRun without installing:
make build-release
./target/release/whyCommon tasks via the Makefile:
make # check + build + test
make build # debug build
make build-release
make install # install debug binary
make install-release
make run ARGS="python"
make check # cargo check + clippy
make fmt # format
make lint # fmt check + clippy
make test
make cleanPerformance breakdown for any query:
WHY_TRACE=1 why protobufReleasing (requires cargo-release and git-cliff):
make release # default minor bump
make release LEVEL=patch # patch bump
make release LEVEL=major # major bumpThe pre-release hook regenerates CHANGELOG.md with git-cliff from your conventional-commit history (grouped into Features, Bug Fixes, etc. per cliff.toml) and commits it alongside the version bump. Pushing the resulting v* tag triggers the release workflow, which builds the multi-platform binaries and publishes a GitHub Release whose notes are generated by git-cliff from the same config.
MIT