External Commands
Homebrew supports executable extensions that can be invoked as brew <command> without modifying Homebrew/brew.
An external command can be installed on PATH or distributed in a tap.
External commands run with the user’s privileges. Review their source and use tap trust to trust only the required command or tap.
Command types
An external command named example can use one of these executable filenames:
brew-examplefor a shell script or another directly executable programexample.rbin a tap’scmddirectory for anAbstractCommandsubclassbrew-example.rbfor a legacy Ruby command that runs when Homebrew requires the file
A directly executable command can use any suitable shebang and receives its remaining command-line arguments unchanged.
Its filename must be exactly brew-example, without a language extension such as .sh.
Homebrew sets variables including HOMEBREW_PREFIX, HOMEBREW_CELLAR, HOMEBREW_REPOSITORY, HOMEBREW_LIBRARY_PATH and HOMEBREW_CACHE.
A Ruby external command runs inside Homebrew and can access Homebrew internals. Those internals can change without compatibility guarantees, so prefer public APIs and keep the extension tested against current Homebrew.
Distribution in a tap
Place commands in the tap’s cmd directory:
homebrew-example/
└── cmd/
├── example.rb
└── brew-other-example
Make each command executable before committing it. See How to Create and Maintain a Tap for repository setup.
After tapping the repository, trust only the required command when whole-tap trust is unnecessary:
brew trust --command user/example/example
Ruby command structure
A Ruby external command in a tap can use Homebrew’s argument parser and AbstractCommand lifecycle.
Save this example as cmd/example.rb without a brew- prefix:
# typed: strict
# frozen_string_literal: true
module Homebrew
module Cmd
class Example < AbstractCommand
cmd_args do
description "Describe what the command does."
switch "--force", description: "Perform the operation without prompting."
named_args :formula, min: 1
end
sig { override.void }
def run
args.named.to_formulae.each do |formula|
puts formula.full_name
end
end
end
end
end
The class name is the command name converted to CamelCase.
Declare accepted positional arguments with named_args and access parsed options through args.
Use internal commands and developer commands as current parser examples.
A legacy brew-example.rb command is only required and executed as a file.
Homebrew does not instantiate an AbstractCommand subclass or call its run method for that filename.
Help output
Ruby commands using cmd_args receive consistent generated help.
A shell or Ruby script can alternatively provide comment-based help with lines beginning #:.
When a non-Ruby executable provides neither form, Homebrew may execute it with --help to obtain its own help output.
A legacy Ruby command without comment-based help receives generic help instead.
See the argument parser API for the supported DSL.