关于 code-search
按问题类型和语言支持情况,将代码搜索任务分配到固定工具阶梯的技能。它指导开发者选择语义搜索、ripgrep、grep 或 Git 历史查询,避免重复无效搜索。
主要功能
- 01每个会话探测一次工具
- 02按问题类型选择搜索方式
- 03语义与文本搜索指引
- 04Git 历史查询指引
- 05命中后读取精确范围
适用场景
- 01查找定义与调用方
- 02跨文件类型搜索文本
- 03查看模块 API
- 04检查旧版本代码
MCP 相关
在仓库语言受支持且 Serena 可用时,建议用 Serena MCP 工具进行结构搜索。其他搜索则使用文本搜索或 Git 工具。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ ctrlcarlitos/ skills --skill code-search安装后在 Claude Code 中输入/code-search确认已加载。
附带文件evals/evals.jsonevals/trigger-eval.json
详细介绍
代码搜索:选定阶梯,然后逐级向下
语义工具(语言服务器)在覆盖代码时,只需一次调用就能回答“谁调用了这个函数”。如果它们无法覆盖,就会什么也找不到;更费时的错误是继续换个说法重复提问。要求“始终先查询图谱/符号服务器”的仓库指令,是针对其覆盖的语言编写的,不一定适用于你当前查看的文件。创建这项技能,就是为了让你根据证据一次性判断哪些工具能看到眼前的代码,然后沿着固定的阶梯逐级向下,而不是反复循环。
1. 每个会话探测一次,记住结果
第一次需要在仓库中搜索时执行此操作,而不是每次提问都执行。将结果记在工作笔记中,这样后续问题就可以直接跳到第 3 步。
| 阶梯 | 探测方式 | 适用条件 |
|---|---|---|
| serena | 列出了 serena MCP 工具,且仓库的主要语言有语言服务器(Go、TypeScript/JavaScript、Python、Rust、Java、C#、C/C++、Ruby、PHP、Kotlin、Elixir) | 项目已针对该语言激活。配置、脚本和文档仓库没有 LSP:此类仓库跳过 serena。 |
| rg | 在 Claude Code 中始终可用(Grep 工具就是 ripgrep);在 shell 中运行 rg --version | 适用于任何文件类型,会遵循 .gitignore,速度足够快,可以进行穷尽搜索。 |
| grep | grep --version | 仅在 rg 不可用时(例如精简容器、远程机器),或必须搜索 rg 会忽略的路径且无法使用 rg --no-ignore -uu 时使用。 |
还有两个工具不属于阶梯,但适用于特定问题:
- 当问题涉及尚未检出的标签、发布版本或提交时,使用
git grep <pattern> <ref>和git show <ref>:<path>。不要检出该版本或读取工作树。 - 当问题是“此文件公开了什么”时,使用 serena
get_symbols_overview——这比读取文件便宜得多。
2. 对问题分类
| 类型 | 示例 | 需要 |
|---|---|---|
| 结构类 | X 定义在哪里、谁调用 X、什么调用什么、修改 X 的影响范围 | 符号感知工具:serena |
| 文本类 | 某个字面值或正则表达式的所有匹配项、错误字符串、标志名称、配置键、跨多种文件类型的任意内容 | rg |
| API 表面 | 此文件或模块公开了什么 | 符号概览 |
| 历史类 | v1.2 时的内容是什么样、此行何时更改 | git grep、git show、git log -S |
| 非代码 | 配置、脚本、模板、文档、YAML、Markdown | rg。语义工具无法查看这些内容。 |
穷尽性问题(“每个调用者”“所有匹配项”)属于文本类,即使听起来像结构类也是如此:符号服务器的引用搜索仍可能漏掉动态分派。请使用 rg 并统计结果。
3. 选择工具
| 问题类型 | 且探测结果为 | 则使用 |
|---|---|---|
| 结构类 | serena 可用 | serena find_symbol、find_referencing_symbols、find_declaration |
| 结构类 | serena 不可用 | 用 rg 搜索定义(rg -n "func X\b"/rg -n "class X\b"),再用 rg 搜索名称以查找调用者,然后阅读匹配结果 |
| 文本类,任何文件类型 | rg 可用 | 使用带 -n 的 rg,并通过 --glob 或指定路径缩小范围,不要改用其他工具 |
| 文本类 | rg 不可用 | 使用带 --include 的 grep -rn |
| API 表面 | serena 可用 | get_symbols_overview |
| 历史类 | git 仓库 | git grep -n <pattern> <ref>、git show <ref>:<path>、git log -S<string> |
语言服务器的引用搜索效果取决于它能否解析引用。它能找到直接调用,但可能漏掉通过重新赋值的引用进行的调用(var submit = approval.SubmitOnDemand)或动态分派。当“没有调用者”会影响你接下来的行动时,请先用 rg 确认,再相信搜索结果。
使用已有的字面标识符(符号、错误字符串、文件名)作为查询内容。rg 对字面匹配的排序高于自然语言查询;使用字面内容也能让空结果变得有意义,而不是含糊不清。
4. 命中后,读取精确范围
上面的每一层都会给出一个文件和行号。在该范围内打开文件
(sed -n 120,160p,或使用带偏移量和限制的 Read 工具)。精确命中后再读取整个文件,会浪费搜索带来的成果。如果结果显示“+N more lines”或片段被截断,请扩展读取范围,不要重新搜索。
防止循环
以下规则最能节省时间,因为每条规则都能阻止一种看似有效、实则无益的模式。
- serena 返回一次空结果,就表示“此工具无法查看这段代码”。转到下一层。不要用同一工具换种说法重复提问。
- rg 的结果有两次过于宽泛,就说明模式太宽松。添加单词边界、
--glob或目录。不要转而使用语义工具,指望它替你筛选。 - 仓库指令、钩子或 MCP 消息催促你“先运行图查询/符号查询”,并不能推翻第 1 步。如果探测结果表明该工具在此处不可用,就在笔记中说明一次,之后忽略这些催促。
- 绝不要重复探测。探测结果在本次会话中一直有效,除非你自己激活了 serena 项目。
示例
已激活 serena 的 Go 服务。 任务:“为什么 Submit 会返回
'daemon unavailable'?”探测结果:已列出 serena MCP 工具,且已激活 Go。结构性问题,且有字面标识符:find_symbol "Submit"
会返回该函数及其范围;find_referencing_symbols 会给出两个调用位置。按范围读取每处内容。两次工具调用,不读取范围以外的文件内容。
包含 PowerShell、shell 和 chezmoi 模板的 dotfiles 仓库。 任务:“安装程序在哪里传递 guardrail 状态标志?”探测结果:这些语言没有 LSP,本次会话不使用 serena。带有字面内容的文本问题:在 *.tmpl 和 scripts/ 中搜索
-State enabled 和 --state enabled。找到四处命中,按行读取每处内容。符号服务在这里也不会返回任何结果——这些文件没有可供索引的符号。
你当前不在其版本上的一条发布错误字符串。 任务:“v0.23.1 在这里输出了什么?”历史查询:git grep -n "approval daemon unavailable" v0.23.1 -- cmd/,然后执行 git show v0.23.1:cmd/guardrail/plane.go | sed -n 280,320p。无需切换版本,也不读取工作树中的文件。