Writing casks

Homebrew provides documentation for writing casks specifically in the Cask repo. With no intention of trying to submit a formula to homebrew, I created a tap on my own private repo at Bitbucket.org. My goal was to be able to install casks of applications downloaded from EclecticLight so I could automate my install process for a clean install of macOS. One reason I’m finding having a personal tap (that’s also private) useful is if you have software that’s your own you would like to install as a cask or fonts, that may not be open-licensed or your own personal patches of fonts.

The formula is pretty straight forward and I’ll have examples of the code and stanzas below.

Generating your own tap

If you plan to host your own tap and not just fork Homebrew for contribution, you can use the following command to Generate the folders required to $(brew --repository)/Library/Taps/<username>/<repo> where is your username (or whoever is wanting to host said tap and is your tap name, typically starting with "homebrew-"

$ brew tap-new <username>/<repo>

Once initialized, you can customize your Readme, and set up your folder structure (if necessary) & run git init and add the configuration your remote to host your tap & keep it under version control. This is also a good time to add a .gitignore.

When you use the brew create command, by default it will create the formula in the homebrew tap. To generate a formula to a given tap (instead of homebrew/core, homebrew/cask etc…) use the flag shown below.

$ brew create --tap=user/repo <URL>

Writing Casks

First, determine a casks token

$ "$(brew --repository)/Library/Taps/Homebrew/homebrew-cask/developer/bin/generate_cask_token" '/full/path/to/new/software.app'

If the software you wish to Cask is not installed, or does not have an associated App bundle, just give the full proper name of the software instead of a pathname:

$ "$(brew --repository)/Library/Taps/Homebrew/homebrew-cask/developer/bin/generate_cask_token" 'Google Chrome'

Once you have your token, you can create the cask with the following command. Your HOMEBREW_EDITOR or default EDITOR will open to fill in the rest of the stanzas for your cask.

$ brew cask create my_new_cask

Cask Stanza Cheat sheet

name value
version application version; give the value :latest if only an unversioned download is available
sha256 SHA-256 checksum of the file downloaded from url, calculated by the command shasum -a 256 <file>. Can be suppressed by using the special value :no_check. (see sha256)
url URL to the .dmg/.zip/.tgz/.tbz2 file that contains the application. A comment should be added if the hostnames in the url and homepage stanzas differ. Block syntax should be used for URLs that change on every visit. See URL Stanza Details for more information.
name the full and proper name defined by the vendor, and any useful alternate names (see Name Stanza Details)
homepage application homepage; used for the brew cask home command
app relative path to an .app bundle that should be moved into the /Applications folder on installation (see App Stanza Details)

A (very) basic ‘template’ of the stanzas for writing a cask

cask '<token>' do
  version '<0.0>'
  sha256 '<checksum>'

  # <URL if different than homepage> was verified as official when first introduced to the cask
  url '<Download Link>'
  name 'App Name'
  homepage '<URL>'

  depends_on macos: '>= :<version>'

  app 'name-of.app'
  app '<path/if/in/folder/name.app>'
end

The comment only belongs above the url stanza if it differs from the homepage where URL_SECTION is the smallest possible portion of the URL that uniquely identifies the app or vendor.

# URL_SECTION was verified as official when first introduced to the cask

Gotchas: Apparently the word “was” between the URL & the rest of the comment is an easy one for me to leave out and not pass brew cask style.

depends_on

The following has a table to use as a cheat-sheet for writing for the depends_on stanza. Minimum os requirements are only covered by major releases (10.12, 10.13…). For contributing to Homebrew, using os versions from the ‘symbol’ column is preferred for better human readability.

symbol string
:el_capitan '10.11'
:sierra '10.12'
:high_sierra '10.13'
:mojave '10.14'

To set a minimum os requirement use a comparison operator like >= followed by the minimum os.

depends_on macos: '>= :mavericks'
depends_on macos: '>= 10.9'

gotcha: make sure there is a space between >= and the os!

The following are all examples of acceptable ways to set a minimum os requirement when writing Casks

depends_on macos: :high_sierra
depends_on macos: [:high_sierra, :mojave]
depends_on macos: '10.13'
depends_on macos: ['10.13', '10.14']

Tasting Testing your cask

Once your formula is filled out, you can begin testing your cask. First, disable auto update temporarily and install your cask. If everything goes smoothly you’ll be good to move on, if not follow the instructions the command line gives you. If your cask name matches that of another, be sure to include the full path to your tap! (brew cask install sticklerm3/pourhouse/alifix)

$ export HOMEBREW_NO_AUTO_UPDATE=1
$ brew cask install my-new-cask

If everything went well, move next run brew cask uninstall my-new-cask just to make sure that goes smoothly as well, & to test if you have any uninstall stanza’s to test! Next up, you’ll want to run an audit!

$ brew cask audit my-new-cask

This is the only form of brew cask audit I’ve gotten to work so far when running audits.

Once you get all that sorted out, run the brew cask style my-new-cask and follow the instructions if that doesn’t finish cleanly. brew cask style --fix can make this super quick!

Updated: