关于 deep-read
deep-read 是面向开发者的代码阅读技能,按六个阶段分析代码库,并要求结论附文件和行号引用。流程涵盖范围界定、执行追踪、逻辑分析与报告。
主要功能
- 01六阶段代码分析流程
- 02限制范围并确定性缩减
- 03追踪执行路径至终端操作
- 04分析逻辑、分支与副作用
- 05引用文件名和行号
适用场景
- 01调查代码流程的具体行为
- 02检查业务逻辑与边界情况
- 03梳理代码范围内的依赖关系
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ pfangueiro/ claude-code-agents --skill deep-read安装后在 Claude Code 中输入/deep-read确认已加载。
附带文件references/reading-strategies.md
详细介绍
深度阅读 — 代码库阅读引擎
以源代码为先的系统化分析协议。阅读实现,而不只是接口。每项发现都引用 file:line。
核心原则: 源代码才是事实依据。文档会出错,注释会过时,函数名称会误导。阅读实际代码。代码图或索引(LSP、代码图工具)可以加快代码定位,但其自身也可能是过时的快照,绝非事实依据。引用任何基于代码图或 LSP 的结果前,都要对照当前源代码核实。
协议
每次调用 /deep-read 时,严格按顺序执行以下 6 个阶段。绝不跳过任何阶段。每个阶段都设有门槛条件;只有满足条件后才能进入下一阶段。
阶段 1:范围 — 定义阅读目标
开始阅读前,先将目标缩小到可处理的范围。
- 将
$ARGUMENTS解析为阅读目标(模块、流程、问题或路径) - 阅读 CLAUDE.md 和 MEMORY.md,了解项目背景,但将其视为提示,而非事实
- 执行初步发现,以估算范围:
- 使用
Glob查找相关文件模式(**/*.ts、**/*.py等) - 使用
Grep搜索目标描述中的关键词 - 统计匹配文件数
- 使用
- 如果范围超过 50 个源文件,则以确定性方式缩小范围 — 此技能在分叉环境中运行,无法询问用户(参见 Fork 说明):
- 按中心性排序(候选集内的导入扇入度),若相同则按最近修改时间排序(
git log -1 --format=%ct -- <file>) - 保留排名最高的 49 个,其余舍弃(下方阶段 1 门槛严格要求少于 50 个)— 绝不随意抽样,也绝不放宽门槛以适应目标
- 在范围定义中记录上限(候选总数、保留数量、排序依据),并在报告中明确重申这一覆盖范围限制
- 如果保留的文件仍涵盖互不相关的子系统,则说明目标过于宽泛,无法连贯阅读:在报告中指出这一点,并列出后续
/deep-read应处理的更具体子目标,而不是把任意选取的部分呈现为整体
- 按中心性排序(候选集内的导入扇入度),若相同则按最近修改时间排序(
- 如果目标是一个问题(例如“佣金如何计算?”):
- 转换为具体搜索词
- 使用
Grep搜索领域术语,定位相关模块
- 如果目标是一个路径(例如
src/services/billing/):- 列出路径中的所有文件
- 确定入口点(导出的函数、路由处理程序、主文件)
输出: 范围定义,列出:
- 目标描述(1–2 句话)
- 文件列表(少于 50 个源文件)
- 如有缩小范围,列出所用上限(候选总数 → 保留数量、排序依据)
- 已确定的入口点
- 明确注明范围之外的区域
门槛: 范围已定义,且包含少于 50 个源文件。入口点已确定。继续。
阶段 2:MAP — 构建结构概览
在深入阅读代码之前,先了解代码的整体结构。
- 目录结构 — 梳理相关目录:
- 使用
Glob按文件类型和目录列出文件 - 记录组织模式(按功能、按层级或按领域)
- 使用
- 技术栈 — 从配置文件中识别(而不是从文档中):
- 阅读
package.json、Cargo.toml、go.mod、requirements.txt或同类文件 - 记录框架、关键依赖和构建工具
- 阅读
- 入口点 — 通过阅读实际文件来验证(不能只看文件名):
- 阅读路由定义、主文件和导出模块
- 阅读每个候选入口点的前 50 行
- 确认哪些文件是真正的入口点,哪些只是辅助文件
- 依赖关系图 — 梳理范围内的内部导入:
- 在范围内的文件中搜索 import/require 语句
- 建立整体认知:哪些内容调用哪些内容,哪些内容依赖哪些内容
- 找出核心文件(被其他文件导入次数最多的文件)
- 满足代码图启发式条件时(见下文“工具使用”),使用已索引的代码图查询(或 LSP 工作区符号)可以一次性返回模块结构和中心性,比逐一搜索导入并跨语言使用各自独立的工具更快;在采信排名之前,请对照源代码确认
- 配置和常量 — 阅读定义行为的文件:
- 配置文件、环境变量模式、常量、枚举和类型
- 这些内容对行为的影响不亚于代码本身
对于包含 20 个以上文件的范围,在 fork 中依次执行步骤 2–4——将每个步骤中彼此独立的 Glob/Grep/Read 调用分别合并到一条消息中,使其并行执行(见 Fork 说明)。
输出: 结构图,包含:
- 附有注释的目录布局
- 技术栈(依据配置,而非文档)
- 入口点(经阅读验证)
- 依赖流向图(文本形式)
- 按中心性排名的核心文件
检查门槛: 已通过阅读实际文件验证入口点。已梳理依赖流向。继续。
阶段 3:TRACE — 追踪执行路径
从入口点开始追踪代码。阅读路径中的每个文件。
- 选择主要执行路径,依据阅读目标确定:
- 针对流程(例如“支付处理”):从面向用户的入口点开始
- 针对模块:从其公共 API / 导出开始
- 针对问题:从最可能包含答案的代码开始
- 从入口点向前追踪:
- 使用 Read 工具完整阅读入口点文件
- 对遇到的每个函数调用、类实例化或模块导入:
- 定位其实现:使用 LSP 的
goToDefinition/outgoingCalls精确跳转一层,或在必要时使用 Grep;对于单次、逐语言 LSP 无法追踪的全仓库传递链或跨语言链,可查询代码图——但仅限满足“工具使用”中双重门槛启发式条件的情况(针对单个符号的追踪,即使跨语言,也应使用 LSP/Grep) - 使用 Grep 定位实现(而不只是类型签名)
- 完整阅读实现所在文件——代码图/LSP 边只会指向文件;门槛仍要求完整阅读该文件
- 定位其实现:使用 LSP 的
- 继续追踪,直到到达终端操作(数据库查询、API 调用、文件 I/O、返回值)
- 记录路径,以包含
file:line引用的链条表示:Request enters at routes/payments.ts:42 (POST /api/payments) -> calls PaymentService.processPayment() at services/payment.ts:87 -> validates input via PaymentSchema at schemas/payment.ts:15 -> calls StripeClient.charge() at clients/stripe.ts:34 -> constructs request at clients/stripe.ts:45-62 -> stores result via PaymentRepository.save() at repos/payment.ts:28 -> returns PaymentResponse at routes/payments.ts:58 - 追踪次要路径(如果阅读目标涉及多个流程):
- 错误路径、边缘情况、回退逻辑
- 由主要路径触发的事件处理程序、webhook、后台任务
- 记录每个分支点——条件、switch、功能标志:
- 哪些因素决定采用哪条路径?
- 阅读条件逻辑,不要只记下“此处存在条件判断”
输出: 完整的执行追踪路径,并为每个步骤标注 file:line 引用。
检查门槛: 至少完整追踪 1 条从入口到终端的路径。已完整阅读路径中的每个文件。继续。
阶段 4:深入阅读——逐行分析关键文件
这是核心阶段。彻底阅读关键文件,理解每一行业务逻辑。
- 从阶段 3 中识别关键文件——包含以下内容的文件:
- 业务逻辑(计算、规则、转换)
- 状态管理(变更、事务、副作用)
- 安全逻辑(身份验证、验证、访问控制)
- 数据转换(映射、筛选、聚合)
- 错误处理(catch 块、错误边界、恢复逻辑)
- 使用 Read 工具完整阅读每个关键文件:
- 不要略读——阅读整个文件
- 对于超过 500 行的文件:分段阅读,但必须读完所有部分
- 对互不依赖的文件并行发起 Read 调用
- 记录每个关键文件的信息:
- 用途: 根据代码(而非注释)说明此文件实际执行的操作
- 关键函数: 说明每个函数的逻辑,并附上引用:
calculateCommission(sale: Sale): number [billing/commission.ts:45-78] - 基本费率:sale.amount 的 5%(第 52 行) - 奖金档位:如果 sale.amount > 10000,则费率 += 2%(第 56 行) - 上限:佣金最高为 5000(第 62 行) - 按比例计算:乘以 daysInPeriod/30(第 67 行) - 返回值:四舍五入到小数点后 2 位(第 74 行) - 公式和条件: 写出实际的数学公式和逻辑,不要只做概述
- 状态变更: 说明发生了哪些变更,以及产生了哪些副作用
- 已处理的边界情况: 空值检查、边界限制、错误恢复
- 未处理的边界情况: 缺失的验证、未经检查的假设
- 交叉引用文件:
- 当文件 A 调用文件 B 时,验证 A 的预期与 B 的实现是否一致
- 记录接口约定与实现之间的任何不匹配
- 检查调用方的错误处理是否与被调用方抛出的错误相匹配
输出: 对每个关键文件进行详细分析,包括:
- 附有
file:line引用的函数级逻辑文档 - 明确写出的公式
- 记录条件和分支逻辑
- 列出状态变更和副作用
关卡: 已完整阅读步骤 1 中识别出的每个关键文件。已使用公式、条件和引用记录逻辑。继续。
阶段 5:CONNECT — 综合理解
退后一步,整体分析系统。使用 sequential-thinking MCP 进行结构化分析。
- 使用阶段 1-4 的所有证据,启动 sequential-thinking 思维链:
mcp__sequential-thinking__sequentialthinking({ thought: "Synthesizing understanding of <target>. Evidence from phases: ...", thoughtNumber: 1, totalThoughts: 8, nextThoughtNeeded: true }) - 识别代码库中的模式(至少 3 个):
- 架构模式(分层、依赖注入、事件驱动等)
- 编码约定(错误处理风格、命名模式、数据流模式)
- 隐含规则(通过约定而非代码强制维护的不变量)
- 反模式或技术债务
- 汇总结构线索——死代码、接口的所有实现者、依赖循环、扇入/扇出热点——如果已建立索引,则从代码图中发现这些线索;将其纳入综合分析,但在通过带有
file:line引用的实时源代码确认之前,不得将其作为任何发现
- 端到端映射数据流:
- 数据如何进入系统?
- 数据经历了哪些转换?(附
file:line引用) - 数据最终到达哪里?(数据库、API 响应、文件、事件)
- 识别风险和假设:
- 代码做出了哪些未经验证的假设?
- 如果这些假设不成立,会出现什么问题?
- 是否存在竞态条件、一致性缺口或安全问题?
- 如果阅读目标是一个问题,则回答最初的问题:
- 提供答案及完整的证据链
- 引用每个来源
使用 sequential-thinking 中的分支功能,探索对含义模糊代码的不同解读。
**输出:**综合分析,包括:
- 识别出 3 个以上模式,并附证据(
file:line) - 端到端数据流图
- 风险评估
- 对最初问题的回答(如适用)
**关卡:**至少完成 5 个推理步骤。至少识别出 3 个模式,并提供 file:line 证据。继续。
阶段 6:REPORT — 结构化交付成果
生成最终报告。每项论述都必须引用 file:line。
## Deep Read Report: <target>
### Scope
- **Target:** <what was analyzed>
- **Files analyzed:** <count> files, <count> read in full
- **Coverage limit:** <none, or: top <N> of <total> candidates by <ranking key>; remainder out of scope>
- **Entry points:** <list with file:line>
### Architecture Overview
<structural summary from Phase 2 — directory layout, tech stack, dependency flow>
### Execution Flow
<traced paths from Phase 3 — entry to terminal with file:line citations>
### Critical Logic
<detailed function-level analysis from Phase 4>
For each critical area:
- **What it does:** <plain language description>
- **How it works:** <formulas, conditions, logic with file:line>
- **State changes:** <what gets mutated>
- **Edge cases:** <handled and unhandled>
### Patterns & Conventions
<synthesized patterns from Phase 5>
1. <pattern> — evidence: <file:line>
2. <pattern> — evidence: <file:line>
3. <pattern> — evidence: <file:line>
### Data Flow
<end-to-end data flow map from Phase 5>
### Risks & Assumptions
<risk assessment from Phase 5>
### Key Findings
<concise bullet list of the most important discoveries>
- <finding> — <file:line>
### Answer
<if the reading target was a question, answer it here with full evidence>
**关卡:**所有部分均已填写。每项发现都引用 file:line。报告完成。
各阶段的工具使用
| 阶段 | 主要工具 | 并行与升级(分叉内) |
|---|---|---|
| 1. 确定范围 | Read、Glob、Grep、Bash(git log,用于按新近程度排序) | -- |
| 2. 绘制地图 | Glob、Grep、Read(配置、入口点)、LSP / 代码图(结构、中心性) | 将步骤 2-4 的查找批量放在一条消息中(20+ 个文件) |
| 3. 追踪 | Read(完整文件)、Grep(交叉引用)、LSP 调用层级、代码图(全仓库传递关系 / 聚合查询——见启发式规则) | 批量处理互相独立的 Grep / LSP 查找 |
| 4. 深入阅读 | Read(完整文件,并行读取) | -- |
| 5. 建立关联 | sequential-thinking MCP、代码图(聚合 / 死代码查询) | 复杂推理使用 deep-analysis 技能 |
| 6. 报告 | 结构化输出 | -- |
分叉说明:
/deep-read以分叉方式运行(context: fork),用于隔离上下文——完整文件读取和追踪不会进入主对话,只有报告会返回。分叉的子 Agent 无法使用Agent启动器或AskUserQuestion,因此本协议无需依赖它们:每个阶段都使用主要工具(Read/Glob/Grep/Bash/LSP/sequential-thinking),阶段 1 以确定性方式缩小范围,而不提问;全文所说的“并行”均指将互相独立的工具调用批量放在一条消息中,绝不启动 Agent。任何确实需要用户选择的事项,都会作为开放问题列入报告,而不会在运行过程中提问。
代码图加速器(可选,与工具无关)。 仅当以下两个条件都满足时,才值得为每个仓库建立一次索引代码图:(1) 仓库较大(数百个以上文件)或涉及多种语言;并且 (2) 问题涉及全仓库传递关系或聚合查询(完整影响范围、广泛重构、死代码、“X 的所有实现者”、架构概览)。只满足一个条件还不够——有针对性的追踪,即使跨越多种语言,或针对小型单语言仓库的聚合问题,都应使用 LSP/Grep/Read。否则,LSP(始终可用、单跳、不会过时)+ Grep + Read 更快。直接查询现有索引;如果索引不存在且两个条件都满足,应在报告中建议建立索引,而不是悄悄进行初始化。任何代码图工具都可以,例如 CodeGraphContext / cgc;它需要选择启用并按仓库使用,不由此框架提供或注册(安装方法请参阅工具自身的文档)。
反模式——此技能旨在避免的问题
| 不良习惯 | /deep-read 的应对方式 |
|---|---|
| 只读 README/CLAUDE.md 就认为完成了 | 阶段 1 将文档视为线索;阶段 3-4 会阅读源代码 |
| 只浏览文件头和导入项 | 阶段 4 要求逐行阅读并附上引用 |
| 总结时没有证据 | 每项论断都必须引用 file:line |
| 在第一个抽象层就停止 | 阶段 3 会追踪完整调用链,直至叶子函数 |
| 根据函数名称推断行为 | 阶段 4 会阅读实现并记录实际逻辑 |
| 给出“看起来像是在做 X”这类含糊描述 | 阶段 4 要求提供具体公式和条件 |
| 阅读类型/接口而不是实现 | 阶段 3 会使用 Grep 查找实现,而不只是签名 |
| 将图或索引查询结果当作事实 | 图和 LSP 是可能过时的快照;引用之前必须在实时源代码中确认每个命中项(file:line) |
| 跳过错误路径和边缘情况 | 阶段 3 会追踪次要路径;阶段 4 会记录边缘情况 |
范围示例
/deep-read payment processing flow from checkout to settlement
/deep-read src/services/billing/
/deep-read how are sales commissions calculated and distributed?
/deep-read the authentication and authorization system
/deep-read data pipeline from ingestion to reporting dashboard
/deep-read how does the caching layer work and when does it invalidate?
何时使用 /deep-read,何时使用其他工具
| 情况 | 使用 |
|---|---|
| 理解现有代码的工作方式 | /deep-read |
| 快速了解“这个函数是做什么的?” | 直接使用 Read 工具 |
| Bug、崩溃、错误或意外行为 | /investigate |
| 架构决策或权衡 | /deep-analysis |
| 决策前探索可选方案(“我们有哪些选择?”) | /diverge |
| 构建新功能 | /execute |
| 理解代码后再进行分析 | /deep-read 然后 /deep-analysis |
| 理解代码后再重新设计 | /deep-read 然后 /deep-analysis 然后 /execute |
| 熟悉陌生的代码库 | /deep-read |
| 在完整上下文下进行代码审查 | /deep-read 然后使用 code-quality agent |
参考资料
有关针对不同代码库类型的阅读策略和上下文管理方法,请参阅 references/reading-strategies.md。