| name | ast-grep |
| description | Search code by AST patterns and perform structural refactoring across files. Use when finding function calls, replacing code patterns, or refactoring syntax that regex cannot reliably match. |
ast-grep
Structural code search and rewriting using AST matching instead of regex.
Contents
Pattern Syntax
ast-grep uses pattern placeholders to match and capture AST nodes:
| Pattern | Description |
|---|
$VAR | Match a single AST node and capture it as VAR |
$$$VAR | Match zero or more AST nodes (spread) and capture as VAR |
$_ | Anonymous placeholder (matches any single node, no capture) |
$$$_ | Anonymous spread placeholder (matches any number of nodes) |
Shell quoting tip: Escape $ as \$VAR or wrap the pattern in single quotes to avoid shell expansion.
Supported Languages
javascript, typescript, tsx, html, css, python, go, rust, java, c, cpp, csharp, ruby, php, yaml
Commands
| Command | Description |
|---|
ast-grep run | One-time search or rewrite (default) |
ast-grep scan | Scan and rewrite by configuration |
ast-grep test | Test ast-grep rules |
ast-grep new | Create new project or rules |
ast-grep lsp | Start language server |
Usage
Basic Search
Find patterns in code:
ast-grep run --pattern 'console.log($$$ARGS)' --lang javascript .
ast-grep run --pattern 'const [$STATE, $SETTER] = useState($INIT)' --lang tsx .
ast-grep run --pattern 'async function $NAME($$$ARGS) { $$$BODY }' --lang typescript .
ast-grep run --pattern 'app.$METHOD($PATH, ($$$ARGS) => { $$$BODY })' --lang javascript .
ast-grep run --pattern 'def $NAME($$$ARGS): $$$BODY' --lang python .
ast-grep run --pattern 'if $ERR != nil { $$$BODY }' --lang go .
Search and Replace (Dry Run)
Preview refactoring changes without modifying files:
ast-grep run --pattern '$A == $B' --rewrite '$A === $B' --lang javascript .
ast-grep run --pattern 'function $NAME($$$ARGS) { $$$BODY }' \
--rewrite 'const $NAME = ($$$ARGS) => { $$$BODY }' --lang javascript .
ast-grep run --pattern 'var $NAME = $VALUE' --rewrite 'let $NAME = $VALUE' --lang javascript .
ast-grep run --pattern '$OBJ && $OBJ.$PROP' --rewrite '$OBJ?.$PROP' --lang javascript .
Apply Changes
Apply refactoring to files:
ast-grep run --pattern '$A == $B' --rewrite '$A === $B' --lang javascript --update-all .
Advanced Scan with Rules
Use inline rules for complex pattern matching with logical operators:
ast-grep scan --inline-rules '{"id": "async-fn", "language": "javascript", "rule": {"kind": "function_declaration", "has": {"pattern": "await $EXPR"}}}' .
ast-grep scan --inline-rules '{"id": "nested-if", "language": "javascript", "rule": {"kind": "if_statement", "inside": {"kind": "if_statement"}}}' .
ast-grep scan --inline-rules '{"id": "catch-log", "language": "javascript", "rule": {"pattern": "console.log($$$ARGS)", "inside": {"kind": "catch_clause"}}}' .
Rule Operators
Rules support these operators for complex matching:
all: All conditions must match
any: Any condition must match
not: Negate a condition
inside: Node must be inside another pattern
has: Node must contain another pattern
kind: Match AST node type
pattern: Match a code pattern
Common Refactoring Examples
JavaScript/TypeScript
ast-grep run --pattern 'const $NAME = require($PATH)' \
--rewrite 'import $NAME from $PATH' --lang javascript .
ast-grep run --pattern 'if ($COND) { return true } else { return false }' \
--rewrite 'return !!$COND' --lang javascript .
ast-grep run --pattern '$PROMISE.then($CALLBACK)' \
--rewrite 'await $PROMISE' --lang javascript .
Python
ast-grep run --pattern '"%s" % ($ARGS)' \
--rewrite 'f"{$ARGS}"' --lang python .
ast-grep run --pattern 'old_function($$$ARGS)' --lang python .
React
ast-grep run --pattern 'class $NAME extends React.Component { $$$BODY }' --lang tsx .
ast-grep run --pattern 'useEffect($CALLBACK, [])' --lang tsx .
Workflow
- Search first: Use
ast-grep run --pattern to find matches
- Preview changes: Add
--rewrite to see what would change
- Verify output: Review the diff output carefully
- Apply changes: Add
--update-all to modify files
- Test: Run tests to verify refactoring didn't break anything
Project Setup
Create a new ast-grep project with rules:
ast-grep new
ast-grep new rule
ast-grep new test
Testing Rules
ast-grep test
ast-grep test -c ./sgconfig.yml
Language Server
tmux new -d -s ast-grep-lsp 'ast-grep lsp'
Tips
- Start with simple patterns and refine
- Use
$_ for parts you don't care about capturing
- Use
$$$ for variable-length matches (arguments, statements)
- Test patterns on a single file first:
ast-grep run --pattern '...' --lang js path/to/file.js
- Use JSON output for programmatic processing:
ast-grep run --pattern '...' --json
- Use
ast-grep new to scaffold rules and tests
Related Skills
- typescript: Use ast-grep for TypeScript-specific refactoring patterns.
- jscpd: Combine with duplicate detection to find and consolidate similar code.