Refactoring English: Month 14

Michael Lynch

Refactoring English:第 14 个月

原文由 Michael Lynch 发布,订阅该博客

一句话总结

发现 AI 沙盒的强大威力

新来的?

你好,我是 Michael。我是一名软件开发者,也是小型独立科技企业的创始人。我目前正在写一本书,叫Refactoring English: Effective Writing for Software Developers

每个月,我都会像这样发布一篇回顾,分享新书的进展以及整体工作情况。

亮点

  • 寻找图书读者的新策略初见成效。
  • 让 AI 智能体在无限制模式下运行,带来了一次突破性的体验。
  • 我一直在用 AI 来纠正当初在技术选型上那些令我后悔的决定。

目标评分

每个月初,我都会定下当月想要完成的目标。以下是本月的完成情况:

发布《Refactoring English》的三个章节

  • 结果:发布了两个新章节
  • 评分:B-

我还是和上个月一样,对 AI 实验过于兴奋,让它占用了写作时间。

发布我的 2025 年度回顾(第八年)

终于完成了!我对最终的呈现很满意。至此,一系列有截稿压力的文章——不管是出于惯例还是话题的时效性——也都告一段落了。

Refactoring English 数据指标

指标2025 年 12 月2026 年 1 月变化
独立访客2,26638,511+36,245 (+1600%)
预售收入$492.55$1,132.75+$640.20 (+130%)
赞助收入$48.25$0.00-$48.25 (-100%)

我在 1 月初发布了《2025 年 Hacker News 上最受欢迎的博客》,效果远超预期。它让 1 月份成为了自去年 Kickstarter 众筹以来,本书访客量和收入最高的月份。

其他收入有所下降,因为我近期没有接到编辑方面的客户,而 TinyPilot 的现任所有者也在 2025 年结束了对本书的赞助。我不打算再去争取商业赞助了,因为企业似乎兴趣不大,而专注于读者反而更轻松。

通过书写他人而获得成功

《2025 年 Hacker News 上最受欢迎的博客》是我过去约六个月一直在探索的一项策略的延续。归结起来就是:推崇其他软件领域的写作者。

去年夏天在一场聚会上,我认识了一位自费出版的言情小说作家。听她聊自己的工作很有意思,尽管我们写作的题材截然不同,却面临着相似的困扰。

我问她是怎么找到读者的,她说:“问到点子上了!”

她告诉我,她通过创办一份通讯来点评其他言情小说——主要是独立作者的作品——取得了很好的效果。这形成了一个良性循环:

  1. 读者在阅读她的通讯后发现并购买了她的书。
  2. 其他独立作者乐于看到自己的作品被点评,于是会把自己的读者引向她的通讯,从而增加了第(1)点。
  3. 她的订阅者则通过她的通讯发现了其他有趣的小说。

我喜欢这种让各方利益一致的策略,于是开始思考如何把它应用到自己的书上。我开始在博客上撰写关于我喜欢的其他博主和图书作者的文章,效果相当不错:

文章独立读者Hacker News 得分Lobsters 得分
The Most Popular Blogs of Hacker News in 202533.8k692-
The Software Essays that Shaped Me25.6k30885
What Makes the Intro to Crafting Interpreters so Good?3.5k-137

发现 AI 沙盒的威力

一年前我第一次开始使用 AI 智能体时,曾有过一次醍醐灌顶的体验。当时我只是让它在我的注视下编辑文件,就已经觉得把这么大的控制权交给大语言模型很可怕了。

过去一年里,我主要用 Cline 在 VS Code 中编程,这是一个 AI 智能体扩展。它加快了我的许多工作流程,但我也对它进行了严格的微观管理,因为我不信任它在我的开发机上随意执行操作。

几周前,我的朋友 okay向我展示了他使用 Codex(OpenAI 的终端 AI 智能体)的工作流。okay 让 Codex 在没有直接监督的情况下编辑文件、执行命令。这让我意识到,自己在看管 AI 智能体、处理 Cline 卡死问题上浪费了多少时间。

okay 说他有时会让 Codex 无人值守地工作一小时甚至更久,我简直不敢相信。如果我给 Cline 一个需要 10 分钟以上的任务,它要么会卡住界面,要么会走错方向,要么会让费用飙升。但 Codex 采用的是固定费用,而不是按 token 计费,这意味着你不再需要去考虑成本。

我依然不信任任何 AI 智能体在我的真实电脑上肆意运行,所以我在本机上搭建了一个运行 AI 智能体的自定义沙盒。我进入某个项目的目录,运行自定义命令:sb。它会启动一个无根(rootless)Podman 容器,该容器无法访问我的本地网络,只能看到当前工作目录。它已预装并使用我的账号完成了 Codex 和 Claude Code 的认证。

有了沙盒,我就可以放心地赋予 AI 编辑文件、安装应用等完整权限。

而效果,天差地别!

看到 AI 智能体在拥有完整权限的情况下运行,对我来说又是另一个突破时刻。以前,如果我说:“把我过去 8 年的收入做成条形图”,大约有 30% 的情况下,AI 智能体会做出部分错误的结果。我得自己检查结果,然后说:“不行,柱子没对齐,改一下。”但当 AI 智能体在其沙盒中拥有 root 权限时,它可以自行启动测试服务器、在浏览器中查看页面,并不断迭代,直到完成任务。

然后我听说了Ralph Loops。我至今还没找到一个好的解释,所以也不确定自己做的算不算“官方”的 Ralph Loop,不过我的做法是这样的。我运行了一个名为 ralph-loop 的 bash 脚本,里面是这样一段简单的代码:

#!/usr/bin/env bash

rm ALL-DONE.txt || true

while true; do
  cat AGENT-WORKFLOW.md | codex exec

  if [[ -f "ALL-DONE.txt" ]]; then
    echo "ALL-DONE.txt detected. Exiting."
    exit 0
  fi
done

AGENT-WORKFLOW.md 的内容是这样的:

1. Pick the top task in TODO.md and begin work on it
   - If no actions remain, write a file called ALL-DONE.txt to the current
     directory, and exit.
1. Complete the task and delete the entry from TODO.md.
   - If the task is unachievable, explain why in the commit message.
1. Commit the changes with a detailed commit message explaining what you
   changed, why you changed it, and what impact it had.

然后我只需创建一个包含任务清单的 TODO.md 文件。有些任务会涉及创建后续任务,因此清单会随着智能体的推进而增减。

Ralph Loop 让我可以让 AI 智能体自主、无人值守地运行 10 多个小时。早上回到电脑前,看到 AI 智能体在我睡觉时已经完成了所有布置的工作,感觉很不真实。

AI 非常擅长移植代码

通过过去几个月对 AI 的尝试,我发现它在以下情况下最能发挥作用:

  1. 可以客观地定义成功的标准。
    • 例如,“找出这次崩溃的原因”是客观、可定义的,而“把这个落地页做得更好”则不是。
  2. AI 智能体可以独立验证是否成功。
    • 例如,“在浏览器中访问页面,并验证点击按钮后背景是否变蓝。”
  3. 问题的难度相当于具备初级软件知识的人,通过搜索引擎、尝试和耐心就能解决的水平。

以下是符合这些标准的一些软件任务类型:

  • 重构带有自动化测试的代码
  • 在保持行为不变的前提下,将代码从一种语言/技术栈移植到另一种
  • 从源码编译项目并安装所有必要的依赖
  • 修复代码以使测试通过

最近,我一直在用 AI 来移植代码。我有一些代码库,当初在技术选型上做了现在让我后悔的决定,但重写一切总是太耗时。而有了 AI,替换技术栈中的某些部分既便宜又快速。

我在几个项目中成功地移植了代码:

  • 将 Zestful 网站从 Vue/Nuxt2 转换为使用 Hugo 的原生 HTML
    • 我收到一条 GitHub 警报,说我通过一个从未听说过的 Node.js 传递性依赖引入了某个愚蠢的漏洞。我想:“要是从此再也不用看到这些警报就好了。”于是我让 AI 用 Hugo 和纯 HTML/JS/CSS 重写了网站。
  • 将 PicoShare 的 CSS 框架从 Bulma 移植到 Bootstrap
    • 创建 PicoShare 时,我想尝试一下 Bulma 这个 CSS 框架。它还不错,但我更喜欢 Bootstrap,所以在其他地方我一直用 Bootstrap,每次做 PicoShare 时都得来回切换思维。
  • 将 LogPaste 的端到端测试从 Cypress 转换为 Playwright
    • 我在发现 Playwright 之前写的端到端测试,现在已经太习惯 Playwright,很难再回到 Cypress 了。
  • 将 fusion RSS 阅读器从 Svelte 转换为原生 HTML + Go 模板
    • 这只是一个概念验证,因为 fusion 并不是我的项目,但我想 fork 它以使用我更喜欢的技术栈。AI 在将所有 Svelte 代码转换为原生 HTML 和 Go 模板方面做得很好,但如果要真正移植,我会希望先搭建更完善的测试设施。
  • 将 MeshCore 网页应用从 Vue.js 转换为 Flutter
    • 这个实际上效果很差,因为它缺少了“AI 可以验证结果”这一步。我原以为 Flutter 会为其网页应用输出语义化的 HTML,但实际上它生成的是古怪的、以 Flutter 为中心的 HTML 方言。而且 MeshCore 应用在很大程度上依赖外部硬件设备(LoRa 无线电),所以我不得不频繁介入。

业余项目

StreamPreserve

我曾想过,如果我目睹了想用手机记录下来的事情,但有可能有人会抢走我的手机、删除视频,甚至彻底毁掉手机,那该怎么办。

于是,我做了 StreamPreserve,一个能将关键视频快速转移到远程安全服务器的网页应用。

StreamPreserve 会捕获重要视频,并以最快的速度将其转移到远程服务器。

它的工作原理如下:

  1. 我打开 StreamPreserve 应用并开始录制视频。
  2. 应用向后端服务器串流低分辨率视频,并根据可用带宽调整串流质量。
  3. 应用将高分辨率视频以离散的分块形式录制到浏览器存储中。
  4. 在有富余带宽时,应用会在继续串流的同时,将高分辨率的视频分块上传到服务器。
  5. 录制停止后,应用会将高分辨率视频作为下载文件保存在本地设备上。
  6. 当应用处于打开状态且没有正在录制时,它会将设备上的所有高分辨率素材同步到服务器。

所以,这个想法的要点是,如果我录制了某些内容而有人砸了我的手机,我的 StreamPreserve 服务器上仍会保留一份低分辨率的视频副本。而如果有人夺走我的手机想阻止我录制,网页应用仍会在后台上传高分辨率的素材。

当我意识到这个想法有几个缺陷时,热情就消退了:

  • 对于需要录制数小时素材的场景来说,这不是一个好方案。
  • 以网页应用的形式实现会增加复杂性,并有可能丢失素材。它本该是一个原生移动应用,但我不喜欢做移动开发
  • 这不是一个适合交给 AI 的任务,因为它依赖于浏览器相机 API,而在 AI 沙盒中模拟这个 API 很麻烦。

收尾

完成了什么?

经验教训

  • 推崇其他软件写作者有助于我找到新读者。
  • 当 AI 智能体运行在拥有 root 权限、可以安装应用和联网搜索的环境中时,其作用会显著提升。
  • 当能够客观地定义成功标准,且智能体有办法验证成功并通过迭代自我纠正时,AI 非常善于解决问题。
  • AI 非常擅长将代码从一种技术栈移植到另一种。

下月目标

  • 发布《Refactoring English》的两个章节。
  • 为《Refactoring English》的读者安排一场线上直播活动。

本文章由 muse-spark-1.2-contributor 进行翻译

评论