# ast-grep > This skill should be used when the user asks to "find all console.log calls", "find functions without error handling", "find async functions missing try-catch", "remove all debug statements", "find deprecated API usage", "find classes that extend X", "find React components using useState", "bulk refactor function calls", "find all imports of X", "replace all X with Y across codebase", or any find/replace code patterns where text search misses formatting or argument variations. - Author: kylesnowschwartz - Repository: kylesnowschwartz/claude-skill - Version: 20251221171848 - Stars: 0 - Forks: 0 - Last Updated: 2026-02-07 - Source: https://github.com/kylesnowschwartz/claude-skill - Web: https://mule.run/skillshub/@@kylesnowschwartz/claude-skill~ast-grep:20251221171848 --- --- name: ast-grep description: This skill should be used when the user asks to "find all console.log calls", "find functions without error handling", "find async functions missing try-catch", "remove all debug statements", "find deprecated API usage", "find classes that extend X", "find React components using useState", "bulk refactor function calls", "find all imports of X", "replace all X with Y across codebase", or any find/replace code patterns where text search misses formatting or argument variations. --- # ast-grep Code Search ast-grep uses Abstract Syntax Tree (AST) patterns to match code by structure rather than text. This enables precise search across codebases where grep/ripgrep would miss variations in whitespace, arguments, or formatting. ## Workflow ### Step 1: Clarify the Query Before writing rules, clarify: - What code pattern or structure to find - Which programming language - Edge cases or variations to match - What to include or exclude ### Step 2: Create Example Code Create a code snippet representing the target pattern: **Example** - finding "async functions that use await": ```javascript // test_example.js async function example() { const result = await fetchData(); return result; } ``` ### Step 3: Write the ast-grep Rule Translate the pattern into a rule. Start simple, add complexity as needed. **Key principles:** - Always use `stopBy: end` for relational rules (`inside`, `has`) to ensure search goes to the end of the direction - Use `pattern` for simple structures - Use `kind` with `has`/`inside` for complex structures - Break complex queries into smaller sub-rules using `all`, `any`, or `not` **Example rule file (test_rule.yml):** ```yaml id: async-with-await language: javascript rule: kind: function_declaration has: pattern: await $EXPR stopBy: end ``` See `references/rule_reference.md` for comprehensive rule documentation. ### Step 4: Test the Rule Use ast-grep CLI to verify the rule matches the example code. There are two main approaches: **Option A: Test with inline rules (for quick iterations)** ```bash echo "async function test() { await fetch(); }" | ast-grep scan --inline-rules "id: test language: javascript rule: kind: function_declaration has: pattern: await \$EXPR stopBy: end" --stdin ``` **Option B: Test with rule files (recommended for complex rules)** ```bash ast-grep scan --rule test_rule.yml test_example.js ``` **Debugging if no matches:** 1. Simplify the rule (remove sub-rules) 2. Add `stopBy: end` to relational rules if not present 3. Use `--debug-query` to understand the AST structure (see below) 4. Check if `kind` values are correct for the language ### Step 5: Search the Codebase Once the rule matches the example code correctly, search the actual codebase: **For simple pattern searches:** ```bash ast-grep run --pattern 'console.log($ARG)' --lang javascript /path/to/project ``` **For complex rule-based searches:** ```bash ast-grep scan --rule my_rule.yml /path/to/project ``` **For inline rules (without creating files):** ```bash ast-grep scan --inline-rules "id: my-rule language: javascript rule: pattern: \$PATTERN" /path/to/project ``` ## ast-grep CLI Commands ### Inspect Code Structure (--debug-query) Dump the AST structure to understand how code is parsed: ```bash ast-grep run --pattern 'async function example() { await fetch(); }' \ --lang javascript \ --debug-query=cst ``` **Available formats:** - `cst`: Concrete Syntax Tree (shows all nodes including punctuation) - `ast`: Abstract Syntax Tree (shows only named nodes) - `pattern`: Shows how ast-grep interprets your pattern **Use this to:** - Find the correct `kind` values for nodes - Understand the structure of code you want to match - Debug why patterns aren't matching **Example:** ```bash # See the structure of your target code ast-grep run --pattern 'class User { constructor() {} }' \ --lang javascript \ --debug-query=cst # See how ast-grep interprets your pattern ast-grep run --pattern 'class $NAME { $$$BODY }' \ --lang javascript \ --debug-query=pattern ``` ### Test Rules (scan with --stdin) Test a rule against code snippet without creating files: ```bash echo "const x = await fetch();" | ast-grep scan --inline-rules "id: test language: javascript rule: pattern: await \$EXPR" --stdin ``` **Add --json for structured output:** ```bash echo "const x = await fetch();" | ast-grep scan --inline-rules "..." --stdin --json ``` ### Search with Patterns (run) Simple pattern-based search for single AST node matches: ```bash # Basic pattern search ast-grep run --pattern 'console.log($ARG)' --lang javascript . # Search specific files ast-grep run --pattern 'class $NAME' --lang python /path/to/project # JSON output for programmatic use ast-grep run --pattern 'function $NAME($$$)' --lang javascript --json . ``` **When to use:** - Simple, single-node matches - Quick searches without complex logic - When you don't need relational rules (inside/has) ### Search with Rules (scan) YAML rule-based search for complex structural queries: ```bash # With rule file ast-grep scan --rule my_rule.yml /path/to/project # With inline rules ast-grep scan --inline-rules "id: find-async language: javascript rule: kind: function_declaration has: pattern: await \$EXPR stopBy: end" /path/to/project # JSON output ast-grep scan --rule my_rule.yml --json /path/to/project ``` **When to use:** - Complex structural searches - Relational rules (inside, has, precedes, follows) - Composite logic (all, any, not) - When you need the power of full YAML rules **Tip:** For relational rules (inside/has), always add `stopBy: end` to ensure complete traversal. ## Tips for Writing Effective Rules ### Always Use stopBy: end For relational rules, always use `stopBy: end` unless there's a specific reason not to: ```yaml 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 Begin with the simplest rule that could work: 1. Try a `pattern` first 2. If that doesn't work, try `kind` to match the node type 3. Add relational rules (`has`, `inside`) as needed 4. Combine with composite rules (`all`, `any`, `not`) for complex logic ### Use the Right Rule Type - **Pattern**: For simple, direct code matching (e.g., `console.log($ARG)`) - **Kind + Relational**: For complex structures (e.g., "function containing await") - **Composite**: For logical combinations (e.g., "function with await but not in try-catch") ### Debug with AST Inspection When rules don't match: 1. Use `--debug-query=cst` to see the actual AST structure 2. Check if metavariables are being detected correctly 3. Verify the node `kind` matches what you expect 4. Ensure relational rules are searching in the right direction ### Escaping in Inline Rules When using `--inline-rules`, escape metavariables in shell commands: - Use `\$VAR` instead of `$VAR` (shell interprets `$` as variable) - Or use single quotes: `'$VAR'` works in most shells **Example:** ```bash # Correct: escaped $ ast-grep scan --inline-rules "rule: {pattern: 'console.log(\$ARG)'}" . # Or use single quotes ast-grep scan --inline-rules 'rule: {pattern: "console.log($ARG)"}' . ``` ## Common Use Cases ### Find Functions with Specific Content Find async functions that use await: ```bash ast-grep scan --inline-rules "id: async-await language: javascript rule: all: - kind: function_declaration - has: pattern: await \$EXPR stopBy: end" /path/to/project ``` ### Find Code Inside Specific Contexts Find console.log inside class methods: ```bash ast-grep scan --inline-rules "id: console-in-class language: javascript rule: pattern: console.log(\$\$\$) inside: kind: method_definition stopBy: end" /path/to/project ``` ### Find Code Missing Expected Patterns Find async functions without try-catch: ```bash ast-grep scan --inline-rules "id: async-no-trycatch language: javascript rule: all: - kind: function_declaration - has: pattern: await \$EXPR stopBy: end - not: has: pattern: try { \$\$\$ } catch (\$E) { \$\$\$ } stopBy: end" /path/to/project ``` ## Resources ### references/ Contains detailed documentation for ast-grep rule syntax: - `rule_reference.md`: Comprehensive ast-grep rule documentation covering atomic rules, relational rules, composite rules, and metavariables Load these references when detailed rule syntax information is needed.