Skip to content
源码分析手册

Magic Docs:自主文档维护与同步

一句话讲清楚

Magic Docs 是 Claude Code 提供的一种“自生长文档”方案。用户只需在 Markdown 文件的首行添加一个特殊的头部标记(如 # MAGIC DOC: 系统架构),Claude Code 就会在后台持续追踪对话中的关键变更,并在交互间隙自动更新这些文档。

不同于 Auto Memory 这种分散在 .claude/memory 里的知识库,Magic Docs 通常是项目代码库中已有的、面向人类读者的文档文件(如 API.md, DEPLOY.md)。Magic Docs 旨在通过后台代理消除“代码已改,文档未动”的同步鸿沟。

实现机制

Magic Docs 的核心逻辑位于 src/services/MagicDocs/magicDocs.ts

  1. 检测与注册机制 (Detection & Registration)

    • 正则表达式触发:通过 MAGIC_DOC_HEADER_PATTERN 检测文件首行。
    • 指令提取:如果首行之后紧跟着一段斜体文字(如 *请侧重描述组件间的数据流*),detectMagicDocHeader 会将其提取为 instructions(额外指令),作为更新文档时的约束。
    • 按需追踪:系统并不是遍历全盘寻找 Magic Docs,而是通过 registerFileReadListener 在任何工具(如 FileReadTool)读取文件时进行拦截。一旦发现标记,立即通过 registerMagicDoc 将其加入追踪列表(trackedMagicDocs)。
  2. 触发时机与子代理 (Update Loop)

    • Post-Sampling 钩子:Magic Docs 注册了一个 updateMagicDocs 钩子,它在每次模型回复(Sampling)结束后执行。
    • 空闲检测:为了不干扰主对话逻辑,updateMagicDocs 会检查 hasToolCallsInLastAssistantTurn。只有在模型没有产生新的工具调用(即对话处于“空闲/确认”状态)时,才会启动更新。
    • 专职代理getMagicDocsAgent 定义了一个专门的代理。这个代理被严格限制只能使用 FILE_EDIT 工具,且只能操作对应的 Magic Doc 文件。
  3. Prompt 构建与整合buildMagicDocsUpdatePrompt 会将当前对话的完整上下文、文档的当前内容以及提取出的 instructions 喂给子代理,让子代理判断本次对话中是否有值得沉淀到该文档中的新知识。

别踩这些坑

  • 权限沙盒:Magic Doc 子代理的 canUseTool 实现(行 172-192)是一个极佳的安全示例。它通过动态闭包强制限定代理只能对特定 filePath 执行 FILE_EDIT 操作,任何对其它文件的写入尝试都会被拦截。
  • Ant-Only 限制:目前版本的 initMagicDocs 中包含了一个明显的限制:if (process.env.USER_TYPE === 'ant')。这意味着在开源版本中,这一特性可能需要手动开启或通过设置 USER_TYPE=ant 来激活其监听器。
  • 存储位置:Magic Docs 是原位更新(In-place update)的。这意味着它直接修改你的源代码文件,因此建议在 Git 仓库中使用,以便随时对比和回滚。

继续探索

  • 查看 src/services/MagicDocs/prompts.ts 了解如何编写让模型能够精准识别文档更新点的提示词。
  • 研究 src/utils/hooks/postSamplingHooks.ts 了解 Claude Code 的各种生命周期钩子。

源码锚点

  • claude-code-opensource/src/services/MagicDocs/magicDocs.ts: 所有的检测、注册与更新循环实现。
📄 src/services/MagicDocs/magicDocs.ts — 所有的检测、注册与更新循环实现。L21-24 of 255
typescript
  type REPLHookContext,
  registerPostSamplingHook,
} from '../../utils/hooks/postSamplingHooks.js'
import {
  • claude-code-opensource/src/tools/FileReadTool/FileReadTool.ts: 注册监听器的源头,负责 Magic Docs 的“初次发现”。
📄 src/tools/FileReadTool/FileReadTool.ts — 注册监听器的源头,负责 Magic Docs 的“初次发现”。L16-19 of 1184
typescript
  type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
  getFileExtensionForAnalytics,
} from '../../services/analytics/metadata.js'
import {
  • claude-code-opensource/src/utils/fileStateCache.ts: 用于在更新文档前清理缓存,确保读取到的是最新内容。
📄 src/utils/fileStateCache.ts — 用于在更新文档前清理缓存,确保读取到的是最新内容。L4-15 of 143
typescript
export type FileState = {
  content: string
  timestamp: number
  offset: number | undefined
  limit: number | undefined
  // True when this entry was populated by auto-injection (e.g. CLAUDE.md) and
  // the injected content did not match disk (stripped HTML comments, stripped
  // frontmatter, truncated MEMORY.md). The model has only seen a partial view;
  // Edit/Write must require an explicit Read first. `content` here holds the
  // RAW disk bytes (for getChangedFiles diffing), not what the model saw.
  isPartialView?: boolean
}

基于 Claude Code v2.1.88 开源快照的深度分析