Claude Memory Compiler 深度解析:当 AI 编程助手第一次拥有「编译器思维」的记忆系统
背景:AI 编程助手的「金鱼记忆」困境
如果你用过 Claude Code、Cursor、Windsurf 这类 AI 编程助手,一定遇到过这个场景:
你花了两个小时和 AI 讨论了一个复杂的架构决策 —— 为什么选 Supabase 而不是 Firebase,怎么处理 JWT 的刷新逻辑,哪些边界情况需要特殊处理。
第二天你打开项目,AI 对昨天的一切毫无记忆。你不得不从头解释一遍。第三天,同样的事又发生一次。
这不是 bug,这是设计。当前的 AI 编程助手采用「会话隔离」架构 —— 每次对话都是独立的时间胶囊,会话结束,记忆归零。Anthropic 的 Claude Code 虽然有 LCM(Lossless Context Management)做会话内压缩,但那是为了节省 token,不是为了跨会话记忆。
问题的本质:AI 拥有强大的实时推理能力,但缺乏长期知识积累能力。它能理解你今天说的每一句话,但明天它就忘了。
这就像一个天才程序员,每次上班都要重新认识代码库。
核心概念:把「记忆」变成「编译」
2026 年 4 月,一个名为 claude-memory-compiler 的开源项目给出了一个令人惊艳的解法:
把 AI 对话当作「源代码」,把知识提取当作「编译」,把知识库当作「可执行程序」。
这个想法来自 Andrej Karpathy 2024 年提出的 LLM Knowledge Base 架构。Karpathy 的原始想法是:用 LLM 把网络文章「编译」成结构化知识库。claude-memory-compiler 做了一个关键的转向:
不编译网络文章,编译你自己的 AI 对话。
这是一个范式转变。传统的知识管理是你手动整理笔记、打标签、建立关联。这个系统说:你只管和 AI 聊天,编译器自动把对话变成知识。
编译器类比
daily/ = 源代码 (你的对话 —— 原始材料)
LLM = 编译器 (提取和组织知识)
knowledge/ = 可执行程序 (结构化、可查询的知识库)
lint = 测试套件 (一致性健康检查)
queries = 运行时 (使用知识)
你不需要手动组织知识。你只需要对话,LLM 负责综合、交叉引用和维护。
架构分析:三层知识编译流水线
Layer 1: daily/ —— 对话日志(不可变源)
这是「源代码」层。每次 Claude Code 会话结束(或中途压缩),系统自动捕获对话 transcript,提取关键信息,追加到当天的日志文件。
daily/
├── 2026-04-01.md
├── 2026-04-02.md
├── ...
日志格式:
# Daily Log: 2026-04-01
## Sessions
### Session (14:30) - Supabase Auth Setup
**Context:** 用户在配置 Supabase 认证系统
**Key Exchanges:**
- 用户询问 JWT 刷新策略,助手解释了 refresh token rotation
- 决定使用 Row Level Security 而不是应用层权限检查
- 发现 Supabase 的 RLS 策略在 JOIN 查询上有性能陷阱
**Decisions Made:**
- 选择 Supabase 而不是 Firebase(因为需要 PostgreSQL 的 RLS)
- 认证流程:使用 PKCE 而不是 implicit flow
**Lessons Learned:**
- Supabase RLS 策略必须避免在 WHERE 子句中嵌套 SELECT
- JWT 的 aud 字段必须匹配 Supabase project ref
**Action Items:**
- [ ] 测试 RLS 策略在复杂 JOIN 下的性能
- [ ] 设置 refresh token 的过期策略
关键设计:daily/ 是 append-only,永不修改。这是「不可变源代码」原则 —— 你不会修改编译器的输入,只会追加新输入。
Layer 2: knowledge/ —— 编译产物(LLM 所有)
这是「可执行程序」层。LLM 完全拥有这个目录,人类只读不写(除非修复错误)。
knowledge/
├── index.md # 主目录 —— 每篇文章一行摘要
├── log.md # 追加式构建日志
├── concepts/ # 原子知识文章
├── connections/ # 连接 2+ 概念的交叉洞察
└── qa/ # 已归档的查询答案(复利知识)
index.md —— 核心检索机制
这是整个系统的「心脏」。一个 Markdown 表格,列出每篇知识文章:
# Knowledge Base Index
| Article | Summary | Compiled From | Updated |
|---------|---------|---------------|---------|
| [[concepts/supabase-auth]] | Row-level security patterns and JWT gotchas | daily/2026-04-02.md | 2026-04-02 |
| [[connections/auth-and-webhooks]] | Token verification patterns shared across Supabase auth and Stripe webhooks | daily/2026-04-02.md, daily/2026-04-04.md | 2026-04-04 |
为什么不用向量数据库?
这是 Karpathy 的核心洞察:
在个人知识库规模(50-500 篇文章),LLM 读取结构化 index.md 的效果 优于 向量相似度搜索。
向量搜索找的是「相似的词」,LLM 理解的是「你真正在问什么」。当知识库超过 2000 篇文章、index.md 超过上下文窗口时,才需要引入 RAG。
三种文章类型
1. Concept Articles(concepts/) —— 原子知识
---
title: "Supabase Row-Level Security"
aliases: [RLS, supabase-rls]
tags: [auth, database, security]
sources:
- "daily/2026-04-01.md"
- "daily/2026-04-03.md"
created: 2026-04-01
updated: 2026-04-03
---
# Supabase Row-Level Security
Row-Level Security (RLS) 在 PostgreSQL 层强制访问控制,无需应用层权限检查。
## Key Points
- RLS 策略是 SQL 表达式,对每行返回 boolean
- 必须在 JWT 中嵌入用户 ID,策略通过 `auth.uid()` 获取
- 避免在策略 WHERE 子句中嵌套 SELECT —— 会导致 N+1 查询
## Details
[深入解释...]
## Related Concepts
- [[concepts/supabase-jwt]] - JWT 结构和验证
- [[concepts/postgres-policies]] - PostgreSQL 策略语法
## Sources
- [[daily/2026-04-01.md]] - 初始配置时发现
- [[daily/2026-04-03.md]] - 性能调优时深入
2. Connection Articles(connections/) —— 交叉洞察
当对话揭示了两个概念之间的非显而易见关系时,编译器创建连接文章:
---
title: "Connection: Supabase Auth and Stripe Webhooks"
connects:
- "concepts/supabase-auth"
- "concepts/stripe-webhooks"
sources:
- "daily/2026-04-04.md"
---
# Connection: Supabase Auth and Stripe Webhooks
## The Connection
Supabase JWT 验证和 Stripe webhook 签名验证使用相同的「secret + timestamp + payload」模式。
## Key Insight
两者都需要防御 timing attack。Supabase 的 `auth.jwt()` 验证和 Stripe 的 `verify_signature()` 都应该使用恒定时间比较。
## Evidence
[具体代码示例...]
3. Q&A Articles(qa/) —— 复利知识
每次查询可以选择 --file-back,把答案永久存档:
---
title: "Q: How do I handle auth redirects?"
question: "How do I handle auth redirects in Next.js with Supabase?"
consulted:
- "concepts/supabase-auth"
- "concepts/nextjs-middleware"
filed: 2026-04-05
---
# Q: How do I handle auth redirects?
## Answer
使用 Next.js middleware + Supabase 的 `getSession()`...
## Sources Consulted
- [[concepts/supabase-auth]] - 提供了 session 刷新逻辑
- [[concepts/nextjs-middleware]] - middleware 执行顺序
## Follow-Up Questions
- 如何处理 OAuth 回调的 race condition?
- middleware 中如何缓存 session?
复利效应:每次查询都让知识库变聪明。第一次问需要综合多篇概念文章,第二次问直接读 Q&A 文章。
Layer 3: AGENTS.md —— 编译器规范
这个文件定义了整个系统的「语法」和「语义」—— 告诉 LLM 如何编译、如何维护知识库。这是「编译器源码」。
核心操作:编译、查询、健康检查
1. 编译:daily/ → knowledge/
编译流程:
1. 读取 daily log 文件
2. 读取 knowledge/index.md 了解当前知识状态
3. 读取可能需要更新的现有文章
4. 对于日志中的每个知识片段:
- 如果现有概念文章已覆盖该主题:UPDATE,追加 daily log 为来源
- 如果是新主题:CREATE 新的 concepts/ 文章
5. 如果日志揭示了概念间的非显而易见连接:CREATE connections/ 文章
6. UPDATE knowledge/index.md
7. APPEND knowledge/log.md
增量编译:通过 state.json 跟踪每个 daily log 的 SHA-256 哈希,只编译新增或修改的文件。
成本:每个 daily log 约 $0.45-0.65(随知识库增长而增加)。
CLI:
uv run python scripts/compile.py # 编译新增/修改
uv run python scripts/compile.py --all # 强制全量重编译
uv run python scripts/compile.py --file daily/2026-04-01.md
uv run python scripts/compile.py --dry-run
2. 查询:Index-Guided Retrieval
查询流程:
1. 读取 knowledge/index.md(主目录)
2. 基于问题识别 3-10 篇相关文章
3. 读取这些文章的完整内容
4. 综合、生成答案,附带 [[wikilink]] 引用
5. 如果指定 --file-back:创建 qa/ 文章,更新 index 和 log
为什么不用 RAG?
在个人知识库规模,LLM 读取结构化索引的效果优于向量搜索:
- 向量相似度找「相似的词」
- LLM 理解「你真正在问什么」
Karpathy 的实验表明,在 50-500 篇文章规模,index-guided retrieval 的准确率和相关性都优于 embedding-based RAG。
CLI:
uv run python scripts/query.py "What auth patterns do I use?"
uv run python scripts/query.py "What's my error handling strategy?" --file-back
3. 健康检查:Lint
7 项检查:
| 检查项 | 类型 | 捕获问题 |
|---|---|---|
| Broken links | 结构性 | [[wikilinks]] 指向不存在的文章 |
| Orphan pages | 结构性 | 零入链文章(无人引用) |
| Orphan sources | 结构性 | 尚未编译的 daily logs |
| Stale articles | 结构性 | 源日志在编译后被修改 |
| Missing backlinks | 结构性 | A 链接 B 但 B 不链接 A |
| Sparse articles | 结构性 | 少于 200 字的文章 |
| Contradictions | LLM | 文章间的冲突声明 |
CLI:
uv run python scripts/lint.py # 全部检查
uv run python scripts/lint.py --structural-only # 仅结构性检查(免费)
Hook 系统:自动捕获的「隐形之手」
这是整个系统的「魔法」部分 —— 你不需要记得运行任何命令,hooks 会在 Claude Code 的生命周期事件中自动触发。
Hook 配置(.claude/settings.json)
{
"hooks": {
"SessionStart": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": "uv run python hooks/session-start.py",
"timeout": 15
}]
}],
"PreCompact": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": "uv run python hooks/pre-compact.py",
"timeout": 10
}]
}],
"SessionEnd": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": "uv run python hooks/session-end.py",
"timeout": 10
}]
}]
}
}
三种 Hook 的职责
1. SessionStart —— 注入知识
- 纯本地 I/O,无 API 调用,< 1 秒
- 读取
knowledge/index.md和最近的 daily log - 输出 JSON 到 stdout,Claude 在每次会话开始时看到知识库索引
- 最大 20,000 字符上下文
2. SessionEnd —— 捕获对话
- 从 stdin 读取 hook 输入(包含
session_id、transcript_path、cwd) - 复制原始 JSONL transcript 到临时文件
- 以完全分离的后台进程 启动
flush.py - 递归保护:如果
CLAUDE_INVOKED_BY环境变量已设置,立即退出
3. PreCompact —— 压缩前捕获
- 与 SessionEnd 相同的架构
- 在 Claude Code 自动压缩上下文窗口之前触发
- 防护空
transcript_path(Claude Code 已知 bug #13668)
为什么需要 PreCompact 和 SessionEnd 两个?
长时间会话可能触发多次自动压缩,然后你才关闭会话。如果没有 PreCompact,中间的上下文会在压缩时丢失,SessionEnd 永远看不到那些内容。
后台 Flush 进程(flush.py)
由两种 hook 以完全分离的后台进程启动:
- Windows:
CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS标志 - Mac/Linux:
start_new_session=True
这确保 flush.py 在 Claude Code 的 hook 进程退出后仍然存活。
flush.py 做什么:
1. 设置 CLAUDE_INVOKED_BY=memory_flush 环境变量(防止递归)
2. 从临时 .md 文件读取预提取的对话上下文
3. 如果上下文为空或同一会话在 60 秒内已 flush:跳过(去重)
4. 调用 Claude Agent SDK(query() with allowed_tools=[], max_turns=2)
5. Claude 决定什么值得保存 —— 返回结构化 bullet points 或 FLUSH_OK
6. 追加结果到 daily/YYYY-MM-DD.md
7. 清理临时上下文文件
8. 【关键】如果当前时间 > 18:00(本地时间)且今天的 daily log 自上次编译后已改变:
以另一个分离后台进程启动 compile.py
自动日编译:不需要 cron job。只要你在下午 6 点后用过 Claude Code,编译就会自动发生。
代码实战:从零搭建记忆编译器
安装
# 克隆到你的项目
git clone https://github.com/coleam00/claude-memory-compiler.git
cd claude-memory-compiler
# 安装依赖(使用 uv)
uv sync
配置 Hooks
复制 .claude/settings.json 到你的项目:
cp .claude/settings.json /path/to/your/project/.claude/
或者合并到现有配置:
import json
# 读取现有配置
with open('.claude/settings.json') as f:
config = json.load(f)
# 合并 hooks
memory_hooks = {
"SessionStart": [{"matcher": "", "hooks": [{"type": "command", "command": "uv run python hooks/session-start.py", "timeout": 15}]}],
"PreCompact": [{"matcher": "", "hooks": [{"type": "command", "command": "uv run python hooks/pre-compact.py", "timeout": 10}]}],
"SessionEnd": [{"matcher": "", "hooks": [{"type": "command", "command": "uv run python hooks/session-end.py", "timeout": 10}]}]
}
config.setdefault('hooks', {}).update(memory_hooks)
with open('.claude/settings.json', 'w') as f:
json.dump(config, f, indent=2)
验证安装
# 检查 hooks 配置
cat .claude/settings.json
# 测试 session-start hook
uv run python hooks/session-start.py
# 检查依赖
uv run python -c "import claude_agent_sdk; print('Claude Agent SDK OK')"
使用流程
1. 正常使用 Claude Code
cd /path/to/your/project
claude
Hooks 自动激活。你正常和 Claude 对话,不需要做任何特殊操作。
2. 会话结束后检查 daily log
cat daily/$(date +%Y-%m-%d).md
3. 手动触发编译(可选)
uv run python scripts/compile.py
4. 查询知识库
uv run python scripts/query.py "What did I decide about authentication?"
5. 健康检查
uv run python scripts/lint.py
性能优化:成本控制与规模扩展
成本分析
| 操作 | 成本 | 频率 |
|---|---|---|
| Memory flush(每会话) | $0.02-0.05 | 每次会话结束 |
| Compile(每 daily log) | $0.45-0.65 | 每天 1 次 |
| Query(无 file-back) | $0.15-0.25 | 按需 |
| Query(有 file-back) | $0.25-0.40 | 按需 |
| Full lint(含 contradictions) | $0.15-0.25 | 每周 1 次 |
| Structural lint | $0.00 | 随时 |
月度成本估算:
- 每天用 5 次 Claude Code 会话
- 每月 22 个工作日
- 每天自动编译 1 次
- 每周查询 10 次
Flush: 5 sessions × 22 days × $0.03 = $3.30
Compile: 22 days × $0.55 = $12.10
Query: 40 queries × $0.20 = $8.00
Lint: 4 weeks × $0.20 = $0.80
Total: ~$24/月
规模扩展:何时引入 RAG
当前架构的极限:
- index.md 超过 2M tokens(约 2000+ 篇文章)
- 单次查询需要读取的文章超过上下文窗口
引入 RAG 的时机:
# 简单判断:index.md 的 token 数
import tiktoken
def should_use_rag(index_path: str) -> bool:
enc = tiktoken.encoding_for_model("claude-3-5-sonnet-20241022")
with open(index_path) as f:
tokens = len(enc.encode(f.read()))
return tokens > 1_500_000 # 留 500k 给查询和响应
混合检索架构:
def hybrid_retrieve(question: str, index_path: str, kb_dir: str) -> list[str]:
# 1. 关键词搜索(BM25)
keyword_results = bm25_search(question, kb_dir, top_k=20)
# 2. 语义搜索(Embedding)
semantic_results = embedding_search(question, kb_dir, top_k=20)
# 3. 合并去重
candidates = list(set(keyword_results + semantic_results))
# 4. LLM 重排序(可选)
if len(candidates) > 10:
candidates = llm_rerank(question, candidates, top_k=10)
return candidates
增量编译优化
# scripts/compile.py 的核心逻辑
import hashlib
import json
def get_file_hash(filepath: str) -> str:
with open(filepath, 'rb') as f:
return hashlib.sha256(f.read()).hexdigest()
def load_state() -> dict:
try:
with open('scripts/state.json') as f:
return json.load(f)
except FileNotFoundError:
return {'ingested': {}}
def save_state(state: dict):
with open('scripts/state.json', 'w') as f:
json.dump(state, f, indent=2)
def compile_incremental():
state = load_state()
for daily_file in Path('daily').glob('*.md'):
file_hash = get_file_hash(daily_file)
stored = state['ingested'].get(daily_file.name)
# 跳过未改变
if stored and stored['hash'] == file_hash:
continue
# 编译
compile_daily_log(daily_file)
# 更新状态
state['ingested'][daily_file.name] = {
'hash': file_hash,
'compiled_at': datetime.now().isoformat(),
'cost': last_compile_cost
}
save_state(state)
与现有方案的对比
vs. OpenClaw LCM
| 维度 | claude-memory-compiler | OpenClaw LCM |
|---|---|---|
| 目标 | 跨会话知识积累 | 会话内上下文压缩 |
| 存储格式 | Markdown + Wikilinks | JSON summaries |
| 检索方式 | Index-guided(无向量) | LCM DAG traversal |
| 成本 | 使用 Claude 订阅 | 需要 API credits |
| 适用规模 | 50-2000 篇文章 | 无限(但丢失细节) |
互补关系:LCM 解决「token 预算」,memory-compiler 解决「知识积累」。两者可以共存。
vs. Obsidian + 手动整理
| 维度 | claude-memory-compiler | Obsidian 手动 |
|---|---|---|
| 知识来源 | 自动从对话提取 | 手动写笔记 |
| 组织方式 | LLM 自动分类 | 手动打标签、建文件夹 |
| 交叉引用 | LLM 自动发现连接 | 手动添加 [[wikilink]] |
| 维护成本 | 接近零 | 高(需要持续整理) |
兼容性:memory-compiler 的知识库是纯 Markdown + Wikilinks,可以直接用 Obsidian 打开查看图谱、反向链接。
vs. Notion AI / Mem.ai
| 维度 | claude-memory-compiler | Notion AI / Mem.ai |
|---|---|---|
| 数据所有权 | 100% 本地,纯文本 | 云端,专有格式 |
| 可移植性 | Markdown,随处可用 | 需要导出 |
| 成本模型 | 使用现有 Claude 订阅 | 单独订阅费用 |
| 可定制性 | 完全开源,可修改 | 黑盒 |
总结展望:AI 编程助手的「第二大脑」
claude-memory-compiler 解决了一个根本问题:
AI 编程助手拥有强大的实时推理能力,但缺乏长期知识积累能力。
它用「编译器思维」重新定义了知识管理:
- 源代码 = 你的 AI 对话(
daily/) - 编译器 = LLM(提取和组织知识)
- 可执行程序 = 结构化知识库(
knowledge/) - 测试套件 = 健康检查(
lint) - 运行时 = 查询系统(
query)
核心价值
- 零摩擦:你只管对话,系统自动编译
- 复利效应:每次查询都让知识库变聪明
- 100% 本地:数据主权在你,纯 Markdown 格式
- 成本可控:使用现有 Claude 订阅,无需额外 API credits
适用场景
- 长期项目的架构决策记录
- 复杂系统的调试经验积累
- 个人编程偏好和模式沉淀
- 团队知识共享(通过 git 同步
knowledge/)
未来演进方向
- 多项目知识库:当前是项目级,可以扩展到全局级
- 团队协作:通过 git 合并不同开发者的知识库
- 主动推荐:基于当前上下文主动推送相关知识
- 代码生成增强:用知识库 fine-tune 或作为 RAG 上下文
项目地址:https://github.com/coleam00/claude-memory-compiler
灵感来源:Andrej Karpathy's LLM Knowledge Base
一句话总结:当 AI 编程助手第一次拥有「编译器思维」的记忆系统,你的对话不再是过眼云烟,而是持续增值的知识资产。