壹引其纲,万目皆张——2026 年,谈 Coding Agent 与开源软件维护

当开源项目维护者从写代码的人,变成作判断的人

Posted by wszqkzqk on May 10, 2026
本文字数:7246

藏器于身,待时而动

从我小学毕业考试前夕注册算起,我在 GitHub 上已走过十一年。作为一个维护着多个开源项目的个人开发者,我的 GitHub 迄今也累计收获了 7000+ star。今年我想谈谈自己感受到的一个深刻变化——coding agent 对我和我的开源项目之间的影响。

GitHub Profile

我想先从一个小小的个人项目谈起,Live Photo Converter 是我开发的一个 Android 动态照片处理工具。它的核心功能——合成、提取、修复——从一开始就通过命令行完整实现了。CLI 对我够用,一行命令,一秒搞定。

但发布之后,陆续有用户来问”有没有图形界面版本”。

答案一直是:没有。

这并不是我不会做 GUI。我写过好几个 GTK4 / LibAdwaita 项目,基本熟悉这套框架。但写 GUI 不是拖几个控件的事——文件放置区要同时支持拖放和点击浏览、处理大文件时不能阻塞主线程、批量操作的错误要优雅地汇总展示、三标签页的布局要合理、主题切换要适配——这些简单但是琐碎的事情工作量并不小,还很枯燥。

而我根本不需要 GUI,纯 CLI 的使用对我来说一点也不麻烦,这些时间对我而言没有产出,并不值得。

于是这个需求放了两年。直到 2026 年。

工欲善其事,必先利其器

今年的模型可以说有了全方位的提升,在处理小众语言和新兴框架的能力上跃升明显。Vala 语言用的人并不算多,GTK4 还在逐渐取代 GTK3 的过程中——之前的模型很容易把两者的 API 搞混,写出来的代码带上 GTK3 时代已经废弃的 API。这导致 Vala/GTK4 程序此前一直难以让 AI 全面参与。

然而今年,情况变了。

我抱着试一试的态度,对没有什么插件的 opencode 只说了一句话:“给这个项目使用 GTK4 / LibAdwaita 实现一个 GUI。”除此之外,我没有给出任何其他的说明。

Agent 先是花了大约三分钟,用 subagent 把整个项目的源码扫了一遍——CLI 的参数结构、LivePhotoLiveMaker 的抽象类层级、GStreamer 和 FFmpeg 的双后端设计等等。然后它开始写:一个初步的 gui.vala、更新了 Meson 构建文件以支持可选的 GUI 编译目标。整个过程一气呵成。

第一版有不少问题——布局、交互设计不合理,控件使用不合理,甚至出现了 SIGSEGV。但它也大致像个样子:至少三个标签页的结构是正确的,异步处理的基本框架也在。而且它真的能编译通过。

我没有告诉它任何具体的设计要求,但这个项目的 CLI 设计——live-photo-makelive-photo-extractlive-photo-repair 三个子命令的分工——本身就已经暗示了 GUI 应该有三个对应的操作区域。Agent 读懂了这个结构,并把它翻译成了三标签页布局。至少它已经能够从已有设计中推导出合理的 UI 架构。

从那一刻起,我的角色才变成了详细的指导者——指出布局问题、要求按钮固定在页面底部、调整控件间距、要求管理按钮的可用状态等等,打磨细节。每一次迭代都是几分钟的事:我描述问题,Agent 修改,编译验证,继续。一两天之后,一个完整可用的 GTK4 / LibAdwaita 图形界面便可正式推出。

更重要的是一系列配套工作——国际化翻译、Flatpak 打包 CI——这些以前我大概率会因不愿浪费精力而搁置的事情,都顺着同样的节奏完成了。

在这里,Agent 的介入其实解决了开源软件维护中一个矛盾:开发者的有限精力和用户的长尾需求之间的矛盾。用户想要的很多功能,开发者并不是不认同,只是缺乏时间和精力。Agent 做的事情,是把写代码这个环节从体力劳动变成了指挥——而指挥,恰好是那些最熟悉项目、最有经验的维护者最擅长的事。

这还不是全部。我在 Vala 编译器上的经历,则说明它还能把我本身想做但没力气做的也变成现实。

我从 2022 年起就陆陆续续给 Vala 提交代码,一度成为了 Vala 编译器的第二大贡献者。但这些年,我也累积了不少已经发现却只报了 issue 而尚未解决的问题——知道它不阻碍手头的工作,就懒得专门花时间去排查根因。这种事没有什么创造性,但极耗时间:你需要回溯调用链、构造触发条件、验证假设,一个 Bug 排查几个小时是常事。

今年我试着把这些 issue 丢给 Agent。结果发现 Agent 天然适合干这个。编译器本身的逻辑结构清晰、自洽性强,Agent 阅读理解起来反而相当顺手——即使是 Vala 这种小众语言写的自举编译器,它也可以在扫描项目结构时自然学会语法和惯用法。更关键的是,我可以同时开几个并行的 session,每个 session 各引导 Agent 拆分任务给多个 subagent,结论出来时就已经经过了充分的链路研究与交叉验证。以前半天排查一个,现在一个下午能定案好几个。

Vala 算是我一直长期深入参与的项目。而对于那些我并不熟悉、只是因为自己的需要而短期接触的项目,Agent 同样可以改变局面。

今年我给 Krita 做了构建适配,给 libpanel 适配了资源路径等等。这些项目我之前都没有长期跟踪,缺乏对项目细节的了解,在没有 Agent 的情况下,光搞清楚项目结构和构建系统就需要不少时间。但现在,我可以凭借自己的认知和经验给 Agent 设定一个研究起点,让它先去了解项目的相关信息,然后按照最优实践来实现。我要做的,主要是验收它的产出,判断这个实现方案能不能接受,由于细节层面同样可以让 Agent 压实,很多时候验收的工作量也相当小。而这些修改,过了我这关,基本上也就能过上游维护者的关

这其实是 Agent 在开源社区贡献中真正改变的东西。以前,你不仅需要有能力判断一个方案好不好,你还得手上有时间把它实现出来。现在,这两个环节解耦了。Agent 帮你把品味与判断力变成代码,迭代成本大大降低。当然,前提是你能判断——如果你自己分不清什么代码是好代码,Agent 只会成为给上游维护者添麻烦的工具。但对于有经验的维护者来说,Agent 的介入,恰好放大了他们的经验和判断力。

博观约取,厚积薄发

用 Agent 创建新项目,和用它参与已有的社区项目,是两种不同的体验。

我在维护 Arch Linux for Loong64 发行版的过程中,经手了海量的开源软件包。与一般 Linux 发行版社区每个人只负责一类包的组织架构不同,我几乎会接触所有包的构建:我在此过程中会自然地看到大量项目的依赖链路、知道什么库适合什么场景、知道什么样的架构选择在跨平台时会有问题、知道哪里容易踩坑。

这些知识在日常手写代码时发挥的作用有限——你知道某个设计模式是对的,但把它一行行敲出来还是需要时间。但把这些知识用在 coding agent 上,效果完全不同。Agent 擅长的是把明确的需求变成具体的代码,而我脑子里装的正是这些明确的需求,以及见过大量实际项目后沉淀下来的、知道什么行得通什么行不通的判断。

今年从零启动的几个新项目,走的都是这个模式。

LinSYS2 是一个相当独特的想法:使用原生的 Linux 包管理器去兼用 MSYS2 的软件源服务,直接对接管理 MSYS2 生态下的 Windows 原生的工具链、基础库及应用程序,通过 Wine 运行,不借助虚拟机或容器。这个想法之所以可行,是因为我知道 MSYS2 的包管理架构、了解 Wine 对原生 Windows 二进制的兼容性边界,也清楚跨平台的符号链接和路径处理有什么陷阱。而 LinSYS2 从第一条 git commit 到能实际使用的版本,只有一天。

Qt Web Extractor 是一个轻量级网页内容提取引擎,更贴近 Linux 发行版维护的哲学。Playwright 和 Puppeteer 太笨重了,而且在 LoongArch 上构建困难。Qt Web Extractor 用系统的 Qt WebEngine(底层是 Chromium)全功能提取网页,发行版包管理器负责安全更新,代码量小得多。我把这个想法和架构设计交代给 Agent,实现也是一天的事。

guiless-search 是多后端无头搜索引擎,取代了我之前写的 GUILessBingSearch。这次 Agent 从零实现了多后端(Google、DuckDuckGo、Bing、Sogou)、并行与回退搜索模式、速率限制和惰性加载。没有历史包袱,架构更干净。

还有 openmemoryopencode-kimi-search,前者是为 coding agent 设计的分层文件系统记忆插件,后者是给 OpenCode 提供搜索能力的小工具。它们都在一天内完成从想法到发布。

我没有亲手敲其中的代码。我的工作变成了——设计架构、审查监督、迭代修改,然后验收。纲举目张,我只需要把精力投在只有我能做的判断上。

大音希声,大象无形

今年到目前为止,我写了 PvZ-Portable 的系列博客,多达十多篇,覆盖从项目引入、跨平台适配、图形渲染迁移、音频系统重写、到 GL 缓冲区安全、长期运行的溢出稳定性。每一篇的技术分析都足够详细——确切的 git 提交、性能分析的数值、内存安全的具体场景。

博客里没有写的是:这些工作绝大多数也是 AI 完成的。我设计方向、描述问题,Agent 负责写实现。就连审核的事也不必我事必躬亲——基本的逻辑细节正确性和代码风格,Agent 自己就能把关。我要做的,是扫一眼代码就知道它在哪里误入歧途了,应该往哪个方向改。

那篇关于“Zombies On Your Lawn”MV 中背景贴图错乱的 Bug 修复,是我在博客里唯一一次明确提及 AI 的地方。为什么唯独提了它?因为这个 Bug 藏得太反直觉了——看到背景贴图错乱,正常的思路都是去排查 MV 相关的逻辑。结果根因居然是底层 GL 写的有问题。Claude Opus 4.6 的 Agent 连续跑了两个小时、用了不知多少个 subagent 才把它从完全意想不到的位置揪出来。这在当时确实给了我不小的震撼,所以才特意在博客里提一下。

但博客里没有提的,其实更多。全新的跨平台关卡内存档格式、GLES2 迁移、多语言资源包支持、Android/iOS/WebAssembly 的平台适配——这些同样是在我指导下由 Agent 完成的,而且无论是实现效果,还是代码质量都相当优秀。只是这些工作都相对比较符合常规的预期,没什么特别的故事,所以我就没有在博客里专门提到 Agent 的使用。

博客里的所有分析、判断、架构选择,确实是我做的。那些修复方案的方向是我定的,那些跨平台决策的依据是我判断的,Bug 的根因也是在我指导下定位的。Agent 做的只是把这一切翻译成代码——这恰恰也是原来最耗时间的部分。

可能很多人读完博客后的反应是”这个作者真能有精力”。其实,我的精力投入并没有比以前多多少。只是现在我把精力投在了只有我能做好的判断上,而把那些不需要我判断的部分交给了工具。

弗虑胡获

说了这么多做得成的,必须谈谈做不成的。

Arch Linux for Loong64 的发行版维护,是至今难以真正 AI 化的领域。原因不在于工具链——虽然龙架构下目前还没有 bun 支持,但其实我已经给 Arch Linux for Loong64 构建了 openai-codex,gemini-cli 和 qwen-code,已经有不少可用的 coding agent 了。

真正的瓶颈在于,发行版维护中最关键的整体决策,恰恰是当前 Agent 最不擅长的。

发行版维护经常面对这样的场景:一个包编译报错了。错误表面上是这个包的代码问题,但实际要修哪里?可能在这个包自己的补丁里修,可能在构建脚本里绕过,可能在它依赖的另一个包里改一个头文件,也可能需要深挖依赖的依赖等等。每条路径在技术上都是可行的,但后果完全不同——对下游几十上百个包的影响、对后续维护成本的改变、对整个发行版稳定性的扰动,都不一样。

选择哪一条,是一个品味和判断力的问题。你需要对整个发行版的依赖图有全局理解,需要预判每条路径的连锁反应,甚至需要在多个都不完美的方案里挑那个最合适的方向。这种决策,暂时没有任何 Agent 做得很好——它们可以给你列出不少可行的路径,但它们自己选择的方法,在整个开源社区层面看,往往并非最优。而知道该走哪条路,比知道有哪些路可走,要难得多。

LoongArch 维护中 AI 目前能做的,仅限于分析构建日志、检索上游 Bugzilla/GitHub 的相关 issue、提供可能的修复方向供人判断。写代码这一步,在这里反而是最不重要的。知道在哪个环节修,比知道怎么修要难得多。

然而有意思的是,这个项目虽然几乎没有引入 AI,却是我所有项目里维护效率最高的之一

所有人肯定都知道,目前 LoongArch 的上游支持和重视程度比 ARM 差得多,用户数量比 ARM 少得多,硬件也远远不如 ARM。但就是这样,顶着大量上游的不利条件,Arch Linux for Loong64 却长期在 Arch Linux 的几个 ports 中总覆盖率位列第一。一个滚动更新、上万个包的大发行版,很多人可能会以为这需要一个不小的团队,但实际上长期维护的几乎只有两个人——我和 Pluto Yang 老师。而且对我来说,开源只是生活中的一小部分,而 Arch Linux for Loong64 的维护又是这一小部分里的一个小分支——这并不是一个需要不断投入海量精力的项目。

能做到这样,靠的不是堆人力,是架构。靠的是从一开始就把维护的架构搭得足够高效——对上游的充分整合和利用、高效的流程设计、以及在每一个环节上对维护代价最小化的反复优化。只要设计、架构、流程都足够优秀,不用太多精力,也可能实现一个人顶一个师

所以,Arch Linux for Loong64 项目恰好同时说明了两件事。Agent 在今天确实有它碰不到的边界——品味和判断力的缺失,让它们目前还无法自主做出在整个开源社区层面的最优决策。但高效这件事,从来不只是由工具决定的。有 Agent 不代表效率一定高,没有 Agent 也不代表效率一定低。无论用不用 AI,真正决定效率的,始终是那些关键的判断。

从心所欲,不逾矩

有一个经常出现的担心是 AI 写的代码质量不好,会降低项目的可维护性。我的实际体验是:这取决于你怎么用。

如果让 Agent 自己发挥,不审查就合入,那确实会出问题。Agent 常会引入不必要的抽象,把简单的事情过度工程化,遇到 Bug 喜欢在表面打补丁而不是从根源解决。但如果把流程搭对——描述清楚要什么,用合理的结构让 Agent 规划成熟,自我审查——这些问题就都能过滤掉。而且 Agent 的响应速度极快,迭代成本更低的时候,质量反而更容易打磨。

不过,这些都只是操作层面的事。真正让我对 AI 参与代码质量有信心的,是它能发现我根本不会去看的东西。

人写代码的时候,注意力天然是局部的——你盯着当前这个函数、当前这个模块,很难翻遍全部角落去彻底检查路径。Agent 正好相反,可以通过并行的 subagent 来全局扫描代码,追踪隐藏的链路,并汇总结果分析。这些都是人很难做到的,但 Agent 却能轻松胜任。

PvZ-Portable 为例。这个项目的代码质量不仅没有因为 AI 参与而下降,反而在一些维度上提高了项目的可维护性。GL 缓冲区安全的那次修复(delete 被调用在 delete[] 应该使用的场景),是 Agent 在全局扫描代码时发现的——人类更容易关注自己当前在写的那个函数,而不太会主动翻几百行之外的释放路径。资源生命周期安全那次也是——SDL_mixer 的音频回调里对象被析构导致的 use-after-free,Agent 能在完整上下文中追踪对象的所有权流向,人反而容易在局部逻辑中忽略。

项目原来集成的老旧 C++98 历史代码,也是让 Agent 一步步迁移到 C++20 的,整个程序的现代化和可维护性都因此提升了一个档次。在有效的质量把控下,从代码上其实不太容易区分哪些是人写的、哪些是 AI 写的。AI 的引入,不仅不会降低代码质量,反而帮助提高了项目代码的一致性和可维护性。

我近期修复的 Wine 性能回归也是类似的模式。那个 Bug 本是我在 Linux 下用 Wine 测试 Windows 版 PvZ-Portable 的表现时的无意发现。起初我意识到 PvZ-Portable 自身有优化空间——同一帧内的 time 调用完全可以缓存,于是先在应用层面绕过了这个问题。

但我也清楚,这不只是我程序的问题,Wine 的更新确实引入了严重性能回归。即使 PvZ-Portable 自己修复之后不再受影响,这个 Bug 也仍然在那里——每一个在 Wine 上运行的程序都可能踩到。有了 Agent,我有精力去把它查清楚。我圈定了排查范围,Agent 在限定的变更历史中逐个排除,最终发现 Wine 11.4 在 get_timezone_info() 热路径上加了一个无条件 mktime() 调用,导致 NT→Unix 转换的开销暴增约 25 倍。

从发现现象到在 Wine 源码中找到具体的 commit 位点并提交修复 MR,Agent 贯穿了整个流程,而我只进行了范围的引导与修复的最终检查与确认。

这个修复已经被 Wine 上游合入,随 Wine 11.5 发布。

纲举目张

去年这个时候,coding agent 对我来说充其量是一个高级的自动补全、一个检索与建议工具。今年局面完全变了。

《吕氏春秋》有言:“壹引其纲,万目皆张。”纲是网的总绳,目是网眼。以前维护开源项目,我很可能不得不一根根地去拉那些网眼,这难免耗费大量不必要的精力。现在,Agent 替我拉住了那些目,我只需要握紧纲。纲,就是品味,就是判断。知道一个 GUI 该长成什么样,知道什么库适合什么场景,知道哪个调用会在哪里出问题,知道一个移植 Bug 要在哪个层级修而不是在哪个角落打补丁。这些东西,当前的模型还尚未从代码库里很好地学到。它们是我十一年的 GitHub 账号背后,几千个日夜、几千次构建失败和几千次依赖链追溯积累下来的感觉。

有人担心 AI 会让开发者贬值。我的体会恰恰相反。现在,开发的价值被压回了它本来的位置——品味、判断力、方向感。那些最枯燥的体力活被卸掉之后,剩下的反而是只有最纯粹的事。开源维护者的角色,从写代码的人变成了作判断的人。而判断力,永不贬值。


赞赏本文

支付宝 微信支付