macoshomebrewpackage-managers

`brew list` shows many things I did not install. Why? If something installed depends on them, how do I know?


On a new machine, I used brew to install only four things: git, node, sqlite and less. Later on, when I ran brew update I was told many other things that I didn't install were "outdated". I ran brew list and got the following:

brotli              less               pcre2
c-ares              libnghttp2         python@3.9
ca-certificates     libuv              readline
gdbm                mpdecimal          sqlite
gettext             ncurses            xz
git                 node
icu4c               openssl@1.1

Where did these come from? If they were installed because git, node or less needs them, how do I find out?

This matters because I only want to consider updating packages that I specifically installed, and leave decisions about updating dependencies to the packages that depend on them.


Solution

  • Yes, Homebrew (aka brew), like all package managers, automatically installs dependencies. This is a recursive process: If the dependency itself has dependencies, brew will install them too, and so on.

    brew deps

    You can see the dependency tree for anything you installed using the brew deps command:

    > brew deps node --tree
    
    node
    ├── brotli
    ├── c-ares
    ├── icu4c
    ├── libnghttp2
    ├── libuv
    ├── openssl@1.1
    │   └── ca-certificates
    └── python@3.9
        ├── gdbm
        ├── mpdecimal
        ├── openssl@1.1
        │   └── ca-certificates
        ├── readline
        ├── sqlite
        │   └── readline
        └── xz
    

    You can see in this tree many of the things you saw in brew list.

    brew uses

    But to answer your question, you can go in the opposite direction using the brew uses command:

    > brew uses readline --installed
    
    node            python@3.9            sqlite
    

    The --installed flag is important, because without it the above command will list everything that uses readline, whether it is installed on your system or not. Notice also how brew uses is recursive (in the opposite direction as brew deps), showing both python@3.9 which uses readline directly, and node, which uses it indirectly.

    brew desc

    Now if you're curious as to what any of these installed dependencies do, use the brew desc command:

    > brew desc pcre2
    
    pcre2: Perl compatible regular expressions library with a new API
    

    brew leaves -r

    If you just want the short list of what you specifically installed, brew leaves ‑r will work for most cases:

    > brew leaves -r
    
    git
    less
    node
    sqlite
    

    brew leaves lists things installed that aren't dependencies (leaves in the above tree), and the ‑r filters the list to those thing you specifically requested.

    I said "most cases" because it won't include things that you installed manually but are no longer leaves. This happens when you install another thing that depends on something you originally installed manually. For example, if I had installed readline manually, brew leaves ‑r would show it at first, but not after I install node or sqlite.

    For a lot of people, "leaf" and "installed manually" will be the same thing. But the more you install the more likely this will be wrong.

    brew bundle dump ‑‑file -

    This is a harder command to remember (Create an alias!), but it gives a more reliable, complete answer than brew leaves ‑r:

    > brew bundle dump --file -
    
    brew "git"
    brew "less"
    brew "node"
    brew "sqlite"
    cask "rar"
    

    It's more complete because unlike brew leaves it will include things you installed manually even if they are no longer leaves. In addition, it includes taps and casks.

    I learned this trick from @orlp's answer on Ask Different.