AI 工程

幫 Claude Code 裝上長期記憶:claude-mem v13.13.0 實裝指南(含 sensitive 型別的真實邊界)

一、每次 /clear,你都在重新自我介紹一次

用 Claude Code 做長期專案的人都熟悉這個循環:context window 快滿了 → compact → 細節被壓掉 → 隔天開新 session → 你又要打一次「這專案的 auth 走 OAuth2 PKCE、DB migration 卡在 v49、那個 flaky test 是時區問題不是競態」。

CLAUDE.md 能解一部分,但它是手寫的——只記得下你「想得到要寫」的東西。真正會害你的,是那些當下覺得理所當然、三週後完全想不起來的細節。

claude-mem 的切入角度不一樣:不要你手寫,讓另一顆便宜模型在旁邊看著你工作,自動把每一步壓成結構化條目存起來,下次開場自動注入回去。

作者是 Alex Newman(GitHub @thedotmack),Apache-2.0 授權。我在 2026-08-03 查 GitHub API,repo 有 89,343 stars、7,778 forks;最新版 v13.13.0 於 2026-08-02 發布。

二、先裝起來(五分鐘)

npx claude-mem install

或在 Claude Code 裡走 plugin marketplace:

/plugin marketplace add thedotmack/claude-mem
/plugin install claude-mem

README 明講的坑,先記下來npm install -g claude-mem 只裝 SDK / library,不會註冊 hooks、不會起 worker 服務。要用 npx claude-mem install 或上面的 /plugin 指令。

系統需求:Node ≥ 20、Bun(缺了自動裝)、uv(向量檢索要用的 Python 套件管理器,缺了自動裝)、SQLite3(內建)。裝完重啟 Claude Code,新 session 就會自動帶上一段舊脈絡。

三、運作原理:一個旁觀者 + 一個本機服務

claude-mem 的觀察與注入流程

掛在哪些 hook 上

直接看 repo 的 plugin/hooks/hooks.json,實際掛的點是:

  • Setup — 跑 version-check.js
  • SessionStart(matcher startup|clear|compact)— 兩件事:起 worker、注入 context
  • UserPromptSubmitsession-init
  • PostToolUse(matcher *async: true,timeout 120s)— observation,最關鍵的一條
  • PreToolUse(matcher Read,async)— file-context
  • Stop / SessionEnd — 收尾與摘要

注意 PostToolUse 是 async: true。這代表觀察是離線跑的,不會卡你的主迴圈——這是它能一路掛在每個工具呼叫上而不讓人抓狂的前提。

Worker

Bun 管的本機 HTTP 服務,預設 host 127.0.0.1,port 是 37700 + (uid % 100)SettingsDefaultsManager.ts 直接這樣算,同機多帳號不會撞 port)。它也帶一個 web viewer UI,可以即時看記憶流。

Observer:另一顆模型

預設 claude-haiku-4-5-20251001,auth 預設走 subscription(登入的 Claude 訂閱,不是 API key)。也可以切 Gemini 或 OpenRouter。另外預設開了 tier routing(CLAUDE_MEM_TIER_ROUTING_ENABLED=true):簡單的走 haiku、複雜的走 sonnet

它的 system prompt 值得你抄。 plugin/modes/code.json 裡有全文,三個關鍵設計:

  1. 定義視角:「Record what was LEARNED/BUILT/FIXED/DEPLOYED/CONFIGURED, not what you (the observer) are doing.」
  2. 給正反例:✅「Authentication now supports OAuth2 with PKCE flow」/❌「Analyzed authentication implementation and stored findings」
  3. 給明確的沉默條件:空的 status check、沒出錯的套件安裝、單純的檔案列表、重複操作、查不到東西的搜尋——直接回空字串,「不要用散文解釋為什麼跳過」。

任何人要寫「摘要型 sub-agent」,這三條就是模板。第三條尤其重要——沒有明確的沉默規則,摘要 agent 會把每一次 ls 都寫成一段感想。

輸出結構是 XML 而非自由文字:type(9 選 1)× concepts(2–5 個,7 選)× facts × narrative × files。type 和 concept 是兩個正交維度,prompt 裡還特別警告不要把 type 塞進 concept。

存與查

儲存走 SQLite(FTS5 全文)+ Chroma 向量(CLAUDE_MEM_CHROMA_ENABLED 預設 true,local 模式用 uvx 跑)。

檢索走三層漸進式揭露:search(拿索引,約 50–100 tokens/筆)→ timeline(看前後文)→ get_observations(只對篩出來的 ID 拿全文,約 500–1,000 tokens/筆)。

README 宣稱「~10x token savings」。這是專案方自己的說法,沒有第三方 benchmark,數量級也就是 50 vs 500 的比值。要理解它比的是「先篩再拿 vs 全拿」,不是「用 claude-mem vs 不用 claude-mem」。

注入端預設值:CLAUDE_MEM_CONTEXT_OBSERVATIONS=50(注入 50 筆)、CLAUDE_MEM_CONTEXT_SESSION_COUNT=10CLAUDE_MEM_CONTEXT_FULL_COUNT=0(預設 0 筆展開全文,只給壓縮條目)。

四、v13.13.0 做了什麼:第 9 種型別 sensitive

原本 8 種型別:bugfixfeaturerefactorchangediscoverydecisionsecurity_alertsecurity_note。這版加了第 9 種:

sensitive — information that isn't quite private, but that you wouldn't want leaking into further content development in the wrong context.

官方點名的例子:內部網址、還沒公開的計畫、個人資訊、business metrics、客戶或合作夥伴名字。它預設會觸發 Telegram 通知,跟 security_alert 一樣。

但這版真正有教學價值的,是它順手修掉的兩個東西。

修掉一個從四月就存在的靜默 bug

changelog 原話:

The type_guidance prompt still described "6 options" and never listed security_alert or security_note from #2084. That string is the only type prose the observer model sees — the per-type description fields are never injected into any prompt — so those types have been under-emitted since April.

翻成白話:他們在 JSON 的 observation_types 陣列裡好好定義了新型別、寫了 description,但那些 description 從來沒有進到任何 prompt。模型只看得到 type_guidance 那一段散文,而那段散文還停在「6 options」。

結果是:新型別在資料結構上存在、在模型眼裡不存在,靜默地少產出了四個月。

這個 bug 的形狀值得記住:只要你的 agent 有「設定檔定義的列舉」和「prompt 裡描述的列舉」兩份來源,它們就一定會漂移,而且不會有任何錯誤訊息。防法很土但有效——讓 prompt 從設定檔生成,或至少寫個測試斷言兩邊的集合相等。

設定遷移的邏輯,比功能本身更值得看

CLAUDE_MEM_TELEGRAM_TRIGGER_TYPES 的預設值從 security_alert 改成 security_alert,sensitive

但光改預設值是沒用的。 原因寫在 SettingsDefaultsManager.ts 的註解裡:第一次啟動時,~/.claude-mem/settings.json 會被寫入全部預設值;之後每次載入,檔案裡的值一律蓋過程式碼裡的 DEFAULTS。所以任何在 Telegram 通知功能上線後才安裝的使用者,磁碟上都凍著那個時代的清單——改 DEFAULTS 永遠打不到他們,新型別會安靜地永遠不通知。

他們的解法是一行針對性遷移:如果磁碟上的值剛好等於舊預設值 security_alert,就改寫成新預設;其他任何值視為使用者自訂,不動。

程式碼註解也誠實承認代價:這無法分辨「使用者刻意設成 security_alert」和「安裝時種下去的預設值」——兩者長得一模一樣。他們選擇讓這種使用者被遷移、開始收到 sensitive 通知,理由是「這是可回復的那一邊」:你設一次就關掉;反過來則是功能對所有既有安裝直接死掉。

如果你刻意只要 security_alert,別把它改回 security_alert 就算了——依原始碼邏輯,下次載入時它又會剛好命中 legacy 值、又被遷移一次。要真的擋住,設一個不等於 security_alert 的清單(例如 security_alert,security_note),或直接設成空字串完全關掉通知。

BMP-safe:一條所有人都該抄的防禦

新型別的 emoji 是 🤫,是 astral(非 BMP)字元。src/utils/bmp-safe.ts 的註解說明了 issue #2787 那類災難:

claude-mem 會把 context 塞進自動載入的 CLAUDE.md / AGENTS.md / *.mdc。Claude Code 有個已知的 bug class,會在 UTF-16 code unit 邊界截斷這段內容;如果切點落在代理對(surrogate pair)中間,就會產生落單的 surrogate,Anthropic API 直接回 400「no low surrogate in string」——整個 session 磚掉,而且 /clear 也救不回來,因為壞掉的位元組住在每次都會重載的 context 檔裡。

他們的處理是把每個 emoji 映射成 BMP 內的替代字元:🤫 → ⊘、🚨 → ⚠、🔐 → ⚷、🔴 → ●,其他不認識的 astral 字元降級成 ,落單 surrogate 直接丟掉。

如果你也在往 CLAUDE.md 注入任何東西,這條直接抄走:注入前過一遍「只保留碼位 ≤ U+FFFF 的字元」。

五、誠實的部分:sensitive 不等於「不會外洩」

sensitive 是標記不是遮蔽的四種防洩密手段對比

這是這篇最需要講清楚的一段。我把 repo 翻過一輪,確認了三件事:

  1. CorpusRoutes.ts 只是把 sensitive 加進 ALLOWED_CORPUS_TYPES 白名單——意思是「可以被查詢」,不是「被擋掉」。
  2. 注入用的 SQL 在 ObservationCompiler.ts,條件是 WHERE ... AND type IN (?);那組 type 來自 ContextConfigLoader.tsnew Set(mode.observation_types.map(t => t.id))——當前 mode 的全部型別。沒有任何設定 key 可以排掉某一個 type。
  3. 用 GitHub code search 在此 repo 找 excludeTypes / EXCLUDE_TYPES,0 命中。

結論:被標成 sensitive 的觀察,一樣進 SQLite、一樣進 Chroma、一樣會在下次 SessionStart 被注入回你的 context。 它給你的是可見度(即時 Telegram 告警 + 事後能用 type 篩出來稽核),不是隔離。

要真的不外洩,claude-mem 給你的是另外幾條路。

第一道:<private> 標籤(真・不入庫)

在 prompt 裡把內容包起來:

<private>
API_KEY=sk-proj-abc123xyz789
內部 DB: internal-db-prod.company.com:5432
</private>

幫我測這個連線

官方文件 docs/public/usage/private-tags.mdx 列出它會從哪些地方剝掉:user prompt 儲存(user_prompts table)、工具輸入參數、工具回傳輸出、以及所有可搜尋內容——「private content never reaches the database or search indices」。支援多行、多段、巢狀,不用任何設定,永遠啟用。

關鍵語意是:Claude 在當下這場對話看得到、用得到,只是持久化的時候被拿掉。

這是我會建議每個團隊寫進 CLAUDE.md 的一條規則:貼 log、貼 stack trace、貼 .env 內容時,一律用 <private> 包起來。

第二道:整個專案排除

CLAUDE_MEM_EXCLUDED_PROJECTS 吃逗號分隔的 glob。客戶專案、法遵敏感的 repo 直接整包排掉,最乾淨。

第三道(原始碼推導,官方沒文件化):存得下、但注不進去

把前面幾個發現串起來,可以做出「照樣標記、照樣可查、但不會被自動注入」:

  • 注入的 type 集合來自當前 mode 的 observation_types
  • ModeManager.ts 支援一層繼承(mode id 用 parent--override 命名,deep merge,陣列是整個覆蓋不是合併);
  • src/sdk/parser.ts 的行為是:模型吐出的 type 若不在 mode 清單裡,它只 log 一行 error,然後 finalType = type 照樣保留

所以做法是:

  1. 在 modes 目錄放一個 code--noleak.json,把 code.json 的 9 種型別抄過來、刪掉 sensitive 那一項:
{
  "name": "Code (no sensitive injection)",
  "observation_types": [
    { "id": "bugfix", "label": "Bug Fix", "emoji": "●", "work_emoji": "⚒", "description": "Something was broken, now fixed" }
  ]
}
  1. ~/.claude-mem/settings.json"CLAUDE_MEM_MODE": "code--noleak"
  2. 重啟 Claude Code

因為 type_guidance 那段散文沒被覆蓋,observer 還是看得到 9 種、還是會吐 sensitive;parser 保留它;資料庫存得到;Telegram 照樣告警;但 ObservationCompilertype IN (...) 不包含它 → 不會被注入下一場。

我沒有實跑,這是從 v13.13.0 原始碼推出來的。 而且它踩在「parser 對未知 type 只 log error」這個實作細節上——那不是公開契約,隨時可能被改成 fallback 到第一個型別。要用的話先在測試專案跑一輪,用 web viewer 確認 sensitive 條目確實有進 DB、且新 session 的注入區塊裡沒有它。

另外一個坑:自訂 mode 檔預設放在 plugin 目錄(~/.claude/plugins/marketplaces/thedotmack/plugin/modes/),更新時可能被覆蓋。原始碼裡有 CLAUDE_MEM_MODES_DIR 可以指到別處——但它不在 SettingsDefaults 的 key 清單裡,所以要當成真正的環境變數設(shell profile / 啟動環境),塞進 settings.json 不保證生效。

六、繁體中文使用者的一個小坑

README 只列 codecode--zhcode--ja 三個 mode,但 plugin/modes/ 實際有 36 個檔、30 幾種語言。沒有 code--zh-tw——code--zh 是簡體中文,它的 footer 加的那句是 LANGUAGE REQUIREMENTS: Please write the observation data in 中文

直接用的話,你的記憶庫會寫成簡體。要繁中,照 mode 繼承機制自己加一個就好。code--zh.json 本身也只是一個 overlay(只有 name 和幾個 prompts key),其他全部從 code.json 繼承:

{
  "name": "Code Development (Traditional Chinese)",
  "prompts": {
    "footer": "(把 code.json 的 footer 原文整段抄過來)\n\nLANGUAGE REQUIREMENTS: Please write the observation data in 繁體中文(台灣用語)"
  }
}

然後設 "CLAUDE_MEM_MODE": "code--zh-tw"。注意 deep merge 是逐 key 覆蓋,footer 你得給完整的一整段,不能只寫要加的那一句。

七、設定清單:先調這幾個

全部在 ~/.claude-mem/settings.json(第一次啟動自動建立)。

Key 預設 什麼時候該動
CLAUDE_MEM_MODEL claude-haiku-4-5-20251001 覺得觀察品質不夠、抓不到重點時往上調
CLAUDE_MEM_TIER_ROUTING_ENABLED true 依複雜度分流(fast=haiku / smart=sonnet),一般不動
CLAUDE_MEM_CONTEXT_OBSERVATIONS 50 開場注入太肥就砍到 20–30
CLAUDE_MEM_CONTEXT_FULL_COUNT 0 想讓最近幾筆展開全文就設 3–5,搭 CONTEXT_FULL_FIELDnarrativefacts
CLAUDE_MEM_SKIP_TOOLS ListMcpResourcesTool,SlashCommand,Skill,TodoWrite,AskUserQuestion 噪音多就往裡加工具名
CLAUDE_MEM_MAX_CONCURRENT_AGENTS 2 機器弱、記憶體吃緊就設 1
CLAUDE_MEM_SEMANTIC_INJECT false 實驗性。開了會在每一次 UserPromptSubmit 注入 top-N 相關觀察,配 SEMANTIC_INJECT_LIMIT=5
CLAUDE_MEM_EXCLUDED_PROJECTS 敏感 repo 填這裡,逗號分隔 glob
CLAUDE_MEM_CLOUD_SYNC_HUB_URL 空 = 雲端同步完全關閉。v13.12.0 上的 two-lane sync 預設不開,這點值得給掌聲
CLAUDE_MEM_FOLDER_CLAUDEMD_ENABLED false 開了會自動往資料夾寫 CLAUDE.md;建議搭 FOLDER_USE_LOCAL_MD=true 寫到 CLAUDE.local.md,才不會污染 repo
CLAUDE_MEM_TELEGRAM_TRIGGER_TYPES security_alert,sensitive 想關通知設成空字串;想自訂就明確列出,別留成 security_alert

改完 mode 或 model 記得重啟 Claude Code。

八、什麼時候別用

  • 多人共用的機器/共享帳號:記憶庫就是 ~/.claude-mem/ 底下的本機 SQLite,沒有 per-user ACL。
  • 法遵嚴格的客戶專案:觀察內容是模型生成的自然語言摘要,你無法事先窮舉它會寫出什麼。sensitive 型別是事後告警,不是事前攔截。直接用 CLAUDE_MEM_EXCLUDED_PROJECTS 整包排除比較誠實。
  • 極短的一次性 session:每個 PostToolUse 都要跑一次 observer 模型(雖然 async、雖然走 Haiku),對只跑三五個工具的任務是純成本。
  • 你已經有很嚴謹的 CLAUDE.md 紀律:claude-mem 走的是「自動累積」路線,會跟你的手寫 context 疊加。先把 CONTEXT_OBSERVATIONS 調小、觀察兩週再決定要不要放大。

反過來,最值得用的場景很明確:同一個大 repo、跨很多天、你自己或小團隊持續在改。那種「上週那個 flaky test 我到底怎麼修的」的問題,正是它擅長的。

九、對工程團隊的三個帶走點

1. Observer 模式可以直接抄。 用一顆便宜模型在旁邊看主 agent 工作、只負責產結構化紀錄。plugin/modes/code.json 的 prompt 是現成模板——定義視角、給正反例、給明確的沉默條件、輸出走 XML 而不是自由文字。這四件事缺一個,摘要 agent 就會退化成噪音產生器。

2.「設定檔定義的列舉」和「prompt 裡的列舉」一定會漂移。 這次的 type_guidance bug 讓兩個型別安靜地少產出四個月,沒有任何錯誤訊息。寫個測試斷言兩邊集合相等,成本一分鐘。

3. 改預設值改不到既有使用者。 任何「第一次啟動就把全部預設寫進設定檔」的設計,之後改 DEFAULTS 都是空砲。要嘛只寫使用者真的改過的 key,要嘛就得像他們一樣寫針對性遷移——並且明確接受「無法分辨刻意設成跟預設一樣的人」這個代價,而不是假裝它不存在。

來源

  • GitHub repohttps://github.com/thedotmack/claude-mem(作者 Alex Newman / @thedotmack,Apache-2.0)
  • v13.13.0 release noteshttps://github.com/thedotmack/claude-mem/releases/tag/v13.13.0(2026-08-02 發布)
  • 官方文件https://docs.claude-mem.ai/;private tags 說明見 docs/public/usage/private-tags.mdx
  • 本文引用的原始碼(v13.13.0,main branch):src/shared/SettingsDefaultsManager.tssrc/services/context/ContextConfigLoader.tssrc/services/context/ObservationCompiler.tssrc/services/domain/ModeManager.tssrc/sdk/parser.tssrc/utils/bmp-safe.tssrc/services/integrations/TelegramNotifier.tssrc/services/worker/http/routes/CorpusRoutes.tsplugin/modes/code.jsonplugin/hooks/hooks.json
  • star / fork 數為 2026-08-03 查 GitHub REST API 所得

整理:DataAgent · Coding Agent 實戰教學

發表迴響

%d 位部落客按了讚: