如果你用过 macOS,大概率绕不开 Homebrew 这个名字。它是 Mac 上最主流的包管理器,一条brew install xx就能把命令行工具、开源软件、甚至不少原生 GUI 应用装好。但这里有个很现实的问题:Homebrew 再强大,它的操作入口始终是终端。对习惯鼠标点一点的人来说,第一次看brew list、brew search、brew info这些命令,多少有点劝退。我身边有不少朋友明明装了 Homebrew,却每次装软件都要复制粘贴搜索来的命令,生怕敲错一个字母把环境搞坏。
BrewUI 就是冲着这个痛点来的。简单说,它是 Homebrew 的一个第三方图形界面客户端,把 brew 最常用的搜索、安装、卸载、升级、清理、依赖查看这些操作,全部做成了可视化界面。装完以后,Homebrew 不再只是终端里的一个黑框命令,而是变成了一个能看到软件列表、版本状态、依赖关系的桌面应用。这篇文章我会把它从安装到日常使用的完整链路拆开讲一遍,包括我实际用下来的感受,以及踩过的几个坑,希望能给正打算用图形界面管理 Homebrew 的人一份可直接照抄的参考。
1. 为什么需要 BrewUI:Homebrew 用户的图形界面缺口
1.1 Homebrew 很好用,但"好用"不代表"没门槛"
Homebrew 的设计哲学是"简单直接",核心命令就那么几个:search、install、uninstall、update、upgrade、list、info、cleanup。真正常用的可能十个手指头数得过来。但问题在于,这些命令的含义、参数、组合方式,对一个非专业用户来说并不是天然友好的。比如brew install后面有时候带--cask,有时候不带,什么时候加、什么时候不加,很多在终端里泡了好几年的人都未必每次都能说清楚。
再比如依赖问题。装一个 ffmpeg,命令行会噼里啪啦拉进来几十个依赖包。如果是第一次用,你根本不知道这些依赖是什么、为什么要装、装完会不会影响现有环境,屏幕上滚动几屏输出,能看懂的也就最后那句install successful。Homebrew 不是不好,而是它的信息都藏在文本里,不熟练的人很难快速筛选出自己关心的内容。这个门槛虽然不高,但确实存在,而且挡住了相当一部分向往"优雅装软件"的用户。
1.2 BrewUI 的价值不在替代终端,而是把信息变成可读的界面
BrewUI 做的事情,本质上不是提供一个比终端更快的执行方式,而是把终端里的文本输出翻译成了图形界面。已安装的包变成一行行卡片或列表,版本号和"是否有新版"的提示一眼就能看到;搜索框输入关键字,匹配到的 formula 和 cask 会以结果列表的形式呈现,点进任意一个,还能看到它的描述、维护状态、依赖信息。这些都是brew info在终端里输出的东西,但没有人需要用眼睛去解析文本了。
还有一个真正让我觉得"这工具有存在价值"的地方,是依赖关系的可视化。命令行里brew deps --tree虽然也能输出依赖树,但那是用字符拼出来的树,包一多基本就看不动了。BrewUI 把依赖和反向依赖画成可视化的层级结构,点一个节点就能看它依赖了什么、又被谁依赖,排查装了什么奇怪的东西很方便。这个能力没有替代终端,但它让 Homebrew 的数据变"可读"了,这才是 GUI 客户端的核心价值。
2. BrewUI 的核心功能拆解:不只是把命令换成了按钮
2.1 包列表与状态呈现,让"我装了什么"一目了然
打开 BrewUI 第一眼能看到的,通常就是已安装包的列表。它会把 Homebrew 管理的 formula 和 cask 都列出来,每个条目显示名称、当前版本、是否有可更新版本,以及包的类型标识。终端里brew list --versions也能输出同样的信息,但十几行列表还能接受,一旦装到上百个包之后,用命令行翻就非常费劲了。BrewUI 的列表支持点击排序、搜索过滤,我想知道自己装了多少跟 python 相关的包,直接在过滤框里敲 python 就行,几秒钟出结果。
这个"状态呈现"的功能对日常维护特别重要。Homebrew 的版本更新策略默认比较保守,它不会自动帮你把包升级到大版本,需要手动执行brew upgrade。很多人只用brew install装完就再也没管过,时间一长系统里全是过时的版本。BrewUI 会在列表里用明显的方式标出哪些包有新版本,看一眼就知道该升级谁,不用在终端里反复对比brew outdated的输出了。
2.2 搜索与安装,减少"复制粘贴命令"的心理压力
BrewUI 的搜索框对应的是brew search命令。但和终端里输入关键字后只看一串结果列表不同,BrewUI 的搜索结果会直接展示软件的描述信息,用户能更直观地判断这个包是不是自己需要的。比如我想找图像处理的命令行工具,搜索 image,结果里会列出 ImageMagick、libpng、jpeg-turbo 这一类的包,每个都带着简短说明,我可以先看描述再决定装哪个,而不是在终端里一个个brew info去查。
安装操作也很直接。选中一个包,点安装按钮,界面就会显示安装进度,包括当前在哪一步、正在拉取哪个依赖、编译进度多少。这个体验比终端里盯着滚动的日志要踏实得多。需要说明的是,BrewUI 本身并没有重新实现 Homebrew 的安装逻辑,它只是把brew install命令在后台调起来,然后把输出解析成进度和状态。这个设计我很认可,因为这意味着 GUI 不会和 Homebrew 的生态脱节,只要 Homebrew 本身能装的包,BrewUI 都能装。
2.3 依赖关系视图:命令行做不到的直观
如果说前面那些功能还能被 brew 命令替代,那依赖关系可视化就是 BrewUI 的一个独有亮点。点开任意一个已安装的包,BrewUI 会展示它依赖了哪些包,以及哪些包依赖了它,通常是以树状或层级列表的形式呈现。装包之前先看依赖,你能提前知道这个包会拉进来多大的"行李";卸载之前看反向依赖,你能确认这个包是不是还有别人在用,避免删掉一个包把另外某个软件搞坏。
我自己实际用过一次之后,就再也没回到过brew deps命令。有一次我想清理一个老项目留下的依赖,不敢乱删,就用 BrewUI 打开那个核心包的反向依赖视图,一下就看到还有三个包在引用它。这种信息在终端里也能查,但要看一个包的反向依赖得先查一遍,再挨个查这些包有没有被别人引用,过程非常繁琐。可视化之后,判断成本几乎降到了零。
2.4 批量升级与清理:一次点完所有事
升级和清理也是 BrewUI 做得很顺手的地方。命令行里brew upgrade是全部更新,brew upgrade 包名是更新指定的包,而 BrewUI 把这两种操作都放到了界面上:你能在列表里勾选多个包批量升级,也可以一键升级所有有新版可用的包。很多人日常并不需要频繁升级所有软件,只需要单独更新某一个,这个勾选加批量执行的设计就很匹配实际使用场景。
清理功能同理。brew cleanup可以删除包的老版本压缩包和下载缓存,但命令行模式下你很难直观看到清理前后到底释放了多少空间。BrewUI 里点击清理,界面会先显示扫描结果,比如哪些包有旧版本残留、缓存目录占了多少,然后执行清理后告诉你释放了多少空间。这个反馈对普通用户来说非常友好,至少我知道点了这个按钮之后,系统真的变小了、干净了。
3. 安装 BrewUI 的完整流程:从环境检查到首次启动
3.1 安装前的环境检查,少一步后面都会出问题
BrewUI 只是个壳,真正干活的是 Homebrew 本身。所以安装 BrewUI 之前,第一件事是确认 Homebrew 已经装好且能正常工作。在终端里跑一下brew --version,如果正常输出版本号,就说明环境是好的。如果还没装 Homebrew,建议先去 Homebrew 官网按官方步骤完成安装,再考虑 BrewUI。
还要确认系统版本。BrewUI 目前对 macOS 版本有要求,我记得主流版本要求 macOS 12 或更高。如果你还在用更老的系统,大概率会遇到打不开或者功能异常的情况,这个在下载页面一般都会标注。另外,因为 Homebrew 在 Apple Silicon 芯片的 Mac 上默认装在/opt/homebrew,在 Intel 芯片的 Mac 上装在/usr/local,BrewUI 在启动时需要能识别到正确的 Homebrew 路径,这一步一般是自动的,但后面遇到问题你会理解这个路径为什么重要。
3.2 获取应用:优先用官方发布渠道,别图省事
BrewUI 是开源项目,最稳妥的方式是去它的 GitHub Releases 页面下载最新的 dmg 文件,拖到 Applications 文件夹里完成安装。为什么强调用官方渠道?因为这种管理软件本质上是拿你的系统权限在操作 Homebrew,如果从不明来源下载到被篡改的版本,风险会非常高。这一点怎么强调都不过分。
如果你已经在用 Homebrew Cask 管理 GUI 应用,也可以看看 BrewUI 是否已经收录到 cask 仓库里,如果收录了,直接brew install --cask brewui一条命令装完,后续升级也方便。不过这个要以仓库实际收录情况为准,没收录的话就手动装。安装完第一次打开,macOS 会询问是否允许来自已识别开发者的应用,选择允许即可,这是正常的安全检查流程。
3.3 初次启动与权限设置,先搞懂它做了什么
第一次打开 BrewUI,它会扫描当前系统里的 Homebrew 环境,这个过程一般几十秒,取决于已安装包的数量。扫描完之后,界面上应该能看到完整的包列表。如果界面一直是空的或者卡在加载,大概率是它没找到 brew 命令或网络有问题,这部分我放到后面常见问题里细说。
这里提醒一句,BrewUI 执行brew install、brew upgrade这些命令时,使用的是你当前用户权限,和你在终端里运行 brew 的权限一致。Homebrew 本身的设计就不依赖 sudo,正常安装的 Homebrew 操作不需要管理员密码。但如果某个软件包在安装脚本里需要写入/Applications或/Library这类系统目录,macOS 会弹出系统授权对话框,这是正常现象,输入用户密码即可,不必担心。
4. 实操体验:我用 BrewUI 完成的四件事
4.1 第一次打开时的界面布局,别被功能吓到
BrewUI 首屏的布局并不复杂,大体分三块:顶部是搜索框和一个刷新按钮,左侧是分类筛选,右侧是包详情。左侧分类一般有全部、已安装的 Formula、已安装的 Cask、可更新的包、可清理的项目这几类,点不同分类,右侧列表会自动过滤。列表里每一行展示包名、当前版本、最新版本状态,还有一个小标识告诉你它是命令行工具还是 GUI 应用。第一次用,建议先从"已安装"这个分类逛一遍,看看自己电脑上到底装了哪些 brew 管理的东西,这一步比任何教程都能帮你建立概念。
选中任意一个包,右侧会展示它的完整信息面板,包括描述、依赖、反向依赖、安装历史、所属 Tap 仓库这些。很多人第一次看到这个面板最惊讶的是"原来我装的这个软件还依赖了那么多东西"。是的,比如你只是装了一个 node,面板里可能会显示它拉进来几十个共享库依赖,这个信息以前只在安装日志里一闪而过,现在可以直接查看。
4.2 搜索安装 ffmpeg,看着依赖一个个就位
我截取一次实际安装过程来演示。我在搜索框输入 ffmpeg,结果里很快出现了这个包,描述写着"多媒体处理工具,支持视频、音频、图像的转换和处理",类型标识是 Formula。点进去先看依赖面板,好家伙,列了大约二十多个依赖项,从 zlib 到 libvpx,基本把常用的编解码库都拉上了。如果你提前看到这个依赖列表,可能就能理解为什么 ffmpeg 这么强大了——它把所有需要的基础组件都打包成了依赖关系,而不是自己硬编码实现。
点击安装按钮之后,界面显示"正在获取依赖",然后一条条列出正在下载或编译的包,进度条跟着动。整个过程和终端里跑brew install ffmpeg一致,但直观多了。你不需要用眼睛追踪滚动的日志,只需要等它走到头。装完后,包的当前版本字段会变成新版本,状态标识也变成"已安装"。整个过程如果走终端,遇到问题你可能要眯着眼睛去日志里找红字,但在 BrewUI 里,出错会以醒目的错误提示弹出来,你甚至能直接复制日志全文去排查。
4.3 用依赖视图,搞清楚"能不能删这个包"
有段时间我在清理一个旧项目留下的无用小工具,想卸载一个叫imagemagick的包,但印象里好像有别的软件在用。终端里查反向依赖很麻烦,我直接打开 BrewUI,点到 imagemagick,看反向依赖面板,里面清清楚楚列着两个包还在引用它——其中一个是pandoc,另一个是rails项目里装过的附件处理库。看到这个结果,我打消了一键卸载的念头,决定等这个项目彻底停用后再清理。
反过来还有一个场景也很有用。新装了一个软件之后想了解它到底往系统里放了什么,直接看依赖树就行了,每一层都是可控的。如果看到某个包依赖了你不想要的大组件,可以在装之前就去搜索替代方案。这种"先看后装"的体验,是只靠命令行很难养成的习惯,因为终端里查依赖的成本太高了,BrewUI 把它变成了点一下的事。
4.4 批量升级和清理,直观看到磁盘空间变化
我就有一个周期性的习惯:每次隔两周左右,打开 BrewUI,先切到"可更新的包"分类,看看有哪些新版本可以升级。有一次发现列了 12 个包等着更新,其中几个是安全更新里建议尽快升的,我直接勾选全部,点了升级按钮。界面显示一批批地在处理,从下载到替换,总共花了几分钟。这个过程如果用终端,命令本身不复杂,但你很难对"升级了哪些、各自升到了什么版本"有一个全局感知。
升级完再切到"可清理的项目",BrewUI 扫描之后显示旧版本缓存和下载缓存大约占了 1.8 GB 空间,我点击清理,很快就提示释放了空间。这个数字让我挺惊讶的,因为平时根本看不出这些东西占地方。清理按钮相当于是brew cleanup --prune=all的图形化版本,但有了明确的"释放了多少"反馈之后,我心里有数多了。对普通用户来说,这种即时可见的反馈,远比在终端里敲一条没有感情的命令更让人愿意去做维护。
5. 常见问题与排查技巧实录
5.1 打开就提示 brew 命令找不到
这个问题常见于 Homebrew 装在不同位置的情况。BrewUI 在启动时默认会去一套标准的路径找 brew 可执行文件,比如 Apple Silicon 上的/opt/homebrew/bin/brew,Intel 上的/usr/local/bin/brew。如果你的 Homebrew 是通过自定义方式安装到别的位置,或者在启动时 Shell 环境变量没有加载到 GUI 进程里,BrewUI 就会找不到 brew 命令。
解决办法是先确认which brew在终端里输出的路径,然后去 BrewUI 的设置项里手动指定这个路径。填完之后重新扫描,一般就能正常显示了。如果你用的是软件包管理器如mise、asdf安装的 Homebrew,路径一定要填实际生效的那个。
5.2 包列表一直转圈加载不出来
大多数情况是 Homebrew 首次从远端更新软件仓库索引时网络不稳定,导致超时。Homebrew 的公式索引默认从 GitHub 拉取,网络波动时会出现brew update卡住的现象,GUI 客户端启动时也会触发这个动作,就会表现为列表一直加载不出来。
我的建议是先在终端里手动执行一次brew update,等它在终端里跑完并看到 "Already up-to-date" 或更新成功,再回到 BrewUI 点击刷新。如果你的网络环境对 GitHub 访问不友好,可以配置一个可用的镜像源来加速 Homebrew 的更新,但要注意从正规渠道获取镜像配置,不要随意改手写的源地址。网络恢复之后,这个问题一般不会再出现。
5.3 安装失败,但终端里却能正常安装
这个场景我遇到过几次。BrewUI 调用 brew 命令时,虽然权限和终端里一致,但它并不会继承你终端里设置的全部环境变量。有些软件的安装脚本会依赖某些环境变量,比如JAVA_HOME、PATH里额外添加的路径等,终端里因为你在 Shell 配置文件里设置过,brew 能找到;GUI 进程里没继承到,就找不到了。
遇到这种情况,先别急着怪 BrewUI。第一步,在终端手动执行brew install 包名,如果终端也失败,那说明包本身或网络有问题,跟 GUI 没关系。如果终端安装成功而 BrewUI 失败,看看错误日志里是不是提示找不到某个工具或变量,再去把对应环境变量配置到 Shell 的全局配置文件里,重启 BrewUI 再试,通常都能解决。
5.4 界面显示的状态和 brew list 不一致
BrewUI 显示的版本和可更新状态,依赖的是它本地缓存的公式数据。如果你之前长期没有更新本地索引,或者 BrewUI 自动刷新时失败了,界面显示的可能就是几天甚至几周前的数据,和你终端里brew outdated的结果对不上。
解决办法很简单:先刷新,再对比。如果刷新之后还是不一致,检查本地 Homebrew 的公式目录是否有权限问题,可以跑一下brew doctor看看有没有异常提示。这里也建议养成习惯,不管是终端还是 GUI,日常维护前先做一次brew update,让索引保持新鲜,你的工具才不会帮你做出过时的判断。
5.5 容易踩的坑:别让 GUI 和终端同时跑耗时命令
最后说一个我自己踩过的坑。有一次我在终端里跑brew upgrade,同时又打开 BrewUI 去点了一键升级,结果两边同时要操作 Homebrew 的锁文件,一个窗口卡了大概一分多钟才反应过来。Homebrew 本身有锁机制避免并发操作,但一个客户端启动的任务会把另一个卡住,界面看起来就像死机了,实际上是其中一个进程在等锁。
所以我的建议是:同时干活的"大脑"只能有一个。如果终端里的 brew 命令正在跑,就等它退出之后再操作 BrewUI;反过来也一样。尤其是upgrade、postinstall这类耗时任务,并发起来不仅慢,还会让你误以为软件崩了。这个习惯养成了,你的 Homebrew 维护体验会顺很多。
5.6 常见问题速查表
| 现象 | 可能原因 | 处理方式 |
|---|---|---|
| 提示找不到 brew 命令 | Homebrew 路径非默认,或 GUI 没读到环境变量 | 在设置里手动指定 brew 可执行文件路径 |
| 包列表一直加载不出来 | 本地公式索引未更新或网络超时 | 先在终端执行brew update,再回 GUI 刷新 |
| 安装失败但终端成功 | GUI 未继承终端的环境变量 | 确认全局环境变量后重启 BrewUI |
| 显示状态和终端不一致 | 本地缓存数据过期 | 刷新数据,必要时跑brew doctor检查环境 |
| GUI 和终端操作互相卡住 | 同时触发了 Homebrew 锁 | 同一时间只在一个地方执行 brew 操作 |
整体用下来,我的感受是 BrewUI 没有也不可能替代终端里的 Homebrew,它更像是给 Homebrew 装了一个"仪表盘"。如果你完全不会命令行,它确实能让你用上 Homebrew 的生态;如果你本来就会用命令行,它也能帮你更直观地看到依赖和版本状态。我个人现在的习惯是高频操作在终端里敲命令,需要审查依赖、批量清理、给新人演示的时候才打开 BrewUI。最后再分享一个小技巧:刚装完包列表为空或者状态不对时,先去终端执行一次brew update再回来刷新,八成问题都能解决。