WEKEN NEWS 週末哥的數據記錄
claude-codeai-memorycontext-engineering工程實務自動化

Claude Code 記憶檔超過 2,000 行,最新寫的剛好讀不到:索引改 O(1) 三天後,同一個病往下一層跑

直接回答

Claude Code 的記憶檔一旦超過讀檔工具單次 2,000 行的上限,後段就等於不存在,而記憶通常是往檔尾追加,所以最先消失的是最新寫進去的內容。我的最大主題檔長到 4,572 行、近期紀錄檔長到 4,513 行,解法是拆成子主題檔加目錄、近期紀錄改成保留 14 天並在每次開場自動搬走舊段落,兩個檔都降到 2,000 行以內,逐行比對 0 行遺失。

週末哥

三天前我把 Claude Code 的記憶索引從 O(N) 改成 O(1),主檔只列分類、不列單一則記憶,那篇記錄在這裡

今天我以為這件事已經結束了。結果在量另一件事的時候發現,膨脹沒有消失,它往下一層跑了。


先交代怎麼發現的。

我要把這套記憶結構整理成一份說明書,給另一個 AI 參考。寫到「每一層的大小」時,照例每個檔都量一次。

主檔是好的:62 行、4,829 bytes。這三天照常在新增記憶,沒有一條寫進主檔。

但下一層的兩個檔不是:

檔案行數
最大的主題檔(方法論那一份)4,572
近期紀錄檔(AI 每次存檔時寫一段)4,513

這兩個數字的問題不是「大」,是超過了一個具體的上限。

Claude Code 的讀檔工具預設一次讀 2,000 行。超過的部分要指定位置再讀一次,實務上很少會發生。

更糟的是,這兩個檔都是新內容往檔尾加。所以讀不到的那一段,剛好就是最新寫進去的那一段。

我去確認了:近期紀錄檔裡最近 5 天的內容,從第 4,198 行才開始。

Claude Code 讀檔工具預設單次讀 2,000 行。記憶檔若採檔尾追加,超過上限後最先讀不到的是最新內容。實測近期紀錄檔長到 4,513 行時,最近 5 天的紀錄從第 4,198 行開始,最大的主題檔則長到 4,572 行。

主檔改成 O(1) 之後,O(N) 沒有消失,它被推到被索引指到的那一層。


近期紀錄檔這個問題,第一個診斷只對一半。

這個檔從 7 月就設計成「只保留最近 45 天,更早的搬去歷史檔」。規則寫在每月健檢清單裡,兩個多月一次都沒被執行,檔案裡最舊的紀錄還停在 7 月 2 日。

所以第一個結論是:沒有東西去執行滾動。這是對的,但不完整。

我把不同長度的視窗各量一次:

保留天數行數一次讀得完
45 天4,081
30 天3,386
21 天2,253
14 天1,521

就算每天準時滾,45 天的視窗也有 4,081 行,照樣讀不完。

原因是寫入量比 7 月設計時大很多。光 8 月一個月就寫了 3,162 行,一天將近 100 行。

「45 天」這個數字從一開始就不是算出來的,是拍腦袋的。天數固定的視窗,大小會跟著寫入量一起長。

AI 近期紀錄的保留視窗要用行數驗證,不能只用天數設定。實測一天寫入將近 100 行時,45 天視窗 4,081 行、30 天 3,386 行、21 天 2,253 行,都超過讀檔單次 2,000 行上限,只有 14 天的 1,521 行讀得完。


近期紀錄檔的改法是兩件事。

第一,視窗從 45 天改成 14 天。

第二,把「搬走舊段落」寫成程式,掛在每次開場自動執行,不再放在要靠 AI 想起來的清單裡。

程式的安全順序是這樣:先把要搬的段落寫進按月分的歷史檔,讀回來確認每一段都在,再確認「留下的字數加搬走的字數等於原檔字數」。兩項都過才改寫原檔,任何一項不過就停,原檔不動。

我先拿複本試跑,比對過才碰正本。第一次正式跑搬走 95 段,檔案從 4,513 行降到 1,526 行。原檔 4,513 行,搬完「留下的加搬走的」也是 4,513 行,少 0 行。

再跑一次,什麼都沒輸出,因為沒有東西要搬。


主題檔的改法,是把三天前對主檔做的事往下套一層。

4,572 行、218 段,拆成 8 個子主題檔,最大的一個 905 行。原檔保留原本的名字,變成 389 行的目錄,每一段的標題都列在上面,看標題就知道在哪個子主題檔。

保留原檔名是因為有十幾個其他檔案引用它,包括規則檔與專案紀錄。目錄在,那些引用就不會斷,只是多點一層。

切段要注意一件事:以二級標題切的時候,要跳過程式碼區塊。這個檔裡有 24 個程式碼區塊,有些 shell 註解是井字號開頭。這次剛好沒有兩個井字號開頭的,但切段程式還是要跳過程式碼區塊,不然哪天有一行註解長得像標題,就會把程式碼切成一段新的。

搬完之後,段落裡有 2 條相對連結因為資料夾多了一層而失效,改成多一層 ../


拆到一半出了一個小插曲,值得單獨講。

我正式寫檔前做了一次比對,發現原檔跟我拆之前存的備份不一樣,程式直接停下來。

查了一下,是另一個視窗的 Claude Code 在幾分鐘前往這個檔的條目認領段加了一行。我分類時看的是加了那一行的版本,備份卻是更早存的。

如果我照原本的做法直接寫,那一行會被我的舊版本蓋掉。

改法是用最新版本重新存一份快照,以它為準重拆。那一行留在目錄檔裡,原封不動。

多個 session 同時寫同一批記憶檔,是這種系統的常態。任何會改寫整份檔案的操作,寫入前都要比對一次版本。


驗收用的是逐行比對。

把拆之前的快照跟 9 個新檔(8 個子主題加 1 個目錄)的每一行做比對。快照有 4,572 行,在新檔裡找不到的行數是 0。多出來的 333 行,全是目錄與每個子主題檔的檔頭。

把一份 4,572 行、218 段的 AI 記憶主題檔拆成 8 個子主題檔加 1 份目錄,最大子檔 905 行、目錄 389 行。以拆分前快照逐行比對,遺失 0 行,新增 333 行全為目錄與檔頭。原檔名保留當目錄,引用它的其他檔案不需修改。


最後補的是一個看得到的警報。

我再寫一支開場檢查:任何主題檔超過 1,500 行、或近期紀錄超過 2,000 行,就在開場印一行提醒。沒超標就什麼都不印。1,500 比讀取上限低 500 行,留處理的緩衝。

放在開場而不是寫入前,是因為我之前踩過:寫入前的 hook 如果只想警告、不想擋下來,它的訊息 AI 根本看不到。開場 hook 的輸出會直接進對話,才真的會被讀到。

它第一次有機會響,應該是另一個主題檔。那份現在 1,392 行,是下一個。


三天前我以為問題是「索引會長」。今天才知道,問題是「任何只進不出的檔都會長」,索引只是第一個撞牆的。

所以每一種會長的檔,在建立的當下就要決定三件事:上限用行數定,不用天數;退場由程式在一定會跑的時機執行,不放在要靠記性的清單裡;撞牆之前要有一個看得到的警報。

常見問題

Claude Code 讀記憶檔有行數上限嗎?
有。讀檔工具預設一次讀 2,000 行,超過的部分要指定位置分段讀,實務上 AI 很少主動去讀後半段。我的近期紀錄檔長到 4,513 行,最近 5 天的紀錄從第 4,198 行才開始,等於寫了也讀不到。
記憶索引改成只列分類之後,還會膨脹嗎?
主檔不會,但膨脹會往下一層跑。我的主檔改成只列分類三天後是 62 行,這段期間照常新增記憶,沒有一條寫進主檔。可是被索引指到的主題檔還是一直往檔尾加內容,最大的一份已經 4,572 行。O(N) 沒有消失,只是換了一層。
AI 的近期紀錄要保留幾天比較好?
不要用天數決定,用行數驗證。我原本設計保留 45 天,實際量 45 天內有 4,081 行,30 天 3,386 行,21 天 2,253 行,全部超過 2,000 行。只有 14 天的 1,521 行一次讀得完。寫入量會變,天數固定的視窗會跟著寫入量一起長。
拆分或搬移 AI 記憶檔,怎麼確認沒有丟東西?
拆之前存一份快照,拆完把所有新檔的每一行跟快照逐行比對,快照裡有、新檔裡找不到的行數必須是 0。我拆 4,572 行的主題檔,遺失 0 行,新增的 333 行全是目錄與檔頭。另外要偵測拆的途中有沒有別的 session 改過原檔,我這次就真的碰到一次。
記憶檔的清理規則寫進維護清單,為什麼還是沒被執行?
因為它要靠 AI 在對的時間想起來。我的近期紀錄檔從 7 月就寫著「超過 45 天搬走」,這條規則放在每月健檢清單裡,兩個多月一次都沒被執行,檔案裡最舊的紀錄還是 7 月 2 日。改寫成程式、掛在每次開場自動跑之後,第一次執行就搬走 95 段。