# Claude Code Memory 记忆系统深度分析
> 基于 Claude Code 源码(2026-03-31 快照,512K 行 TypeScript)逆向分析
> 核心文件:`src/memdir/`(8个文件)、`src/services/extractMemories/`(2个)、`src/services/SessionMemory/`(3个)、`src/services/teamMemorySync/`(5个)
---
## 1. 三层记忆架构总览
Claude Code 的记忆系统不是一个简单的文件存储,而是一个**三层递进的知识管理体系**:
```
┌─────────────────────────────────────────────────────────────┐
│ 第3层:团队记忆(Team Memory) │
│ 跨用户、按仓库 │ 服务端同步 │ REST API + 乐观锁 │
│ 秘密扫描保护 │ 文件监听器 │ 30种凭证检测规则 │
├─────────────────────────────────────────────────────────────┤
│ 第2层:持久记忆(Persistent Memory / extractMemories) │
│ 跨会话、按项目 │ 本地文件 │ 后台 Fork Agent 自动提取 │
│ 4种类型分类 │ MEMORY.md 索引 │ AI 相关性召回 │
├─────────────────────────────────────────────────────────────┤
│ 第1层:会话记忆(Session Memory) │
│ 仅当前会话 │ 单个文件 │ 10个固定章节 │ 服务于压缩 │
└─────────────────────────────────────────────────────────────┘
```
| 层级 | 范围 | 持久性 | 触发方式 | 存储位置 |
|------|------|--------|----------|----------|
| 会话记忆 | 当前会话 | 临时(会话结束即停用) | 后采样钩子(token+工具调用阈值) | 会话目录下单文件 |
| 持久记忆 | 跨会话、按项目 | 永久(直到手动删除) | 每轮查询结束时(Stop Hook) | `~/.claude/projects/<项目>/memory/` |
| 团队记忆 | 跨用户、按仓库 | 远程服务器 + 本地镜像 | 文件监听器(2秒去抖) | `memory/team/` + Anthropic API |
---
## 2. 持久记忆系统(核心)
### 2.1 记忆文件格式
每条记忆是一个独立的 Markdown 文件,带 YAML frontmatter:
```markdown
---
name: 用户偏好-简洁回复
description: 用户不希望在每次回复末尾加总结
type: feedback
---
不要在回复末尾总结刚做了什么,用户能看到 diff。
**Why:** 用户明确要求过"stop summarizing what you just did"
**How to apply:** 所有回复结束时,直接结束,不加回顾性总结。
```
### 2.2 四种记忆类型
```typescript
const MEMORY_TYPES = ['user', 'feedback', 'project', 'reference'] as const
```
| 类型 | 用途 | 保存时机 | 作用域(团队模式) |
|------|------|----------|:------------------:|
| **user** | 用户角色、目标、知识背景 | 了解到用户的身份信息时 | 始终私有 |
| **feedback** | 用户对工作方式的指导 | 用户纠正或确认做法时 | 默认私有 |
| **project** | 项目进展、目标、事件 | 了解到工作计划、截止日期时 | 偏向团队 |
| **reference** | 外部系统指针 | 了解到 Linear/Grafana/Slack 等资源时 | 通常团队 |
**每种类型要求的结构:**
- feedback 和 project 类型必须包含 `**Why:**` 和 `**How to apply:**` 行
- 相对日期必须转换为绝对日期(如"周四"→"2026-03-05")
- user 类型的示例:"深度 Go 经验,React 新手——用后端类比解释前端概念"
### 2.3 明确不保存的内容
源码中硬编码了 6 类排除项(即使用户明确要求也不保存):
1. 代码模式、架构、文件路径、项目结构——可从代码推导
2. Git 历史、最近变更——`git log`/`git blame` 是权威来源
3. 调试方案或修复步骤——修复在代码中,commit message 有上下文
4. CLAUDE.md 中已有的内容——不重复
5. 临时任务细节:进行中的工作、当前对话上下文
6. 如果用户要求保存 PR 列表或活动摘要,要追问"什么是令人意外的或不明显的?"——只保存那部分
### 2.4 MEMORY.md 索引机制
```
MEMORY.md 是索引,不是记忆本身
```
**格式:** 纯 Markdown,无 frontmatter。每条一行,约 150 字符以内:
```markdown
- [用户偏好-简洁回复](feedback_concise.md) — 不在回复末尾加总结
- [项目-合并冻结](project_freeze.md) — 3月5日起移动端发布冻结
```
**限制:**
- 最大 200 行(`MAX_ENTRYPOINT_LINES`)
- 最大 25,000 字节(`MAX_ENTRYPOINT_BYTES`)
- 超出时在末尾追加截断警告
- 截断按行边界执行(不会切断一行的中间)
**两步保存流程:**
1. 写入记忆文件(如 `feedback_concise.md`)
2. 在 MEMORY.md 中添加索引行
可选的 `skipIndex` 模式(通过 `tengu_moth_copse` 特性开关)可跳过第2步。
### 2.5 存储目录结构
```
~/.claude/
projects/
-Users-charlesqin-Desktop-myproject/ ← sanitizePath(项目根目录)
memory/ ← AUTO_MEM_DIRNAME
MEMORY.md ← 索引文件
user_role.md ← 私有记忆文件
feedback_testing.md
project_deadline.md
reference_linear.md
team/ ← 团队记忆子目录
MEMORY.md ← 团队索引
project_api_migration.md
reference_oncall_board.md
logs/ ← KAIROS 每日日志
2026/
03/
2026-03-31.md
```
### 2.6 路径安全机制
`paths.ts` 包含多层安全验证:
| 安全层 | 检查内容 | 防御目标 |
|--------|----------|----------|
| 绝对路径检查 | 拒绝相对路径 | 路径遍历 |
| 根路径检查 | 拒绝长度 < 3 的路径 | 写入系统根目录 |
| UNC 路径检查 | 拒绝 `\\server\share` 和 `//server/share` | NTLM 凭证泄露 |
| Null 字节检查 | 拒绝包含 `\0` 的路径 | 路径截断攻击 |
| Tilde 展开限制 | 拒绝 `~`、`~/`、`~/.`、`~/..` | 匹配整个 HOME |
| **项目设置排除** | `.claude/settings.json` 不能设 `autoMemoryDirectory` | **恶意仓库重定向写入到 `~/.ssh`** |
| NFC 规范化 | Unicode NFC 标准化 | macOS 路径不一致 |
| Git 根规范化 | worktree 共享主仓库的记忆 | 避免重复记忆目录 |
**关键安全设计:** `projectSettings`(提交到仓库的 `.claude/settings.json`)被有意排除在 `autoMemoryDirectory` 的信任来源之外。源码注释明确说明原因:
```typescript
// SECURITY: projectSettings is intentionally excluded —
// a malicious repo could set autoMemoryDirectory: "~/.ssh"
// and gain write access to sensitive directories
```
---
## 3. 自动记忆提取(extractMemories)
### 3.1 触发时机
```
用户输入 → 模型响应 → 工具执行 → 循环... → 模型最终响应(无工具调用)
↓
Stop Hooks 执行
↓
executeExtractMemories() ← 即发即忘
```
**前置条件(全部满足才执行):**
1. `EXTRACT_MEMORIES` 编译时特性开关开启
2. `isExtractModeActive()` = true(`tengu_passport_quail` GrowthBook 开关)
3. `isAutoMemoryEnabled()` = true
4. 非子代理(`!toolUseContext.agentId`)
5. 非 bare 模式
6. 自上次提取以来有新的模型可见消息
### 3.2 互斥机制
```typescript
// 如果主代理在对话中已经直接写了记忆文件,跳过自动提取
if (hasMemoryWritesSince(lastMemoryMessageUuid)) {
// 推进游标但不执行提取——避免覆盖用户显式保存的记忆
lastMemoryMessageUuid = messages[messages.length - 1].uuid
return
}
```
这防止了自动提取和用户手动保存之间的冲突。
### 3.3 Fork Agent 执行
```typescript
const result = await runForkedAgent({
messages: conversationMessages,
system: extractionPrompt,
maxTurns: 5, // 硬上限:5轮(读1轮 + 写1-4轮)
canUseTool: createAutoMemCanUseTool(autoMemPath),
// ... 共享主会话的 prompt cache
})
```
**工具权限白名单:**
| 工具 | 权限 |
|------|------|
| FileRead | 允许(无限制) |
| Grep | 允许(无限制) |
| Glob | 允许(无限制) |
| Bash | 仅只读命令(ls, find, grep, cat, stat, wc, head, tail) |
| FileEdit | 仅限 `autoMemPath` 内 |
| FileWrite | 仅限 `autoMemPath` 内 |
| MCP / Agent / 写入型 Bash | **全部禁止** |
### 3.4 提取节流
```typescript
let turnsSinceLastExtraction = 0
const turnsBeforeExtraction = getFeatureValue('tengu_bramble_lintel', 1)
// 每 N 轮查询才执行一次提取(默认每轮都执行)
if (turnsSinceLastExtraction < turnsBeforeExtraction) {
turnsSinceLastExtraction++
return
}
```
### 3.5 提取后通知
成功提取后,将写入的文件路径列表作为 `SystemMemorySavedMessage` 追加到主对话中,这样主代理知道记忆已更新。
---
## 4. AI 驱动的记忆召回(findRelevantMemories)
### 4.1 召回流程
```
用户发送消息
↓
scanMemoryFiles(memoryDir)
↓ 递归读取所有 .md 文件(排除 MEMORY.md)
↓ 解析前 30 行 frontmatter(description + type)
↓ 按 mtime 降序排序,上限 200 个文件
↓
过滤掉 alreadySurfaced(之前轮次已展示的路径)
↓
selectRelevantMemories(query, memories, signal, recentTools)
↓ 构建文本清单:每行 "- [type] filename (timestamp): description"
↓ 附加 "Recently used tools: ..." 部分
↓
sideQuery → Sonnet 模型
↓ 系统提示:SELECT_MEMORIES_SYSTEM_PROMPT
↓ 用户消息:Query + Available memories
↓ 结构化输出:{ selected_memories: string[] }
↓ max_tokens: 256
↓
返回最多 5 条 RelevantMemory(路径 + mtime)
```
### 4.2 选择提示词的关键规则
```
- 返回最多 5 个文件名
- 要有选择性和辨别力;如果不确定,不要包含
- 如果提供了最近使用的工具列表:
✗ 不要选择这些工具的使用参考/API 文档(已经在用了)
✓ 仍然选择这些工具的警告/陷阱/已知问题
```
### 4.3 记忆新鲜度标注
```typescript
function memoryAge(mtimeMs: number): string {
const days = memoryAgeDays(mtimeMs)
if (days === 0) return 'today'
if (days === 1) return 'yesterday'
return `${days} days ago`
}
function memoryFreshnessText(mtimeMs: number): string {
if (memoryAgeDays(mtimeMs) <= 1) return '' // 新鲜记忆不加警告
return `This memory is ${days} days old.
Memories are point-in-time observations, not live state —
claims about code behavior or file:line citations may be outdated.
Verify against current code before asserting as fact.`
}
```
**设计动机(源码注释):** 用户报告过过期的记忆被模型当作事实断言。"47 days ago" 比 ISO 时间戳更能触发模型的过期推理。
### 4.4 召回前的验证要求
源码中注入的系统提示明确要求模型在使用记忆前验证:
```
- 如果记忆提到一个文件路径 → 检查文件是否存在
- 如果记忆提到一个函数或标志 → grep 搜索它
- 如果用户即将根据你的建议行动 → 先验证
- "记忆说 X 存在"不等于"X 现在存在"
- 活动日志、架构快照是冻结在某个时间点的,优先使用 git log
```
---
## 5. 会话记忆(Session Memory)
### 5.1 与持久记忆的关键区别
| 维度 | 会话记忆 | 持久记忆 |
|------|----------|----------|
| 生命周期 | 当前会话 | 跨会话永久 |
| 文件数量 | 1 个 | 多个 |
| 触发频率 | 每次后采样(需满足阈值) | 每轮查询结束 |
| 主要用途 | **服务于上下文压缩** | 跨会话知识保留 |
| 记忆提取者 | Fork Agent(仅 FileEdit) | Fork Agent(Read/Write/Edit/Grep) |
| 格式 | 10个固定章节 | 自由格式 + frontmatter |
### 5.2 触发阈值
```typescript
// 默认配置(可通过 GrowthBook tengu_sm_config 远程调整)
const defaults = {
minimumMessageTokensToInit: 10_000, // 上下文达到 10K tokens 才激活
minimumTokensBetweenUpdate: 5_000, // 每增长 5K tokens 更新一次
toolCallsBetweenUpdates: 3, // 且至少 3 次工具调用
}
// 触发条件:
// (token 阈值满足 AND 工具调用阈值满足)
// OR (token 阈值满足 AND 最后一轮助手消息无工具调用)
```
### 5.3 会话记忆模板(10 个固定章节)
```markdown
# Session Memory
## Session Title
_Brief description of what this session is about_
## Current State
_What is the current status of the work_
## Task specification
_Detailed description of the current task requirements_
## Files and Functions
_Key files and functions being worked on_
## Workflow
_Steps being followed or processes in use_
## Errors & Corrections
_Errors encountered and how they were resolved_
## Codebase and System Documentation
_Important codebase patterns, conventions, and system behavior_
## Learnings
_Insights gained during this session_
## Key results
_Important outputs, measurements, or achievements_
## Worklog
_Chronological log of actions taken_
```
### 5.4 大小限制
```typescript
const MAX_SECTION_LENGTH = 2_000 // 每个章节最大 2K tokens
const MAX_TOTAL_SESSION_MEMORY_TOKENS = 12_000 // 整个文件最大 12K tokens
```
### 5.5 与压缩的集成
Session Memory 是上下文压缩的优先路径(参见 `sessionMemoryCompact.ts`):
- 自动压缩触发时,优先尝试用 Session Memory 作为摘要
- 保留最近 10K-40K tokens 的消息
- 比传统压缩快得多(不调用 LLM),且摘要质量更可预测
### 5.6 自定义
用户可以自定义模板和提示词:
- 模板:`~/.claude/session-memory/config/template.md`
- 提示词:`~/.claude/session-memory/config/prompt.md`(支持 `{{variableName}}` 替换)
---
## 6. 团队记忆同步
### 6.1 前置条件
同时满足才启用:
1. `TEAMMEM` 编译时特性开关开启
2. `isTeamMemoryEnabled()` = true(`tengu_herring_clock` GrowthBook 开关)
3. 第一方 OAuth + 同时拥有 `INFERENCE_SCOPE` 和 `PROFILE_SCOPE`
4. Git remote 是 github.com(非 GitHub 仓库不同步)
### 6.2 API 端点
```
基础 URL: {baseUrl}/api/claude_code/team_memory?repo={owner/repo}
```
| 方法 | 参数 | 用途 | 关键状态码 |
|------|------|------|:----------:|
| GET | `repo={slug}` | 拉取全部团队记忆 | 200 / 304 / 404 |
| GET | `repo={slug}&view=hashes` | 仅拉取哈希(轻量探测) | 200 / 404 |
| PUT | `repo={slug}` | 上传记忆条目(upsert) | 200 / 412 / 413 |
**认证头:** `Authorization: Bearer {oauthToken}`
### 6.3 同步协议
#### 拉取(Pull)
```
1. GET 请求,携带 ETag(条件请求)
2. 304 = 未变化,跳过
3. 200 = 有更新:
a. 对每个条目验证路径(防遍历攻击)
b. 跳过 >250KB 的文件
c. 跳过本地内容已匹配的文件
d. 并行写入本地文件系统
e. 刷新 serverChecksums
```
#### 推送(Push — Delta 上传 + 乐观锁)
```
1. readLocalTeamMemory(): 遍历 team/ 目录
→ 每个文件扫描秘密(30种规则)
→ 跳过 >250KB 的文件
→ 计算 SHA-256 哈希
2. 计算 delta:仅本地哈希与 serverChecksums 不同的 key
3. 分批上传:贪心装箱,每批 ≤ 200KB (MAX_PUT_BODY_BYTES)
4. 每批携带 If-Match 头(乐观锁)
5. 冲突处理:
412 Conflict → 探测 ?view=hashes → 刷新 serverChecksums → 重算 delta → 重试(最多 2 次)
413 Too Many → 学习 serverMaxEntries 上限,截断后重试
6. 冲突策略:本地优先(local-wins)
→ 当前用户正在编辑的内容覆盖服务端
```
### 6.4 文件监听器
```typescript
// watcher.ts
fs.watch(teamMemDir, { recursive: true })
// macOS: FSEvents(O(1) 文件描述符)
// Linux: inotify(O(子目录数))
// 2 秒去抖:最后一次变更后 2 秒才触发推送
```
**推送抑制:** 永久失败(no_oauth、no_repo、4xx 非 409/429)后,抑制后续推送,直到发生文件删除(恢复动作)或会话重启。
### 6.5 团队 vs 私有的作用域划分
源码注入的系统提示中,每种记忆类型都带有 XML 作用域标签:
```xml
user
always private
...
project
strongly bias toward team
...
```
额外安全要求:
```
MUST avoid saving sensitive data within shared team memories
```
---
## 7. 秘密扫描保护
### 7.1 双层防护
| 层 | 时机 | 文件 | 行为 |
|----|------|------|------|
| 写入时拦截 | FileWrite/FileEdit 调用 | `teamMemSecretGuard.ts` | 阻止写入,返回错误 |
| 上传前扫描 | pushTeamMemory 读取本地文件 | `secretScanner.ts` | 跳过该文件,不上传 |
### 7.2 检测的 30 种秘密模式
**云服务商:**
- AWS Access Token(A3T/AKIA/ASIA/ABIA/ACCA 前缀)
- GCP API Key(AIza 前缀)
- Azure AD Client Secret
- DigitalOcean PAT / Access Token
**AI API:**
- Anthropic API Key(`sk-ant-api03-` 前缀,运行时拼接避免自身匹配)
- Anthropic Admin API Key(`sk-ant-admin01-`)
- OpenAI API Key(`sk-proj`/`svcacct`/`admin` + `T3BlbkFJ` 标记)
- HuggingFace Access Token(`hf_`)
**版本控制:**
- GitHub PAT / Fine-grained PAT / App Token / OAuth / Refresh Token
- GitLab PAT / Deploy Token
**通信平台:**
- Slack Bot/User/App Token(`xoxb-`/`xoxp-`/`xapp-`)
- Twilio API Key
- SendGrid API Token
**开发工具:**
- npm Access Token
- PyPI Upload Token
- Databricks API Token
- HashiCorp Terraform API Token
- Pulumi API Token
- Postman API Token
**可观测性:**
- Grafana API Key / Cloud API Token / Service Account Token
- Sentry User/Org Token
**支付:**
- Stripe Access Token(`sk_test`/`live`/`prod` 或 `rk_`)
- Shopify Access Token / Shared Secret
**密码学:**
- PEM 格式私钥(`BEGIN/END PRIVATE KEY` 块)
### 7.3 设计原则
```typescript
// 匹配到的秘密值永远不被记录或返回——只返回规则 ID 和人类可读标签
// Anthropic API key 前缀在运行时拼接,避免匹配自身的 excluded-strings 检查:
const prefix = ['sk', 'ant', 'api'].join('-')
```
---
## 8. KAIROS 模式的记忆(每日日志)
当 KAIROS(AI 助手模式)激活时,记忆范式完全改变:
```
普通模式:写独立文件 + 更新 MEMORY.md 索引
KAIROS 模式:追加到 logs/YYYY/MM/YYYY-MM-DD.md 日志文件
```
- 只追加,不编辑已有内容
- 每日一个文件,按日期路径组织
- 由单独的 `/dream` 技能在夜间蒸馏日志为主题文件和 MEMORY.md
- 提示词中使用 `YYYY-MM-DD` 占位符而非实际日期(因为提示词被缓存,日期变化不会触发失效)
---
## 9. 记忆系统注入的完整系统提示词
### 9.1 个人模式(auto memory)
```
# auto memory
You have a persistent, file-based memory system at ``.
This directory already exists — write to it directly with the Write tool.
You should build up this memory system over time so that future conversations
can have a complete picture of who the user is, how they'd like to collaborate
with you, what behaviors to avoid or repeat, and the context behind the work.
[如果用户要求记住 → 立即保存]
[如果用户要求忘记 → 找到并删除]
## Types of memory
[4种类型,每种含 description/when_to_save/how_to_use/examples]
## What NOT to save in memory
[6类排除项]
## How to save memories
Step 1: 写入文件(带 frontmatter)
Step 2: 在 MEMORY.md 中添加索引行
## When to access memories
- 看起来相关时
- 用户明确要求时(必须访问)
- 用户说"忽略记忆"时,假装 MEMORY.md 为空
## Before recommending from memory
- 提到文件路径 → 检查文件是否存在
- 提到函数/标志 → grep 搜索
- 用户要行动 → 先验证
## Memory and other forms of persistence
- 实施方案 → 用 Plan,不用记忆
- 当前对话步骤 → 用 Tasks,不用记忆
## Searching past context
[grep 记忆文件,或搜索会话 transcript]
## MEMORY.md
[实际的 MEMORY.md 内容,或"当前为空"]
```
### 9.2 团队模式额外内容
在个人模式基础上增加:
```
## Memory scope
- 私有记忆: — 你的个人偏好、反馈
- 团队记忆: — 项目上下文、外部引用
[类型定义中增加 XML 标签]
额外安全规则:不得在团队记忆中保存敏感数据
```
---
## 10. 团队记忆的路径安全(深度防御)
`teamMemPaths.ts` 是整个记忆系统中安全措施最密集的文件:
### 10.1 自定义错误类
```typescript
class PathTraversalError extends Error {
name = 'PathTraversalError'
}
```
### 10.2 sanitizePathKey — 服务端提供的相对路径清理
```typescript
function sanitizePathKey(key: string): string {
// 1. 拒绝 null 字节
// 2. URL 编码遍历检测:解码 %2e%2e%2f 等
// 3. Unicode 规范化攻击:全角字符 \uFF0E\uFF0E\uFF0F → ../
// 4. 拒绝反斜杠(Windows 路径遍历)
// 5. 拒绝绝对路径
}
```
### 10.3 realpathDeepestExisting — 符号链接解析
```typescript
async function realpathDeepestExisting(path: string): Promise {
// 逐级向上 realpath() 直到成功
// 检测悬挂符号链接(link 存在但 target 不存在)
// → 安全威胁:writeFile 会跟随链接在 team 目录外创建文件
// 检测符号链接循环(ELOOP)→ PathTraversalError
// 不可恢复的错误(EACCES, EIO)→ fail-closed
}
```
### 10.4 validateTeamMemWritePath — 双重验证
```
写入团队记忆文件前的完整验证链:
第1遍:字符串级
1. Null 字节检查
2. path.resolve() 解析
3. startsWith(teamDir) 验证
第2遍:符号链接级
4. realpathDeepestExisting() 解析实际路径
5. isRealPathWithinTeamDir() 验证实际路径在团队目录内
通过 → 返回解析后的路径
失败 → 抛出 PathTraversalError
```
### 10.5 前缀攻击防护
```typescript
// 团队目录路径以分隔符结尾:/foo/team/
// 这样 /foo/team-evil/ 不会通过 startsWith 检查
```
---
## 11. 记忆的生命周期全景
```
会话开始
│
├─ loadMemoryPrompt()
│ → 读取 MEMORY.md → 注入系统提示
│
├─ initSessionMemory()
│ → 注册后采样钩子
│
├─ startTeamMemoryWatcher()
│ → 拉取服务端 → 启动文件监听
│
▼
每轮对话
│
├─ findRelevantMemories(query)
│ → 扫描文件 → Sonnet 选择 → 返回最多 5 条
│ → 新鲜度标注(>1天 → 加过期警告)
│
├─ [模型可能直接读/写记忆文件]
│ → 写入团队记忆 → checkTeamMemSecrets() 拦截秘密
│ → 文件监听触发 → 2秒后推送到服务端
│
├─ Session Memory 后采样钩子
│ → 检查阈值 → Fork Agent 更新单文件
│
├─ 模型最终响应(无工具调用)
│ → Stop Hooks → executeExtractMemories()
│ → 互斥检查 → Fork Agent 提取 → 更新持久记忆文件
│
▼
自动压缩触发时
│
├─ trySessionMemoryCompaction()(优先路径)
│ → 用 Session Memory 内容作为摘要
│ → 保留最近 10K-40K tokens 的消息
│
├─ compactConversation()(回退路径)
│ → Fork Agent 生成 9 章节结构化摘要
│
▼
会话结束
│
├─ drainPendingExtraction()
│ → 等待进行中的记忆提取完成
│
└─ 团队记忆推送最后一批变更
```
---
## 12. 关键设计决策总结
| 决策 | 原因 |
|------|------|
| 记忆文件是独立的 .md 文件,不是数据库 | 用户可以直接编辑、Git 追踪、跨工具使用 |
| MEMORY.md 是索引不是记忆 | 防止单文件膨胀,支持截断不丢核心内容 |
| 自动提取在 Stop Hook 中即发即忘 | 不阻塞主对话循环 |
| 互斥检查(主代理 vs 自动提取) | 防止覆盖用户显式保存的内容 |
| 召回用 Sonnet 不用 Haiku | 需要理解语义相关性,Haiku 不够准确 |
| 新鲜度用"X days ago"不用 ISO 时间 | 模型对相对时间的推理比绝对时间好 |
| 项目设置排除 autoMemoryDirectory | 防止恶意仓库劫持写入路径 |
| 团队记忆双重路径验证 | 符号链接攻击需要在文件系统层面检查 |
| 秘密模式在运行时拼接 | 避免自身的 excluded-strings 检查 |
| 本地优先的冲突策略 | 用户正在编辑 = 最新意图 |
| 断路器(MAX_CONFLICT_RETRIES = 2) | 防止推送冲突的无限重试 |
---
*来自:AI超元域 | B站频道:https://space.bilibili.com/3493277319825652*
*基于 Claude Code 源码逆向分析,2026-03-31*