跳至主要內容
模組 5:Fable 5 時代 5 / 8
進階 Session 29 Memory Context Personalization

持久記憶:Claude Code 如何記住事情

解析 Claude Code 檔案式持久記憶的運作方式 — 一個事實一個檔案、MEMORY.md 索引、四種記憶類型,以及讓回憶保持有用的整潔規則。

2026年7月8日 16 分鐘閱讀

你將學到什麼

在 Claude Code 的歷史上,絕大多數時候每個 session 都是從零開始。你可以把長期規則寫進 CLAUDE.md,但 session 中學到的一切 — 你星期二做的修正、上個月發現的部署地雷 — 都會在 session 結束時煙消雲散。Fable 5 世代用每個專案一個檔案式持久記憶目錄改變了這件事。

完成後,你將了解:

  • 記憶存放在哪裡,以及「一個事實一個檔案」的格式
  • 四種記憶類型:userfeedbackprojectreference
  • MEMORY.md(始終載入的記憶索引檔)如何運作
  • 記憶之間的 wiki 風格 [[links]] 連結
  • 讓記憶保持有用而非淪為雜訊的整潔規則
  • 回憶(recall)如何運作(以及為什麼被回憶的記憶必須重新驗證)
  • 上下文摘要(context summarization)如何取代硬性壓縮

問題所在

一個沒有記憶的 agent 會強迫你充當它的記憶。每個 session 你都要重新解釋:staging 資料庫是名字很怪的那一個、你偏好 squash merge、那個不穩定的測試早就調查過了,問題出在 CI runner 的時鐘。這是實實在在的成本,每次 session 開始都要付一次。

兩種天真的解法都行不通:

  • 重新載入聊天記錄。 逐字稿非常龐大且大多是雜訊 — 工具輸出、死路、被放棄的方案。整批載入等於把上下文視窗燒在垃圾上。
  • 把所有東西塞進 CLAUDE.md。 CLAUDE.md 是給長期規則用的 — 怎麼建置、要遵循什麼慣例。混入短暫的發現(「auth 重構做到一半」)會把你的規則檔變成一個會過期的雜物抽屜。

我們需要的是第三種東西:經過整理、可長期保存的知識 — 能跨 session 累積、載入成本低、錯了還能修正。

如何運作

一個記憶、一個檔案、一個事實

每個專案都有一個記憶目錄:

~/.claude/projects/<project-slug>/memory/
├── MEMORY.md                          ← the index (always loaded)
├── user_prefers-squash-merges.md
├── feedback_use-pnpm-not-npm.md
├── project_auth-refactor-status.md
└── reference_staging-dashboard.md

規則很嚴格:一個記憶 = 一個檔案 = 一個事實。 每個檔案帶有 YAML frontmatter:

  • name — 簡短的 kebab-case slug
  • description — 一行摘要,回憶時用來判斷相關性
  • metadata.typeuserfeedbackprojectreference 其中之一

為什麼一個檔案只放一個事實?因為事實會各自獨立地改變。當 auth 重構完成時,你刪掉那個檔案就好 — 而不是在一份龐大的筆記文件裡翻找它污染到的每一句過期敘述。

四種記憶類型

類型記錄什麼範例
user使用者是誰 — 角色、專長、偏好「偏好 squash merge;資深後端工程師」
feedback修正與已確認的做法,附上 Why(為什麼)與 How to apply(如何套用)「用 pnpm,不要用 npm — npm 會弄壞 lockfile」
project進行中的工作、目標、無法從程式碼或 git 歷史推導出的限制「auth 重構暫停,等待安全審查」
reference指向外部資源的指標 — URL、儀表板、工單「staging 指標在 Grafana 儀表板上」

feedback 類型是主力。它的內文應該回答兩個問題:為什麼(Why)這是正確做法,以及下次如何套用(How to apply)。少了這兩點的修正,只是一條 agent 在稍微不同的情境下就會用錯的規則。

注意有一種東西不是類型:「程式碼結構」。這是刻意的 — 見下方的整潔規則。

MEMORY.md:始終載入的索引

如果每個 session 都載入所有記憶檔案,就會重演聊天記錄的問題。所以系統採用你在第 5 堂課的 skills 中看過的同一套延遲載入哲學:名稱先行,內容按需載入

MEMORY.md 就是索引 — 每個記憶一行:

- [Use pnpm, not npm](feedback_use-pnpm-not-npm.md) — npm installs corrupt the lockfile
- [Auth refactor status](project_auth-refactor-status.md) — paused pending security review

索引在每個 session 都會載入上下文。記憶的內容留在個別檔案裡;索引裡只放指標。agent 每個事實只需掃過一行,只有在相關時才拉出完整檔案。

Wiki 風格連結

記憶之間透過 slug 用 [[wiki-style]] 連結互相連接:

The lockfile issue first surfaced during the [[project_auth-refactor-status]] work.

懸空連結(dangling link)沒有關係 — 指向一個還不存在的記憶的連結,只是標記出一件之後值得寫下來的事。這是一種便宜的方式,可以留下線索而不必停下來把完整的事實寫完。

回憶是背景脈絡,不是聖旨

當記憶在 session 中被回憶起來時,它們會出現在 <system-reminder> 區塊裡 — 由 harness 注入的提示,跟工具可用性變更、模式變更用的是同一套機制。有兩個性質很重要:

  1. 它們是上下文,不是使用者指令。 被回憶的記憶不下命令,只提供資訊。
  2. 它們反映的是寫下當時的真相。 程式碼庫從那之後已經前進了。被回憶的記憶在採取行動前,必須對照當前程式碼重新驗證

第二點正是記憶幫上忙與幫倒忙的分水嶺。一則六週前寫的「config loader 在 src/utils/」的筆記,是一條該去查證的線索,不是一個可以直接蓋上去的事實。

三層知識架構

記憶不會取代 CLAUDE.md 或 skills — 它補齊了一個堆疊:

CLAUDE.md   →  standing rules        ("always use pnpm; run tests before commit")
Memory      →  accumulated experience ("we tried X on 2026-06-12; it broke Y")
Skills      →  procedures             ("how to cut a release, step by step")

規則、經驗、程序。如果你發現自己寫的記憶讀起來像一條規則,就把它移到 CLAUDE.md。如果讀起來像一步一步的流程,那它應該是一個 skill。

摘要取代了硬性壓縮

持久記憶搭配的是長對話處理方式的改變。在舊世代(第 6 堂課),撞到上下文上限會觸發「auto-compact」(自動壓縮)。在 Fable 5 世代,當對話變長時,部分或全部上下文會被摘要;摘要加上任何尚未被摘要的上下文會帶進下一個上下文視窗,工作無縫接續。agent 會被明確告知它需要提前收尾或在任務中途交接。

兩個配套細節補完這幅圖:

  • Scratchpad 目錄(暫存目錄):每個 session 都有一個 session 專屬的 scratchpad 目錄,用於存放所有暫存檔案(而不是 /tmp)— 與專案隔離,且通常不需要權限提示就能使用。短暫的工作檔案放這裡,不要進記憶。
  • 分工很乾淨:摘要保存這個 session 的脈絡;記憶保存應該活得比 session 久的東西;scratchpad 存放完全不該留下來的東西。

實作範例

這是一則貼近實際的 feedback 記憶,按照格式的本意撰寫 — 一個事實、一行方便回憶的描述,以及包含 Why 與 How to apply 的內文:

# File: ~/.claude/projects/my-shop-app/memory/feedback_use-pnpm-not-npm.md
---
name: feedback_use-pnpm-not-npm
description: Always use pnpm in this repo — npm installs corrupt pnpm-lock.yaml
metadata:
  type: feedback
---

# Use pnpm, not npm

Confirmed on 2026-07-08 after a broken deploy.

## Why
The repo is a pnpm workspace. Running `npm install` writes a
package-lock.json and desyncs pnpm-lock.yaml, which broke the
CI install step (see [[project_ci-pipeline]]).

## How to apply
- All installs: `pnpm install`, never `npm install`
- Adding deps: `pnpm add <pkg>` in the relevant workspace package
- If package-lock.json ever appears, delete it and re-run `pnpm install`

以及它在 MEMORY.md 中的索引行:

- [Use pnpm, not npm](feedback_use-pnpm-not-npm.md) — npm installs corrupt pnpm-lock.yaml

注意這些細節:

  • 絕對日期。 寫的是「Confirmed on 2026-07-08」,不是「昨天確認的」。相對日期會腐爛 — 三個月後再讀這個檔案時,「昨天」毫無意義。
  • 懸空連結。 [[project_ci-pipeline]] 可能還不存在。沒關係 — 它標記了一則值得寫的記憶。
  • description 物有所值。 回憶時就是用這一行判斷相關性,所以它陳述的是事實本身,而不只是主題。

整潔規則

記憶品質靠的是維護,不是累積。四條規則:

  1. 更新,不要重複。 事實改變時,編輯既有檔案。兩個檔案對同一個事實各說各話,比沒有檔案更糟。
  2. 刪除錯誤的記憶。 一則被證明為假的記憶是負價值。移除它。
  3. repo 已經記錄的東西不要存。 程式碼結構、git 歷史、CLAUDE.md 裡的任何內容 — 這些以 repo 為唯一真相來源,而且永遠是最新的。與之重複的記憶注定會過期。
  4. 把相對日期換成絕對日期。 「上週」改成「2026-07-01」。

前後對比

沒有持久記憶有持久記憶
每個 session 從零開始整理過的事實按專案持久保存
你反覆重新解釋偏好與地雷userfeedback 記憶替你記著
學到的脈絡隨 session 消亡一個事實一個檔案,活得比 session 久
聊天記錄是唯一紀錄(雜訊多、超龐大)MEMORY.md 索引:每個事實一行
CLAUDE.md 變成雜物抽屜規則、經驗、程序 — 各自分層
撞到上下文上限就硬性壓縮摘要讓工作跨視窗延續

關鍵洞見

記憶是整理過的知識,不是聊天記錄。

這個設計在每一個層面都做出同樣的選擇:提煉,而不是堆積。一個檔案一個事實,迫使每則記憶都是一個經過斟酌、可編輯的單位。索引加檔案的拆分,讓始終載入的成本壓到每個事實一行 — 與讓 skills 得以擴展的「名稱先行、內容按需」哲學如出一轍。整潔規則之所以存在,是因為記憶的失效模式不是遺忘 — 而是信心滿滿地記著已經不再為真的事

這也是為什麼回憶是以「需要重新驗證的背景脈絡」的形式到來,而不是必須服從的指令。一個好的記憶系統不是讓 agent 信任它的過去,而是讓過去變得便宜好查證。

下一堂課

第 30 堂課涵蓋 Deferred Tools 與 ToolSearch(延遲載入工具與工具搜尋)— 你現在已經看過兩次的「名稱先行、定義按需」哲學(skills、記憶),如何被推廣到整個工具介面,以及為什麼這對擁有大量工具目錄的 MCP 伺服器最重要。