The Homebrew dependency graph is more than just a list of what’s installed; it’s a precise record of how your system’s packages are stitched together, and understanding it is key to untangling complex installation issues.

Let’s see it in action. Imagine you’ve installed ffmpeg. It’s not just ffmpeg on your system. It’s ffmpeg depending on x264, which depends on openssl, and so on. Homebrew tracks this.

To visualize this, you’ll use the brew deps command. It shows you what a package needs to run. Let’s say you want to see what ffmpeg needs:

brew deps --tree ffmpeg

This will output a tree structure. You’ll see ffmpeg at the top, then its direct dependencies indented below it, and their dependencies further indented.

ffmpeg
├── aom
├── fontconfig
├── freetype
├── fribidi
├── lame
├── libass
├── libbluray
├── libmodplug
├── libsoxr
├── libvmaf
├── libvorbis
├── libvpx
├── opencore-amr
├── openssl@3
├── pkg-config
├── rubberband
├── sdl2
├── snappy
├── sox
├── texinfo
├── theora
├── x264
├── x265
└── zstd

This tree shows you the build-time and run-time dependencies. If you’re troubleshooting why ffmpeg isn’t compiling, this tree is your first stop. Did x264 fail to build? Look at x264’s dependencies.

The --installed flag is crucial when you want to see the dependencies for everything you currently have installed, not just one package.

brew deps --tree --installed

This will produce a massive, nested tree of all your installed packages and their relationships. It’s overwhelming at first, but incredibly powerful for seeing the full picture. You can then pipe this to grep to find specific packages.

brew deps --tree --installed | grep opencv

This helps you identify if other packages rely on a specific version of opencv that you might be considering upgrading or uninstalling.

The --include-build flag is important when you’re debugging build failures. It shows you not only the libraries a package needs to run, but also the tools it needs to compile.

brew deps --tree --include-build gcc

Here, gcc might depend on gmp, mpfr, and libmpc for its own compilation. If gcc fails to build, you’d examine those dependencies first.

The --skip-formula option is useful to prune the output. If you know openssl is a common dependency and you don’t want to see it cluttering your view for every package, you can exclude it:

brew deps --tree --skip-formula openssl@3 ffmpeg

This will show you ffmpeg’s dependencies, but omit openssl@3 and anything that only depends on openssl@3.

The --dot flag generates output in Graphviz DOT format, which is excellent for creating visual diagrams. You can then use Graphviz tools to render an image.

brew deps --tree --dot ffmpeg > ffmpeg_deps.dot
dot -Tpng ffmpeg_deps.dot -o ffmpeg_deps.png

This generates a ffmpeg_deps.png file that visually represents the dependency graph, making it much easier to spot circular dependencies or complex interconnections.

A common pitfall is assuming a dependency is only needed at runtime. Homebrew’s dependency system handles both build-time and run-time requirements. If a build-time dependency is missing or broken, the package installation will fail, even if the final installed binary doesn’t directly interact with that dependency at runtime.

When you run brew install some-package, Homebrew first resolves some-package’s dependencies, then their dependencies, and so on, recursively. It builds this dependency tree and then attempts to install each required package in the correct order. If any step in this chain fails, the entire installation stops, and the error message will often point to the immediate failing component, but the root cause could be much higher up the tree.

The brew config output is also invaluable when diagnosing dependency issues. It shows you your Homebrew environment, including your macOS version, Xcode version, and any relevant environment variables. This context is critical because dependency build failures are frequently due to subtle incompatibilities between the package, its dependencies, and your system’s build tools.

If you encounter a situation where brew install fails and the error message is cryptic, examining the dependency tree of the failing package and its direct dependencies using brew deps --tree is your most effective first step. Often, the issue isn’t with the package you’re trying to install, but with one of its many sub-dependencies that hasn’t been updated or has a conflict with another installed package.

The next problem you’ll likely encounter is understanding how to resolve conflicts when two packages require incompatible versions of the same dependency.

Want structured learning?

Take the full Homebrew course →