[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-78483":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":14,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":14,"stars7d":16,"stars30d":13,"stars90d":15,"forks30d":15,"starsTrendScore":17,"compositeScore":18,"rankGlobal":10,"rankLanguage":10,"license":19,"archived":20,"fork":20,"defaultBranch":21,"hasWiki":22,"hasPages":20,"topics":23,"createdAt":10,"pushedAt":10,"updatedAt":24,"readmeContent":25,"aiSummary":26,"trendingCount":15,"starSnapshotCount":15,"syncStatus":27,"lastSyncTime":28,"discoverSource":29},78483,"ast-bro","aeroxy\u002Fast-bro","aeroxy","Fast, AST-based code-navigation toolkit for source files — surface the shape of a file (signatures with line numbers, no method bodies), the true public API of a package, the dependency graph between files, the call graph between symbols, and search the repo by symbol or behaviour.","",null,"Rust",201,15,1,0,10,3,52.11,"MIT License",false,"main",true,[],"2026-06-12 04:01:23","# ast-bro\n\nFast, AST-based **code-navigation toolkit** for source files — surface the *shape* of a file (signatures with line numbers, no method bodies), the *true public API* of a package, the *dependency graph* between files, the *call graph* between symbols, and search the repo by *symbol* or *behaviour*. Fourteen subcommands, one binary, built for LLM coding agents and humans who’d rather not waste tokens reading every file just to understand a codebase.\n\n[ast-bro](https:\u002F\u002Fgithub.com\u002Faeroxy\u002Fast-bro) is written in Rust and uses [ast-grep](https:\u002F\u002Fgithub.com\u002Fast-grep\u002Fast-grep)’s incredibly fast [tree-sitter](https:\u002F\u002Fgithub.com\u002Ftree-sitter\u002Ftree-sitter) bindings. Thanks to [rayon](https:\u002F\u002Fgithub.com\u002Frayon-rs\u002Frayon), it parses your entire workspace concurrently—often in milliseconds. For Google- or ByteDance-scale monorepos, [ast-bro](https:\u002F\u002Fgithub.com\u002Faeroxy\u002Fast-bro) benefits from the additional abstraction layer provided by [repolayer](https:\u002F\u002Fgithub.com\u002Fzhousiyao03-cyber\u002Frepolayer).\n\n[![crates.io](https:\u002F\u002Fimg.shields.io\u002Fcrates\u002Fv\u002Fast-bro.svg)](https:\u002F\u002Fcrates.io\u002Fcrates\u002Fast-bro)\n[![npm](https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fv\u002F@ast-bro\u002Fcli)](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@ast-bro\u002Fcli)\n[![PyPI](https:\u002F\u002Fimg.shields.io\u002Fpypi\u002Fv\u002Fast-bro)](https:\u002F\u002Fpypi.org\u002Fproject\u002Fast-bro\u002F)\n[![License: MIT](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FLicense-MIT-yellow.svg)](.\u002FLICENSE)\n[![Ask DeepWiki](https:\u002F\u002Fdeepwiki.com\u002Fbadge.svg)](https:\u002F\u002Fdeepwiki.com\u002Faeroxy\u002Fast-bro)\n\n> **Renamed from `ast-outline` (v2.1.x and earlier).** The project outgrew \"outline\" — it now ships dep graphs, call graphs, hybrid semantic search, true public API resolution, and a structural search\u002Frewrite engine, not just structural outlining. The old name also collided with an unrelated [VS Code extension](https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=cancerberosgx.vscode-typescript-ast-outline) and an [npm package](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fast-outline) — too generic to keep.\n>\n> **Upgrading from `ast-outline`?** Run any `ast-bro` command once and it will auto-migrate `.ast-outline\u002F` → `.ast-bro\u002F` (cache), `.ast-outline-ignore` → `.ast-bro-ignore` (per-repo filter), `~\u002F.cache\u002Fast-outline\u002F` → `~\u002F.cache\u002Fast-bro\u002F` (model cache), and any `ast-outline` entries in your MCP config → `ast-bro`. The legacy `ast-outline` binary is still installed as a thin proxy that execs into `ast-bro`, and a shorter `sb` alias ships alongside, so existing scripts keep working.\n\n---\n\n## Purpose\n\n**[ast-bro](https:\u002F\u002Fgithub.com\u002Faeroxy\u002Fast-bro) exists to make LLM coding agents faster, cheaper, and smarter\nwhen navigating unfamiliar code.**\n\nModern agentic coding tools explore codebases by reading files directly. That's reliable but has a massive cost: on a 1000-line file, the agent pays for 1000 lines of tokens just to answer *\"what methods exist here?\"* — and reading is only one of several questions an agent has. *\"Who imports this?\"* *\"What's the public API?\"* *\"Are there cycles?\"* *\"Where in the repo is the login flow?\"* — each one historically required dozens of file reads or noisy `grep`s.\n\n[ast-bro](https:\u002F\u002Fgithub.com\u002Faeroxy\u002Fast-bro) collapses each of those questions into a single command:\n\n1. **Shape over bytes.** `map` \u002F `digest` \u002F `show` give you signatures and line ranges instead of method bodies — typically a **95% token saving** vs reading the file. `implements` finds subclasses with AST accuracy, no `grep` false positives.\n2. **Published API in one call.** `surface` resolves `pub use` re-exports (Rust), `__all__` (Python), barrel files (TypeScript), `export` clauses (Scala) so you see the surface a downstream user actually sees — not the union of every public item per file.\n3. **Dependency graph for free.** `deps` \u002F `reverse-deps` \u002F `cycles` \u002F `graph` build a file-level import graph (Rust, Python, TS\u002FJS, Java, C#, Kotlin, Scala, Go) cached at `.ast-bro\u002Fgraph\u002F`. Use `reverse-deps` before refactoring to know the blast radius. `cycles` exits non-zero — wire it into a CI gate. `graph` emits the full dependency graph (text by default, `--json` for JSON).\n4. **Symbol-level call graph.** `callers` \u002F `callees` answer \"who calls X\" and \"what does X call\" with AST accuracy across all 14 languages — no `grep` false positives on overloaded names, comments, or string literals. Both are kind-aware: ask for a function and you get call-sites; ask for a type and you get implementors \u002F constructions \u002F ancestors. A three-pass resolver (same-file → global symbol table → dep-graph disambiguation) tags every edge `Exact` \u002F `Inferred` \u002F `Ambiguous` so you can filter by precision. Same on-disk cache as the dep graph.\n5. **Hybrid semantic search.** `search` runs BM25 + dense embeddings via [`potion-code-16M`](https:\u002F\u002Fhuggingface.co\u002Fminishlab\u002Fpotion-code-16M) (a static, no-inference model — ~64 MB, runs on CPU in microseconds). `find-related` returns chunks structurally similar to one you already have, with a dep-graph-aware boost when a graph cache exists.\n6. **Fourteen native MCP tools.** Every CLI command is also exposed as an MCP tool — `ast-bro install --mcp \u003Cagent>` wires it into Claude Code, Cursor, Gemini, Codex, or VS Code Copilot in one line.\n\n### The workflow\n\n**Before [ast-bro](https:\u002F\u002Fgithub.com\u002Faeroxy\u002Fast-bro):**\n\n```\nAgent: Read Player.cs            # 1200 lines of tokens\nAgent: Read Enemy.cs             # 800 lines of tokens\nAgent: Read DamageSystem.cs      # 400 lines of tokens\nAgent: grep \"IDamageable\" src\u002F   # noisy, lots of false matches\n...\n```\n\n**With [ast-bro](https:\u002F\u002Fgithub.com\u002Faeroxy\u002Fast-bro):**\n\n```console\nAgent: ast-bro surface .                  # one-page true public API of the crate\u002Fpackage\nAgent: ast-bro digest src\u002FCombat          # ~100 lines, whole module's structure\nAgent: ast-bro implements IDamageable     # precise list, no grep noise\nAgent: ast-bro search \"damage handling\"   # hybrid BM25 + dense semantic, ranked\nAgent: ast-bro show Player.cs TakeDamage  # just the method body\nAgent: ast-bro reverse-deps Player.cs     # who imports this — blast radius before refactor\nAgent: ast-bro callers Player.TakeDamage  # AST-accurate call sites — no grep false positives\nAgent: ast-bro callees Player.TakeDamage  # what TakeDamage itself calls\nAgent: ast-bro cycles src\u002F                # find import cycles via Tarjan SCC\n```\n\nResult: **same understanding, a fraction of the tokens, a fraction of the round-trips.**\nFor \"what does this package actually expose?\" — historically the most expensive question, since the answer was \"read every file\" — `surface` resolves the re-export graph and gives you the answer directly, often replacing dozens of file reads with a single call. For \"what would break if I change this method?\" — `callers` gives you the AST-accurate set of call sites in one shot, instead of `grep`-ing a homonym across the repo.\n\n---\n\n## Supported languages\n\n| Language | Extensions |\n| --- | --- |\n| Rust       | `.rs` |\n| C#         | `.cs` |\n| C++        | `.cpp`, `.cc`, `.cxx`, `.hpp`, `.hh` |\n| Python     | `.py`, `.pyi` |\n| TypeScript | `.ts`, `.tsx` |\n| JavaScript | `.js`, `.jsx`, `.mjs`, `.cjs` |\n| Java       | `.java` |\n| Kotlin     | `.kt`, `.kts` |\n| Scala      | `.scala`, `.sc` |\n| Go         | `.go` |\n| PHP        | `.php` |\n| Ruby       | `.rb` |\n| SQL        | `.sql`, `.ddl`, `.dml` |\n| Markdown   | `.md`, `.markdown`, `.mdx`, `.mdown` |\n\n*More coming soon! Adding another language is a single new adapter file leveraging the massive `ast-grep` language ecosystem.*\n\n---\n\n## What gets walked\n\n[ast-bro](https:\u002F\u002Fgithub.com\u002Faeroxy\u002Fast-bro) skips a lot of files when walking a directory — by design. Filters apply uniformly across every subcommand.\n\n1. **`.gitignore` and friends** — every level's `.gitignore`, your global gitignore, `.git\u002Finfo\u002Fexclude`, and `.ignore` files (the [`ignore`](https:\u002F\u002Fcrates.io\u002Fcrates\u002Fignore) crate's convention used by `ripgrep`\u002F`fd`).\n2. **Hardcoded denylist** — directories almost no one wants walked, even if `.gitignore` doesn't list them: `.git`, `node_modules`, `target`, `dist`, `build`, `__pycache__`, `.venv`, `venv`, `.cache`, `.idea`, `.vscode`, `.next`, `.nuxt`, `.turbo`, `.parcel-cache`, `.gradle`, `.tox`, `.mypy_cache`, `.pytest_cache`, `.ruff_cache`, `.eggs`, `.ast-bro`, and a few others.\n3. **`.ast-bro-ignore`** — per-repo escape hatch. Same syntax as `.gitignore`. Useful for excluding paths from [ast-bro](https:\u002F\u002Fgithub.com\u002Faeroxy\u002Fast-bro) that you *don't* want excluded from git itself, e.g. test fixtures or vendored corpora:\n\n   ```gitignore\n   # .ast-bro-ignore\n   tests\u002Ffixtures\u002Flarge_corpus\u002F\n   benches\u002Fdata\u002F\n   *.generated.rs\n   ```\n4. **Extension allowlist** — files are only opened if their extension is one ast-bro knows how to parse (the table above for map\u002Fdigest\u002Fshow\u002Fimplements; a broader set for the search commands).\n\nWant to see exactly what ast-bro walks? Compare `ast-bro digest some\u002Fdir` with `rg --files some\u002Fdir` — anything in `rg` but not the digest is being filtered by one of the layers above.\n\n---\n\n## Install\n\n### Homebrew (macOS)\n\n```bash\nbrew install aeroxy\u002Ftap\u002Fast-bro\n```\n\n### npm\n\n```bash\nnpm install -g @ast-bro\u002Fcli\n```\n\n### pip\n\n```bash\npip install ast-bro\n```\n\n### Cargo\n\n```bash\ncargo install ast-bro\n```\n\nThis installs the [ast-bro](https:\u002F\u002Fgithub.com\u002Faeroxy\u002Fast-bro) CLI globally into `~\u002F.cargo\u002Fbin` — make sure that's on your `PATH`.\n\n### Nix\n\nYou can run [ast-bro](https:\u002F\u002Fgithub.com\u002Faeroxy\u002Fast-bro) directly with Nix without installing:\n\n```bash\nnix run github:aeroxy\u002Fast-bro\n```\n\nOr add it as a dependency in your Nix flake:\n\n```nix\n{\n  inputs = {\n    nixpkgs.url = \"github:NixOS\u002Fnixpkgs\u002Fnixpkgs-unstable\";\n    ast-bro.url = \"github:aeroxy\u002Fast-bro\";\n  };\n\n  outputs = { self, nixpkgs, ast-bro }:\n    let\n      system = \"x86_64-linux\";\n      pkgs = nixpkgs.legacyPackages.${system};\n    in {\n      devShells.${system}.default = pkgs.mkShell {\n        buildInputs = [ ast-bro.packages.${system}.default ];\n      };\n    };\n}\n```\n\n---\n\n## Quick start\n\n```bash\n# Map the structure of one file\nast-bro map path\u002Fto\u002FPlayer.rs\nast-bro map path\u002Fto\u002Fuser_service.py\n\n# Map a whole directory (recurses supported extensions in parallel)\nast-bro map src\u002F\n\n# Print the exact source of one specific method\nast-bro show Player.cs TakeDamage\n\n# Compact public-API map of a whole module\nast-bro digest src\u002FServices\n\n# True public surface (resolves `pub use` \u002F `__all__`, not every `pub` item)\nast-bro surface .                  # auto-detect Cargo.toml \u002F pyproject.toml \u002F __init__.py\nast-bro surface --tree --include-chain mycrate\u002F\n\n# Every class that inherits\u002Fimplements a given type\nast-bro implements IDamageable src\u002F\n\n# Dependency graph: forward, reverse, cycles, full\nast-bro deps src\u002Fauth.rs --depth 2  # what auth.rs imports (transitively)\nast-bro reverse-deps src\u002Fauth.rs    # who imports auth.rs (refactor blast radius)\nast-bro cycles                      # find import cycles via Tarjan SCC\nast-bro graph .                     # full dependency graph (text)\nast-bro graph . --json              # same, as JSON (ast-bro.graph.v1)\n\n# Call graph: who calls X, what does X call (AST-accurate, all 14 langs)\nast-bro callers TakeDamage              # function\u002Fmethod: in-edges\nast-bro callers Player                  # type: implementors + constructions\nast-bro callees Player.TakeDamage       # function\u002Fmethod: out-edges\nast-bro callees Player --depth 2        # type: ancestor walk (transitive)\nast-bro callers src\u002FPlayer.cs:TakeDamage --include-ambiguous\n\n# Hybrid BM25 + dense semantic search (builds an index on first call)\nast-bro search \"how does login work\"\nast-bro search \"HandlerStack\" -k 5\n\n# Find code semantically similar to a given file:line\nast-bro find-related src\u002Fauth\u002Flogin.rs:42\n\n# Build \u002F refresh \u002F inspect the per-repo search index\nast-bro index            # build or refresh\nast-bro index --stats    # show chunk count, model, etc.\nast-bro index --rebuild  # drop cache and rebuild\n\n# Output a prompt snippet to steer LLM agents\nast-bro prompt >> AGENTS.md\n\n# Machine-readable JSON (stable schema, great for tooling)\nast-bro map src\u002Fplayer.rs --json\nast-bro digest src\u002F --json\nast-bro show Player.cs TakeDamage --json\nast-bro implements IDamageable src\u002F --json\nast-bro search \"json rendering\" --json\n```\n\n---\n\n## Using with LLM coding agents\n\nThis is the main use case. The fastest path is `ast-bro install`,\nwhich writes the agent prompt snippet (and, where supported, a real\n`Read`-interceptor hook) into your coding agent's config.\n\n```bash\n# Install into every supported CLI it can detect on your system.\nast-bro install --all\n\n# Or pick a single target.\nast-bro install --target claude-code\nast-bro install --target gemini --min-lines 150\n\n# See exactly what would change before writing.\nast-bro install --all --dry-run\n\n# Per-repo install (default is global).\nast-bro install --target claude-code --local\n\n# Remove everything we wrote.\nast-bro uninstall --all\n\n# Quick visibility.\nast-bro status\n```\n\nSupported targets: `claude-code`, `gemini`, `tabnine`, `cursor`,\n`aider`, `codex`, `copilot`. Claude Code, Gemini, and Tabnine also get\na tool-call hook that intercepts `Read` on supported source files when\nthey exceed `--min-lines` (default 200) and substitutes the map output.\nThe other targets receive the prompt only.\n\n### Claude Code subagent shadowing\n\nClaude Code has isolated subagents (Explore, Plan, general-purpose) that run in\ntheir own context and cannot see the main `CLAUDE.md`. `ast-bro install` \nautomatically shadows these subagents with `.claude\u002Fagents\u002F\u003CName>.md` files \ncontaining the full ast-bro prompt.\n\nWhen you run `ast-bro install --target claude-code`, you get:\n- `CLAUDE.md` — main agent prompt (global or local per-repo)\n- `.claude\u002Fsettings.json` — `Read` tool hook\n- `.claude\u002Fagents\u002FExplore.md` — Explore subagent with the prompt injected\n\nThis solves the \"why doesn't my subagent use ast-bro?\" problem — subagents\nnow get the prompt automatically. Legacy manual `~\u002F.claude\u002Fagents\u002FExplore.md` files\nare wrapped in marker blocks in-place (non-breaking).\n\n### Skills for manual installation\n\nA `skills\u002F` folder is included in the repo for users who prefer manual setup:\n\n```bash\n# Clone or download the repo\ngit clone https:\u002F\u002Fgithub.com\u002Faeroxy\u002Fast-bro.git\ncd ast-bro\n\n# Copy the skill to your user skills directory\ncp -r skills\u002Fast-bro ~\u002F.claude\u002Fskills\u002Fast-bro\n\n# Then manually invoke from Claude Code\n\u002Fast-bro\n```\n\nThis works alongside `ast-bro install` — the skill definition tells Claude Code\nhow to invoke the [ast-bro](https:\u002F\u002Fgithub.com\u002Faeroxy\u002Fast-bro) CLI with proper tool schemas and documentation.\n\nManual install via `ast-bro prompt` (e.g. project-level):\n\n```bash\nast-bro prompt >> AGENTS.md\nast-bro prompt | pbcopy   # macOS clipboard\n```\n\n### Works with\n\n- Claude Code (+ custom subagents like `Explore`, `codebase-scout`)\n- Cursor agent mode\n- Aider\n- Copilot Chat \u002F Workspace\n- Any custom agent on the Claude \u002F OpenAI \u002F Gemini APIs\n- Humans (the colored terminal format is highly readable; `show` is a nice alternative to `grep -A 20`)\n\n---\n\n## Output format\n\nThe format is designed to be **LLM-friendly**: Python-style indentation,\nline-number suffixes in `L\u003Cstart>-\u003Cend>` form, doc-comments preserved.\nThe header summarises scale and flags partial parses.\n\nWhen you run it yourself, you'll see a gorgeous ANSI-colored output. Don't worry, the terminal colors are automatically stripped when piped to a file or consumed by an agent's shell hook!\n\n### Rust\n\n```\n# src\u002Fcore.rs (490 lines, 3 types, 12 methods, 5 fields)\npub struct Declaration  L10-120\n    pub kind: DeclarationKind  L12\n    pub name: String  L15\n    pub fn lines_suffix(&self) -> String  L30-48\n```\n\n### `show` with ancestor context\n\n`ast-bro show \u003Cfile> \u003CSymbol>` prints a `# in: ...` breadcrumb\nbetween the header and the body so you know what the extracted code is\nnested inside, without a second `map` call:\n\n```\n# Player.cs:30-48  Game.Player.PlayerController.TakeDamage  (method)\n# in: namespace Game.Player → public class PlayerController : MonoBehaviour, IDamageable\n\u002F\u002F\u002F \u003Csummary>Apply damage.\u003C\u002Fsummary>\npublic void TakeDamage(int amount) { ... }\n```\n\n---\n\n## JSON output\n\nAdd `--json` to any command to get the full symbol graph as stable,\nstructured JSON instead of formatted text — ideal for editors, language\nservers, CI tooling, or any script that needs to consume the data\nprogrammatically.\n\n```bash\nast-bro map src\u002Fplayer.rs --json        # per-file map\nast-bro digest src\u002F --json              # digest view\nast-bro show Player.cs TakeDamage --json\nast-bro implements IDamageable src\u002F --json\nast-bro map src\u002F --json --compact       # single-line (no pretty-print)\n```\n\nEvery JSON document includes a `schema` field that is bumped on breaking\nchanges, so downstream tooling can guard on it:\n\n```json\n{\n  \"schema\": \"ast-bro.outline.v1\",\n  \"files\": [\n    {\n      \"path\": \"src\u002Fplayer.rs\",\n      \"language\": \"rust\",\n      \"line_count\": 312,\n      \"error_count\": 0,\n      \"declarations\": [\n        {\n          \"kind\": \"struct\",\n          \"name\": \"Player\",\n          \"signature\": \"pub struct Player\",\n          \"visibility\": \"pub\",\n          \"start_line\": 10,\n          \"end_line\": 40,\n          \"children\": [ ... ]\n        }\n      ]\n    }\n  ]\n}\n```\n\n| Schema | Command |\n|--------|----------|\n| `ast-bro.outline.v1` | default outline, `digest --json` |\n| `ast-bro.show.v1` | `show --json` |\n| `ast-bro.implements.v1` | `implements --json` |\n| `ast-bro.surface.v1` | `surface --json` |\n| `ast-bro.deps.v1` | `deps --json` |\n| `ast-bro.reverse-deps.v1` | `reverse-deps --json` |\n| `ast-bro.cycles.v1` | `cycles --json` |\n| `ast-bro.graph.v1` | `graph --json` |\n| `ast-bro.callers.v1` | `callers --json` |\n| `ast-bro.callees.v1` | `callees --json` |\n| `ast-bro.search.v1` | `search --json` |\n| `ast-bro.related.v1` | `find-related --json` |\n| `ast-bro.index-stats.v1` | `index --stats --json` |\n\n---\n\n## MCP server\n\nRun [ast-bro](https:\u002F\u002Fgithub.com\u002Faeroxy\u002Fast-bro) as a [Model Context Protocol](https:\u002F\u002Fmodelcontextprotocol.io)\nserver over stdio so any MCP-aware coding agent can call the same operations\nas native tools — no shell parsing required:\n\n```bash\nast-bro mcp\n```\n\nThe server speaks line-delimited JSON-RPC 2.0 on stdin\u002Fstdout and exposes fourteen\ntools that map 1:1 to the CLI commands:\n\n| Tool | Equivalent CLI | Returns |\n|------|----------------|---------|\n| `map`          | `ast-bro map \u003Cpaths>`                | text, or `ast-bro.map.v1` with `json: true` |\n| `digest`       | `ast-bro digest \u003Cpaths>`             | text, or `ast-bro.map.v1` with `json: true` |\n| `show`         | `ast-bro show \u003Cpath> \u003Csyms>`         | text, or `ast-bro.show.v1` with `json: true` |\n| `implements`   | `ast-bro implements \u003Ctype> \u003Cpaths>`  | text, or `ast-bro.implements.v1` with `json: true` |\n| `callers`      | `ast-bro callers \u003Csymbol>`           | text, or `ast-bro.callers.v1` with `json: true` |\n| `callees`      | `ast-bro callees \u003Csymbol>`           | text, or `ast-bro.callees.v1` with `json: true` |\n| `surface`      | `ast-bro surface [path]`             | text, or `ast-bro.surface.v1` with `json: true` |\n| `deps`         | `ast-bro deps \u003Cfile>`                | text, or `ast-bro.deps.v1` with `json: true` |\n| `reverse_deps` | `ast-bro reverse-deps \u003Cfile>`        | text, or `ast-bro.reverse-deps.v1` with `json: true` |\n| `cycles`       | `ast-bro cycles [path]`              | text, or `ast-bro.cycles.v1` with `json: true` |\n| `graph`        | `ast-bro graph [path]`               | text by default; `json: true` for `ast-bro.graph.v1` |\n| `search`       | `ast-bro search \"\u003Cquery>\"`           | text, or `ast-bro.search.v1` with `json: true` |\n| `find_related` | `ast-bro find-related \u003Cfile>:\u003Cline>` | text, or `ast-bro.related.v1` with `json: true` |\n| `index`        | `ast-bro index`                      | text, or `ast-bro.index-stats.v1` with `json: true` |\n\nWire it into a client by pointing at the binary:\n\n```jsonc\n{\n  \"mcpServers\": {\n    \"ast-bro\": { \"command\": \"ast-bro\", \"args\": [\"mcp\"] }\n  }\n}\n```\n\nThe server is fully synchronous, has no extra runtime dependencies, and adds\nroughly 1% to the binary size. The CLI itself is unaffected — none of the MCP\ncode runs unless you invoke the `mcp` subcommand.\n\n---\n\n## Semantic search\n\n`ast-bro search` runs hybrid retrieval over a per-repo index:\n\n- **BM25** for exact identifier matches and keyword density.\n- **Dense embeddings** via [`minishlab\u002Fpotion-code-16M`](https:\u002F\u002Fhuggingface.co\u002Fminishlab\u002Fpotion-code-16M) — a static (no inference) `vocab × 256` model that runs on CPU in microseconds.\n- **Reciprocal Rank Fusion** (k = 60) blends the two; alpha auto-resolves to 0.3 for symbol queries (`HandlerStack`, `Sinatra::Base` — lean BM25) and 0.5 for natural language (\"how does login work\" — balanced).\n- A ranking pass adds definition boosts (3× for chunks that *define* a queried symbol), file-coherence boosts (multi-chunk hits in the same file lift the top chunk), file-stem matches for NL queries, and path-based penalties (test files 0.3×, `.d.ts` stubs 0.7×, `__init__.py` 0.5×).\n\n`ast-bro find-related \u003Cfile>:\u003Cline>` is the same engine in semantic-only mode, language-filtered, with the source chunk excluded — useful for \"what else is structured like this?\"\n\n```bash\nast-bro search \"request validation\" -k 5\nast-bro search \"HandlerStack\" --json\nast-bro find-related src\u002Fauth\u002Flogin.rs:42 -k 3\n```\n\n### How indexing works\n\nFirst call to `search` \u002F `find-related` builds an index at `.ast-bro\u002Findex\u002F`:\n\n```text\n.ast-bro\u002F\n  .gitignore           # auto-written, contents: \"*\"\n  index\u002F\n    meta.json          # schema + model + chunk_count\n    chunks.bin         # per-chunk content + line range + language\n    embeddings.f32     # chunk_count × 256 little-endian f32, mmap-friendly\n    bm25.bin           # vocab + idf + postings\n    files.bin          # per-file mtime + xxhash + chunk range\n    lock               # advisory lock for concurrent writers\n```\n\nSubsequent calls walk the tree, compare `(mtime, size)` against `files.bin`, and only hash files where the cheap check fails. If anything changed, the index rebuilds automatically (a v2 will support partial updates against the same on-disk format). Steady-state cost on an unchanged 10k-file repo: ~30 ms of stat syscalls.\n\nThe model is downloaded once (~64 MB) on first use to `~\u002F.cache\u002Fast-bro\u002Fmodels\u002F`. It tries HuggingFace first, falls back to `hf-mirror.com` if blocked. **TLS verification is disabled by default** so corporate MITM proxies don't break setup; integrity is enforced via SHA-256 on every cached file. Set `AST_OUTLINE_TLS_STRICT=1` to enforce strict TLS.\n\nFor more on what gets indexed (the five filter layers, `.ast-bro-ignore` syntax) see the \"What gets walked\" section above. For the security trade-offs around the TLS default, see the [network-security wiki page](https:\u002F\u002Fgithub.com\u002Faeroxy\u002Fast-bro\u002Fblob\u002Fmain\u002Fwiki\u002Fnetwork-security.md) on GitHub.\n\n`find-related` quietly benefits from the dep graph too — when one is cached, results are reranked so files within depth 2 of the source (importer or importee) get a multiplicative boost. Disable with `--no-dep-boost`.\n\n---\n\n## Dependency graph\n\n`ast-bro deps`, `reverse-deps`, `cycles`, and `graph` build a file-level import graph for the project and answer different questions on it:\n\n```bash\nast-bro deps src\u002Fauth.rs --depth 2          # what does auth.rs pull in?\nast-bro reverse-deps src\u002Fauth.rs            # who imports auth.rs? (refactor blast radius)\nast-bro cycles                              # find import cycles via Tarjan SCC (exit 3 if any)\nast-bro graph .                              # full dependency graph (text)\nast-bro graph . --json                      # same, as JSON (ast-bro.graph.v1)\n```\n\nAll four commands share one cache at `.ast-bro\u002Fgraph\u002Findex.bin` (a unified `UnifiedGraph { deps, calls: Option\u003CCallGraph> }` — same file used by `callers` \u002F `callees`, see below). First call builds the dep half (~hundreds of ms for typical repos via the same `ignore`-respecting walk used by search); subsequent calls reuse it via per-file delta detection, with `--rebuild` to force a fresh build. Inside `ast-bro mcp`, every `tools\u002Fcall` shares one in-memory `Arc\u003CUnifiedGraph>` so the second invocation in a session is a memory read, not a disk read.\n\nResolution is per-language but shares one suffix-index resolver:\n\n- **Rust**: `use crate::*` \u002F `use super::*` \u002F `mod foo;` (with `#[path]` attribute support).\n- **Python**: relative imports (`from .x import y`), `__init__.py` packages, bare `import a.b`.\n- **TypeScript \u002F JavaScript**: relative paths with extension probing (`.ts → .tsx → .mts → .cts → .d.ts → .js → ... → .json`), `index.*` fallback, `tsconfig.json` `paths` aliases.\n- **Java \u002F Kotlin \u002F Scala \u002F C#**: FQN suffix index built from each file's `package` \u002F `namespace` declaration. Inner classes resolve via strip-and-retry.\n- **Go**: `go.mod` `module` prefix is stripped; `import \"mymod\u002Fpkg\u002Ffoo\"` resolves to `pkg\u002Ffoo\u002F*.go` (directory-as-package).\n\nThe four commands are also exposed as MCP tools for agents. For internals (suffix index, Tarjan SCC, per-file invalidation, find-related dep boost) see the [deps wiki page](https:\u002F\u002Fgithub.com\u002Faeroxy\u002Fast-bro\u002Fblob\u002Fmain\u002Fwiki\u002Fdeps.md) on GitHub.\n\n---\n\n## Call graph\n\n`ast-bro callers` and `ast-bro callees` answer \"who calls X\" and \"what does X call\" with AST accuracy across all 14 languages. They replace `grep` for refactor blast-radius assessment — no false positives on overloaded names, comments, or string literals.\n\n```bash\nast-bro callers TakeDamage              # function\u002Fmethod: in-edges\nast-bro callees TakeDamage              # function\u002Fmethod: out-edges\nast-bro callers Player                  # type: implementors + constructions\nast-bro callees Player --depth 2        # type: ancestor walk (transitive)\nast-bro callers Player.TakeDamage --include-ambiguous --json\n```\n\nBoth commands are **kind-aware**:\n\n| Target kind | `callers X` | `callees X` |\n|---|---|---|\n| function \u002F method \u002F constructor | call sites that invoke `X` | call sites inside `X`'s body |\n| class \u002F struct \u002F trait \u002F interface \u002F enum \u002F record | implementors + constructions (covers `Foo()`, `new Foo()`, `Foo {}`, `Foo::new()`) | ancestor types and the methods they declare (transitive via `--depth N`) |\n\nSymbol forms accepted by both: bare suffix (`TakeDamage`), dotted (`Player.TakeDamage`), file-scoped (`src\u002FPlayer.cs:TakeDamage`), or flag form (`--file src\u002FPlayer.cs --symbol TakeDamage`).\n\n**Three-pass resolver.** Bare names are disambiguated in three increasing-cost passes:\n\n1. **Same-file** — local definitions + per-file `import` \u002F `use` \u002F `using` bindings.\n2. **Global symbol table** — single-match promotion across the project. Receiver-bearing calls (`obj.bar()`) skip this pass to avoid `builder.hidden()`-style false positives on global homonyms.\n3. **Dep-graph disambiguation** — for ambiguous matches, filter candidates by the caller's transitive forward-dep closure.\n\nEvery edge carries a `Confidence` tag — `Exact` (passes A\u002FB), `Inferred` (pass C narrowed to one), or `Ambiguous` (multiple candidates survive). `--include-ambiguous` (callers) and `--external` (callees) surface the noisier results when explicitly requested.\n\n**Cache.** Same `.ast-bro\u002Fgraph\u002Findex.bin` as the dep graph, lazily promoted — users who only run `deps` \u002F `cycles` never pay the call-graph build cost. Per-file invalidation: edit one file, only that file gets re-extracted and re-resolved.\n\nFor internals (per-language node-kind tables, the call-shape pitfalls each adapter handles, the per-file patch path, cost numbers) see the [calls wiki page](https:\u002F\u002Fgithub.com\u002Faeroxy\u002Fast-bro\u002Fblob\u002Fmain\u002Fwiki\u002Fcalls.md) on GitHub.\n\n---\n\n## Architecture & Development\n\nSee the [wiki](https:\u002F\u002Fgithub.com\u002Faeroxy\u002Fast-bro\u002Fblob\u002Fmain\u002Fwiki\u002Farchitecture.md) on GitHub for details on how [ast-bro](https:\u002F\u002Fgithub.com\u002Faeroxy\u002Fast-bro) leverages `ast-grep` internally and how you can add new language adapters.\n\n### Getting started\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002Faeroxy\u002Fast-bro.git\ncd ast-bro\n\n# With Cargo\ncargo run -- digest src\u002F\n\n# With Nix flake\nnix develop        # Enter development shell\nnix build          # Build the project\nnix flake check    # Run all checks (tests, clippy, formatting)\n```\n\nContributions welcome.\n\n---\n\n## License\n\n[MIT](.\u002FLICENSE)\n","ast-bro 是一个基于抽象语法树（AST）的快速代码导航工具包，用于源文件分析。它能够展示文件结构（包括带行号的签名但不包含方法体）、包的真实公共API、文件间的依赖图、符号间的调用图，并支持通过符号或行为搜索代码库。该项目使用Rust语言编写，利用了ast-grep 的高性能tree-sitter绑定和rayon库实现并行解析，极大提高了处理速度。适用于大型代码库尤其是对于需要高效理解和导航代码的开发者及LLM编码代理来说，ast-bro是一个理想的选择。",2,"2026-06-11 03:56:51","CREATED_QUERY"]