Refactoring English: Month 14

Michael Lynch

Refactoring English(《重构英语》):第14个月

一句话总结

发现 AI sandboxes(AI沙盒)的强大威力

初次来访?

你好,我是 Michael(迈克尔)。我是一名软件开发者,也是小型独立科技企业的创始人。我目前正在创作一本书,名为《重构英语:面向软件开发者的高效写作》

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

亮点

  • 寻找图书读者的新策略已初见成效。
  • 通过让 AI agent 在无限制模式下运行,我获得了一次突破性的体验。
  • 我一直在利用 AI 来纠正自己在技术栈上曾做出后悔的决定。

目标评分

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

发布《重构英语》的三个章节

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

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

发布 2025 年年度回顾(第 8 年)

完成了!我对最终效果很满意。至此,我已经完成了一系列因惯例或时效性而感到必须在特定日期前发布的文章。

《重构英语》数据

指标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 最受欢迎的博客》是我大约六个月前开始探索的一项策略的延续。核心很简单:推崇其他软件作者。

去年夏天在一个聚会上,我遇到了一位自费出版的言情小说家。听她讲述自己的工作很有意思,因为尽管我们写作的主题截然不同,却面临着相似的问题。

我问她如何找到读者,她说:“这就是关键问题!”

她告诉我,她通过开设一个主要点评独立作者言情小说的 Newsletter 取得了很好的效果。这形成了一个良性循环:

  1. 读者在阅读她的 Newsletter 后发现并购买了她的书。
  2. 其他独立作者喜欢看到自己的作品被点评,因此会将自己的读者引向她的 Newsletter,从而促进了(1)。
  3. 她的订阅者通过她的 Newsletter 发现了其他有趣的小说。

我喜欢这种让各方激励一致的策略,于是开始寻找将其应用到自己书中的方法。我开始撰写关于我喜欢的其他博主和图书作者的文章,并发布在我的博客上,效果很好:

文章独立读者Hacker News 得分Lobsters 得分
2025 年 Hacker News 最受欢迎的博客33.8k692-
影响我的软件随笔25.6k30885
《Crafting Interpreters(《打造解释器》)》的前言为何如此出色?3.5k-137

发现 AI sandboxes 的强大威力

一年前,当我第一次开始使用 AI agent时,我有了一次启发性的体验。那时,我只是让它在旁边看着的情况下编辑文件,就觉得把这么大的控制权交给 LLM 已经很可怕了。

在过去一年里,我主要使用 Cline 进行编程,它是 VS Code 中的一个 AI agent 扩展。它加快了我很多工作流程,但我也对它进行了严格的人工监管,因为我不信任它在我的开发机器上执行任意操作。

几周前,我的朋友 okay(奥凯)向我展示了他使用 Codex 的 AI 工作流,Codex 是 OpenAI 的基于终端的 AI agent。奥凯让 Codex 在没有直接监督的情况下编辑文件和运行命令。这让我意识到自己在看管 AI agent 上浪费了多少时间,以及在处理 Cline 卡顿问题上耗费了多少精力。

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

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

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

哇,差别太大了!

看到 AI agent 在拥有完全权限的情况下运行,对我来说是另一个突破性的时刻。以前,如果我说“为我过去 8 年的收入做一个柱状图”,大约有 30% 的概率 AI agent 会实现出部分错误的东西。我得自己检查结果,然后说:“不行,柱子没对齐,修一下。”但当 AI agent 在自己的沙盒中拥有 root 权限时,它可以自行启动测试服务器、在浏览器中查看页面,并独立迭代直到完成任务。

然后我听说了Ralph Loops(Ralph 循环)。我仍然没有找到一个好的解释,所以不确定我做的是否是“官方”的 Ralph 循环,但我的版本是这样的。我运行一个名为 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 文件,列出任务清单。有些任务会涉及创建后续任务,因此清单会随着 agent 的进展而增减。

Ralph 循环让我能够让 AI agent 自主、无人值守地运行 10 多个小时。早上回到电脑前,看到 AI agent 在我睡觉时完成了我分配的所有工作,那种感觉很不真实。

AI 擅长移植代码

通过过去几个月对 AI 的实验,我注意到它在以下情况下影响最大:

  1. 你可以客观地定义成功的标准。
    • 例如,“找出这次崩溃的原因”是客观且可定义的,而“让这个落地页变得更好”则不是。
  2. AI agent 可以独立验证成功。
    • 例如,“在浏览器中访问页面并验证按下按钮时背景是否变蓝。”
  3. 问题的性质是,具备初级软件知识的人通过搜索引擎、实验和耐心就能解决。

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

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

最近,我一直在用 AI 来移植代码。我有一些代码库,希望当初在技术栈上做出不同的选择,但重写所有内容一直太耗时。但有了 AI,替换技术栈中的部分组件变得既便宜又快速。

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

  • 将 Zestful 网站从 Vue/Nuxt2 转换为使用 Hugo 的纯 HTML
    • 我收到了一个 GitHub 警报,说我通过一个从未听说过的间接 Node.js 库存在一个愚蠢的漏洞。我想,“我真希望再也不要看到这些警报了。”于是我让 AI 用 Hugo 和纯 HTML/JS/CSS 重写了网站。
  • 将 PicoShare 的 CSS 框架从 Bulma 移植到 Bootstrap
    • 创建 PicoShare 时,我想尝试一下 Bulma 这个 CSS 框架。它还不错,但我更喜欢 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 沙盒中很难模拟。

收尾

完成了什么?

经验教训

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

下月的目标

  • 发布《重构英语》的两个章节。
  • 为《重构英语》的读者安排一场线上活动。

原文由 Michael Lynch 发布

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