ast-grep Code Search
Overview
Translate user intent into sg patterns/rules, validate quickly, then run against target scope.
General Workflow
Step 1: Understand the Query
Pin down:
- target syntax shape
- language
- file scope
- include/exclude constraints
Step 2: Start with the Smallest Pattern
Use sg run --pattern first.
sg run --pattern 'console.log($ARG)' --lang javascript src
Step 3: Escalate to YAML Rule for Structure Logic
For relational/composite logic (inside / has / precedes / follows / all / any / not / matches), use sg scan --rule.
# rule.yml
id: async-with-await
language: javascript
rule:
kind: function_declaration
has:
pattern: await $EXPR
stopBy: end
sg scan --rule rule.yml src
Step 4: Validate and Search
Test on a tiny sample first, then search the project.
echo "async function f(){ await g() }" | sg scan --rule rule.yml --stdin
sg scan --rule rule.yml src --json=compact
CLI Quick Reference
Inspect Code Structure (--debug-query)
Use when kind/pattern mismatch is unclear.
sg run --pattern 'class $NAME { $$$BODY }' \
--lang javascript \
--debug-query=pattern
Test Rules (scan with --stdin)
echo "const x = await fetch();" | sg scan --inline-rules "id: test
language: javascript
rule:
pattern: await \$EXPR" --stdin --json=compact
Search with Patterns (run)
sg run --pattern 'function $NAME($$$)' --lang javascript src --json=compact
Search with Rules (scan)
sg scan --rule rule.yml src
sg scan --inline-rules "id: find-async
language: javascript
rule:
kind: function_declaration
has:
pattern: await \$EXPR
stopBy: end" src
Tips for Writing Effective Rules
Default to stopBy: end for Deep Searches
For relational rules (inside, has), default to:
has:
pattern: await $EXPR
stopBy: end
This ensures the search traverses the entire subtree rather than stopping at the first non-matching node.
Start Simple, Then Add Complexity
patternkind- add
inside/has - add
all/any/not
Metavariable Rules
- Use exact metavariable forms only:
$A,$$OP,$$$ARGS. - Keep metavariable text as the only content in its AST node.
- If a rule depends on previously captured metavariables, combine sub-rules in
allto guarantee match order.
No-Match Triage
- Run with
--json=compact. - If output is
[], treat as no match and refine pattern/scope. - If stderr has parser/arg errors, fix language, pattern, or flags first.
Resources
references/
rule_reference.md: Full rule syntax (atomic, relational, composite, metavariables)windows.md: PowerShell quoting/escaping tips and Vue SFC script-block workflow
Load only the reference needed for the current task.