ast-grep
SKILL.md
ABOUTME: ast-grep universal guide for AST-aware code search and analysis
ABOUTME: Provides patterns for Go, Python, Bash, Terraform/HCL; replaces grep for structural search
ast-grep Skill
Overview
ast-grep (sg) is the preferred tool for code search. It matches code structure, not text.
When to Use ast-grep vs grep
| Tool | Matches | False Positives | Comments/Strings |
|---|---|---|---|
| grep/ripgrep | Text patterns | Many | Included |
| ast-grep | AST structure | None | Ignored |
Use grep when: Searching non-code files, paths, or full-text documentation.
Use ast-grep when: Searching code for patterns, refactoring, finding anti-patterns.
Quick Reference
# Basic search
sg -p 'pattern' -l go .
# With context
sg -p 'pattern' -l python -C 3 .
# JSON output for parsing
sg -p 'pattern' -l go --json .
# Replace (dry run)
sg -p 'old_pattern' -r 'new_pattern' -l python --dry-run .
# Multiple patterns
sg scan --rule rules.yml .
Pattern Syntax
| Syntax | Meaning | Example |
|---|---|---|
$VAR |
Single identifier | $func($arg) |
$_ |
Any single node (wildcard) | for $_ := range $_ |
$$$ |
Zero or more items | func($$$) |
$$ |
Optional element | func($$, $last) |
Go Patterns
Function Definitions
# Any function
sg -p 'func $NAME($$$) $$$' -l go .
# Method on type
sg -p 'func ($RECV $TYPE) $NAME($$$) $$$' -l go .
# Function returning error
sg -p 'func $NAME($$$) ($$$, error)' -l go .
# Exported functions only
sg -p 'func [A-Z]$NAME($$$) $$$' -l go .
Error Handling
# Naked error return (anti-pattern)
sg -p 'if err != nil { return err }' -l go .
# Error with context (correct)
sg -p 'if err != nil { return fmt.Errorf($$$) }' -l go .
# Ignored errors (anti-pattern)
sg -p '$_, _ := $CALL($$$)' -l go .
# errors.Is usage
sg -p 'errors.Is($ERR, $TARGET)' -l go .
# errors.As usage
sg -p 'errors.As($ERR, &$TARGET)' -l go .
Concurrency Patterns
# Goroutine spawn
sg -p 'go $FUNC($$$)' -l go .
# Goroutine with anonymous function
sg -p 'go func($$$) { $$$ }($$$)' -l go .
# Channel operations
sg -p '$CH <- $VALUE' -l go . # Send
sg -p '$VAR := <-$CH' -l go . # Receive
# Select statement
sg -p 'select { $$$ }' -l go .
# sync.Mutex usage
sg -p '$M.Lock()' -l go .
sg -p '$M.Unlock()' -l go .
# Context cancellation
sg -p 'ctx.Done()' -l go .
Struct and Interface
# Struct definition
sg -p 'type $NAME struct { $$$ }' -l go .
# Interface definition
sg -p 'type $NAME interface { $$$ }' -l go .
# Embedding
sg -p 'type $NAME struct { $EMBED; $$$ }' -l go .
# JSON tags
sg -p '`json:"$TAG"`' -l go .
Common Anti-Patterns
# Global mutable state
sg -p 'var $NAME = $VALUE' -l go .
# Panic in library code
sg -p 'panic($MSG)' -l go .
# Empty interface{}
sg -p 'interface{}' -l go .
# Problematic defer (arguments evaluated immediately)
sg -p 'defer require.$FUNC(t, $CALL($$$))' -l go .
# JSON tag security issue ("-,omitempty" still allows unmarshaling)
sg -p '`json:"-,$_"`' -l go .
Python Patterns
Function Definitions
# Any function
sg -p 'def $NAME($$$): $$$' -l python .
# Async function
sg -p 'async def $NAME($$$): $$$' -l python .
# Method with self
sg -p 'def $NAME(self, $$$): $$$' -l python .
# Class method
sg -p '@classmethod
def $NAME(cls, $$$): $$$' -l python .
Class Definitions
# Any class
sg -p 'class $NAME: $$$' -l python .
# Class with inheritance
sg -p 'class $NAME($PARENT): $$$' -l python .
# Dataclass
sg -p '@dataclass
class $NAME: $$$' -l python .
# Pydantic model
sg -p 'class $NAME(BaseModel): $$$' -l python .
Error Handling
# Try/except
sg -p 'try: $$$ except $EXC: $$$' -l python .
# Bare except (anti-pattern)
sg -p 'try: $$$ except: $$$' -l python .
# Catching Exception (usually bad)
sg -p 'except Exception: $$$' -l python .
# Raise with chaining
sg -p 'raise $EXC from $CAUSE' -l python .
Type Hints
# Function with return type
sg -p 'def $NAME($$$) -> $TYPE: $$$' -l python .
# Optional type
sg -p '$VAR: Optional[$TYPE]' -l python .
# Union type
sg -p '$VAR: $TYPE1 | $TYPE2' -l python .
Common Anti-Patterns
# Mutable default argument
sg -p 'def $NAME($ARG=[]): $$$' -l python .
sg -p 'def $NAME($ARG={}): $$$' -l python .
# eval usage (security risk)
sg -p 'eval($$$)' -l python .
# exec usage (security risk)
sg -p 'exec($$$)' -l python .
# Using assert for validation (stripped in -O)
sg -p 'assert $COND, $MSG' -l python .
# print debugging
sg -p 'print($$$)' -l python .
Bash Patterns
# Function definition
sg -p '$NAME() { $$$ }' -l bash .
# If statement with [[ ]]
sg -p 'if [[ $COND ]]; then $$$; fi' -l bash .
# Old-style [ ] test (anti-pattern)
sg -p 'if [ $COND ]; then $$$; fi' -l bash .
# For loop
sg -p 'for $VAR in $$$; do $$$; done' -l bash .
# Command substitution (correct)
sg -p '$($CMD)' -l bash .
# Backticks (anti-pattern)
sg -p '`$CMD`' -l bash .
Terraform/HCL Patterns
# Resource blocks
sg -p 'resource "$TYPE" "$NAME" { $$$ }' -l hcl .
# Data blocks
sg -p 'data "$TYPE" "$NAME" { $$$ }' -l hcl .
# Variable definitions
sg -p 'variable "$NAME" { $$$ }' -l hcl .
# Output definitions
sg -p 'output "$NAME" { $$$ }' -l hcl .
# Module calls
sg -p 'module "$NAME" { $$$ }' -l hcl .
# Provider configuration
sg -p 'provider "$NAME" { $$$ }' -l hcl .
# Locals block
sg -p 'locals { $$$ }' -l hcl .
Terraform Anti-Patterns
# Hardcoded secrets
sg -p 'password = "$VALUE"' -l hcl .
sg -p 'secret = "$VALUE"' -l hcl .
# Missing description on variable
sg -p 'variable "$NAME" {
type = $TYPE
}' -l hcl .
# Using count (prefer for_each)
sg -p 'count = $VALUE' -l hcl .
YAML Rule Files
For complex searches, use rule files:
# rules.yml
id: naked-error-return
language: go
rule:
kind: if_statement
pattern: |
if err != nil {
return err
}
message: "Error returned without context; wrap with fmt.Errorf"
severity: warning
---
id: ignored-error
language: go
rule:
pattern: '$_, _ := $CALL($$$)'
message: "Error ignored; handle or explicitly document reason"
severity: error
Run with:
sg scan --rule rules.yml .
Workflow: Finding Technical Debt
# Find TODOs, FIXMEs in code
sg -p '// TODO$$$' -l go .
sg -p '# TODO$$$' -l python .
sg -p '# TODO$$$' -l bash .
# Find FIXMEs
sg -p '// FIXME$$$' -l go .
sg -p '# FIXME$$$' -l python .
Workflow: Security Audit
# SQL injection risks
sg -p 'db.Query($SQL + $VAR)' -l go .
sg -p 'cursor.execute($SQL % $VAR)' -l python .
sg -p 'cursor.execute(f"$SQL")' -l python .
# Command injection
sg -p 'exec.Command($CMD + $VAR)' -l go .
sg -p 'os.system($CMD)' -l python .
sg -p 'subprocess.call($CMD, shell=True)' -l python .
# Hardcoded credentials
sg -p 'password := "$VAL"' -l go .
sg -p 'password = "$VAL"' -l python .
sg -p 'api_key = "$VAL"' -l python .
Workflow: Performance Analysis
# N+1 query patterns (Go)
sg -p 'for $_ := range $ITEMS {
$DB.$METHOD($$$)
}' -l go .
# Goroutine leaks (missing done channel)
sg -p 'go func() {
for {
$$$
}
}()' -l go .
# Python: list append in loop (prefer list comprehension)
sg -p 'for $VAR in $ITER:
$LIST.append($$$)' -l python .
Integration with Claude Code
When using Claude Code, prefer ast-grep for structural searches:
# Instead of:
grep -r "func.*error" --include="*.go" .
# Use:
sg -p 'func $NAME($$$) ($$$, error)' -l go .
Benefits:
- No false positives from comments or strings
- Matches actual code structure
- Works across renamed variables
- Provides semantic understanding
Checklist
Before completing a code search task:
- Used ast-grep for structural code patterns
- Used grep/ripgrep only for non-code or full-text searches
- Applied correct language flag (-l go, -l python, etc.)
- Used metavariables ($VAR, $$$, $_) appropriately
- Considered creating a rule file for complex multi-pattern searches
Resources
Weekly Installs
4
Repository
mauromedda/agent-toolkitGitHub Stars
9
First Seen
Feb 16, 2026
Security Audits
Installed on
cline4
github-copilot4
codex4
kimi-cli4
gemini-cli4
cursor4