ast-grep
Structural code search and rewriting using AST matching.
Pattern Syntax
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: Escape $ as $VAR or wrap in single quotes.
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
Search Examples
Find console.log calls
ast-grep run --pattern 'console.log($$$ARGS)' --lang javascript .
Find React useState hooks
ast-grep run --pattern 'const [$STATE, $SETTER] = useState($INIT)' --lang tsx .
Find async functions
ast-grep run --pattern 'async function $NAME($$$ARGS) { $$$BODY }' --lang typescript .
Find Express route handlers
ast-grep run --pattern 'app.$METHOD($PATH, ($$$ARGS) => { $$$BODY })' --lang javascript .
Find Python function definitions
ast-grep run --pattern 'def $NAME($$$ARGS): $$$BODY' --lang python .
Find Go error handling
ast-grep run --pattern 'if $ERR != nil { $$$BODY }' --lang go .
Find all function calls
ast-grep run --pattern '$FUNCTION($$$_)' --lang typescript .
Find specific function calls
ast-grep run --pattern 'fetch($$$_)' --lang typescript .
Find try-catch blocks
ast-grep run --pattern 'try { $$$BODY } catch ($$$_)' --lang typescript .
Find Promise error handling
ast-grep run --pattern '.catch($$$_)' --lang typescript .
Search and Replace (Dry Run)
Replace == with ===
ast-grep run --pattern '$A == $B' --rewrite '$A === $B' --lang javascript .
Replace != with !==
ast-grep run --pattern '$A != $B' --rewrite '$A !== $B' --lang typescript .
Convert function to arrow function
ast-grep run --pattern 'function $NAME($$$ARGS) { $$$BODY }'
--rewrite 'const $NAME = ($$$ARGS) => { $$$BODY }' --lang javascript .
Replace var with let
ast-grep run --pattern 'var $NAME = $VALUE' --rewrite 'let $NAME = $VALUE' --lang javascript .
Add optional chaining
ast-grep run --pattern '$OBJ && $OBJ.$PROP' --rewrite '$OBJ?.$PROP' --lang javascript .
Replace console.log with logger
ast-grep run --pattern 'console.log($$$)' --rewrite 'logger.info($$$)' --lang typescript .
Apply Changes
Apply changes with --update-all
ast-grep run --pattern '$A == $B' --rewrite '$A === $B' --lang javascript --update-all .
Configuration-Based Rules
rules/my-rules.yaml
patterns:
- pattern: "console.log($$$)" rewrite: "logger.info($$$)" languages: [javascript, typescript] message: "Use logger instead of console.log"
Run custom rules
ast-grep scan --project my-rules
Dry-run preview
ast-grep scan --project my-rules --dry-run
Tips
-
Use --dry-run to preview changes before applying
-
Use --update-all to apply to all matching files
-
Use single quotes for patterns with $ variables
-
Combine with --verbose for detailed matching info