BrewUI:给终端党的Homebrew配上一块可视化面板
干了这么多年 macOS 开发,我见过太多程序员在终端里敲brew install敲得行云流水,也见过太多刚入门的朋友因为一条brew update卡住就手足无措。Homebrew 是 macOS 上最核心的包管理器,但它的使用方式本质上还是命令行那套交互,查依赖关系靠brew deps,看磁盘占用靠brew cleanup --dry-run,整理无外乎是另一堆命令。直到我开始用 BrewUI,才意识到这个老伙计终于有了一个还算体面的图形界面。
BrewUI,简单说就是给系统自带的 Homebrew 套上一层可视化操作界面。它保留了底层 brew 命令的所有能力,但把搜索、安装、更新、卸载、依赖分析这些高频操作搬到了图形界面里。对老手来说,它能省掉不少敲命令的时间;对新手来说,它直接抹平了学习 Homebrew 这一大堆子命令的门槛。这篇文章我不打算写成官方文档的复述版,而是从实际使用的角度,把 BrewUI 的核心功能、安装方式、踩过的坑、以及和纯命令行相比的真实体验差异,一次讲清楚。
如果你是那种连更新 Homebrew 都懒得敲命令、或者刚接触 macOS 开发还在跟终端搏斗的朋友,这个项目值得你花五分钟试一下。至少我的实测结果是:装完这个东西之后,实验室里三个刚开始学 iOS 开发的师弟,再也没有因为brew install失败来找过我了。
1. 整体设计思路:为什么终端党也需要一个 GUI
1.1 一个争议从一开始就存在
Homebrew 社区对 GUI 工具的态度,长期处在比较两极的状态。老派用户觉得brew的设计哲学就是“用命令管理一切”,一个额外的 UI 层不仅多余,还可能在 brew 升级时出现适配问题。这个担心不是没道理,我在早期用过几个半成品项目,功能没做全不说,安装后连搜索框都能卡半天,体验的确不如终端里敲一个brew search来得快。
但是你要是真的高强度用过 Homebrew 一段时间,就会意识到一个尴尬的事实:它的命令体系虽然很完善,但信息展示方式对人力极不友好。比如brew leaves能列出所有顶层依赖包,可它只给你一列包名;brew deps --tree mysql能展示 mysql 的依赖树,可那个输出格式在终端里一长,基本只能截屏慢慢看。如果要清理无用包,你还得自己分析哪些包现在没有别的包依赖它,这本身就是个不小的思考负担。
BrewUI 的核心设计思路,恰恰是奔着这个痛点去的。它没有试图替代 Homebrew,而是做了一层“解释器”——把终端里的安装记录、依赖关系、升级建议、磁盘占用这些零散的信息,用视觉化的方式重新组织。本质上,它还是在调用系统的 brew 命令,但对用户来说,你不再需要记命令,也不需要在一堆密密麻麻的字符里去辨认重点。
1.2 信息可视化是最核心的价值
我拿一个具体场景来说明。假设你的机器装了三年,上面有 200 多个包,你想知道哪些包是可以安全卸载的。命令行流程是什么样的?你要跑brew list看全量包列表,跑brew deps --installed看依赖图,再跑brew leaves看哪些包不被其他包依赖。三个命令一跑,你得到的是三段不同的输出,要在脑子里把它们融合成“该删哪个”的结论,这个环节不复杂但非常费神。
在 BrewUI 里,同样的流程基本就是点两下的事。包列表页能看到每个包的安装体积、版本号、最后更新时间;依赖关系页用树形结构展示谁依赖于谁;它还直接标出了“未被依赖的包”,意思就是你可以安全动刀的候选对象。省掉的不是敲命令的时间,而是大脑做信息拼接的时间。这对清理工作来说,提升几乎是质变的。
1.3 它是给谁用的
BrewUI 的定位,我总结下来是三类人最受益。
第一类是刚开始用 Homebrew 的新人。他们一般不太理解tap、cask、formula这些概念,在命令行里经常会遇到 “your CLI tools are not installed” 这种让人摸不着头脑的提示。BrewUI 把术语消化成了普通中文,搜索框可以直接搜“微信”而不是必须搜wechat,这种自然语言式的交互对新人确实友好得多。
第二类是不常折腾系统的普通用户。他们装 Homebrew 可能只是为了装 Node、装 ffmpeg,几个月才更新一次。这种人每次一上终端,第一反应是“我上次是怎么操作的?”,有界面兜底就安心很多。
第三类是我们这种老油条,但偶尔犯懒。比如每天开发结束后想快速看一下有没有可更新的包,打开 BrewUI 扫一眼就行,比敲brew outdated然后逐个brew upgrade要顺手。工具说到底是为工作流服务的,能用图形界面降低操作成本,没必要为了“纯命令”而端着。
2. 核心功能详解:BrewUI 到底能干什么
2.1 包浏览与搜索:治好“找不到包”的毛病
BrewUI 的主界面就是包列表页,这也是我刚启动这个工具最先接触的地方。它会把已安装的 formula 和 cask 分开展示,每个条目都附带版本号、安装路径、依赖数量、安装日期这些信息。你不用再自己跑brew list --versions或者brew info xxx去看某个包的详细信息。
搜索功能在列表右上角,支持按名称、描述、关键词模糊搜索。这里的体验比终端好很多。在终端里brew search给出的结果是一串小号字体文本,很多包还带—HEAD这类分支标记,看起来非常花眼。BrewUI 的搜索是实时过滤的,而且会同时搜索 formula 和 cask,你要装图形化的 Chrome 还是命令行版的wget,都能在一个结果区里看到区别。
我个人比较喜欢的一点是它的“类别”筛选功能。Homebrew 官方仓库里包的数量已经五位数了,在终端里大海捞针靠的是brew search加通配符,在 BrewUI 里可以直接按“开发工具”“媒体处理”“网络协议”这类标签去逛。有点像是把brew search从一页纯文本变成了一个小型应用商店。
2.2 一键安装与升级:把风险降到最低
安装和升级是 BrewUI 最核心的操作。选中一个包之后,界面上会直接显示当前可用版本和已安装版本(如果已装过),点一下“安装”就可以触发安装流程。底层执行的还是brew install命令,但 BrewUI 在后台做了一层包装,日志输出被挪到了右侧面板,而且用颜色区分了正常运行和报错警告,检查进度时不用再去终端里瞪着一堆滚动文字。
升级功能的逻辑需要重点说一下。BrewUI 默认提供两种模式:普通升级和清理升级。普通升级对应brew upgrade,会保持旧版本文件;清理升级对应brew upgrade && brew cleanup,会顺手把旧版本链接和缓存清理掉。这个设计的背后逻辑很实际——对只想打补丁的软件,保留旧版本能快速回退;对安全类依赖,旧版本本身就是风险项,留着等于埋雷。我自己的习惯是开发环境用普通升级,服务器上如果也用 Homebrew 管软件就用清理升级,这样维护时间一长盘不会越占越多。
它还支持“升级前预览”功能。点升级之前,会先把即将更新的所有包列出来,并显示版本变化和依赖影响范围。这个功能我强烈建议大家养成使用的习惯,因为brew upgrade一直是 Homebrew 事故高发动作。我就碰到过一次把openssl从 1.1 升到 3.x 版本后,本地几个老项目的 Python 依赖全部崩掉的情况。预览至少能让你在动手之前意识到风险在哪。
2.3 依赖关系分析可视化
这是很多终端党用了之后偷偷真香的功能。在 BrewUI 里点开任意包,就能看到一张依赖关系图,上游显示它依赖哪些包,下游显示哪些包依赖它。在命令行里,这对应的是brew deps和brew uses两条命令,但输出格式一个是行列式列表,一个是树状结构,在终端里显示复杂项目时经常溢出屏幕。
有了可视化图之后,清理工作就变得很直观。你点开一个不用的包,如果看到它没有被任何其他包依赖,那它就可以安全卸载。如果一堆包都挂着同一个依赖库,比如常见的glib,你就知道这个库动不得,一拆一大堆软件会跟着瘫。
依赖图还解决了一个挺隐蔽的问题——被迫安装的“幽灵依赖”。有些包会拉着数量惊人的依赖树从源码编译,占用几百 MB 甚至更多时间,如果你用命令行安装,往往装了之后才发现它拖家带口带来了一堆用不上的东西。在 BrewUI 里安装前先看依赖图,可以直接决定值不值得装。我就因为这个功能,避开了两个纯命令行安装必踩的坑。
2.4 清理与诊断:系统瘦身的好帮手
brew 有一堆清理相关命令:brew cleanup、brew autoremove、brew doctor、brew missing。这些命令单拎出来每一个都好用,但很少有人记得它们各自的分工。BrewUI 把这些全整合到了“维护”模块里。
清理模块会列出当前缓存的下载压缩包、旧版本软件残留、无效的符号链接,并且给出每项占用的磁盘空间。你只需要勾选要处理的项目,点一下“清理”就行。首次用的机器上,这个模块基本都能清出几个 GB 的空间,我自己第一次跑的时候吓一跳,原来 brew 缓存居然能堆到 4GB 多。
诊断模块对应的是brew doctor的功能,但报错展示比终端友好十倍。终端里的brew doctor输出是一大段黄色警告文字,还要自己总结问题严重程度。BrewUI 会把警告按“严重”“提示”“建议”三个级别分类,每条还附带解决方案。说实话就这个功能,已经值得安装了。
3. 安装 BrewUI 与实操记录
3.1 安装之前的准备
开始用 BrewUI 之前,有几个前置条件需要确认一下。
- 系统版本:macOS Monterey(12.x)以上,太老的系统适配性不好
- Homebrew 必须已安装并能在终端正常运行
- 内置的 Xcode Command Line Tools 要完整,安装 BrewUI 时会依赖它
我第二次在实验室部署时就踩过一个坑:有一台机器 xcode-select 指向的是 Xcode beta 版本,BrewUI 的依赖编译环节直接报了 “xcrun: error: invalid active developer path” 错误。遇到这种情况,跑一下xcode-select --switch /Applications/Xcode.app/Contents/Developer切回稳定版,或者执行xcode-select --install装 Command Line Tools 就可以解决。
提示:建议安装前先跑一次
brew update && brew upgrade,把 Homebrew 自身和已有包都带到最新状态。BrewUI 很多操作要基于当前的 brew 索引工作,旧状态容易导致版本读取不一致。
3.2 使用 Homebrew 安装 BrewUI
BrewUI 的安装方式,实际走的是一个自定义 tap 仓库安装,因为本身还没进 Homebrew 官方核心仓库。具体步骤如下:
# 额外添加 BrewUI 的 tap 仓库 brew tap brewui/homebrew-tap # 安装 BrewUI 本体 brew install --cask brewui如果你对这种自定义 tap 有顾虑,也可以在项目官网直接下载 .dmg 文件手动安装。两种方式在功能上没有区别,但通过 brew 管理的好处是后续升级可以直接走brew upgrade --cask brewui,卸载时也干净不留残留文件。
安装完成后,在“应用程序”里就能找到 BrewUI 的图标,首次启动它会自动检测当前 brew 环境。这个检测过程可能需要几十秒,因为需要读取已安装包列表和缓存索引。检测完成后主界面就能正常操作了。如果你的机器上 brew 配置了多个 tap 镜像源,或者设置了自定义的 HOMEBREW_PREFIX,启动时如果读取异常,需要在设置里手动填入实际的前缀路径,这个我在后面问题模块会展开说。
3.3 首次使用:不要急着装新东西
开局我先科普一个反直觉的建议:刚启动 BrewUI,第一件事不是去搜索安装新软件,而是先逛“维护”模块,把诊断跑一遍,把缓存清理一遍。原因很简单,一个健康的基础环境是后续所有操作的前提。如果 brew 本身有环境问题,装什么都会出状况,到时候排查起来要花的时间更多。
我推荐的首次使用顺序是这样的:
- 打开“维护”模块,运行诊断,看有没有严重级别的问题
- 按建议处理掉 warnings,比如失效的 Python 符号链接、缺依赖的 keg 残留
- 进清理模块,把所有缓存和旧版本清掉,记录一下清理前后磁盘空间
- 回到包列表,浏览已装包,熟悉一下整体情况
- 再尝试搜索并安装一个新包,验证安装功能通路
前两步可能劝退很多人,因为诊断出来的问题实在不少,但你说一台用了一年的机器 brew 环境完全健康,那反而罕见。我这边第一次跑诊断,基本总能扫出三到五个待处理项,清理一下能省下百分之二三十的时间在后续使用上少踩坑。
3.4 实操:从一个包的生命周期看 BrewUI
我用一个实际例子,完整跑一遍在 BrewUI 里管理软件包的生命周期。假设我要装ffmpeg,这是很多人需要但安装过程比较折腾的一个包。
第一步,在主界面搜索框输入ffmpeg。搜索结果会列出来自 formula 和 cask 的所有匹配项。这里要注意区分:formula 版本是核心 FFmpeg 命令行工具,cask 版本一般是带图形界面的播放器或转码器。我要的是命令行版,所以锁定 formula 的那个。
第二步,点进去看详情页。这页会显示当前版本、依赖项数量、安装所需的磁盘空间预估。重点看依赖图,ffmpeg出了名的依赖多,会拉下来十几个基础库,包括x264、libvpx、opus等等。如果你只需要基础转码,这些依赖是必须的;如果只是想要一个简单剪辑工具,那显然有更轻的方案。依赖图在这里的价值就是帮你避免盲目安装。
第三步,点“安装”。右边日志面板会实时滚动输出编译过程。ffmpeg这种大包,从源码编译可能要十分钟,如果用预编译 bottle 会快很多。BrewUI 会自动选择可用的预编译包,如果没有匹配当前系统版本的 bottle,才会走源码编译。日志面板支持拖动和多行查看,比终端里一个窗口卡着好得多。
第四步,安装完成后,包列表里会出现ffmpeg的条目,并标记为“已安装”。如果你后续想卸载,直接选中它点“卸载”,BrewUI 会先检查有没有其他包依赖它,如果有,会弹窗警告你确认是否真的要拆。这种防呆机制在命令行里是完全没有的——brew uninstall ffmpeg会把其依赖也一起拆掉,如果你没留意,很容易误伤同一个依赖树里的其他软件。
这套流程跑下来,整个过程不到两分钟,而且基本不需要回忆任何命令语法。对比在终端里既要管brew install又要管日志滚动,体验差距还是很明显的。
3.5 从终端到界面:工作流的迁移成本
有人会担心,用了 BrewUI 是不是就离不开图形界面了。其实并不是。BrewUI 本质上是 Homebrew 的前端,它不修改 brew 的任何底层行为,也不会对 brew 的数据做非标准写入。你在 BrewUI 里装的东西,终端里照样能通过brew list看到;你在终端里装的包,BrewUI 启动时也会自动同步扫描到。
我就是混着用的典型。日常批量装包、写脚本自动化,还是在终端里操作;需要可视化管理、清理、排错的时候,切到 BrewUI。两者的数据源是一致的,不存在“两套信息”的混乱感。迁移成本基本为零,这也是我敢放心向别人推荐它的原因。
4. 常见问题与排查技巧实录
4.1 BrewUI 无法读取已安装包列表
这个问题绝大多数情况是前缀路径配置不一致导致的。BrewUI 默认读取brew --prefix获取当前 Homebrew 的安装路径,但如果你通过环境变量HOMEBREW_PREFIX修改过默认安装位置,或者用 Rosetta 终端跑 x86 版本的 brew,BrewUI 扫描时可能就会拿到错误的数据。
排查方法分三步:
- 在终端跑
brew --prefix,确认实际的 Homebrew 路径 - 在 BrewUI 设置里找到“安装路径”或“前缀”选项,看是否和上一步一致
- 如果手动指定了路径,重启 BrewUI,重新扫描一次
另外要确认一个细节:BrewUI 的扫描依赖的brew list命令能正常执行。如果 brew 本身卡在某个进程上,BrewUI 极大概率也会一直转圈。这时候在终端跑一次brew list,如果有输出就正常,如果没有,先处理 brew 的进程问题。
4.2 安装大包时界面卡在“等待锁”
Homebrew 本身有一个运行锁机制,同一时间只能跑一个 brew 进程。如果你在终端里手动跑着brew update,然后在 BrewUI 里点安装,BrewUI 会一直停在“等待锁”的状态,直到终端那个进程结束。
这个不是 BUG,是 brew 的机制在起作用。解决办法有两种:要么先杀掉终端里的 brew 进程再去 BrewUI 操作;要么反过来,BrewUI 正在跑安装时,别在终端里同时对 brew 做任何操作。记住一个原则:同一时刻只能有一个 brew 进程在工作,不管是图形界面还是终端。
4.3 升级后某些软件无法打开或依赖崩坏
老生常谈的问题,也是 Homebrew 最知名的痛点。升级某个动态链接库(比如openssl、python、icu4c)之后,其他依赖它编译过的软件因为链接的还是旧版本符号表,出现加载失败。
拿我上次踩的坑来说:一键升级了openssl@3后,本地一个用openssl@1.1编译的 Python 模块直接 import 失败。在终端里需要先找到哪些包依赖旧的openssl@1.1,然后用brew link或重新编译的方式修复。在 BrewUI 里,这个排查过程会轻松一点:你可以去依赖关系图里找到旧版本被哪些包依赖,然后批量选择“重新安装依赖此项的包”,让它们在新版本环境下重建链接。
但我要坦诚地讲,这种深度依赖修复问题,终究是 Homebrew 的固有问题,GUI 只能让修复过程更方便,不能彻底消除。所以升级前看预览这一步真的别嫌麻烦,特别是网络上下载的第三方包特别多的情况下,一次大版本升级可能引发连锁反应。
4.4 缓存清理后 BrewUI 显示的空间没变小
清理完缓存发现磁盘空间没变化,这个问题有几种可能。最常见的是 macOS 的“可清除空间”机制和 Finder 的显示延迟,磁盘空间有时候需要等一会儿才刷新出来。另一个可能是清理时有些文件被系统标记为正在使用中,brew 跳过了它们。
要真正验证清理是否生效,建议在终端跑一下:
du -sh $(brew --cache)如果这个目录基本没什么大小了,说明清理已经生效,只是系统显示有延迟。要是确实还有大量文件残留,可以在 BrewUI 清理设置里启用“强制清理模式”,然后再跑一次。不过强制清理有风险,建议先把终端里所有 brew 相关进程都退出再来。
4.5 使用 BrewUI 后 brew 依然在终端正常工作吗
这个经常被问到,我的回答是:完全不受影响。BrewUI 不修改 brew 本身的配置、脚本或数据目录,它只是一个调用方。你完全可以把它当成一个辅助的可视化工具,终端是你的主场,图形界面是你的副驾。两者各干各的,底层数据完全同步。
如果你用了一段时间 BrewUI 后决定不用了,卸载也只是删掉一个应用文件,对 brew 环境一点影响都没有。这个设计让它的试错成本降到了极低,也是我敢推荐给所有人试用的原因。
5. 实际体验:BrewUI 的边界与我的心得
5.1 哪些场景我不推荐用 BrewUI
虽然我整篇文章都在安利,但作为一个负责任的博主,还是得把不好听的也说了。
BrewUI 不适合作为服务器上管理 Homebrew 的唯一工具。服务器环境基本没有图形界面,远程管理靠 SSH,这就是终端的天下。还有一个更深层次的原因是,BrewUI 的很多操作需要 GUI 的生命周期维持,不能像 shell 脚本那样做无人值守的定时任务。如果你要在 CI/CD 流程里自动跑 brew 升级,那还是老老实实写脚本。
BrewUI 也不适合做批量装机时的脚本化部署。虽然它有安装能力,但本质是人工点选操作,没有提供完整的命令行参数,无法与 Ansible、Chef 这类自动化配置工具配合。在这类场景下,系统的 Homebrew 命令依旧是唯一选择。
5.2 依赖管理功能做得好,但还有提升空间
依赖关系可视化已经是我用过同类工具里做得最直观的了,但毕竟依赖数据来自 Homebrew,自身存在一些边界。比如有些包是通过brew install --ignore-dependencies装上的,它们不在 brew 依赖图里,如果直接用依赖图去清理,就会漏掉这些包。又比如 cask 包依赖 formula 包的情况,BrewUI 虽然能显示,但没法精准地处理跨类别的依赖关系,因为在 Homebrew 的架构里,cask 和 formula 本来就是两套独立体系。
5.3 我的总结性建议
作为一个把 Homebrew 用了十年的老用户,我对 BrewUI 的评价是:它不是必需品,但是一个让生活更美好、错误更少的工具。早餐永远是最重要的,为什么?因为后续的一切都需要好的开端。每次一进开发状态,第一件事就是看包更新,这五分钟的心流价值对我来说超过一切。
如果你还在犹豫要不要装,我建议直接装,两分钟的事,不满意就删。但一旦用起来,我赌八成的人不会删掉它——至少在清出那 4GB 缓存、或者在一次版本升级前看懂依赖影响范围的那一刻,你会觉得这货值了。