| name | ast-grep-searching |
| description | Use ast-grep for structural code search, AST-based pattern matching, and safe refactoring. Triggers on ast-grep, AST search, code refactoring, codemod, rewrite code, structural search, syntax-aware search, rename API, change imports, transform code, pattern-based refactoring, policy enforcement, code quality checks. |
AST-Grep Searching Skill
Purpose
Master structural code search and refactoring using ast-grep, a syntax-aware tool that parses code into Abstract Syntax Trees (AST) for precise pattern matching and safe code transformations.
When to Use
Use ast-grep when:
- Structural accuracy over raw text matching
- Safe refactoring and code transformations
- Codemods to update APIs across codebase
- Policy enforcement with AST-based rules
- Syntax-aware search ignoring comments/strings
Use ripgrep for: Text search, strings, quick recon Use ast-grep for: Refactoring, transforming, enforcing patterns
Core Principles
- Structure over text - Matches AST nodes, not raw text
- Language-aware - Understands syntax of each language
- Safe transformations - Rewrites preserve code structure
- Pattern-based - Use code patterns, not regex
Table of Contents
- Quick Start
- Pattern Matching
- Code Transformation
- Language Support
- Common Use Cases
- Best Practices
- Reference Files
Quick Start
Installation
brew install ast-grep # macOS
cargo install ast-grep # Rust
npm install -g @ast-grep/cli # npm
Essential Commands
# Search
ast-grep run -l <lang> -p '<pattern>'
# Replace (preview)
ast-grep run -l <lang> -p '<old>' -r '<new>'
# Replace (apply)
ast-grep run -l <lang> -p '<old>' -r '<new>' -U
# Scan with rules
ast-grep scan
# Test rules
ast-grep test
Pattern Matching
Simple Patterns
# Find method definitions
ast-grep run -l ruby -p 'def $METHOD($ARGS)'
# Find method calls
ast-grep run -l javascript -p 'console.log($$$ARGS)'
# Find imports
ast-grep run -l typescript -p 'import { $IMPORTS } from "$MODULE"'
Metavariables
# $VAR - Single AST node
ast-grep run -l ruby -p 'render $VAR'
# $$$ARGS - Multiple nodes (0 or more)
ast-grep run -l javascript -p 'function($$$ARGS) { $$$BODY }'
# Named capture for reuse
ast-grep run -l ruby -p 'User.find($ID)' -r 'User.find_by(id: $ID)'
Pattern Examples
# Ruby: require statements
ast-grep run -l ruby -p 'require "$MODULE"'
# JavaScript: async functions
ast-grep run -l javascript -p 'async function $NAME($$$ARGS) { $$$BODY }'
# TypeScript: type annotations
ast-grep run -l typescript -p 'const $VAR: $TYPE = $VALUE'
# Python: decorators
ast-grep run -l python -p '@$DECORATOR\ndef $FUNCTION($$$ARGS):'
Code Transformation
Basic Rewriting
# Preview (dry-run)
ast-grep run -l ruby -p 'User.find($ID)' -r 'User.find_by(id: $ID)'
# Apply changes
ast-grep run -l ruby -p 'User.find($ID)' -r 'User.find_by(id: $ID)' -U
# Interactive mode
ast-grep run -l ruby -p 'User.find($ID)' -r 'User.find_by(id: $ID)' -i
Common Transformations
# var to const (JavaScript)
ast-grep run -l javascript -p 'var $VAR = $VALUE' -r 'const $VAR = $VALUE' -U
# require to import (JavaScript)
ast-grep run -l javascript \
-p 'const $VAR = require("$MODULE")' \
-r 'import $VAR from "$MODULE"' -U
# Rename methods
ast-grep run -l ruby -p 'old_method($$$ARGS)' -r 'new_method($$$ARGS)' -U
# Convert instance variables (Ruby)
ast-grep run -l ruby -p '@$VAR = $VALUE' -r '$VAR = $VALUE' -U
Language Support
| Language | Flag | Common Patterns |
|---|---|---|
| Ruby | -l ruby |
def, class, module, require |
| JavaScript | -l js |
function, const, import |
| TypeScript | -l ts |
interface, type, async |
| Python | -l python |
def, class, import |
| Go | -l go |
func, type, struct |
| Rust | -l rust |
fn, struct, impl |
Language Examples
# Ruby: ActiveRecord callbacks
ast-grep run -l ruby -p 'before_save :$METHOD'
# JavaScript: React hooks
ast-grep run -l javascript -p 'const [$STATE, $SETTER] = useState($INITIAL)'
# TypeScript: interfaces
ast-grep run -l typescript -p 'interface $NAME { $$$FIELDS }'
# Python: class methods
ast-grep run -l python -p 'def $METHOD(self, $$$ARGS):'
# Go: function declarations
ast-grep run -l go -p 'func $NAME($$$PARAMS) $$$RETURN { $$$BODY }'
Common Use Cases
API Migration
# Migrate API calls
ast-grep run -l ruby \
-p 'OldAPI.call($$$ARGS)' \
-r 'NewAPI.execute($$$ARGS)' -U
# Update method signatures
ast-grep run -l javascript \
-p 'oldMethod($ARG1, $ARG2)' \
-r 'newMethod({ arg1: $ARG1, arg2: $ARG2 })' -U
Import Management
# Convert require to import
ast-grep run -l javascript \
-p 'const $VAR = require("$MODULE")' \
-r 'import $VAR from "$MODULE"' -U
# Update import paths
ast-grep run -l typescript \
-p 'import { $IMPORTS } from "old/path"' \
-r 'import { $IMPORTS } from "new/path"' -U
Code Quality
# Find var declarations
ast-grep run -l javascript -p 'var $VAR = $VALUE'
# Find console.log
ast-grep run -l javascript -p 'console.log($$$ARGS)' src/
# Find deprecated patterns
ast-grep run -l ruby -p 'deprecated_method($$$ARGS)'
Best Practices
1. Preview Before Applying
# Always preview
ast-grep run -l ruby -p 'old' -r 'new'
# Then apply
ast-grep run -l ruby -p 'old' -r 'new' -U
2. Use Specific Patterns
# ❌ Too broad
ast-grep run -l ruby -p '$METHOD'
# ✅ Specific
ast-grep run -l ruby -p 'User.$METHOD($$$ARGS)'
3. Test on Small Subset
# Single file first
ast-grep run -l ruby -p 'old' -r 'new' app/models/user.rb
# Then expand
ast-grep run -l ruby -p 'old' -r 'new' app/models/
4. Use Version Control
# Commit before refactoring
git commit -m "Before refactoring"
# Run transformation
ast-grep run -l ruby -p 'old' -r 'new' -U
# Review
git diff
# Rollback if needed
git checkout .
5. Combine with ripgrep
# Find files with ripgrep (fast)
rg -l "old_method" app/
# Transform with ast-grep (precise)
rg -l "old_method" app/ | xargs ast-grep run -l ruby \
-p 'old_method($$$ARGS)' -r 'new_method($$$ARGS)' -U
Quick Reference
Commands
# Search
ast-grep run -l <lang> -p '<pattern>'
# Replace (preview)
ast-grep run -l <lang> -p '<old>' -r '<new>'
# Replace (apply)
ast-grep run -l <lang> -p '<old>' -r '<new>' -U
# Interactive
ast-grep run -l <lang> -p '<old>' -r '<new>' -i
# Scan with rules
ast-grep scan
# Test rules
ast-grep test
Flags
-l, --lang LANG Target language
-p, --pattern PAT Search pattern with metavariables
-r, --rewrite REW Replacement pattern
-U, --update-all Apply changes to files
-i, --interactive Confirm each replacement
--json Output as JSON
Troubleshooting
Pattern not matching?
- Verify syntax for target language
- Check language flag
-l - Test incrementally - start simple
- Use playground: https://ast-grep.github.io/playground
Replacement breaking code?
- Preview first (without
-U) - Test on one file
- Ensure all
$VARin pattern appear in replacement - Use version control for easy rollback
Performance slow?
- Limit scope to specific directory
- Pre-filter with
rg -l - Use specific patterns
- Exclude vendor/, node_modules/
Reference Files
advanced-rules.md
- Rule file syntax and structure
- Complex pattern matching
- Conditional rules and constraints
- Testing strategies
- CI/CD integration
pattern-library.md
- Language-specific examples
- Common refactoring patterns
- Migration recipes
- Code quality rules
- Ready-to-use templates
Key Reminders
✅ Structure over text - Matches AST nodes, not strings
✅ Preview before apply - Always run without -U first
✅ Language-aware - Respects syntax, ignores comments
✅ Safe refactoring - Preserves code structure
✅ Version control - Commit before large transformations
✅ Test incrementally - Start small, expand scope
✅ Combine with ripgrep - Use rg for recon, ast-grep for refactoring
Skill Status: Complete - Following Anthropic best practices ✅ Line Count: < 500 lines (following 500-line rule) ✅ Progressive Disclosure: Reference files for advanced content ✅