Creating Brew external command

Recently I had the need to create a homebrew external command to extend homebrew default behavior. My goal is to extend brew deps command by creating a new command brew deps-group. Executing the command will list all top-level packages in homebrew that is related to each other by common dependencies, doing so will let me know if it safe for me to actually delete the package without breaking other packages.


To achieve this, the overall file structure consist of:

  1. Formula - this tells homebrew about where to get file for your packages and their dependencies.
  2. Application - actual implementation and I wrote my simple app in Python.
|------ Formula/
|      |--- brew-deps-group.rb
|------ brew-deps-group.rb

I noticed that your package needs to start with homebrew-app-name.


Explanation in comments

require "formula"

# this will translate to brew-deps-group as the formula name
class BrewDepsGroup < Formula
  homepage ""
  # this is the source of your package
  # when you run brew install, it will be installed from this source
  url ""

  # my package depends on python
  depends_on :python if MacOS.version <= :snow_leopard

  # this is the dependency for my formula
  resource "networkx" do
    url ""
    sha1 "ac2db3b29c7c4d16435f2a7ebe90fc8bd687b59c"

  # skip cleaning path in formula
  skip_clean "bin"

  def install
    # since my python application has other dependency, we need to install it
    # and ensure it is installed in /vendor
    # to avoid pollution with system packages
    ENV.prepend_create_path "PYTHONPATH", libexec/"vendor/lib/python2.7/site-packages"
    %w[networkx].each do |r|
      resource(r).stage do
          system "python", *Language::Python.setup_install_args(libexec/"vendor")

    # if your python application has, then uncomment this line
    # this will install your application in the correct location
    # ENV.prepend_create_path "PYTHONPATH", libexec/"lib/python2.7/site-packages"
    # system "python", *Language::Python.setup_install_args(libexec)

    # copies your python application to bin
    # since we don't have any, I don't need this
    # instead, we are just going to copy the actual file (see next section below)
    # bin.install Dir[libexec/"bin/*"]
    # bin.env_script_all_files(libexec/"bin", :PYTHONPATH => ENV["PYTHONPATH"])

    # copies all files to bin so we can execute the files from other scripts
    bin.install ''
    bin.install 'brew-deps-group.rb'
    (bin + '').chmod 0755
    (bin + 'brew-deps-group.rb').chmod 0755

Entry point

So our application/command needs an entry point, i.e. when I run brew deps-group, some file should be executed right? In our case, this will call brew-deps-group.rb which in turn will call up

require 'keg'
require 'formula'

module BrewDepsGroup

  def run
    if ['-h', '?', '--help'].include? ARGV.first
      puts USAGE
      exit 0
    if ['-a', '--all'].include? ARGV.first
      # call our python executable file
      # we don't need python since the file is already executable and is in our path
      system "", "all"
exit 0
#! /usr/bin/env python
# our dependency we declared in our formula can now be used
import networkx as nx

def main(argv):
    option = argv[0]
    # do something
    print "hello world"

if __name__ == '__main__':

If you need the full source code, you can find it here