Create PKG Installers from Homebrew Formulas

brew-pkg is a Homebrew external command that builds macOS installer packages from Homebrew formulas. The formula must first already be installed on the system.

Install brew-pkg

First, add the brew-pkg formulae tap:

brew tap timsutton/formulae

Then install it:

brew install brew-pkg

Creating a Package

Assuming the formula ntfs-3g is already installed:

brew pkg ntfs-3g

The output will be something like:

  MTeam7 [~] $ brew pkg --with-deps --without-kegs ntfs-3g
==> Creating package staging root using Homebrew prefix /usr/local
==> Staging formula ntfs-3g
==> Staging formula pkg-config
==> Staging formula gettext
==> Building package ntfs-3g-2017.3.23_1.pkg

  Mteam7 [~] $ ls ntfs-3g-2017.3.23_1.pkg
9.0M -rw-r--r-- 1 Mteam7 staff 9.0M Aug 11 23:44 ntfs-3g-2017.3.23_1.pkg

  Mteam7 [~] $ lsbom $(pkgutil --bom ntfs-3g-2017.3.23_1.pkg) | head -30
.                             40700     0/0
./usr                         40755     0/0
./usr/local                   40755     0/0
./usr/local/.brew             40755     0/0
./usr/local/.brew/gettext.rb  100644    0/0    1487     3776327809
./usr/local/.brew/ntfs-3g.rb  100644    0/0    2510     363375937
./usr/local/bin               40755     0/0
./usr/local/bin/autopoint     100555    0/0    27026    164851193
./usr/local/bin/envsubst      100555    0/0    39592    2668043940
./usr/local/bin/gettext       100555    0/0    39308    2298554039
./usr/local/bin/    100555    0/0    5190     3488949678
./usr/local/bin/gettextize    100555    0/0    42298    3448148383
./usr/local/bin/lowntfs-3g    100555    0/0    61952    3749278950
./usr/local/bin/msgattrib     100555    0/0    28304    3131124536
./usr/local/bin/msgcat        100555    0/0    28412    1398000252
./usr/local/bin/msgcmp        100555    0/0    29248    133122482
./usr/local/bin/msgcomm       100555    0/0    28408    3242228031
./usr/local/bin/msgconv       100555    0/0    27952    2052481136
./usr/local/bin/msgen         100555    0/0    27960    2829033349
./usr/local/bin/msgexec       100555    0/0    27520    3583181032
./usr/local/bin/msgfilter     100555    0/0    33548    1504121072
./usr/local/bin/msgfmt        100555    0/0    80120    1675568021
./usr/local/bin/msggrep       100555    0/0    10916    1305508188
./usr/local/bin/msginit       100555    0/0    48892    1109971268
./usr/local/bin/msgmerge      100555    0/0    58928    2435734692
./usr/local/bin/msgunfmt      100555    0/0    38612    5012713
./usr/local/bin/msguniq       100555    0/0    28224    1131948277
./usr/local/bin/ngettext      100555    0/0    39332    4164570214
./usr/local/bin/ntfs-3g       100555    0/0    56552    3583091600
./usr/local/bin/ntfs-3g.probe 100555    0/0    13460    527138039


Usage: brew pkg [--identifier-prefix] [--with-deps] [--without-kegs] formula

Build an OS X installer package from a formula. It must be already
installed; 'brew pkg' doesn't handle this for you automatically. The
'--identifier-prefix' option is strongly recommended in order to follow
the conventions of OS X installer packages.

  --identifier-prefix     set a custom identifier prefix to be prepended
                          to the built package's identifier, ie. 'org.nagios'
                          makes a package identifier called 'org.nagios.nrpe'
  --with-deps             include all the package's dependencies in the built package
  --without-kegs          exclude package contents at /usr/local/Cellar/packagename
  --scripts               set the path to custom preinstall and postinstall scripts


If a formula has defined a launchd plist, brew-pkg will also install this to the package's root in /Library/LaunchDaemons.


By default behaviour brew pkg include all package kegs located in /usr/local/Cellar/packagename. If you need to exclude it, specify option --without-kegs


You can set the path to custom preinstall and postinstall scripts with the --scripts option which is just literally passed through to the pkgbuild command. If this directory contains scripts named preinstall and/or postinstall, these will be run as the top-level scripts of the package.

Pkgbuild's Script Help

--scripts scripts-path
     Archive the entire contents of scripts-path as the package
     scripts. If this directory contains scripts named preinstall
     and/or postinstall, these will be run as the top-level
     scripts of the package. If you want to run scripts for spe-
     cific bundles, you must specify those in a component property
     list; see more at COMPONENT PROPERTY LIST.  Any other files
     under scripts-path will be used only if the top-level or com-
     ponent-specific scripts invoke them.

     When you package a destination root, you can use a component property
     list to specify how bundles in that root should be handled by the OS X
     Installer. This property list should be an array of dictionaries, where
     each dictionary specifies a single bundle. The dictionary keys are as

     Key                          Description
     RootRelativeBundlePath       Path to bundle relative to the destination
     root (string)

     BundleIsRelocatable          Install bundle over previous version if
     moved by user? (bool)

     BundleIsVersionChecked       Don't install bundle if newer version on
     disk? (bool)

     BundleHasStrictIdentifier    Require identical bundle identifiers at
     install path? (bool)

     BundleOverwriteAction        How to treat existing on-disk version of
     bundle (string)

     BundlePreInstallScriptPath   Relative path to bundle-specific
     preinstall script

     BundlePostInstallScriptPath  Relative path to bundle-specific
     postinstall script

     ChildBundles                 Bundles under this bundle
     (array of dictionaries)

     The easiest way to create a component property list is to use the
     --analyze option and point pkgbuild at your current destination root. The
     output will be a component property list with default attributes, which
     you can then edit as needed. You can also specify a previous version of
     your component property list when using --analyze, which will cause the
     attributes of previously existing bundles to be propagated forward.

     BundleOverwriteAction specifies how an existing version of the bundle on
     disk should be handled when the version in the package is installed. If
     you specify upgrade, the bundle in the package atomically replaces any
     version on disk; this has the effect of deleting old paths that no longer
     exist in the new version of the bundle.  If you specify update, the bun-
     dle in the package overwrites the version on disk, and any files not con-
     tained in the package will be left intact; this is appropriate when you
     are delivering an update-only package.  Another effect of update is that
     the package bundle will not be installed at all if there is not already a
     version on disk; this allows a package to deliver an update for an app
     that the user might have deleted.

     BundlePreInstallScriptPath and BundlePostInstallScriptPath are meaningful
     only if --scripts was used to specify a scripts directory. The paths
     given by these keys must be relative to the scripts directory.

     ChildBundles can be used to represent nesting of bundles, but it does not
     change the meaning of RootRelativeBundlePath within lower-level dictio-
     naries (i.e. it is always relative to the destination root).  If you
     write a component property list manually, you do not need to use
     ChildBundles at all; you can simply put all bundle dictionaries in the
     top-level array.
{{ message }}

{{ 'Comments are closed.' | trans }}