ast-search-js
v1.10.0
Published
AST-based code search for JavaScript, TypeScript, and Vue
Maintainers
Readme
ast-search-js
Structural code search for JS/TS/Vue — designed for large-scale refactors and AI agent workflows. Finds code by shape, not string.
Accepts a query and searches all supported files under a directory, printing each match with its file path, line, and column. Language support is provided by plugins — the core handles JS/TS/Vue; additional languages are opt-in.
Agents: see AGENTS.md for tool descriptions, output format details, and usage patterns.
Table of Contents
Example
Say you have Vue SFCs with setup() functions that improperly access this:
export default {
setup() {
const value = computed(() => {
return this.testValue // shouldn't be here
})
}
}Find all such occurrences across your whole repo:
ast-search 'ObjectMethod[key.name="setup"] ThisExpression'Output:
src/components/Foo.vue:5:13: return this.testValue
src/components/Bar.vue:9:18: return this.otherPropInstallation
npm install -g ast-search-js
# Optional: add Python support
npm install -g ast-search-pythonAgent and LLM usage
ast-search is designed to work well as a tool in AI agent workflows:
- Token-efficient — outputs only match locations, not whole file contents
- Machine-readable —
--format jsonreturns a structured array ready for parsing - Structurally precise — selector-based queries eliminate false positives from string matching
- Composable —
--format filesproduces a newline-delimited list suitable for piping toxargsor subsequent tool calls - Multi-query — pass multiple queries in one invocation; each file is parsed once and all queries run against it, eliminating redundant I/O
Usage
ast-search <query> [query2 ...] [--dir <path>] [--format <fmt>] [--lang <id>] [--plugin <pkg>]Multiple queries can be passed as positional arguments. All queries run against each file's AST in a single repo walk — each file is parsed once regardless of how many queries you provide. In --format json, every match includes a query field identifying which selector produced it.
| Argument | Description | Default |
| ------------------ | ------------------------------------------------------------- | ------------ |
| <query> [query2 ...] | One or more query strings (see Query Syntax below) | required |
| -d, --dir | Root directory to search | current dir |
| -f, --format | Output format: text, json, files, or count | text |
| -l, --lang | Restrict search to one language backend (e.g. js, python) | all languages |
| -p, --plugin | Load a language plugin package (repeatable) | none |
| -C, --context | Show N lines of context around each match (like grep -C) | 0 |
| --ast | Print AST for a code snippet (positional arg) or --file; useful for writing queries | off |
Output formats
text(default) — one match per line asfile:line:col: source; when the query uses regex matchers, captured values are appended after|files— unique file paths only, one per line; useful for piping toxargsjson— full match array as JSON; includes acapturesfield when regex matchers were usedcount— per-file match counts sorted by frequency, plus a summary line; useful for scoping a refactor before running a full search
Query syntax
JavaScript / TypeScript / Vue
Queries use esquery CSS selector syntax over Babel AST node types. A few examples:
# Find all arrow functions inside a function named "setup"
ast-search 'ObjectMethod[key.name="setup"] ArrowFunctionExpression'
# Find await expressions anywhere
ast-search 'AwaitExpression'
# Find assignments inside catch clauses
ast-search 'CatchClause AssignmentExpression'
# Find logging calls across multiple methods — regex attribute matching
# Captures the matched method name: | callee.property.name=warn
ast-search 'call[callee.property.name=/^(log|info|warn|error)$/]'Attribute selectors support both exact strings ([prop="value"]) and regex literals ([prop=/pattern/flags]). Regex matchers automatically capture the matched value in the result's captures field.
Shorthands
Common node types can be written as short keywords:
| Shorthand | Expands to |
| ---------- | --------------------------- |
| this | ThisExpression |
| await | AwaitExpression |
| yield | YieldExpression |
| new | NewExpression |
| call | CallExpression |
| arrow | ArrowFunctionExpression |
| fn | FunctionExpression |
| member | MemberExpression |
| ternary | ConditionalExpression |
| template | TemplateLiteral |
| tagged | TaggedTemplateExpression |
| assign | AssignmentExpression |
| binary | BinaryExpression |
| logical | LogicalExpression |
| spread | SpreadElement |
The original Vue this example using shorthands:
ast-search 'ObjectMethod[key.name="setup"] this'Optional chaining
Optional chains (?.) are normalized transparently — CallExpression and MemberExpression selectors match both regular and optional-chain variants:
# Matches both items.map(...) and items?.map(...)
ast-search 'CallExpression[callee.property.name="map"]'The optional flag is preserved on matched nodes, so you can still narrow to strictly optional calls:
ast-search 'CallExpression[optional=true]'Python
For Python support, see ast-search-python.
Supported file types
Core: .js .ts .jsx .tsx .mjs .cjs .vue
Via plugin: see ast-search-python for .py / .pyw support.
Plugin API
Language support is extensible. See the Plugin API section in the repository README for the LanguageBackend interface and instructions for writing a language plugin.
