ast-index: an AST-aware SQLite index for code navigation, built for agents that call Bash
Cli allows AST search, ~40-50% economy tokens. Claude/Codex/Cursor searches (suitable for any AI agent that can use Bash)
At a glance
- What is it?
- The CLI indexes symbols, references and imports into a local SQLite database so that Claude Code, Codex or Cursor can query structure instead of dumping whole files. The design is sound for large polyglot repos; the token-saving figure is the project's own claim, not an independent measurement.
- Who is it for?
- Adopt ast-index if your repository is large enough that grep-style text search returns more noise than signal and your agent already shells out to Bash, because the value comes from structural commands like class, usages and implementations rather than from search alone.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem ast-index targets: agents reading files they did not need
A coding agent asked where a payment flow lives has two options. It can grep for a string and then read the surrounding files, or it can ask a structural question and receive a narrow answer. The first approach scales badly. On a large repository, a single grep for a common identifier returns matches across hundreds of files, and the agent pays for every one of them in context. The README frames the fix directly: it builds a local SQLite index of symbols, references, imports, modules, dependencies and inheritance so that both humans and agents move through code by exact structure rather than text matches. The target user is not a developer browsing a small project. It is someone running an agent against a multi-language repository where the cost of context is the binding constraint, and the agent can invoke a Bash command to get an answer. The README states the goal as saving roughly 40-50% of agent tokens on large repositories by returning structural slices of code instead of whole files. Treat that number as the project's own claim. No methodology for it appears in the material available here.
What the SQLite index actually stores, and how a query resolves
The mechanism is a persistent local database rather than an on-the-fly parse. Running ast-index rebuild walks the project, auto-detects the project type, and writes an index of symbols, references, imports, modules, dependencies and inheritance into SQLite. Every read command then queries that database. This is why the README's benchmark table shows imports at 0.3ms against 90ms for grep on a roughly 29k-file, 300k-symbol Android project: the work was done at rebuild time, not at query time. The command surface is layered. explore is the broad entry point for a question phrased in words. symbol, class, outline and refs resolve exact definitions. usages, implementations and callers traverse the reference graph, and deps walks dependency paths. That split matters for agent design, because a cheap explore call can narrow the space before an expensive read. Freshness is handled by ast-index update, which the README says to run after edits or branch switches. Hooks can queue a trailing-debounced refresh with ast-index update --background --debounce-ms 500, and the README notes that index-reading commands wait with a bounded timeout for an already queued generation, so they do not observe stale results. That wait is the detail worth noticing: it is a deliberate trade of latency for consistency, and it means a read can block briefly rather than return an answer from the previous generation.
Install paths, and the one that ships a prebuilt binary
Homebrew is the shortest route and the one that avoids a Rust toolchain: brew tap defendend/ast-index followed by brew install ast-index. Cargo works too, via cargo install ast-index --locked, and the README is explicit that both Homebrew and Cargo build from source. If you want prebuilt release binaries, the README points to Homebrew, npm or Winget. Windows users get winget install --id defendend.ast-index. Building the unreleased default branch is a separate command: cargo install --locked --git https://github.com/defendend/Claude-ast-index-search ast-index. A manual build produces target/release/ast-index at roughly 44 MB, which is worth knowing if you are shipping this into a constrained container. There is also a documented failure mode on install. If brew install ast-index fails with merge conflict markers, the README's fix is to reset the local tap: cd into /opt/homebrew/Library/Taps/defendend/homebrew-ast-index, run git fetch origin and git reset --hard origin/main, then reinstall. That is a tap hygiene problem rather than a defect in the tool, but it is the kind of thing that stops a first-time install cold. Migration from the older kotlin-index is spelled out as uninstall, untap, re-tap under the new name, install.
Monorepos and worktrees: opt-in parent lookup, separate indexes per worktree
The monorepo behaviour is the most opinionated design decision in the README, and it is worth reading carefully before you file a bug. Read commands stop at the nearest project marker. If your repository has subdirectories carrying their own VCS markers, such as git submodules, subtrees, or nested Cargo.toml and settings.gradle files, those commands will not reuse a parent-level index even when one exists. You opt in with --walk-up or AST_INDEX_WALK_UP=1, and the README explains why this is not the default: silently preferring a far-away parent database could surface a stale or misconfigured index left by an earlier accidental rebuild higher up. That is a defensible position. It does mean a monorepo team has to make a deliberate choice per invocation or per environment, and an agent that forgets the flag will quietly query a narrower index than the operator expects. Worktrees are handled separately. Independent git worktrees get independent indexes because their canonical root paths differ, and the README says to rebuild once inside each worktree and not to attach worktrees to one another. For source trees that genuinely form one workspace, the supported path is subtree add: rebuild the primary project, run ast-index subtree add shared ../shared-library, then ast-index update or rebuild, and query with --subtree shared or --local. The README notes that the legacy root commands remain compatibility aliases and that new automation should use subtree add/remove/list.
Agent integration is a plugin and a rules file, not a wrapper
The integration model assumes the agent can run Bash and that you will teach it when to do so. For Claude Code there are two install routes: claude plugin marketplace add defendend/Claude-ast-index-search followed by claude plugin install ast-index, or ast-index install-claude-plugin if the binary is already present. A restart is required. The plugin ships /initialize as the default setup command, which auto-detects project stacks including KMP and polyglot repos, then writes .claude/settings.json and .claude/rules/ast-index.md. The README lists /initialize-android, /initialize-ios, /initialize-web, /initialize-rust, /initialize-csharp and /initialize-ruby as manual overrides rather than the default path. The rules file is the part that determines whether this works in practice. The README points to examples/.claude/rules/ast-index.md as a template that teaches the agent to use ast-index for structural navigation, outline before reading large files, and pass the same instructions to subagents, and it says to adapt the file before dropping it into your project. Codex support is thinner and more manual: symlink or copy the skill directory into ~/.codex/skills, for example ln -s /absolute/path/to/Claude-ast-index-search/plugin/skills/ast-index ~/.codex/skills/ast-index. The README describes Cursor as a supported consumer of the same Bash commands, but the material here does not document a Cursor-specific install step.
Where ast-index is the wrong tool
The index is only as current as the last update. The README instructs you to run ast-index update after edits or branch switches, which means every workflow that changes files outside a hook has a window in which queries describe the previous state. The bounded wait for a queued generation narrows that window; it does not remove the need to trigger an update at all. Second, the opt-in monorepo behaviour cuts both ways. A team that standardises on AST_INDEX_WALK_UP=1 for convenience is trusting a parent index that the README itself warns could be stale or misconfigured, and nothing in the material suggests a staleness check that would catch it. Third, language coverage is broad but it is a list, not a guarantee. If your language is not among the roughly three dozen named, the index will not have the structure to answer class or usages questions. Fourth, the token-economy figure is the project's own. If your repository is small, or your agent's questions are mostly free-text rather than structural, the index adds a rebuild step and a SQLite artifact without changing the cost of the answers. Finally, ast-index is a query layer, not an editor integration or a language server. It answers questions about structure; it does not resolve types across a build graph the way a compiler-backed tool would.
Compared with a language server, and with grep plus a text index
Two realistic alternatives exist, and they differ from ast-index in kind. A language server, in the LSP sense, resolves symbols against the compiler's own view of the project. It knows types, generics and overload resolution, and it stays current as you edit because the editor and server keep a session alive. ast-index does not attempt type resolution. It parses structure into SQLite and answers from that snapshot, which is why it can cover Kotlin, Swift, Rust, Python, Go, Protocol Buffers, BSL and GDScript in one binary without shipping a compiler front end per language. The trade is precision for breadth and for a command line an agent can call without a persistent session. The second alternative is grep plus a text index such as ripgrep or a code search server. Those return matches, not definitions, and they cannot answer implementations or callers at all without the caller doing the graph work. The README's own comparison table puts search at 11ms against 280ms for grep and usages at 8ms against 90ms, but the more meaningful difference is categorical: grep tells you a string appears, while implementations tells you which types satisfy an interface. The README also links a dated, source-backed CodeGraph comparison document, which is the right place to look if you are choosing between graph-oriented tools rather than between ast-index and grep.
Maintenance cost and licence
The release cadence visible in the material is fast: v3.50.0 in late July 2026, v3.51.0 in early September, v3.52.0 the same day as the last push to main. A project moving that quickly will occasionally rename or deprecate commands, and the README already shows one such transition, with the legacy root commands kept as compatibility aliases while subtree add/remove/list is designated for new automation. Budget for reading release notes before upgrading, and note that the Claude Code plugin has its own update path: brew upgrade ast-index && claude plugin update ast-index. The index itself is a local SQLite artifact, so the storage cost is per project and per worktree, not shared. The project is MIT licensed, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are retained. That is a permissive licence, not legal advice, and if you are embedding the binary in a distributed product you should confirm the notice requirements against the LICENSE file in the repository rather than against this summary. The README also links a Telegram channel at t.me/defendend_ai_dev, which is where project announcements appear; it is not a support contract.
Editorial conclusion
Adopt ast-index if your repository is large enough that grep-style text search returns more noise than signal and your agent already shells out to Bash, because the value comes from structural commands like class, usages and implementations rather than from search alone. Do not adopt it for a small single-language repo, for a polyglot monorepo whose nested VCS markers you are unwilling to manage with --walk-up, or for any workflow that cannot tolerate a rebuild step after branch switches. Verify two things before committing: that your language appears in the supported list, and that the ~40-50% token economy claim holds on your own tree, since the README reports it without publishing the method behind it.
Community notes