上一篇文章之后,我把 Codex 额度横幅隐藏器开源了

林小卫很行

前阵子,我写过一篇 Codex 额度横幅太烦?我让它给自己做了个隐藏器

当时的起点其实很小,Codex 的通用额度用完以后,横幅一直死死占着输入框上方的位置。我不需要它替我恢复额度,也不想去点 Upgrade 或者 Reset usage,只希望它不要长期挡住我的工作区。 Codex通用额度耗尽横幅截图

那篇文章的重点,在于怎么给 AI 交代一个清晰的本地改造任务,目标要克制,边界要严密,验收和卸载方式也得提前写进需求里。


这几天,我把那次一次性的本地脚本完整整理了一遍,做成了一个真正可以随时检查、安装、卸载并且能够继续迭代的开源项目。 Codex 额度横幅隐藏器 GitHub 开源仓库页面

仓库地址在这里,代码完全公开,采用 MIT 协议, GitHub,DavidLam-oss/codex-limit-banner-hider

它是一个面向 macOS Codex 桌面版的用户级界面定制工具。当「通用 Codex / Work usage 已耗尽」横幅出现时,只在能够唯一确认目标的前提下,隐藏横幅并释放它占据的屏幕空间。

先把最重要的话放在前面,它不会增加、恢复或绕过任何 Codex 额度。 它也不是 OpenAI 的官方功能。

这次后续,最有价值的不是「做出来了」

如果只是把上一篇写完的代码随手打包扔到 GitHub 上,其实没有太大意思。

真实使用之后,我们遇到了一个真正要命的问题,输入文字和切换会话的时候,Codex 有时会出现明显的卡顿和掉帧。

很有意思的是,当时自动化测试全都是绿的,DOM 的性能回归测试也顺顺利利跑完了。但这些冷冰冰的指标,根本推翻不了肉眼可见的体感卡顿。

写代码的人都知道,工具卡不卡,手指敲在键盘上最诚实。

于是我把旧版本彻底卸掉,花时间老老实实做了一轮实机 A/B 对比。

顺着调用栈一路摸下去,核心问题根本不在「隐藏横幅的那几行前端脚本」,而是在于底层的启动方式

早期实现为了接管新启动的 Codex,直接从底层用命令行派生进程。这样虽然能跑起来,却完全跳过了 macOS 官方的 Launch Services 前台应用生命周期。输入法框架和窗口会话的归属由此错乱,体感上的卡顿就是这么来的。

这个排查结果让我感触很深,

测试通过,只能说明你测到的用例通过了,它不等于用户用起来真正觉得舒服。

真实手感 vs 绿灯测试

所以开源版不是换个 README 就完事,而是把底层的启动和注入架构彻底重构了一遍。

现在的项目,究竟是怎样工作的?

尽量用大白话来讲,整个过程大致是这样的,

你像平时一样正常启动 Codex

用户级控制器捕获刚启动的官方 Codex 进程

严格核对应用路径、Bundle ID、官方签名与进程身份

通过 macOS 正常的 Launch Services 路径完成交接

启动阶段短暂连接页面,注入严格匹配的隐藏脚本

确认脚本生效,立刻断开连接

之后 Codex 完全按正常前台应用的方式运行,控制器不再打扰

这里有三个特别值得单独聊聊的技术细节。

1. 它绝对不改动官方应用包

这个项目从头到尾不会修改 /Applications/ChatGPT.app 里的任何文件,不碰 app.asar,不碰登录凭据,不碰 Keychain,也不干扰官方的自动更新,更不会去做恶心的重签名。

所有东西都规规矩矩放在你的用户目录下,一个用户级 LaunchAgent、一份控制器代码和一份清晰可读的注入脚本。

卸载的时候,当前正在跑的 Codex 不会被粗暴杀死。等你正常退出再重新打开,界面就干干净净回到官方原始行为。

这比直接去应用包里改一行 CSS 稍微繁琐一点,但更新、排错和还原的路径清晰太多了。

2. 它不是看到横幅就无脑删掉

真正危险的前端定制,往往只有一句草率的代码,找到页面上所有的 aside,找到所有带 limit 的词,通通隐藏。

开源版完全反过来做。它会同时核对主页面、标题文字、正文模板、横幅整体结构、内置图标以及当前允许存在的按钮。

只有当整个页面里出现唯一一个完全符合条件的候选时,才会加上专用的隐藏标记。

图片生成限额、单模型额度用尽、接近额度的提醒、系统安全提示、报错弹窗,或者带着未知新按钮的提示,统统不在处理范围内。

只要页面结构变了、出现多个相似候选,或者它拿捏不准,就会直接走 Fail Closed 策略,什么都不隐藏,同时在状态里如实汇报 structure-rejectedambiguous

我特别喜欢这个取舍,一个优秀的本地工具,最得体的自我保护不是强行工作,而是在看不清状况时明确停下来。

严密守门与 Fail Closed

3. 一个需要坦诚说清楚的架构取舍

上一篇文章里,我们探讨的是私有进程间通道。现在的开源版为了保留 macOS 正常的前台应用上下文,改为让 Chromium 在启动时随机分配一个仅绑定 127.0.0.1 的本地回环调试端口,控制器通过它完成一次性脚本注入,随后立刻切断。

说得再透彻一点,它不是固定端口,绝不对外网开放,更不是一个日常常驻的 DevTools 长连接。但它确实在启动的那一瞬间,存在一个本地回环端口。

这是当前版本明确写进 README 的架构取舍,我们把它摆在明处,不玩任何文字游戏。

在日常使用期间,控制器不再频繁向渲染器发指令,更不常驻连接页面。横幅稍后冒出来的时候,由已经驻留的脚本做极低频的定向检查。当窗口被隐藏时,这个检查也会自动挂起。

为什么一定要把它开源?

因为这种触碰到本地环境的工具,最关键的是「别人能不能独立看清它到底碰了哪里」。

如果它只是我自己电脑里一段私密的脚本,你只能选择相信我口头上说的边界。

但把它开源之后,所有事情都可以被任何人独立核对:

  • 它到底有没有改动官方应用包里的文件
  • 它会不会暗中点击购买、重置或者确认按钮
  • 它究竟在匹配什么页面、过滤什么元素
  • 遇到官方界面改版时,它会不会误伤其他重要通知
  • 出了问题怎么查状态,怎么几秒钟内卸载干净

项目里把这些交付物全都放整齐了,完全可读的源代码、中英双语 README、安装脚本、状态命令、卸载脚本、自动化测试,以及安全漏洞的报告指引。

我从来不觉得开源就等于绝对安全。但它至少让原本苍白的「请相信我」,变成了一句踏实的「你可以自己随时检查」。

想试试的话,先看这几个前提

这个项目目前只支持 macOS 上、安装在默认官方位置的 Codex 桌面版,并且启动时会严密核对 Bundle ID 和官方代码签名。重签名版本、第三方打包版、Windows 和 Linux 都不在支持范围内。

另外,你的电脑里需要安装 Xcode Command Line Tools,因为控制器会在本机完成编译。

确认好这些前提,安装只需要简单的三步,

git clone https://github.com/DavidLam-oss/codex-limit-banner-hider.git
cd codex-limit-banner-hider
./install.sh

安装脚本非常克制,不会为了强行生效而突然把你正在写的 Codex 关掉。它会保护当前正在工作的进程,第一次生效只需要你在没有任务的时候正常 Cmd + Q 退出软件,重新打开即可。

在项目目录下,平时可以随时运行这行命令查看状态,

./status.sh

如果是在新开的终端窗口,先 cd codex-limit-banner-hider 进入目录即可。

如果状态显示 hidden,说明目标横幅已被精准识别并隐藏。如果显示 absent,说明控制器运行良好,只是当前页面没有出现额度横幅。

status 状态自检命令运行结果

如果你看到 structure-rejected 或者 ambiguous,请千万不要去修改代码放宽匹配规则。那说明官方界面更新了,我们应该先检查新界面的结构,补上针对性的测试和适配。

不想用的时候,同样在项目目录下,一行命令就能还原,

./uninstall.sh

项目文件和 LaunchAgent 会被平稳移到系统的废纸篓,这是特意留下的一条可恢复的退路。

这个项目不适合所有人

如果你需要随时看到额度恢复的时间倒计时,或者心里对在用户目录下运行一个 LaunchAgent 有顾虑,那就不要装。

如果你追求的是「不管官方怎么改版我都必须强行隐藏」,它也同样不适合你。Codex 内部界面不是公开稳定的 API,我的设计哲学是,兼容时优雅应用,不兼容时宁可保留横幅,也绝不瞎猜乱动。

但如果你和我一样,心里很清楚额度的状态,只是单纯不想让一条大横幅长期霸占工作视野,同时又希望有明确的安全边界、状态反馈和优雅的卸载退路,那它或许是一份更放心的答卷。

从一段 Prompt 到一个可复用的工具

回头看,上一篇文章讲的是「怎么让 AI 替自己做一次轻量改造」。而这次的开源更像是那场实验的下半场。

一段 Prompt 确实可以快速启动一次尝试,写出一个能跑通的小 demo。

但如果要把它变成别人也能安心用在日常生产里的工具,后面还有很长的一段路要走,真机长周期的真实体验、翻车后的复盘深挖、底层架构的重新推导、防御性用例测试、完备的文档与状态工具、克制的卸载机制,以及接受公开审视的勇气。

这可能也是我越来越喜欢借助 AI 编程的原因。它能把原本停留在「我想改一下」的脑中灵感,以极快的速度拉齐成形。

但最终的边界和审美,始终得由人来把关。什么可以动,什么绝对不能碰,什么叫真正解决问题,什么只是表面上看起来差不多。

这一次,我把这些边界也一起开源了。