关于 ast-index
ast-index 是面向多语言、多平台项目的 Rust 代码索引与搜索命令行工具,适合需要理解代码结构和追踪符号引用的开发者。它结合 SQLite 与 FTS5,并提供相关性排序、符号关系及 Git 历史排序能力。
主要功能
- 01跨多语言项目建立索引
- 02按意图或符号搜索代码
- 03查看定义、调用与继承关系
- 04按 Git 历史和依赖关系排序
- 05查找符号使用位置与文件
适用场景
- 01了解代码库中特定功能的实现
- 02重构前追踪符号的使用位置
- 03从多个同名实现中筛选候选项
- 04定位项目中的类、函数和测试
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ defendend/ claude-ast-index-search --skill ast-index安装后在 Claude Code 中输入/ast-index确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/android-commands.mdcpp-commands.mdcsharp-commands.mddart-commands.mdgo-commands.mdios-commands.mdmatlab-commands.mdmodule-commands.mdperl-commands.mdproto-commands.mdpython-commands.mdruby-commands.mdrust-commands.mdtypescript-commands.mdwsdl-commands.md详细介绍
ast-index - 多平台项目的代码搜索
快速的原生 Rust CLI,可使用 SQLite + FTS5 索引,在 Android/Kotlin/Java、iOS/Swift/ObjC、Dart/Flutter、TypeScript/JavaScript、Rust、Ruby、C#、Scala、PHP、Perl、Python、Go、C++ 和 Proto 项目中进行结构化代码搜索。
关键规则
任何代码搜索任务都必须始终先使用 ast-index。 以下规则为强制要求:
- ast-index 是主要搜索工具 — 在 grep、ripgrep 或 Search 工具之前使用它
- 根据已知信息选择命令:
- 你有一个意图或描述(“如何处理身份验证”“处理更新管理员”)→
ast-index explore "<query>"。它会按相关性排序并打印源码。 - 你有一个确切的标识符(
UserService、parseConfig)→ast-index search/symbol/class。需要定义主体时,在symbol中添加--with-content;不确定确切限定名称或类型时,在search中添加该选项。 - 如果多词查询没有字面匹配,
search本身会回退到explore排序,因此选错命令并不会造成严重问题 — 但对于问题,explore才是正确的首选调用。
- 你有一个意图或描述(“如何处理身份验证”“处理更新管理员”)→
- 不要重复搜索结果 — 如果 ast-index 找到了用法/实现,这就是完整答案
- ast-index 返回结果后,不要为了“完整性”再运行 grep
- 不要重新读取
--with-content返回的主体 — 成功返回的结果可替代通常的sed/awk/grep/rg或读取文件步骤。只有在主体被截断或不可用,或者需要定义之外的文本时,才使用这些工具。 - 仅在以下情况使用 grep/Search:
- ast-index 返回空结果
- 搜索正则表达式模式(ast-index 使用字面匹配)
- 搜索代码中的字符串字面量(
"some text")——usages和refs会跳过字符串和注释中的名称 - 搜索注释内容
原因: ast-index 的速度比 grep 快 17-69 倍(1-10ms,而 grep 为 200ms-3s),并且能返回结构化、准确的结果。
前置条件
使用前安装 CLI:
brew tap defendend/ast-index
brew install ast-index
在项目根目录初始化索引:
cd /path/to/project
ast-index rebuild
索引存储在 ~/Library/Caches/ast-index/<project-hash>/index.db(macOS)或 ~/.cache/ast-index/<project-hash>/index.db(Linux)。重建会生成全新索引并替换旧索引;具名子树和收集到的 Git 历史记录(hotspots --collect)会予以保留。
支持的项目
| 平台 | 语言 | 模块系统 |
|---|---|---|
| Android/Java | Kotlin、Java | Gradle (build.gradle.kts)、Maven (pom.xml) |
| iOS | Swift、Objective-C | SPM (Package.swift) |
| Web | TypeScript、JavaScript、React、Vue、Svelte | package.json |
| Rust | Rust | Cargo.toml |
| Ruby | Ruby、Rails、RSpec | Gemfile |
| .NET | C#、ASP.NET、Unity | *.csproj |
| Dart/Flutter | Dart | pubspec.yaml |
| Scala | Scala | Bazel (WORKSPACE, BUILD) |
| PHP | PHP | composer.json |
| Perl | Perl | Makefile.PL、Build.PL |
| Python | Python | 无(*.py 文件) |
| Go | Go | 无(*.go 文件) |
| Proto | Protocol Buffers (proto2/proto3) | 无(*.proto 文件) |
| WSDL | WSDL、XSD | 无(.wsdl、.xsd 文件) |
| C/C++ | C、C++ (JNI、uservices) | 无(.cpp、.h、*.hpp 文件) |
| Godot | GDScript | project.godot |
| 混合 | 以上全部 | 全部 |
项目类型会根据标记文件自动检测(build.gradle.kts、Package.swift、Makefile.PL 等)。Python、Go、Proto、WSDL 和 C++ 文件会与主要项目类型的文件一同编入索引。
不会索引或搜索压缩后的 JavaScript/CSS:文件名为 *.min.* 或 *-min.* 的 .js/.mjs/.cjs/.css 文件,或前 64 KiB 为压缩器输出的文件(代码行平均长度为 1000 字节以上,而非一条长字符串)。基于 grep 的命令也会跳过这些文件;对这类文件运行 outline/imports 时会打印 Skipped: minified file,而不是进行解析。设置 AST_INDEX_SKIP_MINIFIED=0 可关闭此过滤。
核心命令
探索(单次获取上下文)
explore - 为查询中最相关的符号排序,展示最佳文件
——提供类型或模块的大纲及行范围(其中的定义、用 → 标记选中的定义)、函数的源码(从磁盘实时读取)、
图邻居(调用者/子类),并按路径约定定位测试
——一次调用即可完成。若要了解某个领域,优先使用此工具,而不是反复搜索和读取;接下来读取大纲中某一行指向的代码片段。
与语言无关且能识别供应商(node_modules 中的 .d.ts 和跨技术栈匹配会降低排名,但不会删除)。
ast-index explore applicant merge MergeService # bag of symbol/file names
ast-index explore "how does auth session work" # natural-language question
ast-index explore PaymentService --rwr # --rwr: re-rank via call/inheritance graph
ast-index explore Repository --max-files 8 # cap source files shown (default 6)
ast-index explore Session request --rwr --format json
- 默认(Stage A)按词法匹配和多词印证进行排序。问题中的词也会连在一起读取(
pdf to html service可找到PdfToHtmlService),并用于匹配文件路径,因此可以通过 CamelCase 类的组成词找到该类;文件所命名的类型排名高于辅助项,而语句(has_many :x、scope、include)和仅包含命名空间的模块排名低于定义。问题中的词(how、does、work)会被忽略。 --rwr(Stage B)会在内存中构建调用/继承图,并按个性化 PageRank 重新排序,在“图邻居”部分展示调用者/子类。速度稍慢;适合关注谁调用了什么的场景。
通用搜索
search - 同时搜索文件、符号和模块。
ast-index search "Payment" # Finds files, classes, functions matching "Payment"
ast-index search "Payment" --with-content # Include matched symbol bodies
ast-index search "ViewModel" # Returns files, symbols, modules in ranked order
ast-index search "Store" --fuzzy # Fuzzy: exact → prefix → contains matching
ast-index search "Handler" --module "core/" # Search within a module
ast-index search "Handler" --with-content # Include matched symbol bodies
ast-index search "UserService" # Find Java/Spring services
ast-index search "@RestController" # Find Spring REST controllers (annotation search)
ast-index search "@GetMapping" # Find GET endpoint mappings
符号按层级排列:先是名称完全匹配,然后是名称最后一个 :: 或 . 段与查询匹配的符号(例如,查询 Invoice 会匹配 Billing::Invoice,查询 email 会匹配模式列 users.email),最后是部分匹配。在每个层级中,定义排在导入之前,项目代码排在 node_modules 之前;在部分匹配中,测试符号(测试文件、test_*、TestX)排在最后。
search --rank <preset> - 根据文件的 Git 历史和符号在依赖图中的位置,为“文件”和“符号”部分重新排序,并在每个结果旁附上说明其排名依据的档案。当问题不是“X 在哪里”,而是“这些 X 中哪个更合适”时使用:
ast-index search Service --fuzzy --module app/services/ --rank proven # a settled example to copy
ast-index search Merge --rank risky # dangerous to touch: many dependents + unstable history
ast-index search Import --rank hotspots # keeps being changed and fixed
ast-index search Import --rank hotspots --exclude-tests # same, spec/test files left out
ast-index search Event --module app/models/ --rank central # what the rest leans on (PageRank)
ast-index --format json search Merge --rank risky # rank.applied / rank.missing + per-result dossier
| 预设 | 分数 | 需要 |
|---|---|---|
proven | mean(1 − hotspot score, maturity, used 1/0) × substance(存根为 0.5)× lineage(基类不再有扩展时为 0.5) | hotspots --collect + graph build |
hotspots | 文件热点分数(提交次数、变更量、修复错误比例 pct) | hotspots --collect |
risky | 依赖者 pct × 热点分数 | 两者 |
central | PageRank pct | graph build |
- 相关性仍是首要因素:候选范围是普通排序中排名最高的 100 个项目符号;名称完全匹配始终排在部分匹配之前;在同一层级中,排序依据为
0.9 × score + 0.1 × 1/(1 + position/20)。文件路径匹配会根据匹配所在位置(文件名主体、文件名、目录)计算相关性。 - 历史记录按文件统计——同一文件中的所有符号共享该历史记录(输出中标为“文件历史”)。图数据按符号统计;文件结果会采用其最强符号的图数据。
- 缺失数据绝不会按零分参与排序:不会应用预设,结果保留普通顺序,输出会指出要运行的命令(JSON 中的
rank.missing[].command)。过时的图会触发警告。 - 第三方代码(
node_modules、.d.ts)不会计分,并会列在所有项目结果之后。 - 这些公式通过在一个包含 4 万个文件的单体仓库上回测下一年的错误修复情况来选定;
proven还参考了人工判断的“该复制哪一个”查询;相关数据见 USER_GUIDE.md(“搜索结果排序”)。数据表现安全,并不代表它就是一个好的范例:proven无法判断团队更偏好两种现存风格中的哪一种。
文件搜索
file - 按名称模式查找文件。
ast-index file "Fragment.kt" # Find files ending with Fragment.kt
ast-index file "ViewController" # Find iOS view controllers
符号搜索
symbol - 按名称查找符号(类、接口、函数、属性)。
ast-index symbol "PaymentInteractor" # Find exact symbol
ast-index symbol "PaymentInteractor" --with-content # Include its source body
ast-index symbol "Presenter" # Find all presenters
ast-index symbol "Store" --fuzzy # Fuzzy: exact → prefix → contains matching
ast-index symbol "Mapper" --in-file "payments/" --limit 10 # Scoped search
ast-index symbol "Mapper" --with-content # Include bounded source bodies
ast-index symbol "@Service" # Find all @Service annotations
命名空间类可通过短名称或完整名称查找:LedgerImporter 和
Billing::LedgerImporter 都能找到 class Billing::LedgerImporter(在
class、refs、hierarchy、implementations 中也一样)。精确匹配的短名称优先于带命名空间的名称。usages Billing::LedgerImporter 会列出行中写出完整名称的
LedgerImporter 引用;usages LedgerImporter 会列出所有引用。
类搜索
class - 查找类、接口或协议定义。
ast-index class "BaseFragment" # Find Android base fragment
ast-index class "UIViewController" # Find iOS view controller subclass
ast-index class "Store" --fuzzy # Find all classes containing "Store"
ast-index class "Repository" --module "features/payments" # Filter by module
ast-index class "UserController" # Find Java/Spring controller class
用法搜索
usages - 查找符号所有被使用的位置。重构时至关重要。
ast-index usages "PaymentRepository" # Find all usages of repository
ast-index usages "onClick" # Find all click handler usages
ast-index usages "fetchData" --in-file "src/api/" # Scoped to file path
ast-index usages "Repository" --module "features/auth" --limit 100
ast-index usages "parse_config" # snake_case calls: Python, Rust, Go, C, PHP, ...
用法(此处以及 refs 中)会先列出生产文件,再列出测试文件;每组按路径和行号排列。在 JSON 中,测试引用带有
"test": true。
索引的用法包括首字母大写的名称和写作 name( 的调用,也包括 snake_case 和 _private 名称。不会记录保留字(sizeof (x)、#if defined(X)、Go 的
func (r *T)、Python 的 None)。
性能:索引符号的查询约需 8ms。
交叉引用
refs - 在一个视图中显示符号的交叉引用:定义、导入和用法。
ast-index refs "PaymentRepository" # Definitions + imports + usages
ast-index refs "BaseFragment" --limit 10 # Limit results per section
实现搜索
implementations - 查找所有扩展或实现给定类/接口/协议的类。参数应为父类型,而非方法或函数名称。支持按相关性排序的部分名称匹配(精确匹配 → 后缀匹配 → 包含匹配)。
ast-index implementations "BasePresenter" # Find all presenter implementations
ast-index implementations "Repository" # Find repository implementations (exact match)
ast-index implementations "Service" # Partial: finds UserService, PaymentService impls too
ast-index implementations "ViewModel" --module "features/" # Scoped to module
ast-index implementations "Repository" --with-content # Include bounded source bodies
类层次结构
hierarchy - 显示完整的类层次结构树。
ast-index hierarchy "BaseFragment" # Show fragment inheritance tree
调用者搜索
callers - 查找调用某个函数的行,在查询时按名称匹配(name(、.name 等)。它会打印调用位置,而非每个调用所在的函数;要查看后者,请使用 call-tree。
ast-index callers "onClick" # Find all onClick calls
ast-index callers "fetchUser" # Find API call sites
在 Ruby 中,表示符号的方法名称也算作调用位置(before_save :name、
validate :name、delegate :name、map(&:name));:name?、:name! 和
:name= 表示其他方法,不算调用位置,::name 路径也不算(use super::name;、
Billing::Name),除非它被调用(Mod::name(、
Billing::Name.new)。
调用树
call-tree - 显示向上的调用层次结构:每次调用所在的函数,然后是它的调用者。适用于所有已索引语言:对于 tree-sitter 语言(Ruby、TypeScript/JavaScript、Python、Go、Rust、Java、Kotlin、Swift、C#、C/C++、PHP 等),调用者是行范围包含该调用的最内层定义;对于没有行范围的基于正则表达式的解析器(Perl、WSDL/XSD),则回退到该调用上方最近的定义。
ast-index call-tree "processPayment" --depth 3 --limit 10
ast-index call-tree "getUsers" # Java: finds callers of getUsers() method
每个调用者都会连同其文件一起打印,包括其他文件中同名的定义(两个 it "works" 代码块算作两个调用者)。调用者按名称查找,因此每个名称只展开一次:之后遇到的同名调用者会标记为
(expanded above);(recursive) 只标记其自身调用路径上已有的定义,也就是真正的循环。导入和注解(use、include Mod、Rails 回调)都不构成调用的所属位置,包含它们的定义才是;声明函数本身的行也不算对该函数的调用。
符号依赖图
graph - 根据索引构建的有向符号间依赖图:边表示“包含引用的定义” -> “该引用指向的定义”。与 callers / call-tree(查询时进行文本搜索)不同,它基于预计算的边作答,并说明对每个目标的判断有多确定。
ast-index graph build # Build/refresh the graph (explicit, ~seconds)
ast-index graph status # Built? Stale? Edge counts per confidence
ast-index graph dependents ApplicationService # Who depends on it (incoming edges)
ast-index graph dependents "Billing::Invoice#total" # A member of one class
ast-index graph dependents MergeService --exclude-tests # Production dependents only (also on impact)
ast-index graph dependencies CheckoutController --members # What a class and its methods use
ast-index graph impact PaymentGateway --depth 3 # Blast radius: dependents per depth, files
ast-index graph path OrdersController Invoice # Shortest dependency path(s) between two symbols
ast-index graph cycles --path app/models # Strongly connected components
ast-index graph top --kind class --exclude-tests # Most central symbols (PageRank)
ast-index graph metrics Invoice Payment # fan-in/out, dependents, PageRank per symbol
每条边都标记了目标解析时的级别:
local(同一文件)、scoped(显式命名空间 A::B::Name、词法嵌套、常量接收者 Type.method 或继承/混入)、import(源文件导入目标模块)、unique(该名称在该语言中只有一个定义)、ambiguous(有多个候选,或在类型未知的接收者上调用——candidates 会说明候选数量)。入边数、出边数、依赖者和 PageRank 仅统计已解析的边;歧义边会单独统计,并通过 --include-ambiguous 列出(在 impact 中,该选项会在仅统计已解析边的数字旁给出上限)。
Rust 路径按照编译器的解析方式解析:文件即模块(src/db.rs 是 db),crate:: / super:: / self:: 遍历模块树,use 声明(分组、别名、glob 导入、pub use 重新导出)会绑定名称,因此 db::open_db(...) 会指向 src/db.rs,形成一条 scoped 边,而通过 use 导入的名称会形成一条 import 边。另一个工作区 crate 通过其 Cargo.toml 库名称访问;std:: 和依赖项路径不会解析到同名的项目定义。
类符号仅包含其类级引用(超类、混入);对 dependents / dependencies / impact 传入 --members,可涵盖类内部的定义。path 始终将类视为自身及其成员,并可能从类进入成员(显示为 contains),因为像 Service.call -> process 这样的分派无法静态识别。
一个裸名称可能匹配多个定义(call,或作为模型的 Applicant、TypeScript 类型和规范桩):此时 dependents / dependencies / impact 会合并这些定义的边,说明匹配的定义数量,最多列出 --limit 个,并建议使用 Outer::Name、Class#member、--in-file 或 --kind。
在 Rails 应用中,db/schema.rb 的表会与模型匹配(self.table_name、单表继承、table_name_prefix / isolate_namespace、嵌套、复数形式的类名);在模型内部调用的列读取器或属性方法(status、self.status、status?、saved_change_to_status?)会解析为指向列的 scoped 边:ast-index graph dependents applicants.first_name(或 applicants#first_name)。对其他接收者的调用(applicant.first_name)不会猜测列,因此大多数列读取都不会形成这类边——结果会说明这一点;ast-index usages first_name 会列出每一次读取。graph build 会报告没有模型的表和没有表的模型。
rebuild / update 不会重新构建依赖图。更新改变索引后,查询会打印过时警告(JSON 中为 "stale": true);重新运行 graph build,或在查询中添加 --refresh,即可先重新构建。
文件分析
imports - 列出指定文件中的所有导入。
ast-index imports "path/to/File.kt" # Show Kotlin file imports
outline - 显示文件中定义的所有符号,解析方式与索引一致(大多数语言使用 tree-sitter)。
ast-index outline "PaymentFragment.kt" # Show Kotlin fragment structure
ast-index outline "UserController.java" # Show Java controller methods
ast-index outline "App.tsx" # Show TypeScript/React components and functions
ast-index outline "handler.rs" # Show Rust structs, impls, functions
ast-index outline --format json "app.rb" # {schema_version: 1, file, symbols: [{name, kind, line, end_line}]}
各行按源代码顺序排列。跨多行的定义会显示其范围(:12-40 Invoice [class]),因此 Read 可以精确读取该范围;单行定义则显示为 :12。如果解析器未报告范围,JSON 中的 end_line 为 null。
在 schema 转储文件(db/schema.rb)中,列会折叠到所属表的行中(:96-149 orders [table] 33 columns),以保持大纲简洁;--full 会列出每一列,而 symbol --type column --pattern 'users.*' 会列出单个表的列。
代码质量
todo - 查找代码中的 TODO/FIXME/HACK 注释。
ast-index todo # Find all TODO comments
ast-index todo --limit 10 # Limit results
deprecated - 查找 @Deprecated 注解。
ast-index deprecated # Find deprecated items
unused-symbols - 查找可能未使用的导出符号。
ast-index unused-symbols --module path/to/module # In specific module
ast-index unused-symbols --export-only # Only exported (public) symbols
Git/Arc 集成
changed - 快速汇总检测到的 Git/Arc 仓库中的分支级文件。它比较
merge-base(base, HEAD) 与 HEAD,并报告相对于仓库的路径及
A(新增)、M(修改)、D(删除)或 R(重命名)状态。若未指定
--base,Git 会解析 origin/HEAD,然后依次尝试
origin/main、origin/master、main、master 和 trunk;Arc 使用
trunk。对于重命名,JSON 包含 old_path。
ast-index changed # Auto-detect Git base; Arc uses trunk
ast-index changed --base main # Explicit base branch
ast-index --format json changed --base trunk # Stable JSON schema v1
ast-index changed --timeout-ms 30000 # Bound VCS execution time
ast-index changed --verbose # Exact VCS argv and timing on stderr
文本输出示例:
Changed files against main (5):
A src/new.rs
M src/lib.rs
D src/obsolete.rs
R src/old.rs -> src/current.rs
M src/generated\nname.rs
文本模式会转义控制字符和反斜杠,确保每条结果都保持在一行内。 脚本应请求 JSON,而不是解析文本摘要。
JSON 输出示例:
{
"schema_version": 1,
"vcs": "git",
"base": "main",
"head": "HEAD",
"scope": null,
"changes": [
{ "status": "M", "path": "src/lib.rs" },
{ "status": "R", "path": "src/current.rs", "old_path": "src/old.rs" }
]
}
在仓库根目录,scope 为 null;在嵌套工作目录中,它是相对于仓库的
目录路径。
changed 直接读取 VCS 状态,不依赖 ast-index
数据库/缓存。其作用范围是当前工作目录,但输出路径仍相对于仓库根目录。
可用它在审查前盘点分支文件;如需补丁块,请使用原始的 git diff / arc diff。
它不会报告变更的符号,也不会包含仅存在于暂存区/未暂存工作树中的修改。
hotspots - 根据文件的 Git 历史对文件进行排名:提交数、变更量(新增 + 删除的行数,以及对于 10 行及以上的文件,相对于当前文件大小的变更量)、修复错误的提交占比、不同作者数、文件年龄,以及距最近一次变更的时间。
在多个相似文件中选择一个作为模式参考,或确定重构范围时可使用它:一个有 28 次提交且 54% 为修复错误提交的文件,与一个仅编写过一次、86 天未改动的文件并不相同。
阈值是此仓库内的百分位数,并非固定值——28 次提交对一个库来说很多,但在单体仓库中可能很寻常。标签旁始终会打印原始数值。
ast-index hotspots --collect # Read new Git history, then report
ast-index hotspots --limit 50 --sort fixes # Report only; no Git subprocess
ast-index hotspots --path src/parsers # Narrow output; percentiles stay global
ast-index hotspots --exclude-tests # Hide spec/test files; percentiles stay global
ast-index hotspots --collect --full # Discard the cursor, rescan everything
ast-index --format json hotspots --limit 10 # Paginated JSON schema v2
收集操作不会自动执行:rebuild 和 update 不会运行它。首次使用 --collect 时,会遍历完整历史并存入按提交划分的存储;之后的运行会通过集合差异将其推进到当前 HEAD——HEAD 不再能到达的提交(切换分支、变基、重置、强制推送)会被扣除,新提交会被添加——因此,切换分支所需的时间与差异提交数成正比,切回时则无需重新读取。所得数值与在该 HEAD 上完整重新收集的结果一致;行数来自工作树,因此未提交的编辑会在后续 --collect 重新计算该文件时,或在使用 --full 时计入。只有游标提交已被垃圾回收、项目根目录发生变化,或使用 --full 时,才会从头重建。rebuild 会保留已收集的历史(它不依赖索引),除非这些历史来自较旧版本、其他工作树或其他作用范围;遇到这种情况时,下次 --collect 会重新读取历史。
标签:churn:high / churn:elevated、rewritten-often(相对变更量,仅适用于 10 行及以上的文件:低于此行数时,行数不再能衡量内容,例如单行打包文件、测试夹具、被掏空的视图)、fixes:high /
fixes:elevated(仅适用于至少有 4 次提交的文件)、authors:many、veteran。
--sort 接受 score(默认值)、commits、churn、relative-churn、
fixes、authors、recent。打印的 score 会四舍五入;排序(以及
JSON 中的 score_exact)使用未四舍五入的百分位数均值,因此大型仓库顶部的结果不会都挤成并列。fixes 会按经过历史记录稀疏度折减的修复错误提交占比排序(95% Wilson 区间下限:11 次中的 17 次高于 2 次中的 2 次),提交少于 4 次的文件排在最后。修复错误检测采用提交主题启发式规则(支持英语和俄语;会先去除开头的跟踪器编号;[HOTFIX] / [FIX] 等标签也计为修复);合并提交会被排除,重命名时历史会沿用到新路径。
公共 API
api - 显示模块的公共 API。接受模块路径或模块名称(点号会转换为斜杠)。
ast-index api "path/to/module" # By path
ast-index api "module.name" # By module name (dots → slashes)
项目洞察
项目概览
map - 显示精简的项目概览:按大小排列的顶层目录及其符号类型计数。使用 --module 深入查看特定区域的完整类和继承详情。
ast-index map # Summary: top 50 dirs with kind counts (~54 lines)
ast-index map --limit 20 # Show only top 20 directories
ast-index map --module features/payments # Detailed: classes with inheritance for a module
ast-index map --module src/core --per-dir 10 # More symbols per directory in detailed mode
ast-index map --format json # JSON output
摘要模式输出(默认,不使用 --module):
Project: Android (Kotlin/Java) | 29144 files | 859 modules | top 50 of 728 dirs
features/taxi_order/impl/ 1626 files | 371 iface, 94 obj, 1834 cls
features/masstransit/impl/ 862 files | 165 obj, 1261 cls, 280 iface
详细模式输出(使用 --module):
features/payments/impl/ (250 files)
PaymentInteractor : class > BaseInteractor
PaymentRepository : interface
PaymentMapper : class
项目约定
conventions - 从已索引的代码库中自动检测架构模式、框架和命名约定。运行只读 SQL 查询,无需扫描文件。
ast-index conventions # Text output (~30 lines)
ast-index conventions --format json # JSON output
检测内容:
- 架构:Clean Architecture、Feature-sliced、BLoC、MVC、MVVM、MVP、Redux、Composition API、Hooks
- 框架:DI(Hilt、Dagger、Koin)、异步(Coroutines、RxJava、Combine)、网络(Retrofit、OkHttp)、数据库(Room、Realm、ActiveRecord、Sequel)、UI(Compose、SwiftUI、React、Flutter)、测试(JUnit、Kotest、XCTest、pytest、Jest、RSpec)、Web(Rails、Django、Flask、FastAPI、Express)、任务(Sidekiq、Celery)——根据导入和
require名称检测,并按完整名称段匹配(sequel-combine不会被识别为 Combine) - 命名模式:ViewModel、Repository、UseCase、Service、Controller、Fragment 等(附带计数)
常用标志
大多数搜索命令(search、symbol、class、usages、implementations、refs)支持:
| 标志 | 说明 |
|---|---|
--fuzzy | 模糊搜索:精确匹配 → 前缀匹配 → 包含匹配(仅适用于 search、symbol、class) |
--in-file <PATH> | 按文件路径筛选结果(子串匹配;也适用于 callers 和 call-tree) |
--module <PATH> | 按路径前缀筛选结果 |
--limit <N> | 返回的最大结果数 |
--format json | 输出 JSON,以便进行结构化处理 |
何时使用 --fuzzy: 不确定准确名称时。ast-index class "Store" --fuzzy 可查找 Store、StoreImpl、AppStore、DataStoreRepository 等。--fuzzy 标志执行三阶段匹配:先精确匹配,再前缀匹配,最后包含匹配。
索引管理
ast-index rebuild # Full rebuild with dependencies
ast-index rebuild --no-deps # Skip module dependency indexing
ast-index rebuild --no-ignore # Include gitignored files (build/, etc.)
ast-index rebuild --sub-projects # Index each sub-project separately (large monorepos)
ast-index rebuild -j 32 # Use 32 threads (for network/FUSE filesystems)
ast-index rebuild -v # Verbose logging with timing per step
ast-index update # Incremental update (changed files only)
ast-index stats # Show index statistics
ast-index clear # Delete index for current project
ast-index restore /path/to/index.db # Restore index from a .db file
ast-index watch # Watch for file changes and auto-update index
按目录范围搜索
从子目录运行搜索时,结果会自动限制在该子树中(通过缓存中的索引数据库检测项目根目录):
cd /project/root
ast-index rebuild # Index entire project
ast-index search "Payment" # Finds results across entire project
cd /project/root/services/payments
ast-index search "Payment" # Only finds results within services/payments/
ast-index class "PaymentService" # Only classes in services/payments/ subtree
此功能适用于所有搜索命令:search、symbol、class、implementations、usages。
多根项目
为有意跨越同级源代码树的工作区附加具名子树。这些子树会与主项目一同建立索引;主项目必须先建立索引:
ast-index subtree add shared ../shared-library # Attach a named subtree
ast-index update # Index its files
ast-index subtree list # List attached subtrees
ast-index subtree remove shared # Detach, then rebuild to drop its files
ast-index --subtree shared search "Payment" # Query one subtree
ast-index --local search "Payment" # Query the primary project only
add-root、remove-root 和 list-roots 仍作为兼容别名保留。不要将一个 git worktree 附加到另一个 worktree:每个 worktree 都有自己的索引。
实用命令
ast-index version # Show CLI version
ast-index help # Show help message
ast-index help <command> # Show help for specific command
ast-index install-claude-plugin # Install Claude Code plugin to ~/.claude/plugins/
程序化访问(SQL 和 SDK)
对于需要组合多个查询、筛选或聚合的复杂分析,请使用直接 SQL 访问,而不要串联多个命令。
结构化搜索(ast-grep)
使用 AST 模式进行结构化代码搜索。需要安装 sg(ast-grep)。
# Simple pattern matching
ast-index agrep "router.launch($$$)" --lang kotlin
ast-index agrep "@Inject constructor($$$)" --lang kotlin
ast-index agrep "suspend fun $NAME($$$)" --lang kotlin
# Find classes extending a specific base
ast-index agrep "class $NAME : BasePresenter($$$)" --lang kotlin
# Find async functions (Swift)
ast-index agrep "func $NAME($$$) async" --lang swift
# Find React components
ast-index agrep "export default function $NAME($$$)" --lang typescript
# JSON output for programmatic use
ast-index agrep "@Composable fun $NAME($$$)" --lang kotlin --json
模式语法(ast-grep):
$NAME— 匹配单个 AST 节点(捕获为元变量)$$$— 匹配零个或多个 AST 节点(可变参数)- 其他所有内容都是与 AST 匹配的字面模式
何时使用 agrep 而非内置命令:
composables、inject、suspend→ 使用内置命令(更快,且已预先配置)- 自定义结构模式、否定匹配、上下文查询 → 使用
agrep
原始 SQL 查询
# Execute any SELECT query against the index database (JSON output)
ast-index query "SELECT s.name, s.kind, f.path FROM symbols s JOIN files f ON s.file_id = f.id WHERE s.kind = 'class'"
# With limit
ast-index query "SELECT * FROM symbols WHERE name LIKE '%Service%'" --limit 50
# Complex joins — find classes that implement an interface but have no usages
ast-index query "SELECT s.name, f.path FROM symbols s JOIN files f ON s.file_id = f.id JOIN inheritance i ON s.id = i.child_id WHERE i.parent_name = 'Repository' AND s.name NOT IN (SELECT name FROM refs)"
# Find files with most symbols (complexity hotspots)
ast-index query "SELECT f.path, COUNT(*) as sym_count FROM symbols s JOIN files f ON s.file_id = f.id GROUP BY f.id ORDER BY sym_count DESC LIMIT 20"
# Find unused classes (defined but never referenced)
ast-index query "SELECT s.name, s.kind, f.path FROM symbols s JOIN files f ON s.file_id = f.id WHERE s.kind IN ('class', 'interface') AND s.name NOT IN (SELECT name FROM refs) AND s.name NOT IN (SELECT parent_name FROM inheritance)"
# Module dependency analysis — find modules with most dependencies
ast-index query "SELECT m.name, COUNT(*) as dep_count FROM module_deps md JOIN modules m ON md.module_id = m.id GROUP BY m.id ORDER BY dep_count DESC"
# CTE — transitive dependency chain
ast-index query "WITH RECURSIVE chain AS (SELECT md.dep_module_id, m.name, 1 as depth FROM module_deps md JOIN modules m ON md.dep_module_id = m.id WHERE md.module_id = (SELECT id FROM modules WHERE name LIKE '%payments%') UNION ALL SELECT md.dep_module_id, m.name, c.depth + 1 FROM chain c JOIN module_deps md ON md.module_id = c.dep_module_id JOIN modules m ON md.dep_module_id = m.id WHERE c.depth < 5) SELECT DISTINCT name, depth FROM chain ORDER BY depth, name"
安全性:只允许使用 SELECT、WITH 和 EXPLAIN 查询。修改操作(INSERT、UPDATE、DELETE、DROP)会被拦截。
数据库架构
# Show all tables with columns and row counts (JSON)
ast-index schema
主要表:
| 表 | 描述 | 关键列 |
|---|---|---|
files | 已索引的源文件 | path、mtime、size |
symbols | 类、函数、属性等 | name、kind、line、file_id、signature |
symbols_fts | 对符号进行 FTS5 全文搜索 | name、signature |
inheritance | 父子类型关系 | child_id、parent_name、kind |
refs | 符号引用/使用情况 | name、line、file_id、context |
modules | 构建模块(Gradle、Maven 等) | name、path、kind |
module_deps | 模块 → 模块依赖 | module_id、dep_module_id |
transitive_deps | 预先计算的传递依赖 | module_id、dependency_id、depth |
xml_usages | Android XML 布局类的使用情况 | class_name、file_path |
resources | Android 资源定义 | type、name、file_path |
直接访问数据库(SDK / 脚本编写)
# Get the SQLite database path for external tools
ast-index db-path
# Output: /Users/me/.cache/ast-index/abc123/index.db
任何支持 SQLite 的语言均可使用此方式:
import sqlite3, json
db_path = subprocess.check_output(["ast-index", "db-path"]).decode().strip()
conn = sqlite3.connect(db_path)
# Example: find all classes implementing an interface with no references
unused_impls = conn.execute("""
SELECT s.name, f.path, i.parent_name
FROM symbols s
JOIN files f ON s.file_id = f.id
JOIN inheritance i ON s.id = i.child_id
WHERE s.name NOT IN (SELECT name FROM refs)
ORDER BY i.parent_name, s.name
""").fetchall()
for name, path, parent in unused_impls:
print(f" {name} implements {parent} — {path}")
何时使用 query,何时使用预定义命令:
- 简单查找 → 使用
search、class、usages(速度更快,输出格式化) - 复杂联接、聚合、否定条件 → 使用
query(一次调用即可,无需调用 N 次) - 批量分析、脚本编写、CI 流水线 → 使用
db-path+ 直接访问 SQLite
性能参考
单次调用的实际耗时(包含进程启动):小型项目,以及一个包含 40k 个文件(30 万个符号)的 Rails + React 单体仓库,页面缓存已预热。
| 命令 | 小型项目 | 40k 个文件 | 备注 |
|---|---|---|---|
| class / symbol | ~10ms | ~20ms | 直接索引查找 |
| usages / implementations | ~10ms | ~20-40ms | 索引引用搜索 |
| imports | ~10ms | ~20ms | 基于文件的查找 |
| outline | ~10ms | ~50ms | 解析文件 |
| search | ~10ms | ~250-550ms | FTS5 符号搜索,并扫描文件内容 |
| explore | ~15ms | ~100-150ms | --rwr ~200ms |
| graph queries | ~10ms | ~100ms | 需要 graph build(~1-2s) |
| callers | ~20ms | ~200ms | 在查询时进行文本匹配 |
| call-tree | ~20ms | ~500ms | 查找调用者的调用者 |
| map / conventions | ~20ms | ~0.1-1s | SQL 聚合 |
| rebuild | 秒级 | 分钟级 | 完整项目索引 |
平台专属命令
Android/Kotlin/Java/Spring
参阅:references/android-commands.md
Java 解析器会索引:类、接口、枚举、方法、构造函数、字段和重要注解(@RestController、@Service、@Repository、@Component、@Entity、@GetMapping、@PostMapping、@Autowired、@Override、@Transactional、@SpringBootApplication、@Test、@Inject、@Data、@Builder 等)。
除 Gradle 模块外,也全面支持 Maven 模块(pom.xml)。
- DI 命令:
provides、inject(@Inject + @Autowired)、annotations - Compose 命令:
composables、previews - 协程命令:
suspend、flows - XML 命令:
xml-usages、resource-usages - 代码质量:
deprecated、suppress、todo - 扩展:
extensions - 导航:
deeplinks
iOS/Swift/ObjC
参阅:references/ios-commands.md
- Storyboard 和 XIB:
storyboard-usages - 资源:
asset-usages - SwiftUI:
swiftui - Swift 并发:
async-funcs、main-actor - Combine:
publishers
TypeScript/JavaScript
参阅:references/typescript-commands.md
- 索引:
class、interface、type、function、const、装饰器 - 支持:React(hooks、组件)、Vue SFC、Svelte、NestJS、Angular
outline和imports可用于 TS/JS 文件
Rust
参阅:references/rust-commands.md
- 索引:
struct、enum、trait、impl、fn、macro_rules!、mod - 支持:派生项、属性(
#[test]、#[derive]) outline和imports可用于 Rust 文件
Ruby
参阅:references/ruby-commands.md
- 索引:
class、module、def、常量(A::B = ...)、Rails DSL - 支持:RSpec(
describe、it、let)、Rails(关联、验证) db/schema.rb(即使被 gitignore 忽略也会建立索引):将表作为table、将列作为column,命名为table.column—ast-index search first_name -t columnoutline和imports适用于 Ruby 文件
C#/.NET
参阅:references/csharp-commands.md
- 索引:
class、interface、struct、record、enum、方法、属性 - 支持:ASP.NET 属性、Unity(
MonoBehaviour、SerializeField) outline和imports适用于 C# 文件
Dart/Flutter
参阅:references/dart-commands.md
- 索引:
class、mixin、extension、extension type、enum、typedef、函数、构造函数 - 支持:Dart 3 修饰符(sealed、final、base、interface、mixin class)
outline和imports适用于 Dart 文件
Python
参阅:references/python-commands.md
- 索引:
class、def、async def、装饰器 outline和imports适用于 Python 文件
Go
参阅:references/go-commands.md
- 索引:
package、type struct、type interface、func outline和imports适用于 Go 文件
Scala
- 索引:
class、case class、object、trait、enum(Scala 3)、def、val、var、type、given - 支持:继承(
extends/with)、伴生对象 outline和imports适用于 Scala 文件
PHP
- 索引:
namespace、class、interface、trait、enum、function、method、const、property、use - 支持:Laravel(模型、traits、facades)、
extends/implements、命名空间导入 outline和imports适用于 PHP 文件
Perl
参阅:references/perl-commands.md
- 导出:
perl-exports - 子程序:
perl-subs - POD:
perl-pod - 导入:
perl-imports - 测试:
perl-tests
模块分析
参阅:references/module-commands.md
- 模块搜索:
module - 依赖项:
deps、dependents - 未使用的依赖项:
unused-deps - 未使用的符号:
unused-symbols - 公共 API:
api
工作流建议
- 在项目根目录运行一次
ast-index rebuild以构建索引 - 开始一个会话,运行
ast-index conventions+ast-index map以了解项目结构(约 80 行,约 500 个 token) - 使用
ast-index map --module <path>深入查看特定区域 - 探索时使用
ast-index search进行快速通用搜索 - 使用
ast-index class精确查找类/接口 - 重构前使用
ast-index usages查找所有引用(使用graph dependents查找某个定义的依赖方) - 使用
ast-index implementations了解继承关系 - 代码审查前使用
ast-index changed --base main清点分支文件 - 定期运行
ast-index update以保持索引最新
JSON 输出(可选)
默认输出为人类可读的纯文本——除非确实需要用于脚本的结构化数据,否则请使用默认输出。
仅在以下情况添加 --format json:
- 以编程方式解析输出(管道、脚本)
- 需要精确字段值(文件路径、状态、行号、符号类型)
- 与其他工具集成
支持 JSON 输出的命令包括 search、explore、file、symbol、class、usages、callers、implementations、refs、stats、changed、hotspots、graph …、unused-symbols、map 和 conventions;其他命令(outline、call-tree、hierarchy、imports、todo)无论如何都输出文本。
ast-index --format json search "Query" | jq '.symbols[].path'
其他资源
如需查看平台特定命令的详细信息,请参阅:
references/android-commands.md- DI、Compose、Coroutines、XMLreferences/ios-commands.md- Storyboard、SwiftUI、Combinereferences/typescript-commands.md- React、Vue、Svelte、NestJS、Angularreferences/rust-commands.md- 结构体、trait、impl 块、宏references/ruby-commands.md- Rails、RSpec、类、模块references/csharp-commands.md- ASP.NET、Unity、控制器、接口references/dart-commands.md- Dart/Flutter 类、mixin、扩展references/perl-commands.md- Perl 导出项、子程序、PODreferences/python-commands.md- Python 类、函数references/go-commands.md- Go 结构体、接口references/cpp-commands.md- C/C++ 类、JNI 函数references/proto-commands.md- Protocol Buffers 消息、服务references/wsdl-commands.md- WSDL 服务、XSD 类型references/module-commands.md- 模块依赖