Homebrew/install: the install.sh and uninstall.sh scripts behind brew
📥 Homebrew (un)installer
At a glance
- What is it?
- Homebrew's own installer is a pair of shell scripts, not a package. Here is what install.sh does, how to run it non-interactively with a custom prefix, and where it stops being the right tool.
- Who is it for?
- Adopt Homebrew/install if you want the canonical bootstrap of Homebrew on macOS or Linux, especially in automation where NONINTERACTIVE=1 and --path give you a deterministic prefix. Do not use it if you need an MDM-deployable artifact on Apple Silicon, where the README points at the .pkg from Homebrew's latest GitHub release, or if you expect the script to install Git for you, since the shell installer aborts when Git is missing or unusable.
- Can I use it commercially?
- Yes. BSD-2-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 6 days ago.
- What is it written in?
- Mainly Shell, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 24, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What Homebrew/install actually is, and who needs it
This repository is not a package manager. It is the distribution channel for the two shell scripts that put Homebrew onto a machine and take it off again: install.sh and uninstall.sh. The repository layout is small (install.sh, uninstall.sh, tests/, LICENSE.txt, README.md and .github/), which tells you the maintenance surface is the scripts themselves rather than a library.
The audience is narrow but real. First, people on a fresh macOS or Linux box who want brew without downloading a disk image by hand. Second, automation authors who need a repeatable, non-interactive bootstrap inside a Dockerfile, a CI job or a provisioning script. Third, administrators migrating an existing Homebrew between prefixes, for example from an Intel /usr/local layout to an Apple Silicon one.
If you already have brew and it works, this repository has nothing for you. It is a bootstrap, not a runtime.
How the one-line installer works
The documented invocation is a curl piped into bash. There is no compiled artifact and no package registry involved: the script is fetched from the HEAD branch of the repository and executed immediately by the system shell. That is the whole mechanism, and it is worth being clear about the consequence. You are running whatever is on HEAD at the moment of the curl, so pinning a version means downloading the script first and executing the local copy instead.
The script then decides where Homebrew lives. The default prefix is /opt/homebrew on macOS and /home/linuxbrew/.linuxbrew on Linux, and the README notes that --path lets you choose another one, subject to two constraints: the path must be absolute, and after resolving symlinks it must be no longer than the platform default. That second rule exists because bottles are relocated into the chosen prefix, and relocation depends on the prefix not being longer than what the bottles were built against.
Privilege handling is the part most people misread. The installing account does not need administrator membership when the prefix is writable. On macOS, falling back to the staff group removes group and other write permissions from the prefix and cache. Filesystem operations try without sudo first and only request elevation when needed, and HOMEBREW_NO_SUDO=1 disables sudo calls entirely. Missing sudo, recognised privilege failures and explicit policy denials are detected automatically. If sudo is unavailable, the installer skips the system PATH file and prints shell setup instructions instead, and Command Line Tools installation is skipped as well, with CLT failures treated as non-fatal.
One hard stop: the shell installer aborts if Git is missing or unusable. A working Git on PATH, or one supplied by Xcode, is supported. So on a bare Linux container you install Git before you run this.
Installing Homebrew and running a first non-interactive install
The README gives the interactive form as the primary path. It prompts for a password where elevation is needed, so it is the wrong shape for unattended scripts.
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"Run that on macOS or Linux and the script reports progress, asks for confirmation and a password if it needs one, then prints shell setup instructions for your shell profile. On Linux and WSL the README points at a separate requirements page, so install the prerequisite packages first or the script will fail partway through.
For automation, set NONINTERACTIVE. This suppresses the password prompt and the confirmation question.
NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"To control the prefix, pass --path after a double dash. The README's own example installs into /opt/brew.
NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" -- --path /opt/brewThe double dash matters: it separates the arguments consumed by bash -c from those the script receives. After this completes, the prefix contains the Homebrew tree and the script prints the shell lines you need to add. Because sudo was not required for a writable prefix, the system PATH file is skipped, so those printed lines are not optional.
In geolocated environments, the README documents two environment variables that redirect the Git remotes used during installation and later by brew update.
export HOMEBREW_BREW_GIT_REMOTE="..." # put your Git mirror of Homebrew/brew here
export HOMEBREW_CORE_GIT_REMOTE="..." # put your Git mirror of Homebrew/homebrew-core here
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"The default remote is used when the corresponding variable is unset. The README also notes that HOMEBREW_NO_INSTALL_FROM_API causes Homebrew/homebrew-core to be tapped, which by default it is not, since the README states tapping is no longer necessary.
Uninstalling, and migrating between prefixes
Removal mirrors installation. The interactive form is a curl piped into bash against uninstall.sh.
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/uninstall.sh)"The non-interactive variant adds NONINTERACTIVE=1 in the same position as the installer. The interesting case is a prefix-specific removal, which is what you want when moving from an Intel layout to Apple Silicon. The README downloads the script first and runs it against /usr/local.
curl -fsSLO https://raw.githubusercontent.com/Homebrew/install/HEAD/uninstall.sh
/bin/bash uninstall.sh --path /usr/localRunning the downloaded script with --help lists further uninstall options. Note the asymmetry with install.sh: here the script is fetched to disk first, which is also the pattern to copy if you want any kind of version pinning for the installer itself. The README does not document a rollback path if an uninstall removes more than you expected, so treat the removal step as one-way and take a snapshot of the prefix first.
Where the script approach breaks down
The README is explicit that for MDM deployments on Apple Silicon Macs, the recommended route is the .pkg installer from Homebrew's latest GitHub release, not this script. That is the clearest case of the wrong tool: fleet management wants a signed, installable artifact with a package receipt, and a curl-to-bash script gives you neither. The README adds that HOMEBREW_PKG_USER selects an existing non-root account to own the installation, and that installing without Git or developer tools requires a package release containing a specific upstream pull request. So the .pkg path is also the only documented route when Git is not available.
A second limitation is that the script is fetched from HEAD. There is no documented version pinning in the README, which means the code you execute today is not necessarily the code you executed last month. For a bootstrap that is usually acceptable; for a reproducible build image it is a real gap, and the workaround is to download the script and vendor it.
The third is the prefix length rule. It is easy to pick a descriptive path like /opt/homebrew-staging and discover that it exceeds the platform default after symlink resolution, at which point bottle relocation is not supported. The README states the constraint but not the failure message you will see.
Finally, the sudo-free path is not a full install. Skipping the system PATH file and the Command Line Tools step means a working brew that is not on your PATH until you apply the printed instructions yourself. In a non-interactive script, nobody reads stdout, so that step is silently dropped.
Homebrew/install compared with the .pkg installer
The alternative within the same project is the .pkg from Homebrew's latest GitHub release, and the difference is not cosmetic. The shell script is a live fetch of a script that then performs the installation itself, deciding on privileges, prefix and PATH along the way. The .pkg is a built artifact: the filesystem changes are declared in advance, the installer framework handles elevation, and MDM tooling can push it, report on it and remove it. The README recommends it specifically for MDM deployments on Apple Silicon.
The trade-off runs the other way too. The .pkg is macOS-only, so a Linux or WSL bootstrap has no equivalent and the shell script is the documented path. The .pkg also needs a release that contains the upstream change for Git-less installation, so older packages will not help you on a machine without developer tools. And the .pkg does not give you --path in the same shape as the script; the documented knob there is HOMEBREW_PKG_USER for choosing the owning account.
If your machines are managed, the .pkg is the better fit. If you are provisioning a Linux container or a developer's laptop by hand, the script is the shorter route.
Licence and maintenance cost
The repository is BSD-2-Clause. That is a permissive licence, and the practical reading is that you can vendor install.sh into your own provisioning repository, modify it and ship it, provided you keep the copyright notice and the licence text. This is not legal advice; check LICENSE.txt and your own policy if you plan to redistribute a modified script.
Maintenance cost is low precisely because the repository holds two scripts. The last push to the default branch was on 2026-09-23, and the repository is not archived. The cost that does land on you is upgrade cost at the edges: because the documented install path fetches from HEAD, you inherit upstream changes the next time you run it, and because the README ties Git-less installation to a specific upstream pull request being present in a package release, an old pinned artifact can quietly fall behind what the current script supports. Pinning the script yourself removes the first problem and creates the second, since you then have to re-vendor deliberately.
Editorial conclusion
Adopt Homebrew/install if you want the canonical bootstrap of Homebrew on macOS or Linux, especially in automation where NONINTERACTIVE=1 and --path give you a deterministic prefix. Do not use it if you need an MDM-deployable artifact on Apple Silicon, where the README points at the .pkg from Homebrew's latest GitHub release, or if you expect the script to install Git for you, since the shell installer aborts when Git is missing or unusable. Before rolling it out, verify that your chosen prefix is absolute and no longer than the platform default after symlink resolution, and confirm whether your environment can supply sudo, because without it the installer skips the system PATH file and prints shell setup instructions you must apply yourself.
Frequently asked questions
How do I install Homebrew with the official script?
Run /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" on macOS or Linux. On Linux or WSL the README says there are prerequisite packages to install first.
How do I run install.sh non-interactively?
Set NONINTERACTIVE=1 in front of the same command, for example NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)". The README documents this for automation scripts that must not prompt for passwords.
How do I install Homebrew into a different prefix?
Pass --path after a double dash, as in the README example that installs into /opt/brew. The path must be absolute and, after resolving symlinks, no longer than the platform default of /opt/homebrew on macOS or /home/linuxbrew/.linuxbrew on Linux.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/homebrew-install)
Community notes