重構英文:第 14 個月
原文由 Michael Lynch 于 發布,訂閱此部落格
一句話總結
發現 AI 沙盒的威力
第一次來嗎?
嗨,我是 Michael。我是一名軟體開發者,也是小型獨立科技公司的創辦人。我目前正在寫一本書,叫做Refactoring English: Effective Writing for Software Developers。
每個月,我都會像這樣發表一篇回顧,分享新書的進展以及整體工作上的近況。
本月亮點
- 尋找書籍讀者的新策略已見成效。
- 讓 AI 代理在無限制模式下運行,帶來了突破性的體驗。
- 我一直在用 AI 來修正過去在技術選型上令我後悔的決定。
目標成績
每個月月初,我都會訂下當月想完成的目標。以下是這次的達成狀況:
發表《Refactoring English》的三個章節
- 結果:發表了兩個新章節
- 評分:B-
跟上個月一樣,我還是對 AI 實驗太過興奮,結果壓縮到了寫作時間。
發表我的 2025 年度回顧(第八年)
- 結果:已發表
- 評分:A
完成了!我對成果很滿意。之前有一連串覺得必須在特定期限前發表的文章,不管是出於慣例還是主題的時效性,現在總算都告一段落了。
《Refactoring English》數據
| 指標 | 2025 年 12 月 | 2026 年 1 月 | 變化 |
|---|---|---|---|
| 不重複訪客 | 2,266 | 38,511 | +36,245 (+1600%) |
| 預購收入 | $492.55 | $1,132.75 | +$640.20 (+130%) |
| 贊助收入 | $48.25 | $0.00 | -$48.25 (-100%) |
我在 1 月初發表了「The Most Popular Blogs of Hacker News in 2025」,表現遠超出我的預期。這讓 1 月成為自去年 Kickstarter 募資以來,本書網站訪客數與收入最高的月份。
其他收入則有所下滑,因為我最近沒有接到編輯案,而 TinyPilot 的現任經營者也在 2025 年結束了對本書的贊助。我不打算再主動尋求企業贊助了,因為企業似乎興趣不高,而且專注在讀者身上反而更單純。
透過書寫其他作者來獲得成功
「The Most Popular Blogs of Hacker News in 2025」是我過去半年來嘗試的一個策略的延續。簡單來說就是:肯定、推崇其他軟體寫作者。
去年夏天在一場聚會上,我遇到一位自行出版的羅曼史小說家。聽她聊工作很有意思,因為儘管我們寫的主題天差地遠,卻面臨著相似的難題。
我問她都怎麼找到讀者,她說:「這就是關鍵問題啊!」
她說她透過創辦一個電子報來評論其他羅曼史小說,特別是獨立作者的作品,獲得了很好的成效。這形成了一個正向循環:
- 讀者在看了她的電子報後,發現並購買了她的書。
- 其他獨立作者樂見自己的作品被評論,因此會把自己的讀者導向她的電子報,進而強化了第 1 點。
- 她的訂閱者則透過電子報發現了其他有趣的小說。
我很喜歡這種讓所有人誘因一致的策略,所以開始思考如何把它套用到我的書上。我開始在部落格上撰寫關於我喜歡的其他部落客與書籍作者的文章,效果相當不錯:
| 文章 | 不重複讀者 | Hacker News 分數 | Lobsters 分數 |
|---|---|---|---|
| The Most Popular Blogs of Hacker News in 2025 | 33.8k | 692 | - |
| The Software Essays that Shaped Me | 25.6k | 308 | 85 |
| What Makes the Intro to Crafting Interpreters so Good? | 3.5k | - | 137 |
發現 AI 沙盒的威力
一年前,當我第一次開始使用 AI 代理時,有過一次令人大開眼界的體驗。當時我只是讓它在我盯著的情況下編輯檔案,就已經覺得把這麼大的掌控權交給 LLM 很可怕了。
過去一年來,我主要都是用 Cline 這個 VS Code 上的 AI 代理擴充套件來寫程式。它加速了很多工作流程,但我也因為不信任它在我的開發電腦上執行任意操作,而對它管得很緊。
幾週前,我的朋友 okay 向我展示了他用 Codex(OpenAI 推出的終端機 AI 代理)的工作流程。okay 讓 Codex 在沒有直接監督的情況下編輯檔案、執行指令。這讓我意識到,自己花了多少時間在緊盯 AI 代理,以及處理 Cline 當掉的問題。
okay 說他有時會讓 Codex 在無人看管的情況下跑上一小時甚至更久,我完全不敢相信。如果我交給 Cline 一個超過 10 分鐘的任務,它不是把介面卡死、就是走錯方向,或是把費用炸開。但 Codex 是固定費用制,而不是按 token 計費,所以就不用再去煩惱成本問題。
我還是不信任任何 AI 代理在我的實體電腦上橫衝直撞,所以我在電腦上為 AI 代理打造了一個專屬的沙盒。我只要到某個專案的目錄下執行自訂指令:sb。它就會啟動一個無 root 權限的 Podman 容器,這個容器無法存取我的區域網路,而且只能看到當前的工作目錄。裡面已經預先安裝好 Codex 和 Claude Code,並用我的帳號完成驗證。
把 AI 關在沙盒裡之後,我就能放心地給它完整的權限去編輯檔案、安裝應用程式等等。
而哇,差別真的非常大!
看著 AI 代理在擁有完整權限的情況下運行,對我來說是另一次突破性的時刻。以前如果我說:「幫我把過去 8 年的收入做成長條圖」,大概有三成的機率,AI 代理會做出部分錯誤的東西。我得自己檢查結果,然後說:「不行,長條沒有對齊,修正一下。」但當 AI 代理在自己的沙盒裡擁有 root 權限時,它可以自己架起測試伺服器、在瀏覽器中檢視頁面,然後獨立反覆修正,直到完成任務。
接著我聽說了Ralph Loops。我到現在還沒找到清楚的解釋,所以不確定我做的算不算「正統」的 Ralph Loops,但我的版本是這樣。我執行一個叫做 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 實驗,我注意到它在以下幾種情況下最能發揮影響力:
- 你可以客觀地定義成功的標準。
- 例如,「找出這次當機的原因」是客觀且可定義的,而「把這個登陸頁面變得更好」則不是。
- AI 代理可以獨立驗證是否成功。
- 例如:「在瀏覽器中開啟頁面,確認按下按鈕後背景會變成藍色。」
- 這個問題的性質,是具備初階軟體知識的人,靠著搜尋引擎、實驗和耐心就能解決的。
以下是有符合這些條件的幾類軟體任務:
- 有自動化測試的程式碼重構
- 在保留原有行為的前提下,將程式碼從一種語言/技術移植到另一種
- 從原始碼編譯專案,並安裝所有必要的依賴套件
- 修正程式碼以通過測試
最近,我一直在用 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 的 e2e 測試從 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 會擷取重要影片,並以最快的速度搬移到遠端伺服器。
運作方式如下:
- 我打開 StreamPreserve 應用程式並開始錄影。
- 應用程式會將低解析度影片串流到後端伺服器,並根據可用頻寬自動調整串流品質。
- 應用程式同時會將高解析度影片以分段的方式錄製到瀏覽器儲存空間中。
- 在持續串流的同時,應用程式會利用任何剩餘頻寬,將高解析度影片的片段上傳到伺服器。
- 停止錄影後,應用程式會將高解析度影片儲存為本地裝置上的下載檔。
- 當應用程式開啟且沒有在錄影時,它會將裝置上所有高解析度影片同步到伺服器。
所以概念是,如果我錄了東西而有人砸爛我的手機,我的 StreamPreserve 伺服器上仍會保留一份低解析度的影片備份。而如果有人奪走我的手機想阻止我錄影,網頁應用程式仍會在背景繼續上傳高解析度的影片。
當我意識到這個想法有幾個缺陷後,就失去熱情了:
- 對於需要錄製數小時影片的情境來說,這不是個好解法。
- 用網頁應用程式來實作會增加複雜度,也有可能導致影片遺失。它應該做成原生手機應用程式才對,但我不喜歡做行動開發。
- 這也不是個適合交給 AI 的任務,因為它依賴瀏覽器的相機 API,而要在 AI 沙盒中模擬這個 API 很麻煩。
總結
完成了什麼?
- 發表了《我作為獨立創辦人的第八年》
- 發表了《Refactoring English》的兩個新章節
- 修復了 PoDoFo PDF 閱讀器中的一個當機問題,這是我透過我的 PDF 模糊測試工作流程發現的
學到的教訓
- 肯定其他軟體寫作者有助於我找到新讀者。
- 當 AI 代理在擁有 root 權限、可以安裝應用程式並上網搜尋的環境中運行時,實用性會大幅提升。
- 當你能客觀定義成功標準,且代理有辦法自行驗證成果並透過反覆嘗試自我修正時,AI 就很擅長解決問題。
- AI 很擅長將程式碼從一種技術移植到另一種。
下個月的目標
- 發表《Refactoring English》的兩個章節。
- 為《Refactoring English》的讀者安排一場線上直播活動。
隨機一篇部落格
留言
登入後參與討論