第 8 期:Skill 2 — Smart Explore(智能代码探索)

⏱ 预计阅读 12 分钟 更新于 2026/5/7
💡 进群学习加 wx: agentupdate
(申请发送: agentupdate)

本期场景:博客项目已经有 20+ 个文件了。你想让 Claude 理解 src/api/ 目录下的 API 结构。如果逐个 read_file,20 个文件 × 平均 200 行 = 4,000 行代码 = ~60,000 tokens。有没有更聪明的方式?


8.1 问题:read_file 太贵了

传统方式下,Claude 要理解一个文件,必须读取全部内容:

read_file("src/api/comments.ts")
→ 返回 500 行完整代码
→ 消耗 ~8,000 tokens
→ Claude 其实只需要知道"这个文件有哪些函数、每个函数做什么"

Smart Explore 的核心理念:给 Claude 一把"X 光机",让它看到代码的骨架结构,而不是每一行细节。


8.2 三个 MCP 工具

工具 1:smart_search — 语义代码搜索

基于 AST(抽象语法树)的代码搜索,比 grep 更懂代码结构。

smart_search(
  query: "评论",              // 搜索什么(必填)
  path: "src/api",           // 在哪个目录搜(必填)
  file_pattern: "*.ts"       // 文件类型过滤(可选)
)

返回:匹配的函数名、类名、变量名及其位置

src/api/comments.ts
  ├── createComment (line 15) - 创建评论
  ├── deleteComment (line 45) - 删除评论
  └── getCommentsByPost (line 72) - 获取文章评论

src/api/notifications.ts
  └── notifyOnComment (line 23) - 评论通知

对比 grep:grep 会返回每一行包含"评论"二字的代码,可能是注释、字符串、变量名混在一起,Token 消耗大且噪声高。

工具 2:smart_outline — 文件骨架透视

只返回文件的结构骨架:导出的函数签名、类定义、接口、类型 —— 不包含函数体实现。

smart_outline(
  filepath: "src/api/comments.ts"  // 文件路径(必填)
)

返回(~350 tokens):

// src/api/comments.ts - 文件概览

export async function createComment(postId: string, body: CreateCommentInput): Promise<Comment>
export async function deleteComment(commentId: string, userId: string): Promise<void>
export async function getCommentsByPost(postId: string, page: number): Promise<PaginatedComments>
export async function updateComment(commentId: string, body: UpdateCommentInput): Promise<Comment>

// 被引用的类型
interface CreateCommentInput { content: string; authorId: string }
interface UpdateCommentInput { content: string }
interface PaginatedComments { items: Comment[]; total: number; page: number }

对比 read_file:读取完整文件要 ~8,000 tokens,smart_outline 只需 ~350 tokens。节省 95%

工具 3:smart_unfold — 精准展开

当 Claude 通过 outline 知道了文件结构后,对某个特定函数感兴趣,可以只展开那一个函数的完整代码。

smart_unfold(
  filepath: "src/api/comments.ts",  // 文件路径(必填)
  entity_name: "createComment",     // 函数/类名(必填)
  line_start: 15                    // 起始行号(必填)
)

返回(~200 tokens):

export async function createComment(postId: string, body: CreateCommentInput): Promise<Comment> {
  // 验证输入
  const validated = commentSchema.parse(body);
  
  // 检查文章是否存在
  const post = await prisma.post.findUniqueOrThrow({ where: { id: postId } });
  
  // 创建评论
  const comment = await prisma.comment.create({
    data: {
      content: validated.content,
      authorId: validated.authorId,
      postId: post.id,
    },
    include: { author: true },
  });
  
  // 触发通知
  await notifyOnComment(comment);
  
  return comment;
}

8.3 为什么用 AST 而不是 grep?

Smart Explore 底层使用 Tree-sitter 解析器来理解代码的语法结构。

graph LR
    subgraph "grep 方式"
        G1["搜索 'comment'"] --> G2["逐行文本匹配"]
        G2 --> G3["返回所有包含
'comment' 的行"] G3 --> G4["混杂: 注释、字符串、
变量名、函数名..."] end subgraph "AST 方式 (Smart Explore)" A1["搜索 'comment'"] --> A2["解析语法树"] A2 --> A3["识别代码结构:
函数、类、接口、类型"] A3 --> A4["只返回有意义的
代码实体"] end G4 --> R1["噪声高 ❌
Token 浪费"] A4 --> R2["精准 ✅
Token 节省"] style R1 fill:#ef4444,color:#fff style R2 fill:#10b981,color:#fff
维度 grep Smart Explore (AST)
理解代码结构 ❌ 不理解 ✅ 知道什么是函数、类、接口
返回结果 所有匹配行(含无关噪声) 只返回代码实体(函数签名等)
Token 消耗 高(每匹配行都返回) 低(只返回骨架信息)
跨文件导航 需要对每个文件单独搜索 一次搜索覆盖整个目录

8.4 Token 对比实验

假设博客项目的 src/api/comments.ts 有 500 行代码:

方法 Token 消耗 获得的信息
read_file("comments.ts") ~8,000 全部 500 行代码
smart_outline("comments.ts") ~350 4 个函数签名 + 3 个类型定义
smart_unfold("comments.ts", "createComment", 15) ~200 1 个函数的完整实现
outline + unfold 1 个函数 ~550 全局结构 + 1 个函数详情

节省率:93%(550 vs 8,000)

如果 Claude 需要理解整个 src/api/ 目录(20 个文件):

方法 Token 消耗
逐个 read_file 20 × 8,000 = 160,000
逐个 smart_outline 20 × 350 = 7,000
节省率 95.6%

8.5 Smart Explore 的三步使用模式

graph TD
    A["想理解一个项目/目录的结构"] --> B["Step 1: smart_search
搜索关键词,定位相关文件"] B --> C["Step 2: smart_outline
查看各文件骨架,找到目标函数"] C --> D["Step 3: smart_unfold
只展开需要深入了解的函数"] B1["消耗: ~200 tokens"] --> B C1["消耗: ~350 tokens/文件"] --> C D1["消耗: ~200 tokens/函数"] --> D style A fill:#6366f1,color:#fff style D fill:#10b981,color:#fff

8.6 支持的语言

Smart Explore 通过 Tree-sitter 支持的语言:

语言 解析器
TypeScript / JavaScript tree-sitter-typescript
Python tree-sitter-python
Go tree-sitter-go
Rust tree-sitter-rust
Java tree-sitter-java
Ruby tree-sitter-ruby

可以在 .claude-mem.json 中配置自定义解析器。


实操练习

  1. 确保博客项目已有多个 API 文件

  2. 让 Claude 用 Smart Explore 理解项目结构:

    • "帮我梳理一下 src/api/ 下所有文件的功能"
  3. 观察 Claude 的工具调用顺序 —— 它应该先 outline 全部文件,再对感兴趣的函数 unfold

  4. 对比:让 Claude 再用 read_file 读所有文件一次,感受 Token 差异


下期预告

Memory Search 搜历史,Smart Explore 读代码。但如果你的项目历史太长(500+ 条 Observations),即使搜索也不够精准。下一期介绍 Knowledge Agent —— 把散乱的历史记忆"打包压缩"成一个可问答的知识胶囊。

➡️ 第 9 期:Skill 3 — Knowledge Agent 知识库代理