martin_heller
Contributor

Homebrew tutorial: How to use Homebrew for MacOS

how-to
Dec 20, 201826 mins
Open SourceSoftware Development

The open source Homebrew package manager gives Mac users access to Unix command-line utilities that Apple left out — and a lot more

sort filter separate  process packages
Credit: Thinkstock

In the beginning was the command-line. That’s true of almost all operating systems, but somewhere along the way a graphical user interface became the “face” of the computer, and only old hackers or initiates even knew how to open a command-line console or terminal.

Many Mac users can manage marvelously without ever opening the Terminal app, much less typing commands into the Bash shell. If you spend your day editing still images with Lightroom, the MacOS command line likely has little utility for you.

More technical users, and especially software developers, need to work in the shell at least occasionally, if not on a daily basis. Technical users with some Unix or Linux background will discover that not all the usual utilities are installed in MacOS as it comes from the factory, even though at its heart MacOS is a BSD Unix system.

As a software developer and a software reviewer, I often run into this issue. The first time it happened I was following online installation instructions that purported to work on Linux and Linux-like systems (such as Mac OS X, as it was known at the time), but had only actually been tested on one or two distros of Linux. The installation command provided was based on <a href="https://www.gnu.org/software/wget/manual/wget.html#Overview" rel="nofollow">wget</a>, a utility for non-interactive download of files from the web.

Unfortunately for me, wget doesn’t come installed on a Mac, although the somewhat similar <a href="https://manpages.debian.org/stretch/curl/curl.1.en.html" rel="nofollow">curl</a> utility does. Translating wget options to curl options was an annoying extra step I didn’t need; the lack of recursive downloads in curl was a complete showstopper for downloading the HTML documentation.

Apple has no official mechanisms for adding new command-line utilities. What it has for a package manager is the App Store, but that’s only for applications (apps). When I searched the web for “wget not found mac” I quickly discovered that there were several ways to solve my problem, including building wget from the source code. Of these, the most frequently recommended was Homebrew.

What is Homebrew?

Homebrew calls itself “The missing package manager for MacOS” (emphasis mine). That’s pithy, but a little cavalier. Homebrew is certainly a package manager for MacOS, but there are others, such as MacPorts and Fink. And for that matter, the App Store is a package manager, albeit specialized to, um, App Store apps. Nevertheless, Homebrew is the most popular third-party package manager for MacOS, and supplies functionality missing from the App Store.

You can use Homebrew (brew) to install, uninstall, and upgrade any of thousands of “formulae” (i.e. package definitions) from its core public repository, plus any tap repositories you care to use. You can also use the Homebrew cask facility (brew-cask) as a way to install, uninstall, and upgrade precompiled MacOS binaries (such as apps, but not App Store apps) from the command line. If you wish, you can create your own Homebrew packages and write your own Homebrew formulae.

Install Homebrew

Since Homebrew itself is only for MacOS, it has fairly simple installation instructions — at least, if your OS version is more recent than OS X Lion 10.7. Homebrew basically just runs a Ruby script after downloading it from GitHub; you’ll note in the screenshot below that Homebrew uses curl for the download, not wget, for reasons I discussed earlier.

homebrew home IDG

It’s easy to install Homebrew. Just follow the instructions on the website. 

Homebrew also confines itself to Ruby code supported by the Ruby version that ships with the oldest OS X version that it supports, 10.5 Leopard.

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

It is possible that the Homebrew installation will ask you to install Xcode or the Command Line Tools for Xcode. Whether it does and which it suggests would be dependent on your OS version and the versions of the C and C++ compilers installed on your system.

According to the Homebrew installation page, if you have an older version of Mac OS X (Lion 10.7 or before), then you need to add the --insecure argument (or equivalently -k, making the full argument list -fsSLk) to the curl command. That’s because the version of curl on your system won’t successfully talk to GitHub using HTTPS. Homebrew will fix that if you install it and then ask it to update itself and its dependencies with brew update.

If you download the install script and read it, you’ll see it includes logic to abort if the Mac OS X version is less than 10.5. If that triggers, the script will refer you to TigerBrew, which is an experimental fork of Homebrew that adds support for PowerPC Macs and Macs running Tiger.

There is also a “we don’t support this version” warning that will trigger for MacOS versions that are too old or too new, currently set at 10.11 and 10.13. That doesn’t mean Homebrew won’t work on those versions; it mostly means that the developers don’t test against them.

Use Homebrew to install a package

As a basic example, let’s try installing wget with Homebrew. First, launch Terminal.

The installation command is just as listed in the image above: brew install wget. On my machine, it produced the rather lengthy output below. Note that the installation began with an auto-update of Homebrew, then installed wget’s dependencies, and then finally installed wget.

Updating Homebrew...
==> Homebrew is run entirely by unpaid volunteers. Please consider donating:
  https://github.com/Homebrew/brew#donations
==> Auto-updated Homebrew!
Updated 2 taps (homebrew/core, homebrew/cask).
==> New Formulae
amtk                                        kustomize                                   range-v3
aws-okta                                    libsignal-protocol-c                        safe
badtouch                                    lsusb                                       serverless
black                                       luarocks                                    sfst
cash-cli                                    micronaut                                   sonarqube-lts
docker-credential-helper-ecr                miniserve                                   squashfuse
docker-machine-driver-hyperkit              pcapplusplus                                thors-serializer
fauna-shell                                 perltidy                                    weaver
gambit                                      petsc-complex                               wiremock-standalone
gptfdisk                                    pijul                                       wskdeploy
gradio                                      prettier                                    xcodegen
helmfile                                    pulumi                                      xsimd
infrakit                                    pyside                                      yarn-completion
kubernetes-service-catalog-client           python-yq                                   zlog
==> Updated Formulae
automake                        fbi-servefiles                   libpcap                          puzzles
cmake                           fd                               libphonenumber                   py2cairo
cockroach                       fdclone                          libpq                            py3cairo
eigen                           fdroidserver                     libpqxx                          pyenv
libpng                          feh                              libpst                           pyinvoke
numpy                           ffmpeg                           libqalculate                     qbs
openssl                         ffmpeg@2.8                       librdkafka                       qcachegrind
subversion                      fibjs                            librealsense                     qemu
abcde                            file-formula                     libsoup                          qjackctl
abcm2ps                          file-roller                      libssh                           qpdf
ace                              fio                              libtensorflow                    qtkeychain
acpica                           firebase-cli                     libtorrent-rasterbar             quicktype
activemq                         flintrock                        libtrace                         rabbitmq
adr-tools                        flow                             libuv                            radare2
advancemame                      fluent-bit                       libvirt                          rakudo-star
agda                             flyway                           libwps                           rancher-cli
aircrack-ng                      fmt                              libxkbcommon                     raylib
allure                           fn                               lighttpd                         re2
amazon-ecs-cli                   folly                            link-grammar                     reattach-to-user-namespace
angband                          fonttools                        linkerd                          redis
angle-grinder                    fortio                           liquibase                        rename
angular-cli                      fq                               liquigraph                       restic
annie                            freeciv                          llvm                             riemann-client
ansible                          freeimage                        lmod                             ripgrep
ansible-cmdb                     freetds                          log4cplus                        rocksdb
ansiweather                      fribidi                          logtalk                          roll
ant                              frugal                           lrzsz                            root
ant@1.9                          fruit                            lsof                             roswell
apache-arrow                     fselect                          lua                              rsyslog
apache-arrow-glib                fuseki                           lua@5.1                          rtv
apache-flink                     futhark                          lxc                              ruby-build
app-engine-python                fwknop                           lynis                            ruby-install
appscale-tools                   fwup                             lynx                             rust
arangodb                         gammaray                         macvim                           rustup-init
argyll-cms                       gauche                           mafft                            s-nail
ark                              gcc                              mapcrafter                       s3cmd
arm-linux-gnueabihf-binutils     gdb                              mariadb                          s3fs
armadillo                        gdbm                             mariadb@10.0                     samtools
arpack                           gegl                             mariadb@10.1                     sane-backends
artifactory                      geoipupdate                      mariadb@10.2                     sbcl
asdf                             geos                             math-comp                        sbt
ask-cli                          geoserver                        mbedtls                          sbtenv
ats2-postiats                    get_iplayer                      mdds                             sccache
aws-elasticbeanstalk             giflib                           mdp                              sceptre
aws-sdk-cpp                      gimme                            megatools                        schema-evolution-manager
awscli                           git-annex                        memcached                        schismtracker
azure-cli                        git-archive-all                  menhir                           scrcpy
b2-tools                         git-extras                       mercurial                        selenium-server-standalone
babel                            git-ftp                          meson                            sfk
babl                             git-lfs                          metabase                         shairport-sync
bacula-fd                        git-quick-stats                  micro                            shellharden
ballerina                        gitbucket                        mikutter                         shfmt
bareos-client                    giter8                           mill                             shibboleth-sp
bartycrouch                      gitlab-gem                       mingw-w64                        singular
bat                              gitlab-runner                    minimal-racket                   sipp
bats-core                        gjstest                          mint                             skaffold
bazel                            glib                             mitmproxy                        skafos
bcftools                         glib-networking                  mkcert                           skinny
bdw-gc                           globus-toolkit                   mkdocs                           skktools
bear                             glslviewer                       mkl-dnn                          sleuthkit
beast                            gmt@4                            mkvtoolnix                       snakemake
bench                            gnatsd                           mlkit                            sonarqube
bettercap                        gnome-builder                    modd                             sord
bgpstream                        gnome-latex                      modules                          spdlog
binaryen                         gnu-prolog                       monero                           sphinx-doc
bind                             gnumeric                         mongo-c-driver                   spotbugs
binutils                         gnupg                            mongo-cxx-driver                 sqlmap
bit                              gnupg@1.4                        mongodb                          sqoop
bitcoin                          gnuradio                         mongodb@3.6                      squid
bitrise                          gnutls                           mongoose                         sratoolkit
bitwarden-cli                    go-bindata                       mono                             ssh-copy-id
blockhash                        go-jira                          mosquitto                        ssh-permit-a38
bowtie2                          go-statik                        mpd                              sshguard
buildifier                       gobuster                         mpop                             sshrc
byobu                            gocryptfs                        mr                               sshtrix
byteman                          goenv                            mrtg                             sslsplit
bzt                              goffice                          msgpack                          sslyze
cabextract                       gomplate                         msitools                         stanford-ner
cake                             goreleaser                       mujs                             stanford-parser
camlp4                           gosu                             mutt                             stern
camlp5                           gpac                             mvtools                          stone-soup
capstone                         gr-osmosdr                       mypy                             suite-sparse
cargo-completion                 gradle                           mysql                            sundials
cassandra                        grafana                          mysql-client                     suricata
ccextractor                      grails                           mysql@5.5                        swift
ccrypt                           grakn                            mysql@5.6                        swift-protobuf
ceres-solver                     graphite2                        mysql@5.7                        swiftformat
certbot                          groonga                          nagios                           swiftlint
cfr-decompiler                   groovy                           nativefier                       syncthing
cglm                             groovysdk                        naturaldocs                      sysdig
chakra                           grpc                             nco                              talloc
charm                            grunt-completion                 neo4j                            tarantool
checkstyle                       gsoap                            neomutt                          taskell
chrome-cli                       gst-editing-services             neovim                           tbox
chronograf                       gst-libav                        net-snmp                         telegraf
cimg                             gst-plugins-bad                  nginx                            teleport
circleci                         gst-plugins-base                 nifi                             tepl
citus                            gst-plugins-good                 nnn                              termius
ckan                             gst-plugins-ugly                 node                             terraform
clamav                           gst-python                       node-build                       terraform_landscape
clblast                          gst-rtsp-server                  node@6                           terragrunt
clingo                           gst-validate                     node@8                           the_platinum_searcher
clojure                          gstreamer                        nodeenv                          the_silver_searcher
closure-compiler                 gtk-vnc                          npth                             tig
cmark-gfm                        guile                            nsd                              tiger-vnc
collectd                         gupnp                            ntl                              tippecanoe
commandbox                       gutenberg                        ntp                              titlecase
composer                         hadolint                         nuget                            tkdiff
conan                            hadoop                           nuxeo                            tmate
confluent-oss                    hana                             nvc                              tmux-xpanes
confuse                          haproxy                          nyancat                          todolist
conjure-up                       harfbuzz                         ocaml                            tomcat@8
consul                           hashcat                          ocaml-num                        tor
convox                           hcloud                           ocamlbuild                       tox
coq                              heroku                           ocamlsdl                         traefik
corsixth                         hexgui                           ocrmypdf                         trafficserver
couchdb                          hh                               octave                           translate-shell
cquery                           highlight                        odpi                             trash
credstash                        hive                             ola                              travis
creduce                          hlint                            open-mpi                         triton
cromwell                         hopenpgp-tools                   openapi-generator                ttfautohint
cryptol                          hss                              openblas                         tty-solitaire
crystal                          htslib                           opencoarrays                     tup
csvkit                           httpd                            opendetex                        twarc
csvprintf                        hub                              openimageio                      twoping
curl                             hugo                             opensaml                         txr
cython                           hyperfine                        openshift-cli                    typescript
dar                              hyperscan                        openssh                          u-boot-tools
darksky-weather                  i2p                              openssl@1.1                      ubertooth
dartsim                          icdiff                           openvdb                          uhd
dateutils                        igv                              osc                              unixodbc
dbus                             imagemagick                      osmium-tool                      upx
dcd                              imagemagick@6                    osquery                          urh
dcos-cli                         imageoptim-cli                   overmind                         uriparser
ddclient                         influxdb                         p11-kit                          utf8proc
deark                            ios-webkit-debug-proxy           packer                           util-linux
dep                              ipfs                             paket                            uwsgi
dependency-check                 ipython                          pandoc                           v8
dhall-json                       ipython@5                        pango                            vala
di                               isl                              parallel                         vapoursynth
diff-pdf                         jboss-forge                      pari                             vault
diffoscope                       jenkins                          passenger                        vcftools
discount                         jenkins-job-builder              pazpar2                          vdirsyncer
distcc                           jenkins-lts                      pc6001vx                         vegeta
dita-ot                          jfrog-cli-go                     pcb2gcode                        verilator
django-completion                jhipster                         pdftoedn                         vert.x
dlib                             jlog                             pdftoipe                         vim
dmd                              joplin                           pegtl                            vips
dnscrypt-proxy                   jpeg-archive                     percona-server-mongodb           virtuoso
dnsdist                          jpeg-turbo                       percona-server@5.6               vnu
docfx                            json-fortran                     percona-toolkit                  vowpal-wabbit
docker                           jsonnet                          perl-build                       vrpn
docker-completion                juju                             pgbouncer                        vsts-cli
docker-compose                   jump                             pgcli                            wabt
docker-compose-completion        kafka                            pgplot                           wandio
docker-credential-helper         kerl                             pgpool-ii                        watchexec
dovecot                          kitchen-sync                     php                              webdis
draco                            knot                             php-code-sniffer                 webpack
dropbear                         knot-resolver                    php-cs-fixer                     webtorrent-cli
druid                            kompose                          php@5.6                          weechat
dscanner                         kontena                          php@7.0                          whois
dtc                              kops                             php@7.1                          wine
duck                             kotlin                           phplint                          winetricks
duply                            kube-aws                         phpmyadmin                       wiredtiger
dwarfutils                       kubecfg                          phpunit                          wireguard-tools
dxpy                             kubectx                          picard-tools                     wireshark
dynare                           kubeless                         pilosa                           wp-cli
e2fsprogs                        kubernetes-cli                   pkcs11-helper                    wtf
eccodes                          kubernetes-helm                  plantuml                         wxmac
efl                              lablgtk                          platformio                       xapian
elektra                          landscaper                       pmd                              xml-security-c
elixir                           latex2rtf                        pony-stable                      xml-tooling-c
elm                              lensfun                          ponyc                            xmrig
elvish                           lf                               poppler                          xonsh
emscripten                       libatomic_ops                    postgresql                       xtensor
ephemeralpg                      libcouchbase                     postgresql@9.4                   yafc
erlang                           libdazzle                        postgresql@9.5                   yara
erlang@19                        libdill                          postgresql@9.6                   yarn
erlang@20                        libdvbpsi                        pre-commit                       yaz
etcd                             libextractor                     prest                            ykman
ethereum                         libfixbuf                        presto                           yle-dl
exercism                         libgit2                          primesieve                       you-get
exomizer                         libgpg-error                     prometheus                       youtube-dl
expat                            libgphoto2                       proselint                        yq
exploitdb                        libgsf                           protobuf-c                       zabbix
f3                               libhdhomerun                     protobuf@2.6                     zanata-client
faas-cli                         libical                          proxychains-ng                   zebra
fabric                           libmagic                         pspg                             zero-install
fakeroot                         libomp                           pulseaudio                       zimg
fastqc                           libosmium                        pushpin                          znc
==> Deleted Formulae
artifactory-cli-go        boot2docker-completion    ghc@8.0                   gpg-agent                 wry
boot2docker               dirmngr                   gnupg@2.0                 node@4

==> Installing dependencies for wget: gettext, libunistring, libidn2, openssl
==> Installing wget dependency: gettext
==> Downloading https://homebrew.bintray.com/bottles/gettext-0.19.8.1.high_sierra.bottle.tar.gz
######################################################################## 100.0%
==> Pouring gettext--0.19.8.1.high_sierra.bottle.tar.gz
==> Caveats
gettext is keg-only, which means it was not symlinked into /usr/local,
because macOS provides the BSD gettext library & some software gets confused if both are in the library path.

If you need to have gettext first in your PATH run:
  echo 'export PATH="/usr/local/opt/gettext/bin:$PATH"' >> ~/.bash_profile

For compilers to find gettext you may need to set:
  export LDFLAGS="-L/usr/local/opt/gettext/lib"
  export CPPFLAGS="-I/usr/local/opt/gettext/include"

==> Summary
🍺  /usr/local/Cellar/gettext/0.19.8.1: 1,935 files, 16.9MB
==> Installing wget dependency: libunistring
==> Downloading https://homebrew.bintray.com/bottles/libunistring-0.9.10.high_sierra.bottle.tar.gz
######################################################################## 100.0%
==> Pouring libunistring--0.9.10.high_sierra.bottle.tar.gz
🍺  /usr/local/Cellar/libunistring/0.9.10: 54 files, 4.4MB
==> Installing wget dependency: libidn2
==> Downloading https://homebrew.bintray.com/bottles/libidn2-2.0.5.high_sierra.bottle.tar.gz
######################################################################## 100.0%
==> Pouring libidn2--2.0.5.high_sierra.bottle.tar.gz
🍺  /usr/local/Cellar/libidn2/2.0.5: 68 files, 668.6KB
==> Installing wget dependency: openssl
==> Downloading https://homebrew.bintray.com/bottles/openssl-1.0.2p.high_sierra.bottle.tar.gz
######################################################################## 100.0%
==> Pouring openssl--1.0.2p.high_sierra.bottle.tar.gz
==> Caveats
A CA file has been bootstrapped using certificates from the SystemRoots
keychain. To add additional certificates (e.g. the certificates added in
the System keychain), place .pem files in
  /usr/local/etc/openssl/certs

and run
  /usr/local/opt/openssl/bin/c_rehash

openssl is keg-only, which means it was not symlinked into /usr/local,
because Apple has deprecated use of OpenSSL in favor of its own TLS and crypto libraries.

If you need to have openssl first in your PATH run:
  echo 'export PATH="/usr/local/opt/openssl/bin:$PATH"' >> ~/.bash_profile

For compilers to find openssl you may need to set:
  export LDFLAGS="-L/usr/local/opt/openssl/lib"
  export CPPFLAGS="-I/usr/local/opt/openssl/include"

For pkg-config to find openssl you may need to set:
  export PKG_CONFIG_PATH="/usr/local/opt/openssl/lib/pkgconfig"

==> Summary
🍺  /usr/local/Cellar/openssl/1.0.2p: 1,793 files, 12.3MB
==> Installing wget
==> Downloading https://homebrew.bintray.com/bottles/wget-1.19.5.high_sierra.bottle.tar.gz
######################################################################## 100.0%
==> Pouring wget--1.19.5.high_sierra.bottle.tar.gz
🍺  /usr/local/Cellar/wget/1.19.5: 50 files, 3.7MB
==> Caveats
==> gettext
gettext is keg-only, which means it was not symlinked into /usr/local,
because macOS provides the BSD gettext library & some software gets confused if both are in the library path.

If you need to have gettext first in your PATH run:
  echo 'export PATH="/usr/local/opt/gettext/bin:$PATH"' >> ~/.bash_profile

For compilers to find gettext you may need to set:
  export LDFLAGS="-L/usr/local/opt/gettext/lib"
  export CPPFLAGS="-I/usr/local/opt/gettext/include"

==> openssl
A CA file has been bootstrapped using certificates from the SystemRoots
keychain. To add additional certificates (e.g. the certificates added in
the System keychain), place .pem files in
  /usr/local/etc/openssl/certs

and run
  /usr/local/opt/openssl/bin/c_rehash

openssl is keg-only, which means it was not symlinked into /usr/local,
because Apple has deprecated use of OpenSSL in favor of its own TLS and crypto libraries.

If you need to have openssl first in your PATH run:
  echo 'export PATH="/usr/local/opt/openssl/bin:$PATH"' >> ~/.bash_profile

For compilers to find openssl you may need to set:
  export LDFLAGS="-L/usr/local/opt/openssl/lib"
  export CPPFLAGS="-I/usr/local/opt/openssl/include"

For pkg-config to find openssl you may need to set:
  export PKG_CONFIG_PATH="/usr/local/opt/openssl/lib/pkgconfig"

When I test the new installation with wget --help, it tells me it is GNU Wget 1.19.5 and gives me the help text. The command man wget also works at this point. Running which wget tells me that the installation is at /usr/local/bin/wget, and ls -l /usr/local/bin/wget tells me that it’s a pointer to ../Cellar/wget/1.19.5/bin/wget. That is consistent with what Homebrew reported during the installation.

As an aside, note that wget will only retrieve URLs that give it permission, and it respects the Robot Exclusion Standard (/robots.txt). So, for example, if you try to download a site that doesn’t want to be scraped, you’ll get a 403 Forbidden error.

$ wget pcpitstop.com
--2018-08-27 11:18:20--  http://pcpitstop.com/
Resolving pcpitstop.com (pcpitstop.com)... 104.20.82.39, 104.20.83.39
Connecting to pcpitstop.com (pcpitstop.com)|104.20.82.39|:80... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: http://www.pcpitstop.com/ [following]
--2018-08-27 11:18:20--  http://www.pcpitstop.com/
Resolving www.pcpitstop.com (www.pcpitstop.com)... 104.20.83.39, 104.20.82.39
Connecting to www.pcpitstop.com (www.pcpitstop.com)|104.20.83.39|:80... connected.
HTTP request sent, awaiting response... 403 Forbidden
2018-08-27 11:18:20 ERROR 403: Forbidden.

By contrast, curl will blithely download the single pages you request, whether or not the site has robot exclusions. curl http://www.pcpitstop.com will output a bunch of HTML from the site’s home page.

As an example where wget will work fine, consider this example from the Gnu wget documentation:

wget ftp://ftp.gnu.org/pub/gnu/
links index.html

I tried it, and the wget part worked, but the links command wasn’t found:

$ wget ftp://ftp.gnu.org/pub/gnu/
--2018-08-27 11:35:34--  ftp://ftp.gnu.org/pub/gnu/
           => ‘.listing’
Resolving ftp.gnu.org (ftp.gnu.org)... 208.118.235.20
Connecting to ftp.gnu.org (ftp.gnu.org)|208.118.235.20|:21... connected.
Logging in as anonymous ... Logged in!
==> SYST ... done.    ==> PWD ... done.
==> TYPE I ... done.  ==> CWD (1) /pub/gnu ... done.
==> PASV ... done.    ==> LIST ... done.
.listing                           [ <=>                                                 ]  24.87K  --.-KB/s    in 0.01s  

2018-08-27 11:35:34 (2.11 MB/s) - ‘.listing’ saved [25466]

Removed ‘.listing’.
Wrote HTML-ized index to ‘index.html’ [37782].
Martins-Retina-MacBook:~ martinheller$ links index.html
-bash: links: command not found

What should you do to install links? Your first guess is probably correct:

$ brew install links
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 2 taps (homebrew/core, homebrew/cask).
==> New Formulae
eslint                   geogram                  go@1.10                  json11                   luit
==> Updated Formulae
go                  diff-pdf             gmt@4                libphonenumber       pdal                 tomcat
hdf5                dynare               godep                libtensorflow        pdftoedn             tomcat-native
angular-cli          elasticsearch@5.6    goenv                mdcat                pdftoipe             tomcat@7
armadillo            elixir               gromacs              meson                perl-build           tomcat@8
augeas               feedgnuplot          hcloud               minizinc             plantuml             vtk
awscli               field3d              iso-codes            mkcert               poppler              yubico-piv-tool
bwfmetaedit          flann                jenkins              nco                  prettier             zsh-completions
caffe                folly                jenkins-job-builder  ncview               s6
cimg                 git-cola             kallisto             netcdf               saxon
ckan                 git-quick-stats      kibana@5.6           nghttp2              sratoolkit
convox               gitlab-runner        libbi                octave               svtplay-dl
dartsim              gmt                  libmatio             pcl                  thors-serializer

==> Downloading https://homebrew.bintray.com/bottles/links-2.16.high_sierra.bottle.tar.gz
######################################################################## 100.0%
==> Pouring links--2.16.high_sierra.bottle.tar.gz
🍺  /usr/local/Cellar/links/2.16: 19 files, 1.8MB
Martins-Retina-MacBook:~ martinheller$ links index.html

By the way, an alternative to links on MacOS is simply to open the HTML file in your browser. From the command line, that’s open index.html.

Query Homebrew

You saw above that Homebrew will list the recipes that have changed in its directory after an automatic update and will flag the installed recipes that have changed in bold with green checkmarks . You can also ask Homebrew to show you what it currently has installed:

$ brew ls
apr            cockroach    gflags       jpeg           links     pcre         subversion
apr-util       delve        glog         leveldb        lmdb      perl         swig
autoconf       eigen        go           libidn2        nmap      pkg-config   szip
automake       fontconfig   gperftools   libpng         numpy     readline     webp
boost          freetype     graphviz     libtiff        opencv    scons        wget
boost-python   gd           hdf5         libtool        openexr   snappy
cmake          gettext      ilmbase      libunistring   openssl   sqlite

Any option flags are passed to ls, for example:

$ brew ls -l
total 0
drwxr-xr-x  3 martinheller  admin   96 Apr  9 16:37 apr
drwxr-xr-x  3 martinheller  admin   96 Apr  9 16:37 apr-util
drwxr-xr-x  3 martinheller  admin   96 Oct 19  2016 autoconf
drwxr-xr-x  3 martinheller  admin   96 Oct 19  2016 automake
drwxr-xr-x  4 martinheller  admin  128 Jan  5  2017 boost
drwxr-xr-x  4 martinheller  admin  128 Jan  5  2017 boost-python
drwxr-xr-x  4 martinheller  admin  128 Dec  9  2016 cmake
drwxr-xr-x  3 martinheller  admin   96 Dec 15  2017 cockroach
drwxr-xr-x  4 martinheller  admin  128 Jul  5 14:03 delve
drwxr-xr-x  4 martinheller  admin  128 Dec  9  2016 eigen
drwxr-xr-x  3 martinheller  admin   96 Jan  5  2017 fontconfig
drwxr-xr-x  3 martinheller  admin   96 Jan  5  2017 freetype
drwxr-xr-x  3 martinheller  admin   96 Jan  5  2017 gd
drwxr-xr-x  3 martinheller  staff   96 Aug 24 14:33 gettext
drwxr-xr-x  4 martinheller  admin  128 Dec  9  2016 gflags
drwxr-xr-x  4 martinheller  admin  128 Dec  9  2016 glog
drwxr-xr-x  3 martinheller  admin   96 Jul  5 14:03 go
drwxr-xr-x  3 martinheller  admin   96 Oct 19  2016 gperftools
drwxr-xr-x  4 martinheller  admin  128 Jan  5  2017 graphviz
drwxr-xr-x  4 martinheller  admin  128 Jan  5  2017 hdf5
drwxr-xr-x  3 martinheller  admin   96 Oct 19  2016 ilmbase
drwxr-xr-x  3 martinheller  admin   96 Oct 19  2016 jpeg
drwxr-xr-x  3 martinheller  admin   96 Oct 19  2016 leveldb
drwxr-xr-x  3 martinheller  staff   96 Aug 24 14:34 libidn2
drwxr-xr-x  5 martinheller  admin  160 Jan  5  2017 libpng
drwxr-xr-x  4 martinheller  admin  128 Dec  9  2016 libtiff
drwxr-xr-x  3 martinheller  admin   96 Oct 19  2016 libtool
drwxr-xr-x  3 martinheller  staff   96 Aug 24 14:34 libunistring
drwxr-xr-x  3 martinheller  staff   96 Aug 27 11:37 links
drwxr-xr-x  4 martinheller  admin  128 Jan  5  2017 lmdb
drwxr-xr-x  3 martinheller  admin   96 Mar 22 14:29 nmap
drwxr-xr-x  3 martinheller  admin   96 Oct 19  2016 numpy
drwxr-xr-x  4 martinheller  admin  128 Jan  5  2017 opencv
drwxr-xr-x  3 martinheller  admin   96 Oct 19  2016 openexr
drwxr-xr-x  6 martinheller  staff  192 Aug 24 14:34 openssl
drwxr-xr-x  3 martinheller  admin   96 Apr  9 16:37 pcre
drwxr-xr-x  3 martinheller  admin   96 Apr  9 16:37 perl
drwxr-xr-x  4 martinheller  admin  128 Apr  9 16:37 pkg-config
drwxr-xr-x  3 martinheller  admin   96 Apr  9 16:37 readline
drwxr-xr-x  3 martinheller  admin   96 Apr  9 16:38 scons
drwxr-xr-x  3 martinheller  admin   96 Oct 19  2016 snappy
drwxr-xr-x  3 martinheller  admin   96 Apr  9 16:37 sqlite
drwxr-xr-x  3 martinheller  admin   96 Apr  9 16:38 subversion
drwxr-xr-x  3 martinheller  admin   96 Apr  9 16:37 swig
drwxr-xr-x  3 martinheller  admin   96 Oct 19  2016 szip
drwxr-xr-x  3 martinheller  admin   96 Jan  5  2017 webp
drwxr-xr-x  3 martinheller  staff   96 Aug 24 14:34 wget

You can use list as well; ls is an alias for list.

How can you find out what Homebrew supports? It’s a long list, so you probably wouldn’t want to output it in your terminal window, although you can search your current installed core and cask formula lists with brew search <name> or brew search --desc <keyword>. The core list of Homebrew packages is on the web, however, which can sometimes be more convenient, since you can scroll through and search with CMD-f:

homebrew formulae IDG

A list of core Homebrew formulae, or package definitions, is available online. 

You can also ask Homebrew about its commands:

$ brew commands
Built-in commands
--cache         cat             doctor          link            postinstall     tap             untap
--cellar        cleanup         fetch           list            prune           tap-info        update
--env           command         gist-logs       log             readall         tap-pin         update-report
--prefix        commands        help            migrate         reinstall       tap-unpin       update-reset
--repository    config          home            missing         search          uninstall       upgrade
--version       deps            info            options         sh              unlink          uses
analytics       desc            install         outdated        style           unpack          vendor-install
cask            diy             leaves          pin             switch          unpin

Built-in developer commands
audit             create            irb               mirror            release-notes     test
bottle            edit              linkage           prof              ruby              tests
bump-formula-pr   formula           man               pull              tap-new           update-test

And you can ask Homebrew to see the source code of any Homebrew formula on your machine, whether or not it is installed:

$ brew cat delve
class Delve < Formula
  desc "Debugger for the Go programming language."
  homepage "https://github.com/derekparker/delve"
  url "https://github.com/derekparker/delve/archive/v1.0.0.tar.gz"
  version "1.0.0"
  sha256 "38117c9db41db23a27a1c2e99be17d7fb73d1653de0751ee1262b460a2b26dc4"

  head "https://github.com/derekparker/delve.git"

  depends_on "go" => :build

  def install
    dlv_cert = "dlv-cert"

    File.open("dlv-cert.cfg", "w") do |file|
      file.write(%(
[ req ]
default_bits            = 2048                  # RSA key size
encrypt_key             = no                    # Protect private key
default_md              = sha512                # MD to use
prompt                  = no                    # Prompt for DN
distinguished_name      = codesign_dn           # DN template

[ codesign_dn ]
commonName              = "dlv-cert"

[ codesign_reqext ]
keyUsage                = critical,digitalSignature
extendedKeyUsage        = critical,codeSigning
          ))
    end

    find_output = `security find-certificate -Z -p -c #{dlv_cert} 
Library/Keychains/System.keychain`
    if find_output.start_with? "SHA-1 hash"
      ohai "#{dlv_cert} is already installed, no need to create it"
    else
      ohai "Generating #{dlv_cert}"
      system "openssl", "req", "-new", "-newkey", "rsa:2048", "-x509", 
        "-days", "3650", "-nodes", "-config", "#{dlv_cert}.cfg", 
        "-extensions", "codesign_reqext", "-batch", 
        "-out", "#{dlv_cert}.cer", "-keyout", "#{dlv_cert}.key"

      ohai "[SUDO] Installing #{dlv_cert} as root"
      system "sudo", "security", "add-trusted-cert", "-d", "-r", "trustRoot", 
        "-k", "/Library/Keychains/System.keychain", "#{dlv_cert}.cer"
      system "sudo", "security", "import", "#{dlv_cert}.key", "-A", 
        "-k", "/Library/Keychains/System.keychain"

      ohai "[SUDO] Killing taskgated"
      system "sudo", "pkill", "-f", "/usr/libexec/taskgated"
    end

    mkdir_p buildpath/"src/github.com/derekparker"
    ln_sf buildpath, buildpath/"src/github.com/derekparker/delve"

    ENV["GOBIN"] = buildpath
    ENV["GOPATH"] = buildpath
    ENV["CERT"] = dlv_cert

    if head?
      system "make", "build"
    else
      system "make", "build", "BUILD_SHA=v#{version}"
    end
    bin.install "dlv"
  end

  def caveats; <<~EOS
    If you get "could not launch process: could not fork/exec", you need to try
    in a new terminal.

    When uninstalling, to remove the dlv-cert certificate, run this command:

        $ sudo security delete-certificate -t -c dlv-cert /Library/Keychains/System.keychain

    Alternatively, you may want to delete from the Keychain (with the Imported private key).

    EOS
  end

  test do
    system bin/"dlv", "version"
  end
end

You can quickly find out where any Homebrew formula is hosted and what it does:

$ brew info gdbm
gdbm: stable 1.18 (bottled)
GNU database manager
https://www.gnu.org/software/gdbm/
Not installed
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/gdbm.rb
==> Options
--with-libgdbm-compat
    Build libgdbm_compat, a compatibility layer which provides UNIX-like dbm and ndbm interfaces.

For additional description, you can bring up the formula’s home page in your default browser:

$ brew home gdbm

You may be interested in knowing the dependencies of one or more brew formulae without seeing all the Ruby code, for example:

$ brew deps mongodb
gdbm
openssl
python@2
readline
sqlite

Or you may want to see the dependencies for all installed formulae:

$ brew deps --installed
apr:
apr-util: apr openssl
autoconf:
automake: autoconf
boost:
boost-python: boost
cmake:
cockroach:
go-delve/delve/delve:
eigen:
fontconfig: freetype libpng
freetype: libpng
gd: fontconfig freetype jpeg libpng libtiff webp
gettext:
gflags:
glog: gflags
go:
gperftools:
graphviz: fontconfig freetype gd jpeg libpng libtiff libtool webp
hdf5: gcc gmp isl libmpc mpfr szip
ilmbase:
jpeg:
leveldb: gperftools snappy
libidn2: gettext libunistring
libpng:
libtiff: jpeg
libtool:
libunistring:
links: openssl
lmdb:
nmap: openssl
numpy: gdbm openssl python readline sqlite xz
opencv: eigen ffmpeg gdbm ilmbase jpeg libpng libtiff numpy openexr openssl python
python@2 readline sqlite tbb xz
openexr: ilmbase
openssl:
pcre:
perl:
pkg-config:
readline:
scons:
snappy:
sqlite: readline
subversion: apr apr-util openssl perl sqlite
swig: pcre
szip:
webp: jpeg libpng
wget: gettext libidn2 libunistring openssl

Troubleshoot Homebrew

Many utilities can be installed using Homebrew as well as with another method, such as a PKG installer or a DMG disk image. There are potential dangers when you use multiple installation methods. If you don’t pay attention, or you don’t remember what you did the last time (my hand is up for that one), you can wind up with multiple copies of a program in different locations. The first searched path that has the program is the one that will run: you may want to uninstall one of the copies.

You can find out the location of the copy that will run with the which command, for example which go. You can get the full information with ls, for example ls -l `which go`. If the copy you want to uninstall was installed with Homebrew, you can delete it with brew uninstall <name>, for example brew uninstall go.

Brew doesn’t delete old versions by default when you install new versions. To delete all brewed versions of one particular program, use the --force flag, for example brew uninstall --force go.

To delete all old versions for all installed formulae, you can use brew cleanup. You’ll see something like this:

$ brew cleanup
Warning: Skipping automake: most recent version 1.16.1_1 not installed
Warning: Skipping boost: most recent version 1.67.0_1 not installed
Warning: Skipping boost-python: most recent version 1.67.0 not installed
Warning: Skipping cmake: most recent version 3.12.1 not installed
Warning: Skipping cockroach: most recent version 2.0.5 not installed
Removing: /usr/local/Cellar/delve/0.12.1... (6 files, 8MB)
Warning: Skipping eigen: most recent version 3.3.5 not installed
Warning: Skipping fontconfig: most recent version 2.13.0 not installed
Warning: Skipping freetype: most recent version 2.9.1 not installed
Warning: Skipping gd: most recent version 2.2.5 not installed
Warning: Skipping gflags: most recent version 2.2.1 not installed
Warning: Skipping glog: most recent version 0.3.5_3 not installed
Warning: Skipping gperftools: most recent version 2.7 not installed
Removing: /usr/local/Cellar/graphviz/2.38.0_1... (506 files, 67.0MB)
Warning: Skipping hdf5: most recent version 1.10.3 not installed
Warning: Skipping ilmbase: most recent version 2.2.1 not installed
Warning: Skipping jpeg: most recent version 9c not installed
Warning: Skipping leveldb: most recent version 1.20_2 not installed
Warning: Skipping libpng: most recent version 1.6.35 not installed
Warning: Skipping libtiff: most recent version 4.0.9_4 not installed
Warning: Skipping lmdb: most recent version 0.9.22 not installed
Warning: Skipping numpy: most recent version 1.15.1 not installed
Warning: Skipping opencv: most recent version 3.4.2 not installed
Warning: Skipping openexr: most recent version 2.2.0_1 not installed
Removing: /usr/local/Cellar/openssl/1.0.2j... (1,695 files, 12MB)
Removing: /usr/local/Cellar/openssl/1.0.2n... (1,792 files, 12.3MB)
Removing: /usr/local/Cellar/openssl/1.0.2o_1... (1,791 files, 12.3MB)
Warning: Skipping perl: most recent version 5.28.0 not installed
Removing: /usr/local/Cellar/pkg-config/0.29.1_2... (10 files, 627.4KB)
Warning: Skipping readline: most recent version 7.0.5 not installed
Warning: Skipping snappy: most recent version 1.1.7_1 not installed
Warning: Skipping sqlite: most recent version 3.24.0 not installed
Warning: Skipping subversion: most recent version 1.10.2 not installed
Removing: /Users/martinheller/Library/Caches/Homebrew/subversion--serf-1.3.9.tar.bz2... (141.7KB)
Warning: Skipping szip: most recent version 2.1.1_1 not installed
Warning: Skipping webp: most recent version 1.0.0 not installed
Removing: /Users/martinheller/Library/Caches/Homebrew/openssl-1.0.2n.high_sierra.bottle.tar.gz... (3.7MB)
Removing: /Users/martinheller/Library/Caches/Homebrew/readline-7.0.3_1.high_sierra.bottle.tar.gz... (495.5KB)
Removing: /Users/martinheller/Library/Caches/Homebrew/cockroach-1.1.3.high_sierra.bottle.tar.gz... (21MB)
Removing: /Users/martinheller/Library/Caches/Homebrew/sqlite-3.23.0.high_sierra.bottle.tar.gz... (1.4MB)
Removing: /Users/martinheller/Library/Caches/Homebrew/perl-5.26.1.high_sierra.bottle.1.tar.gz... (15.3MB)
Removing: /Users/martinheller/Library/Caches/Homebrew/openssl-1.0.2o_1.high_sierra.bottle.tar.gz... (3.7MB)
Removing: /Users/martinheller/Library/Caches/Homebrew/subversion-1.9.7.tar.bz2... (7.5MB)
Removing: /Users/martinheller/Library/Caches/Homebrew/go-1.10.3.high_sierra.bottle.tar.gz... (102.6MB)
Removing: /Users/martinheller/Library/Logs/Homebrew/pkg-config... (64B)
Removing: /Users/martinheller/Library/Logs/Homebrew/go... (64B)
Removing: /Users/martinheller/Library/Logs/Homebrew/swig... (64B)
Removing: /Users/martinheller/Library/Logs/Homebrew/boost... (6 files, 19.8MB)
Removing: /Users/martinheller/Library/Logs/Homebrew/apr-util... (64B)
Removing: /Users/martinheller/Library/Logs/Homebrew/perl... (64B)
Removing: /Users/martinheller/Library/Logs/Homebrew/scons... (64B)
Removing: /Users/martinheller/Library/Logs/Homebrew/readline... (64B)
Removing: /Users/martinheller/Library/Logs/Homebrew/delve... (3 files, 57.9KB)
Removing: /Users/martinheller/Library/Logs/Homebrew/sqlite... (64B)
Removing: /Users/martinheller/Library/Logs/Homebrew/fontconfig... (910B)
Removing: /Users/martinheller/Library/Logs/Homebrew/boost-python... (64B)
Removing: /Users/martinheller/Library/Logs/Homebrew/apr... (64B)
Removing: /Users/martinheller/Library/Logs/Homebrew/cockroach... (64B)
Removing: /Users/martinheller/Library/Logs/Homebrew/pcre... (64B)
Removing: /Users/martinheller/Library/Logs/Homebrew/nmap... (64B)
Removing: /Users/martinheller/Library/Logs/Homebrew/openssl... (64B)
Removing: /Users/martinheller/Library/Logs/Homebrew/subversion... (17 files, 1.4MB)
Removing: /Users/martinheller/Library/Logs/Homebrew/protobuf... (15 files, 1.5MB)
==> This operation has freed approximately 291MB of disk space.

All of those warnings mean that I didn’t upgrade some of my installed brews. I can fix that, first by updating Homebrew to have a current catalog, and then by upgrading all brews:

$ brew update
Updated 2 taps (homebrew/core, homebrew/cask).
==> Updated Formulae
crystal                         influxdb                        thors-serializer
fortio                          juju                            youtube-dl
Martins-Retina-MacBook:~ martinheller$ brew upgrade
==> Upgrading 29 outdated packages, with result:
libtiff 4.0.7 -> 4.0.9_4, leveldb 1.19 -> 1.20_2, ilmbase 2.2.0 -> 2.2.1, libpng 1.6.27 -> 1.6.35, cmake 3.7.1 -> 3.12.1, freetype 2.7.1 -> 2.9.1, hdf5 1.8.18 -> 1.10.3, boost 1.63.0 -> 1.67.0_1, perl 5.26.1 -> 5.28.0, readline 7.0.3_1 -> 7.0.5, glog 0.3.4_1 -> 0.3.5_3, webp 0.5.2 -> 1.0.0, sqlite 3.23.0 -> 3.24.0, eigen 3.3.1 -> 3.3.5, numpy 1.11.2 -> 1.15.1, openexr 2.2.0 -> 2.2.0_1, fontconfig 2.12.1_2 -> 2.13.0, gflags 2.2.0 -> 2.2.1, boost-python 1.63.0 -> 1.67.0, lmdb 0.9.19 -> 0.9.22, opencv 2.4.13.2 -> 3.4.2, gperftools 2.5 -> 2.7, snappy 1.1.3 -> 1.1.7_1, gd 2.2.3_1 -> 2.2.5, cockroach 1.1.3 -> 2.0.5, jpeg 8d -> 9c, szip 2.1 -> 2.1.1_1, subversion 1.9.7_3 -> 1.10.2, automake 1.15 -> 1.16.1_1
==> Upgrading readline
==> Downloading https://homebrew.bintray.com/bottles/readline-7.0.5.high_sierra.bottle.tar.gz
######################################################################## 100.0%
==> Pouring readline--7.0.5.high_sierra.bottle.tar.gz

By the way, the brew upgrade step was lengthy on my machine. One issue was that hdf5, which is a prerequisite for the deep learning package Keras (itself installed with pip, not brew), has a dependency of gcc, the Gnu C++ compiler. Amusingly, or annoyingly, depending on your point of view, the gcc installation on MacOS requires the Xcode Command Line Tools — in other words, you need a working Apple C++ compiler to build the Gnu C++ compiler. The process was slowed down significantly by the antivirus scan that was running, which must have been triggered by all the new downloads. I should have run the upgrade overnight or during a meal.

As the late Jerry Pournelle used to say, we do stupid stuff so that you don’t have to.

Once the upgrade completed, I re-ran the cleanup and freed another 900 MB of disk space. Then I checked my installation with brew doctor, which discovered a few actual problems in addition to warning about many benign conditions. I then ran brew prune to get rid of broken symlinks, and brew install with a list of missing dependencies.

Homebrew bottles, casks, and taps

Homebrew can install formulae two ways: by building from source code (often time-consuming) or by unpacking and installing (pouring) from a binary bottle. Bottles are gzipped tarballs of compiled binaries. Any metadata is stored in a formula’s bottle DSL and in the bottle filename (i.e. MacOS version, revision). You can see that in action in the printouts above, for example the readline installation, which pours readline--7.0.5.high_sierra.bottle.tar.gz.

By default, Homebrew formulae come from the core list. If you want to use other repositories of formulae, called taps, you can add them with brew tap <user/repo>.

Homebrew casks are command-line binary installers for apps that aren’t in the Mac App Store. There are currently about four thousand of them, but they aren’t in the Homebrew formulae list. Instead they can be found in the shell with brew search. For example, you can find all formulae and casks whose name contains “chrome” with this command:

$ brew search chrome
==> Formulae
chrome-cli                                        chrome-export

==> Casks
chrome-devtools                                   google-chrome
chrome-remote-desktop-host                        mkchromecast
chromedriver                                      homebrew/cask-versions/google-chrome-beta
dmm-player-for-chrome                             homebrew/cask-versions/google-chrome-canary
epichrome                                         homebrew/cask-versions/google-chrome-dev

The prefix homebrew/cask-versions/ refers to the tap for alternate versions of casks. The cask google-chrome is the current production version of Chrome; homebrew/cask-versions/google-chrome-canary is the “canary” channel version of Chrome, for early adopters and testers. You can add a tap hosted on GitHub with brew tap <user/repo>, add a Git repository hosted somewhere else using the URL, and remove a tap with brew untap <name>.

If you wish, you can create your own Homebrew formulae and casks. It’s quite easy if you are familiar with Ruby and Git. The developer commands are listed several pages into the Homebrew manual man brew. Additional information, sample code, and tools can be found in the online Homebrew documentation.

martin_heller
Contributor

Martin Heller is a contributing editor and reviewer for InfoWorld. Formerly a web and Windows programming consultant, he developed databases, software, and websites from his office in Andover, Massachusetts, from 1986 to 2010. More recently, he has served as VP of technology and education at Alpha Software and chairman and CEO at Tubifi. Disclosure: He also writes for Hewlett-Packard’s TechBeacon marketing website.

More from this author