第 8 期:Skill 2 — Smart Explore(智能代码探索)
(申请发送: 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:#fff8.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 中配置自定义解析器。
实操练习
确保博客项目已有多个 API 文件
让 Claude 用 Smart Explore 理解项目结构:
- "帮我梳理一下 src/api/ 下所有文件的功能"
观察 Claude 的工具调用顺序 —— 它应该先 outline 全部文件,再对感兴趣的函数 unfold
对比:让 Claude 再用 read_file 读所有文件一次,感受 Token 差异
下期预告
Memory Search 搜历史,Smart Explore 读代码。但如果你的项目历史太长(500+ 条 Observations),即使搜索也不够精准。下一期介绍 Knowledge Agent —— 把散乱的历史记忆"打包压缩"成一个可问答的知识胶囊。