這種事我遇過不只一次:晚上我和團隊一起討論了區塊的幾個版本,隔天早上有人問,為什麼標題變短了。對話裡有幾十則訊息,記憶裡只剩下"好像背景是淺色的"這種印象,準確的決定就在一次次修改之間消失了。
這種時候,requests.log 就派上用場。這是一份簡短的外部工作紀錄,可以用一般編輯器打開,從上到下讀完。我看重它,不是因為行數多,而是因為它能把請求和最後真正保留下來的結果連起來。

為什麼需要外部紀錄
這些年工作下來,我習慣把四件事分開:請求、決定、對話紀錄,以及檔案已儲存的版本。它們回答的是不同的問題,雖然在同一次工作階段裡很容易混成一團模糊的歷史。
| 來源 | 能從中知道什麼 | 不能證明什麼 |
|---|---|---|
requests.log | 提出了什麼請求、紀錄何時出現 | 修改已經完成並被採納 |
| 決定的標記 | 選了哪個方案、誰做的標記 | 目前儲存的檔案長什麼樣子 |
| 對話紀錄 | 討論的脈絡和回覆 | 什麼進入了專案的目前版本 |
| 版本控制系統 | 儲存了哪些檔案和哪些行 | 為什麼選了這個方案 |
日誌的作用像指標:帶您回到對的時刻和準確的字句,但不會自己還原程式碼。如果要看頁面已儲存的版本,請看檔案和專案的版本歷史。
這裡有一條重要的界線,我在這上面見過不少錯誤的結論。UserPromptSubmit 事件的 hook,會在 Claude Code 處理請求之前,從 prompt 欄位取得文字。這樣的一行紀錄只能證明文字送出了,這個時候任務的結果還不知道。
這張圖清楚呈現了分析日誌時重要的差異。上面那條鏈顯示工作過程,下面那條顯示日誌裡實際留下的內容。自動紀錄的那一行出現在結果之前;決定的標記只在確認之後才會出現。兩者不能互相替代。
一則有用的紀錄由什麼組成
我用三種寫法來示範。實際專案裡這三種我都遇過。
好了這樣一行幾乎沒用:不知道誰做了什麼、什麼時候做的,這個"好了"對應的是哪個任務。
使用者:把卡片標題弄短一點...
Claude:好的,我先看一下這個元件...
使用者:間距也縮小一點...
Claude:已修正...這一種又太多了,不方便快速查找。完整的對話流程放在對話紀錄裡很好,但另外開一份日誌,很快就會變成一份不方便使用的複本。我試過這樣做,結果自己也花了不少時間在往下捲動找東西。
2026-09-08T14:32:11+03:00 | prompt_submitted | actor=user | ref=card-header | text="把卡片標題縮到一行"
2026-09-08T14:41:06+03:00 | decision_recorded | actor=user | ref=card-header | text="採用短標題,字級 24 px"第三種我最喜歡:留下了簡短的事實、含時區的時間、作者,以及把幾行連起來的 ref 標記。這裡的欄位名稱是為這個練習專案設計的,是這份檔案自己的格式,不是 Claude Code 規定的方案。這次分析中,ref 標記是人工加到相關的行上的。hook 不會自己猜出請求屬於哪個區塊:基礎事件 UserPromptSubmit 本身不帶這種語意標記。就算沒有連結欄位,您的日誌仍然可以用精確的字句去搜尋。
記錄那一刻已知道什麼
prompt_submitted 這一行只說明一件事:工作階段收到了這樣一則請求,hook 把它記下來了。通常這是您輸入的文字,但不一定。UserPromptSubmit 在 /loop 的下一輪、背景子代理的回報,以及來自其他工作階段的訊息上也會觸發,所以我們格式裡的 actor=user 只是這個教學範例的假設。由此並不能推出 Claude Code 已經修改了頁面、驗證已經通過,或者結果讓大家滿意。
結果應該在真正確定之後才記錄。在我們的例子裡,這是查看頁面之後另外加上的一則標記。如果您的格式裡有 result 或 error 欄位,請填入實際觀察到的事實,而不是對任務結局的預測。
該在哪裡標記已採納的決定
只有在有人明確記下決定之後,決定才算存在。上面例子中,這一行是使用者看過頁面之後加上的。作者記在 actor 裡,和請求的關聯則靠 ref=card-header 保存。
標記可以是人工加的,這沒問題。自動紀錄保存的是輸入內容,而由人來確認結果的意義。沒有作者、也沒有關聯的"好了"這一行,不值得信任。
讀請求日誌
來分析一份只有五行的小日誌。要還原決定的來龍去脈時,我通常就是從這種短片段開始的。
2026-09-08T14:32:11+03:00 | prompt_submitted | actor=user | ref=card-header | text="把卡片標題縮到一行"
2026-09-08T14:36:20+03:00 | prompt_submitted | actor=user | ref=card-header | text="給我看兩種版本:24 px 和 28 px"
2026-09-08T14:41:06+03:00 | decision_recorded | actor=user | ref=card-header | text="採用短標題,字級 24 px"
2026-09-08T15:03:44+03:00 | prompt_submitted | actor=user | ref=card-shadow | text="讓卡片陰影柔和一點"
2026-09-08T15:08:17+03:00 | prompt_submitted | actor=user | ref=card-header | text="試試更深一點的標題顏色"假設您要找出關於標題格式最後採納的決定。先在編輯器裡搜尋 card-header,會得到四行。最後一行是關於顏色的新想法,不是決定。所以結論依據的是 14:41:06 這一行:採用了 24 px 的短標題。
我的閱讀順序很簡單:
- 先想清楚問題:要找的是請求、決定,還是觀察到的錯誤。
- 找出共同的標記、元件名稱或精確的字句。
- 只留下對應類型的紀錄,按時間順序讀。
- 指出支持結論的那幾行。剩下的老實標成未知,不去補。
不啟動 Claude Code 也能做這種分析。這是個有用的習慣:先自己把結論和檔案對過一遍,再把同樣的工作交給代理。
日誌裡沒有決定的時候
現在把 14:41:06 這一行拿掉。剩下的只有要求看兩種尺寸的請求,和後來想改顏色的想法。最後選了哪個尺寸?日誌沒有答案。
這種時候很容易忍不住選 24 px,因為那是最先提出的方案。不要這麼做。請求顯示的是想比較方案的意圖,不是最終選擇的結果。老實的結論只有一個:日誌裡沒有記錄關於尺寸的已採納決定。
分岔點取決的不是想法出現的順序,而是找到的紀錄類型。有明確的決定標記,結論可以確認。只剩下請求,就記為未知,不用猜測去填補空白。這種克制到頭來能省下不少時間。
當 Claude Code 分析日誌時,我會要求它指出結論所依據的確切紀錄。如果沒有能佐證的那一行,就應該列進未知清單,不能猜測結果是成功的。
什麼不該放進日誌
我不打算把一份有用的日誌變成什麼都塞的儲藏室。紀錄該放什麼內容,要看之後會拿它來回答什麼問題。要查決定的話,通常時間、事件類型、作者、關聯標記和一小段文字就夠了。
- 不要複製金鑰、token、
.env的內容,以及個人資料。 - 如果只需要狀態或操作的 ID,不要把外部服務的完整回應整段搬過來。
- 只有真正需要的地方才留完整的 prompt。這篇文章裡它是完整的,只是因為例子本身是虛構的、篇幅短。
- 定期檢查檔案大小和舊紀錄還有沒有用。所有專案並沒有統一的保留期限。
把每一行截到一百個字元能提升可讀性,但不會自動移除機密資訊。一個短 token 完全可以塞進前一百個字元裡。請先決定哪些資料本來就可以記錄。該從這條規則開始,而不是從行的長度開始。
怎麼跟 Claude Code 一起分析日誌
Claude Code 很擅長整理時間順序、快速找出相關的行。但為此它得明確去讀那個檔案:專案裡有 requests.log 這個事實本身,不代表它的內容已經在上下文裡。
給代理一個具體的任務:
請讀取 requests.log。找出關於卡片標題(card-header)
尺寸最後一個明確採納的決定。指出您依據的是哪幾行紀錄。
如果日誌裡只有想法,請直接說明。
另外列出還有哪些是未知的。好的回答會把事實和結論分開:引用時間、事件類型和決定的文字,接著列出沒有得到確認的疑問。請把這些引用和原始的行對照一遍。代理一旦把最後一個想法稱為"已採納的方案",錯誤就特別明顯。
對這份練習用的日誌,答案應該是這樣:尺寸的決定由 2026-09-08T14:41:06+03:00 這一行紀錄確認;之後出現了想換更深顏色的請求,但關於顏色最後採納了什麼,仍屬未知。我認為這樣的回答才可靠:它沒有給出比檔案裡更多的承諾。
- hook 在請求被處理之前就把它存下來,所以這一行不能證明結果。
- 另外的標記會按時間或關聯標記,把已採納的決定和請求連起來。
- 查找從具體問題開始,以指向原始紀錄結束。
- 如果沒有佐證,日誌就留一個空白,不需要自己去補。
就這樣,requests.log 依然是一份不大的工作紀錄:能幫您找到討論裡的關鍵轉折,但不假裝自己是專案的備份,也不假裝自己是任務完成的證明。日誌設計得誠實,您才會真的願意回頭去查它。
GO TO FULL VERSION