If you’ve built a command-line tool and want to make it easy for users to install, Homebrew is one of the best distribution methods available. In this guide, I’ll walk you through creating your own Homebrew tap—a custom repository that allows users to install your software with a simple brew install command.
Steps Overview
- Prepare Your Binary Releases
- Create Your Tap Repository
- Write Your Formula
- Get SHA256 Checksums
- Push Your Formula
- Test Your Tap
- Share Your Tap
What is Homebrew?
Homebrew is the most popular package manager for macOS, and it also works on Linux. It allows users to install software from the command line with simple commands like brew install wget. Think of it as an app store for command-line tools and applications.
Understanding Homebrew Vocabulary
Before we dive in, let’s clarify some key terms:
Formula: A Ruby script that tells Homebrew how to download, build, and install a piece of software. It’s essentially a recipe for installing your application.
Tap: A third-party repository of formulas. While Homebrew has a main repository (homebrew-core) with thousands of formulas, taps allow anyone to create their own custom repository. The name comes from the idea of “tapping a keg”—you’re adding a new source of software.
Bottle: A pre-compiled binary version of software. Instead of compiling from source, users can download a ready-to-use binary, making installation much faster.
Cask: A formula specifically for installing GUI applications (like browsers or editors) rather than command-line tools.
Cellar: The directory where Homebrew installs software (
/usr/local/Cellaron Intel Macs,/opt/homebrew/Cellaron Apple Silicon).
Why Create a Tap?
Creating your own tap is perfect when:
- You want to distribute your own CLI tools or applications
- Your software isn’t popular enough (yet!) for homebrew-core
- You need faster iteration without going through the homebrew-core review process
- You want to maintain multiple versions or experimental releases
Prerequisites
Before starting, make sure you have:
- A GitHub account
- A CLI tool or application you want to distribute
- Binary releases of your application (we’ll cover this)
- Basic familiarity with Git and GitHub
Step 1: Prepare Your Binary Releases
Homebrew formulas need downloadable binaries. The most common approach is to use GitHub Releases.
Using GoReleaser (for Go projects)
If your project is written in Go, GoReleaser makes this incredibly easy. Add a .goreleaser.yml file:
builds:
- env:
- CGO_ENABLED=0
goos:
- linux
- darwin
goarch:
- amd64
- arm64
archives:
- format: tar.gz
name_template: >-
{{ .ProjectName }}_{{ .Version }}_
{{- title .Os }}_
{{- if eq .Arch "amd64" }}x86_64
{{- else }}{{ .Arch }}{{ end }}
checksum:
name_template: "checksums.txt"
Then create a release:
git tag -a v1.0.0 -m "First release"
git push origin v1.0.0
goreleaser release --clean
Manual Binary Releases
If you’re not using Go or GoReleaser, you’ll need to:
- Build binaries for different platforms (macOS Intel, macOS ARM, Linux x86_64, Linux ARM64)
- Package them as
.tar.gzarchives - Upload them to a GitHub release
- Generate SHA256 checksums
Example for generating checksums:
shasum -a 256 your-app-darwin-arm64.tar.gz
shasum -a 256 your-app-darwin-amd64.tar.gz
shasum -a 256 your-app-linux-amd64.tar.gz
Step 2: Create Your Tap Repository
Your tap must be a GitHub repository with a specific naming convention:
Create a new repository named
homebrew-<your-tap-name>- For example:
homebrew-toolsorhomebrew-myapp - The
homebrew-prefix is required
- For example:
Create the directory structure:
mkdir -p Formula
That’s it! Homebrew only needs the Formula directory.
Step 3: Write Your Formula
Create a file at Formula/<your-app>.rb. Here’s a complete example for a CLI tool called “sky”:
class Sky < Formula
desc "A powerful CLI tool for cloud management"
homepage "https://github.com/yourusername/sky-cli"
version "1.0.0"
on_macos do
if Hardware::CPU.arm?
url "https://github.com/yourusername/sky-cli/releases/download/v1.0.0/sky_1.0.0_Darwin_arm64.tar.gz"
sha256 "abc123...your-arm64-sha256-here"
else
url "https://github.com/yourusername/sky-cli/releases/download/v1.0.0/sky_1.0.0_Darwin_x86_64.tar.gz"
sha256 "def456...your-x86_64-sha256-here"
end
end
on_linux do
if Hardware::CPU.arm?
url "https://github.com/yourusername/sky-cli/releases/download/v1.0.0/sky_1.0.0_Linux_arm64.tar.gz"
sha256 "ghi789...your-linux-arm64-sha256-here"
else
url "https://github.com/yourusername/sky-cli/releases/download/v1.0.0/sky_1.0.0_Linux_x86_64.tar.gz"
sha256 "jkl012...your-linux-x86_64-sha256-here"
end
end
def install
bin.install "sky"
end
test do
system "#{bin}/sky", "--version"
end
end
Understanding the Formula
Let’s break down each section:
class Sky < Formula: The class name must match your filename (sky.rb → Sky class), capitalizeddesc: A short, one-line description of your toolhomepage: Your project’s website or GitHub repositoryversion: The version numberon_macos/on_linux: Platform-specific configurationsHardware::CPU.arm?: Detects ARM architecture (M1/M2 Macs, ARM Linux)url: The download URL for your binarysha256: The checksum to verify download integrityinstall: Instructions for installing your binary (typically just copying to the bin directory)test: A simple test to verify the installation works
Step 4: Get SHA256 Checksums
You need SHA256 checksums for each binary. The easiest way:
# Download and checksum in one command
curl -sL https://github.com/yourusername/app/releases/download/v1.0.0/app_Darwin_arm64.tar.gz | shasum -a 256
# Or if you have the file locally
shasum -a 256 app_Darwin_arm64.tar.gz
Copy these checksums into your formula where indicated.
Step 5: Push Your Formula
git add Formula/your-app.rb
git commit -m "Add formula for your-app v1.0.0"
git push origin main
Step 6: Test Your Tap
Now you can test your tap locally:
# Add your tap
brew tap yourusername/your-tap-name
# Install your application
brew install your-app
# Test it works
your-app --version
Step 7: Share Your Tap
Users can now install your application with just two commands:
brew tap yourusername/your-tap-name
brew install your-app
Or in a single command:
brew install yourusername/your-tap-name/your-app
Updating Your Formula
When you release a new version:
- Create a new GitHub release with updated binaries
- Get the new SHA256 checksums
- Update your formula with new version, URLs, and checksums
- Commit and push
Users can then update with:
brew update
brew upgrade your-app
Advanced Tips
Auto-update with Dependabot
Add .github/dependabot.yml to your tap repository:
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
Adding Dependencies
If your app requires other software:
depends_on "[email protected]"
depends_on "git"
Multiple Binaries
If your release contains multiple executables:
def install
bin.install "main-app"
bin.install "helper-tool"
bin.install "utility"
end
Configuration Files
Install configuration or documentation files:
def install
bin.install "your-app"
etc.install "config.yml" => "your-app/config.yml"
doc.install "README.md"
end
Troubleshooting Common Issues
“Formula not found” error
Make sure your repository name starts with homebrew- and your formula is in the Formula/ directory.
SHA256 mismatch
If you get a checksum error, recalculate your SHA256:
curl -sL YOUR_URL | shasum -a 256
Cached formula not updating
Force Homebrew to refresh:
brew untap yourusername/your-tap
brew tap yourusername/your-tap
Or clear the cache:
rm -rf $(brew --repository)/Library/Taps/yourusername/homebrew-your-tap
brew tap yourusername/your-tap
Downloads failing with 404
Verify your release assets are publicly accessible. Go to your GitHub release page and try downloading the files manually. If your repository is private, the assets won’t be accessible via Homebrew.
Best Practices
- Test before publishing: Always test your formula locally before pushing
- Use semantic versioning: Follow semver (1.0.0, 1.1.0, 2.0.0)
- Keep formulas simple: Don’t add unnecessary complexity
- Document installation: Add installation instructions to your project’s README
- Maintain checksums: Always verify SHA256 checksums match your binaries
- Support multiple platforms: Provide binaries for both Intel and ARM architectures
- Add a test block: Include a simple test to verify installation
Next Steps
Now that you have your tap set up, consider:
- Adding your tap to awesome lists and directories
- Writing documentation for your users
- Automating formula updates with CI/CD
- Eventually submitting to homebrew-core once your project gains traction
Have questions or run into issues? Check out the official Homebrew documentation.