ast-index
ast-index - Code Search for Multi-Platform Projects
Fast native Rust CLI for structural code search in Android/Kotlin/Java, iOS/Swift/ObjC, Dart/Flutter, TypeScript/JavaScript, Rust, Ruby, C#, Scala, PHP, Perl, Python, Go, C++, and Proto projects using SQLite + FTS5 index.
Critical Rules
ALWAYS use ast-index FIRST for any code search task. These rules are mandatory:
- ast-index is the PRIMARY search tool — use it before grep, ripgrep, or Search tool
- DO NOT duplicate results — if ast-index found usages/implementations, that IS the complete answer
- DO NOT run grep "for completeness" after ast-index returns results
- Use grep/Search ONLY when:
- ast-index returns empty results
- Searching for regex patterns (ast-index uses literal match)
- Searching for string literals inside code (
"some text") - Searching in comments content
Why: ast-index is 17-69x faster than grep (1-10ms vs 200ms-3s) and returns structured, accurate results.
Prerequisites
Install the CLI before use:
brew tap defendend/ast-index
brew install ast-index
Initialize index in project root:
cd /path/to/project
ast-index rebuild
The index is stored at ~/Library/Caches/ast-index/<project-hash>/index.db (macOS) or ~/.cache/ast-index/<project-hash>/index.db (Linux). Rebuild deletes the DB file entirely and creates a fresh index.
Supported Projects
| Platform | Languages | Module System |
|---|---|---|
| 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 | None (*.py files) |
| Go | Go | None (*.go files) |
| Proto | Protocol Buffers (proto2/proto3) | None (*.proto files) |
| WSDL | WSDL, XSD | None (*.wsdl, *.xsd files) |
| C/C++ | C, C++ (JNI, uservices) | None (*.cpp, *.h, *.hpp files) |
| Mixed | All above | All |
Project type is auto-detected by marker files (build.gradle.kts, Package.swift, Makefile.PL, etc.). Python, Go, Proto, WSDL, and C++ files are indexed alongside main project type.
JSON Output
Most commands support --format json for structured output:
ast-index search "Query" --format json
ast-index symbol "Name" --format json
ast-index class "Name" --format json
ast-index usages "Symbol" --format json
ast-index implementations "Parent" --format json
ast-index refs "Symbol" --format json
ast-index stats --format json
ast-index unused-symbols --format json
ast-index map --format json
ast-index conventions --format json
Core Commands
Universal Search
search - Perform universal search across files, symbols, and modules simultaneously.
ast-index search "Payment" # Finds files, classes, functions matching "Payment"
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 "UserService" # Find Java/Spring services
ast-index search "@RestController" # Find Spring REST controllers (annotation search)
ast-index search "@GetMapping" # Find GET endpoint mappings
File Search
file - Find files by name pattern.
ast-index file "Fragment.kt" # Find files ending with Fragment.kt
ast-index file "ViewController" # Find iOS view controllers
Symbol Search
symbol - Find symbols (classes, interfaces, functions, properties) by name.
ast-index symbol "PaymentInteractor" # Find exact symbol
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 "@Service" # Find all @Service annotations
Class Search
class - Find class, interface, or protocol definitions.
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
Usage Search
usages - Find all places where a symbol is used. Critical for refactoring.
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
Performance: ~8ms for indexed symbols.
Cross-References
refs - Show cross-references for a symbol: definitions, imports, and usages in one view.
ast-index refs "PaymentRepository" # Definitions + imports + usages
ast-index refs "BaseFragment" --limit 10 # Limit results per section
Implementation Search
implementations - Find all classes that extend or implement a given class/interface/protocol. Supports partial name matching with relevance ranking (exact → suffix → contains).
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
Class Hierarchy
hierarchy - Display complete class hierarchy tree.
ast-index hierarchy "BaseFragment" # Show fragment inheritance tree
Caller Search
callers - Find all places that call a specific function.
ast-index callers "onClick" # Find all onClick calls
ast-index callers "fetchUser" # Find API call sites
Call Tree
call-tree - Show complete call hierarchy going UP (who calls the callers). Supports Kotlin, Java, Swift, Perl, ObjC.
ast-index call-tree "processPayment" --depth 3 --limit 10
ast-index call-tree "getUsers" # Java: finds callers of getUsers() method
File Analysis
imports - List all imports in a specific file.
ast-index imports "path/to/File.kt" # Show Kotlin file imports
outline - Show all symbols defined in a file. Uses tree-sitter for accurate parsing of all supported languages.
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
Code Quality
todo - Find TODO/FIXME/HACK comments in code.
ast-index todo # Find all TODO comments
ast-index todo --limit 10 # Limit results
deprecated - Find @Deprecated annotations.
ast-index deprecated # Find deprecated items
unused-symbols - Find potentially unused exported symbols.
ast-index unused-symbols --module path/to/module # In specific module
ast-index unused-symbols --export-only # Only exported (public) symbols
Git/Arc Integration
changed - Show symbols changed in git/arc diff. Auto-detects VCS and base branch.
ast-index changed # Auto: trunk (arc) or origin/main (git)
ast-index changed --base main # Explicit base branch
ast-index changed --base trunk # For arc projects
Public API
api - Show public API of a module. Accepts module path or module name (dots converted to slashes).
ast-index api "path/to/module" # By path
ast-index api "module.name" # By module name (dots → slashes)
Project Insights
Project Map
map - Show compact project overview: top directories by size with symbol kind counts. Use --module to drill down into a specific area with full class/inheritance details.
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
Summary mode output (default, no --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
Detailed mode output (with --module):
features/payments/impl/ (250 files)
PaymentInteractor : class > BaseInteractor
PaymentRepository : interface
PaymentMapper : class
Project Conventions
conventions - Auto-detect architecture patterns, frameworks, and naming conventions from the indexed codebase. Runs read-only SQL queries — no file scanning needed.
ast-index conventions # Text output (~30 lines)
ast-index conventions --format json # JSON output
Detects:
- Architecture: Clean Architecture, Feature-sliced, BLoC, MVC, MVVM, MVP, Redux, Composition API, Hooks
- Frameworks: DI (Hilt, Dagger, Koin), Async (Coroutines, RxJava, Combine), Network (Retrofit, OkHttp), DB (Room, Realm), UI (Compose, SwiftUI, React, Flutter), Testing (JUnit, Kotest, XCTest, pytest, Jest)
- Naming patterns: ViewModel, Repository, UseCase, Service, Controller, Fragment, etc. (with counts)
Common Flags
Most search commands (search, symbol, class, usages, implementations) support:
| Flag | Description |
|---|---|
--fuzzy |
Fuzzy search: exact match → prefix match → contains match |
--in-file <PATH> |
Filter results by file path (substring match) |
--module <PATH> |
Filter results by module path (substring match) |
--limit <N> |
Max results to return |
--format json |
JSON output for structured processing |
When to use --fuzzy: When you don't know the exact name. ast-index class "Store" --fuzzy finds Store, StoreImpl, AppStore, DataStoreRepository, etc. The --fuzzy flag performs three-stage matching: exact match first, then prefix match, then contains match.
Index Management
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
Directory-Scoped Search
When running search from a subdirectory, results are automatically limited to that subtree (the index DB in cache is used to detect the project root):
cd /project/root
ast-index rebuild # Index entire project, creates .ast-index-root
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
This works with all search commands: search, symbol, class, implementations, usages.
Multi-Root Projects
Add additional source roots for monorepos or multi-project setups. Extra roots are indexed alongside the primary project and their module dependencies are included.
ast-index add-root /path/to/other/source # Add source root (warns on overlap)
ast-index add-root ./subdir --force # Force add even if inside project root
ast-index remove-root /path/to/other/source # Remove source root
ast-index list-roots # List configured roots
Utility Commands
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/
Programmatic Access (SQL & SDK)
For complex analysis that requires combining multiple queries, filtering, or aggregation — use direct SQL access instead of chaining multiple commands.
Structural Search (ast-grep)
Structural code search using AST patterns. Requires sg (ast-grep) installed.
# 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
Pattern syntax (ast-grep):
$NAME— matches a single AST node (captures as metavariable)$$$— matches zero or more AST nodes (variadic)- Everything else is literal pattern matching against the AST
When to use agrep vs built-in commands:
composables,inject,suspend→ use built-in (faster, pre-configured)- Custom structural patterns, negative matching, context queries → use
agrep
Raw SQL Query
# 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"
Security: Only SELECT, WITH, and EXPLAIN queries allowed. Mutations (INSERT, UPDATE, DELETE, DROP) are blocked.
Database Schema
# Show all tables with columns and row counts (JSON)
ast-index schema
Key tables:
| Table | Description | Key columns |
|---|---|---|
files |
Indexed source files | path, mtime, size |
symbols |
Classes, functions, properties, etc. | name, kind, line, file_id, signature |
symbols_fts |
FTS5 full-text search on symbols | name, signature |
inheritance |
Parent-child type relationships | child_id, parent_name, kind |
refs |
Symbol references/usages | name, line, file_id, context |
modules |
Build modules (Gradle, Maven, etc.) | name, path, kind |
module_deps |
Module → module dependencies | module_id, dep_module_id |
transitive_deps |
Pre-computed transitive deps | module_id, dependency_id, depth |
xml_usages |
Android XML layout class usages | class_name, file_path |
resources |
Android resource definitions | type, name, file_path |
Direct Database Access (SDK / Scripting)
# Get the SQLite database path for external tools
ast-index db-path
# Output: /Users/me/.cache/ast-index/abc123/index.db
Use this path with any language that supports 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}")
When to use query vs predefined commands:
- Simple lookups → use
search,class,usages(faster, formatted output) - Complex joins, aggregation, negative conditions → use
query(one call instead of N) - Batch analysis, scripting, CI pipelines → use
db-path+ direct SQLite access
Performance Reference
| Command | Time | Notes |
|---|---|---|
| search | ~10ms | Indexed FTS5 search |
| class | ~1ms | Direct index lookup |
| usages | ~8ms | Indexed reference search |
| imports | ~0.3ms | File-based lookup |
| callers | ~1s | Grep-based search |
| map | ~1-3s | SQL aggregation (scales with project size) |
| conventions | ~1-4s | SQL aggregation + import matching |
| rebuild | ~25s–5m | Full project indexing (depends on size) |
Platform-Specific Commands
Android/Kotlin/Java/Spring
Consult: references/android-commands.md
Java parser indexes: classes, interfaces, enums, methods, constructors, fields, and significant annotations (@RestController, @Service, @Repository, @Component, @Entity, @GetMapping, @PostMapping, @Autowired, @Override, @Transactional, @SpringBootApplication, @Test, @Inject, @Data, @Builder, etc.).
Maven modules (pom.xml) are fully supported alongside Gradle modules.
- DI Commands:
provides,inject(@Inject + @Autowired),annotations - Compose Commands:
composables,previews - Coroutines Commands:
suspend,flows - XML Commands:
xml-usages,resource-usages - Code Quality:
deprecated,suppress,todo - Extensions:
extensions - Navigation:
deeplinks
iOS/Swift/ObjC
Consult: references/ios-commands.md
- Storyboard & XIB:
storyboard-usages - Assets:
asset-usages - SwiftUI:
swiftui - Swift Concurrency:
async-funcs,main-actor - Combine:
publishers
TypeScript/JavaScript
Consult: references/typescript-commands.md
- Index:
class,interface,type,function,const, decorators - Supports: React (hooks, components), Vue SFC, Svelte, NestJS, Angular
outlineandimportswork with TS/JS files
Rust
Consult: references/rust-commands.md
- Index:
struct,enum,trait,impl,fn,macro_rules!,mod - Supports: Derives, attributes (
#[test],#[derive]) outlineandimportswork with Rust files
Ruby
Consult: references/ruby-commands.md
- Index:
class,module,def, Rails DSL - Supports: RSpec (
describe,it,let), Rails (associations, validations) outlineandimportswork with Ruby files
C#/.NET
Consult: references/csharp-commands.md
- Index:
class,interface,struct,record,enum, methods, properties - Supports: ASP.NET attributes, Unity (
MonoBehaviour,SerializeField) outlineandimportswork with C# files
Dart/Flutter
Consult: references/dart-commands.md
- Index:
class,mixin,extension,extension type,enum,typedef, functions, constructors - Supports: Dart 3 modifiers (sealed, final, base, interface, mixin class)
outlineandimportswork with Dart files
Python
Consult: references/python-commands.md
- Index:
class,def,async def, decorators outlineandimportswork with Python files
Go
Consult: references/go-commands.md
- Index:
package,type struct,type interface,func outlineandimportswork with Go files
Scala
- Index:
class,case class,object,trait,enum(Scala 3),def,val,var,type,given - Supports: Inheritance (
extends/with), companion objects outlineandimportswork with Scala files
PHP
- Index:
namespace,class,interface,trait,enum,function,method,const,property,use - Supports: Laravel (models, traits, facades),
extends/implements, namespace imports outlineandimportswork with PHP files
Perl
Consult: references/perl-commands.md
- Exports:
perl-exports - Subroutines:
perl-subs - POD:
perl-pod - Imports:
perl-imports - Tests:
perl-tests
Module Analysis
Consult: references/module-commands.md
- Module Search:
module - Dependencies:
deps,dependents - Unused Dependencies:
unused-deps - Unused Symbols:
unused-symbols - Public API:
api
Workflow Recommendations
- Run
ast-index rebuildonce in project root to build the index - Start a session with
ast-index conventions+ast-index mapto understand project structure (~80 lines, ~500 tokens) - Use
ast-index map --module <path>to drill down into specific areas - Use
ast-index searchfor quick universal search when exploring - Use
ast-index classfor precise class/interface lookup - Use
ast-index usagesto find all references before refactoring - Use
ast-index implementationsto understand inheritance - Use
ast-index changed --base mainbefore code review - Run
ast-index updateperiodically to keep index fresh
Additional Resources
For detailed platform-specific commands, consult:
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- Structs, traits, impl blocks, macrosreferences/ruby-commands.md- Rails, RSpec, classes, modulesreferences/csharp-commands.md- ASP.NET, Unity, controllers, interfacesreferences/dart-commands.md- Dart/Flutter classes, mixins, extensionsreferences/perl-commands.md- Perl exports, subs, PODreferences/python-commands.md- Python classes, functionsreferences/go-commands.md- Go structs, interfacesreferences/cpp-commands.md- C/C++ classes, JNI functionsreferences/proto-commands.md- Protocol Buffers messages, servicesreferences/wsdl-commands.md- WSDL services, XSD typesreferences/module-commands.md- Module dependencies