Introducing Homebrew, the missing package manager for MacOS
Published on

Introducing Homebrew, the missing package manager for MacOS

Authors
Table of Contents

Install Homebrew for MacOS

Homebrew is a package manager similar to apt-get, but it's explicitly created for MacOS because we don't have any official package manager from Apple. So internally, Homebrew is just ruby & git, so anyone who has knowledge can hack away after reading some documentation 🤣.

Homebrew is a command line tool that will be called in the bash terminal as brew. We can install brew from the below command, which you can also find on their homepage. It may require your admin password if you didn't run the bash terminal with admin privileges.

> /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

==> Checking for `sudo` access (which may request your password)...
Password:
==> This script will install:
/opt/homebrew/bin/brew
/opt/homebrew/share/doc/homebrew
/opt/homebrew/share/man/man1/brew.1
/opt/homebrew/share/zsh/site-functions/_brew
/opt/homebrew/etc/bash_completion.d/brew
/opt/homebrew

Press RETURN/ENTER to continue or any other key to abort:
==> /usr/bin/sudo /usr/sbin/chown -R vm:admin /opt/homebrew

==> Downloading and installing Homebrew...
remote: Enumerating objects: 4088, done.
remote: Counting objects: 100% (1768/1768), done.
remote: Compressing objects: 100% (15/15), done.
remote: Total 4088 (delta 1756), reused 1760 (delta 1752), pack-reused 2320
Receiving objects: 100% (4088/4088), 1.85 MiB | 1017.00 KiB/s, done.
Resolving deltas: 100% (2855/2855), completed with 453 local objects.
From https://github.com/Homebrew/brew
 * [new branch]          less-agressive-core-tap -> origin/less-agressive-core-tap
   29e3e5906..3be635040  master                  -> origin/master
 * [new branch]          setup-homebrew-test     -> origin/setup-homebrew-test
 * [new branch]          sorbet-files-update     -> origin/sorbet-files-update
 * [new tag]             3.6.17                  -> 3.6.17
 * [new tag]             3.6.18                  -> 3.6.18
 * [new tag]             3.6.9                   -> 3.6.9
HEAD is now at 3be635040 Merge pull request #14359 from gromgit/check-brew-branch
Updated 3 taps (azure/functions, homebrew/core and homebrew/cask).
==> Installation successful!

==> Homebrew has enabled anonymous aggregate formulae and cask analytics.
Read the analytics documentation (and how to opt-out) here:
  https://docs.brew.sh/Analytics
No analytics data has been sent yet (nor will any be during this install run).

==> Homebrew is run entirely by unpaid volunteers. Please consider donating:
  https://github.com/Homebrew/brew#donations

==> Next steps:
- Run brew help to get started
- Further documentation:
    https://docs.brew.sh

Once you install it, you can install different open-source packages like wget/python/java and other executables similar to Linux.

To test your brew installation, you can write brew --help

> brew --help

Example usage:
  brew search TEXT|/REGEX/
  brew info [FORMULA|CASK...]
  brew install FORMULA|CASK...
  brew update
  brew upgrade [FORMULA|CASK...]
  brew uninstall FORMULA|CASK...
  brew list [FORMULA|CASK...]

Troubleshooting:
  brew config
  brew doctor
  brew install --verbose --debug FORMULA|CASK

Contributing:
  brew create URL [--no-fetch]
  brew edit [FORMULA|CASK...]

Further help:
  brew commands
  brew help [COMMAND]
  man brew
  https://docs.brew.sh

What is the difference between cask/formulae in Homebrew?

Formulae: Homebrew, in general, is used to download libraries and command-line executables, which are generally available as open-source; these are named formulae

Cask: Extends Homebrew and allows you to install large binary files via a command-line tool. You can, for example, install applications like Google Chrome, Dropbox, VLC, and Spectacle. No more downloading .dmg files and dragging them to your Applications folder!

The applications you usually have to search in Google and then download like Visual Studio Code, etc.

Installing packages with Homebrew

Let us say you've found a handy tool/package called imagemagick. It is an open-source library with a vast suite of image functions. Now you're thinking if MacOS would support it. So now, how do you search for it with Homebrew? You can use search.

> brew search imagemagick
==> Formulae
imagemagick
imagemagick@6

==> Casks
imagemin

To find out if this is the same package, you can use info to give more information about this package.

> brew info imagemagick

==> imagemagick: stable 7.1.0-57 (bottled), HEAD
Tools and libraries to manipulate images in many formats
https://imagemagick.org/index.php
Not installed
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/imagemagick.rb
License: ImageMagick
==> Dependencies
Build: pkg-config ✔
Required: freetype ✔, ghostscript ✘, jpeg-turbo ✔, libheif ✘, liblqr ✘, libpng ✘, libraw ✘, libtiff ✔, libtool ✘, little-cms2 ✘, openexr ✔, openjpeg ✘, webp ✔, xz ✘, libomp ✘
==> Options
--HEAD
  Install HEAD version
==> Analytics
install: 167,265 (30 days), 462,823 (90 days), 1,988,074 (365 days)
install-on-request: 148,394 (30 days), 411,511 (90 days), 1,759,473 (365 days)
build-error: 7 (30 days)

Now we are sure that this is the package which we want to install

> brew install imagemagick

Running `brew update --auto-update`...
==> Auto-updated Homebrew!
Updated 2 taps (homebrew/core and homebrew/cask).
==> New Casks
runcat-plugins-manager

You have 39 outdated formulae and 1 outdated cask installed.
You can upgrade them with brew upgrade
or list them with brew outdated.

==> Fetching dependencies for imagemagick: libpng, fontconfig, jbig2dec, libidn, lz4, xz, zstd, little-cms2, openjpeg, ghostscript, highway, imath, pcre2, glib, libheif, liblqr, jasper, libomp, libraw, m4 and libtool
==> Fetching libpng
==> Downloading https://ghcr.io/v2/homebrew/core/libpng/manifests/1.6.39
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libpng/blobs/sha256:5fcb6945c7fe220f8b983c18edd7a42d8d84a9d62696b4fec001c1697300fb61
==> Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sha256:5fcb6945c7fe220f8b983c18edd7a42d8d84a9d62696b4fec001c1697300fb61?se=2023-
######################################################################## 100.0%
==> Fetching fontconfig
==> Downloading https://ghcr.io/v2/homebrew/core/fontconfig/manifests/2.14.1
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/fontconfig/blobs/sha256:d0dc5e1f28f8c7ded2351b6da95dc10c483f6a302390660b2b861a3b94c6cd18
==> Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sha256:d0dc5e1f28f8c7ded2351b6da95dc10c483f6a302390660b2b861a3b94c6cd18?se=2023-
######################################################################## 100.0%
...

Upgrading Homebrew and installed packages

When you run update it will update your Homebrew and list the old formulae and casks.

> brew update

Updated 1 tap (homebrew/core).
==> Outdated Formulae
azure-functions-core-tools@4            libffi                                  maven                                   openssl@3
git-lfs                                 libnghttp2                              node                                    terraform
gradle                                  libuv                                   openjdk
==> Outdated Casks
powershell

You have 11 outdated formulae and 1 outdated cask installed.
You can upgrade them with brew upgrade
or list them with brew outdated.

Once this is done, you can upgrade your already installed packages to a newer version.

> brew upgrade

==> Upgrading 11 outdated packages:
git-lfs 3.1.2 -> 3.3.0
terraform 1.1.7 -> 1.3.7
libuv 1.43.0 -> 1.44.2
maven 3.8.4 -> 3.8.7
libnghttp2 1.46.0 -> 1.51.0
gradle 7.4 -> 7.6
openjdk 17.0.2 -> 19.0.1
azure/functions/azure-functions-core-tools@4 4.0.4704 -> 4.0.4915
openssl@3 3.0.5 -> 3.0.7
node 17.6.0 -> 19.4.0
libffi 3.4.2 -> 3.4.4
==> Fetching openssl@3
==> Downloading https://ghcr.io/v2/homebrew/core/openssl/3/manifests/3.0.7
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/openssl/3/blobs/sha256:5b3d605f5c1fcadfea094c5670091e4bec2b2de7c121874be166bc737ef64ccf
==> Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sha256:5b3d605f5c1fcadfea094c5670091e4bec2b2de7c121874be166bc737ef64ccf?se=2023-
######################################################################## 100.0%
...

Listing installed packages with Homebrew

Now let us list the packages that are installed on your system. Of course, you wouldn't have any if this was your first installation. However, I've quite a few installed using Homebrew, so we get a list below.

> brew list

==> Formulae
aom
libpthread-stubs
azure-cli
libraw
azure-functions-core-tools@4
librsvg
brotli
libtiff
c-ares
libtool
ca-certificates
libuv
cairo
libvmaf
docbook
libx11
docbook-xsl
libxau
erlang
libxcb
fontconfig
libxdmcp
freetype
libxext
fribidi
libxrender
gdbm
little-cms2
...

==> Casks
powershell
visual-studio-code

Deleting Packages with Homebrew

Let me try uninstalling imagemagick by running the below command, as I have it installed in my system.

> brew uninstall imagemagick
Uninstalling /opt/homebrew/Cellar/imagemagick/7.1.0-51... (805 files, 30.8MB)

As it has a lot of dependencies that can be removed. You can run autoremove, which will delete all dependent packages.

> brew autoremove
==> Autoremoving 11 unneeded formulae:
ghostscript
jasper
jbig2dec
libidn
liblqr
libomp
libraw
libtool
little-cms2
m4
openjpeg
Uninstalling /opt/homebrew/Cellar/libtool/2.4.7... (75 files, 3.8MB)
Uninstalling /opt/homebrew/Cellar/ghostscript/10.0.0... (644 files, 146.9MB)
Uninstalling /opt/homebrew/Cellar/liblqr/0.4.2_1... (25 files, 176.8KB)
Uninstalling /opt/homebrew/Cellar/libraw/0.20.2_3... (73 files, 5.7MB)
Uninstalling /opt/homebrew/Cellar/openjpeg/2.5.0... (536 files, 13.9MB)
Uninstalling /opt/homebrew/Cellar/jbig2dec/0.19... (13 files, 420.6KB)
Uninstalling /opt/homebrew/Cellar/m4/1.4.19... (13 files, 742.4KB)
Uninstalling /opt/homebrew/Cellar/libidn/1.41... (73 files, 1MB)
Uninstalling /opt/homebrew/Cellar/libomp/15.0.3... (7 files, 1.6MB)
Uninstalling /opt/homebrew/Cellar/jasper/3.0.6_2... (44 files, 1.6MB)
Uninstalling /opt/homebrew/Cellar/little-cms2/2.13.1_1... (21 files, 1.4MB)

If you want to clean old packages, i.e., older versions installed with Homebrew, you can run brew cleanup, which would clean it up. Unfortunately, Homebrew sometimes doesn't remove the old packages/cache but would keep them as a backup in case you wanted to switch to an older version.

> brew cleanup

Warning: Skipping azure-cli: most recent version 2.44.1 not installed
Warning: Skipping azure/functions/azure-functions-core-tools@4: most recent version 4.0.4915 not installed
Warning: Skipping ca-certificates: most recent version 2023-01-10 not installed
Removing: /Users/snrahul11/Library/Caches/Homebrew/ca-certificates--2022-10-11... (127.5KB)
Warning: Skipping erlang: most recent version 25.2 not installed
Warning: Skipping fontconfig: most recent version 2.14.1 not installed
Removing: /Users/snrahul11/Library/Caches/Homebrew/fontconfig--2.14.0... (626KB)
Warning: Skipping gdk-pixbuf: most recent version 2.42.10 not installed
Removing: /Users/snrahul11/Library/Caches/Homebrew/gdk-pixbuf--2.42.9... (758.5KB)
Warning: Skipping git: most recent version 2.39.0 not installed
Removing: /Users/snrahul11/Library/Caches/Homebrew/git--2.38.1... (17.2MB)
Warning: Skipping git-lfs: most recent version 3.3.0 not installed
Warning: Skipping glib: most recent version 2.74.4 not installed
Removing: /Users/snrahul11/Library/Caches/Homebrew/glib--2.74.0... (6.4MB)
Warning: Skipping gradle: most recent version 7.6 not installed
Warning: Skipping harfbuzz: most recent version 6.0.0 not installed
Removing: /Users/snrahul11/Library/Caches/Homebrew/harfbuzz--5.3.1... (2.0MB)
Warning: Skipping highway: most recent version 1.0.2 not installed
Removing: /Users/snrahul11/Library/Caches/Homebrew/highway--1.0.1... (376.9KB)
Warning: Skipping imath: most recent version 3.1.6 not installed
Removing: /Users/snrahul11/Library/Caches/Homebrew/imath--3.1.5... (182.3KB)
Warning: Skipping libffi: most recent version 3.4.4 not installed
Warning: Skipping libheif: most recent version 1.14.2 not installed
Removing: /Users/snrahul11/Library/Caches/Homebrew/libheif--1.13.0_1... (1.3MB)
Warning: Skipping libnghttp2: most recent version 1.51.0 not installed
Warning: Skipping libpng: most recent version 1.6.39 not installed
Removing: /Users/snrahul11/Library/Caches/Homebrew/libpng--1.6.38... (448KB)
Warning: Skipping librsvg: most recent version 2.55.1 not installed
Removing: /Users/snrahul11/Library/Caches/Homebrew/librsvg--2.54.5... (16.0MB)
Warning: Skipping libuv: most recent version 1.44.2 not installed
Warning: Skipping libx11: most recent version 1.8.3 not installed
Removing: /Users/snrahul11/Library/Caches/Homebrew/libx11--1.8.1... (2.1MB)
...
==> This operation has freed approximately 154MB of disk space.

Managing your installed packages with Homebrew

Below is a very useful command to get the parent packages with homebrew. Normally when you list the packages with homebrew you really don't know if the package is a dependent one or a main package. With this command you can find out all the parent packages and review them easily. That way you can clear the clutter.

brew leaves | xargs brew deps --formula --for-each | sed "s/^.*:/$(tput setaf 4)&$(tput sgr0)/"

azure-cli: ca-certificates gdbm mpdecimal [email protected] [email protected] readline sqlite xz
azure/functions/azure-functions-core-tools@4: 
gh: 
git: gettext pcre2
git-lfs: 
imagemagick: aom brotli fontconfig freetype gettext ghostscript giflib glib highway imath jasper jbig2dec jpeg-turbo jpeg-xl libde265 libheif libidn liblqr libomp libpng libraw libtiff libtool libvmaf little-cms2 lz4 m4 openexr openjpeg pcre2 shared-mime-info webp x265 xz zstd
jpeg: 
librsvg: cairo fontconfig freetype fribidi gdk-pixbuf gettext glib graphite2 harfbuzz icu4c jpeg-turbo libpng libtiff libx11 libxau libxcb libxdmcp libxext libxrender lz4 lzo pango pcre2 pixman xorgproto xz zstd
maven: cairo fontconfig freetype gettext giflib glib graphite2 harfbuzz icu4c jpeg-turbo libpng libtiff libx11 libxau libxcb libxdmcp libxext libxrender little-cms2 lz4 lzo openjdk pcre2 pixman xorgproto xz zstd
node: brotli c-ares ca-certificates icu4c libnghttp2 libuv [email protected]
openjdk@17: cairo fontconfig freetype gettext giflib glib graphite2 harfbuzz icu4c jpeg-turbo libpng libtiff libx11 libxau libxcb libxdmcp libxext libxrender little-cms2 lz4 lzo pcre2 pixman xorgproto xz zstd
openssl@3: ca-certificates
terraform: 

Once you uninstall your brew packages make sure to run brew autoremove. This will remove all the orphaned packages which are installed due to the parent dependency which we removed. Once this is done we can run the cleanup command and add -s option then it would also cleanup your HomeBrew cache as which is maintained so that if you install the same package Homebrew would pull the files from the cache instead of downloading from the internet.

> brew cleanup -s

Removing: /Users/snrahul11/Library/Caches/Homebrew/erlang--25.2.3... (108.8MB)
Removing: /Users/snrahul11/Library/Caches/Homebrew/wxwidgets--3.2.2.1... (7.7MB)
Removing: /Users/snrahul11/Library/Caches/Homebrew/gobject-introspection--1.74.0... (1.8MB)
Removing: /Users/snrahul11/Library/Caches/Homebrew/rabbitmq--3.11.9... (27.8MB)
Removing: /Users/snrahul11/Library/Caches/Homebrew/gradle--8.0.1... (149.3MB)
Removing: /Users/snrahul11/Library/Caches/Homebrew/unixodbc--2.3.11... (587.0KB)
Removing: /Users/snrahul11/Library/Caches/Homebrew/Cask/vagrant--2.3.4.dmg... (58.5MB)
Removing: /Users/snrahul11/Library/Caches/Homebrew/Cask/virtualbox--7.0.6,155176.dmg... (126.8MB)
Removing: /Users/snrahul11/Library/Caches/Homebrew/Cask/vagrant-vmware-utility--1.0.21.dmg... (7.5MB)
==> This operation has freed approximately 488.7MB of disk space.

The below is a another useful command to know the parent packages and its dependency tree but takes up more space so harder to view in your console if you have a lot of dependencies installed.

> brew deps --include-build --tree $(brew leaves)

azure-cli
├── [email protected]
│   └── ca-certificates
├── [email protected]
│   ├── gdbm
│   ├── mpdecimal
│   ├── [email protected]
│   │   └── ca-certificates
│   ├── readline
│   ├── sqlite
│   │   └── readline
│   ├── xz
│   └── pkg-config
└── rust
    ├── [email protected]
    │   └── ca-certificates
    ├── pkg-config
    ├── cmake
    ├── ninja
    │   └── [email protected]
    │       ├── mpdecimal
    │       ├── [email protected]
    │       │   └── ca-certificates
    │       ├── sqlite
    │       │   └── readline
    │       ├── xz
    │       └── pkg-config
    └── [email protected]
        ├── mpdecimal
        ├── [email protected]
        │   └── ca-certificates
        ├── sqlite
        │   └── readline
        ├── xz
        └── pkg-config

azure/functions/azure-functions-core-tools@4

gh
└── go

git
├── gettext
└── pcre2

Conclusion

I hope this post introduces you to Homebrew, the package manager for MacOS; you can explore more about it in its official docs.