把 Claude Code 對話紀錄整理成開發回顧 : recap
前言
現在我大部分的程式都是跟 Claude Code 一起寫的。一個專案做下來,claude 開了又關、--continue 接了又接,一個月少說幾十個 session。某天要寫月報,我才發現一個尷尬的事實:這個月到底做了什麼,最完整的紀錄其實就在這些對話裡,但我完全不知道它們存在哪,也沒辦法一次撈出來看。
這篇記錄我怎麼從「這些對話存在哪裡?」一路做到一個一行指令就能安裝的小工具 recap,以及過程中踩到的幾個坑。
為什麼現成的方法不夠用?
先講我一開始試過的幾條路。
claude --resume 可以列出這個資料夾的歷史 session,但它是拿來「跳回某個對話」的,不是拿來「回顧一段時間」的。一次只能看一個,沒辦法依月份彙整。
社群上也有像 ccusage 這類工具,可以依日、依月統計 token 用量和費用。很實用,但它回答的是「花了多少」,不是「做了什麼」。
最致命的是第三件事:**Claude Code 預設只保留 30 天的對話紀錄**,超過的會在啟動時被自動清掉。也就是說,就算我寫了工具,等我想回顧上一季的時候,資料早就不在了。
所以我要的東西其實很明確:先讓紀錄留得住,再把它依專案、依月份撈出來,最後讓 Claude 自己讀完寫摘要。
第一步:找到紀錄在哪裡
Claude Code 會把每個 session 存成一個 JSONL 檔:
|
1 |
~/.claude/projects/<專案路徑編碼>/<session-id>.jsonl |
資料夾名稱是把專案路徑的 / 換成 -,例如 /workspace/next/snq-client 會變成 -workspace-next-snq-client。每一行是一筆紀錄,裡面有 type(user / assistant)、timestamp、cwd、sessionId 和訊息內容。
直覺上會想「把目前路徑編碼一下,去找對應的資料夾」,但我的 Claude Code 是跑在 Docker 裡的:
|
1 2 3 |
volumes: - "${STORAGE_PATH}:/workspace" - ~/.claude-data:/root/.claude |
主機上的路徑跟容器內的路徑根本不一樣,而且編碼規則也不是完全可逆的。後來的解法是**不靠資料夾名稱,直接比對每一筆紀錄裡的 cwd 欄位**。這樣不管在哪個環境跑、路徑長什麼樣子,只要 cwd 落在目前專案底下(含子資料夾),就算這個專案的紀錄。
順帶一提,同一個設定目錄下用 /logout、/login 切換帳號,紀錄會寫在同一個地方,所以兩個帳號的開發紀錄會一起被收錄。
第二步:讓紀錄留得住
保留天數是 settings.json 裡的 cleanupPeriodDays:
|
1 2 3 |
{ "cleanupPeriodDays": 365 } |
改這一行就好,但要注意兩件事。第一,它只能保住「之後」的紀錄,已經被清掉的找不回來,我自己 8 月的紀錄就是這樣沒了大半。第二,我的設定目錄是從主機掛載進容器的,所以要改的是主機上的 ~/.claude-data/settings.json,不是容器裡另外找一份。
第三步:匯出腳本的設計
1. 每個月一個檔案
|
1 2 3 4 5 |
.recap/ ├── 2026-08.md ├── 2026-09.md ├── 2026-10.md └── summary-2026-08_2026-10.md |
跨月的 session(例如 10/31 晚上開、11/1 繼續)會依每則訊息的時間拆到各自月份。全部收進 .recap/ 資料夾,.gitignore 加一行就好,不會把專案根目錄弄亂。
2. 只留文字,不留工具呼叫
JSONL 裡有大量的 tool_use 和 tool_result,讀檔、跑指令、改檔案的完整內容都在裡面。全部匯出的話檔案會膨脹好幾倍,而且對「回顧做了什麼」幫助不大。所以腳本只保留使用者和 Claude 的文字內容。
3. 用 Node 寫,而不是 Python
跑 Claude Code 的地方一定有 Node**,所以用 Node 寫、零相依套件,在任何能跑 Claude Code 的環境都能直接執行。
為什麼不直接叫 Claude 去讀 JSONL?
直接說「幫我整理這個月的對話紀錄」不就好了?
1. 原始資料太大
JSONL 裡有大量工具呼叫的內容,一個 session 動輒幾 MB。讓 Claude 直接讀,大部分的 context 都花在它不需要的東西上,真正的對話反而被擠掉。
2. 篩選這件事不該交給模型
「哪些紀錄屬於這個專案、哪些落在這個月」是純粹的資料處理,有明確的對錯。交給腳本做,結果每次都一樣;交給模型做,就多了一個可能出錯的環節,而且很難察覺。
3. 分工清楚,各做擅長的事
腳本負責把資料整理乾淨、切好月份;Claude 負責它真正擅長的部分:讀懂對話脈絡,判斷哪些是功能、哪些是 bug、哪些討論最後變成了決策。
第四步:用 Slash Command 當入口
腳本能跑之後,我不想每次都切出去下指令,所以做成 Slash Command。指令檔放在 ~/.claude/commands/recap/ 底下,Claude Code 會自動轉成命名空間的形式:
|
1 2 |
commands/recap/month.md → /recap:month commands/recap/export.md → /recap:export |
放在使用者層級的 ~/.claude/commands/,所有專案都能用;而且 ! 執行的指令是在目前專案目錄下跑的,所以在哪個專案輸入 /recap:month,就只會撈出那個專案的紀錄。
整個流程變成:
|
1 2 3 4 5 6 7 |
/recap:month 2026-08 2026-10 ↓ 腳本匯出 .recap/2026-08.md、2026-09.md、2026-10.md ↓ Claude 逐月讀完 ↓ 寫出 .recap/summary-2026-08_2026-10.md |
第五步:打包成 npm,一行安裝
|
1 |
npx @virtualorz/recap install |
安裝程式會依照跟 Claude Code 相同的規則找設定目錄(CLAUDE_CONFIG_DIR,沒有就用 ~/.claude),然後:
– 把 cleanupPeriodDays 改成 365。修改前自動備份;原本設得更長就不動;settings.json 格式壞掉就整個中止,不留半套。
– 把腳本複製到設定目錄裡,執行時不依賴 npx,也不需要網路。
– 安裝兩個全域指令。如果遇到同名但不是 recap 裝的指令檔,先備份再覆蓋。
另外加了一個 doctor 指令,專門回答「紀錄到底在哪裡」這個問題,會列出設定目錄、紀錄數量、目前的保留天數和安裝版本。
紀錄不是為了留著,是為了能被讀
做完之後回頭看,這個工具真正解決的不是「匯出」,而是把散落在幾十個 session 裡的開發過程,變成一份可以回頭讀、可以交接、可以拿去寫月報的東西。而讀這些紀錄、整理重點這件最花時間的事,剛好又可以交回給 Claude 自己做。
如果你也想試試 recap,可以用一行指令安裝:
|
1 |
npx @virtualorz/recap install |
npm:https://www.npmjs.com/package/@virtualorz/recap
github : https://github.com/virtualorz/recap