AgentSkillsCN

ast-grep

使用Bun初始化项目、管理依赖、运行脚本、执行测试,并打包代码。当您需要处理package.json、安装软件包、运行开发服务器,或为生产环境构建应用时,本技能将为您提供便捷支持。

SKILL.md
--- frontmatter
name: ast-grep
description: Search code by AST patterns and perform structural refactoring across files. Use when finding function calls, replacing code patterns, or refactoring syntax that regex cannot reliably match.

ast-grep

Structural code search and rewriting using AST matching instead of regex.

Contents

Pattern Syntax

ast-grep uses pattern placeholders to match and capture AST nodes:

PatternDescription
$VARMatch a single AST node and capture it as VAR
$$$VARMatch 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 tip: Escape $ as \$VAR or wrap the pattern in single quotes to avoid shell expansion.

Supported Languages

javascript, typescript, tsx, html, css, python, go, rust, java, c, cpp, csharp, ruby, php, yaml

Commands

CommandDescription
ast-grep runOne-time search or rewrite (default)
ast-grep scanScan and rewrite by configuration
ast-grep testTest ast-grep rules
ast-grep newCreate new project or rules
ast-grep lspStart language server

Usage

Basic Search

Find patterns in code:

bash
# 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 .

Search and Replace (Dry Run)

Preview refactoring changes without modifying files:

bash
# Replace == with === (preview)
ast-grep run --pattern '$A == $B' --rewrite '$A === $B' --lang javascript .

# Convert function to arrow function (preview)
ast-grep run --pattern 'function $NAME($$$ARGS) { $$$BODY }' \
  --rewrite 'const $NAME = ($$$ARGS) => { $$$BODY }' --lang javascript .

# Replace var with let (preview)
ast-grep run --pattern 'var $NAME = $VALUE' --rewrite 'let $NAME = $VALUE' --lang javascript .

# Add optional chaining (preview)
ast-grep run --pattern '$OBJ && $OBJ.$PROP' --rewrite '$OBJ?.$PROP' --lang javascript .

Apply Changes

Apply refactoring to files:

bash
# Apply changes (use --update-all)
ast-grep run --pattern '$A == $B' --rewrite '$A === $B' --lang javascript --update-all .

Advanced Scan with Rules

Use inline rules for complex pattern matching with logical operators:

bash
# Find functions containing await
ast-grep scan --inline-rules '{"id": "async-fn", "language": "javascript", "rule": {"kind": "function_declaration", "has": {"pattern": "await $EXPR"}}}' .

# Find nested if statements
ast-grep scan --inline-rules '{"id": "nested-if", "language": "javascript", "rule": {"kind": "if_statement", "inside": {"kind": "if_statement"}}}' .

# Find console.log inside catch blocks
ast-grep scan --inline-rules '{"id": "catch-log", "language": "javascript", "rule": {"pattern": "console.log($$$ARGS)", "inside": {"kind": "catch_clause"}}}' .

Rule Operators

Rules support these operators for complex matching:

  • all: All conditions must match
  • any: Any condition must match
  • not: Negate a condition
  • inside: Node must be inside another pattern
  • has: Node must contain another pattern
  • kind: Match AST node type
  • pattern: Match a code pattern

Common Refactoring Examples

JavaScript/TypeScript

bash
# Convert require to import
ast-grep run --pattern 'const $NAME = require($PATH)' \
  --rewrite 'import $NAME from $PATH' --lang javascript .

# Simplify boolean return
ast-grep run --pattern 'if ($COND) { return true } else { return false }' \
  --rewrite 'return !!$COND' --lang javascript .

# Convert Promise.then to async/await
ast-grep run --pattern '$PROMISE.then($CALLBACK)' \
  --rewrite 'await $PROMISE' --lang javascript .

Python

bash
# Convert string formatting
ast-grep run --pattern '"%s" % ($ARGS)' \
  --rewrite 'f"{$ARGS}"' --lang python .

# Find deprecated function calls
ast-grep run --pattern 'old_function($$$ARGS)' --lang python .

React

bash
# Find class components
ast-grep run --pattern 'class $NAME extends React.Component { $$$BODY }' --lang tsx .

# Find useEffect with empty deps
ast-grep run --pattern 'useEffect($CALLBACK, [])' --lang tsx .

Workflow

  1. Search first: Use ast-grep run --pattern to find matches
  2. Preview changes: Add --rewrite to see what would change
  3. Verify output: Review the diff output carefully
  4. Apply changes: Add --update-all to modify files
  5. Test: Run tests to verify refactoring didn't break anything

Project Setup

Create a new ast-grep project with rules:

bash
# Initialize project with sgconfig.yml
ast-grep new

# Create a new rule
ast-grep new rule

# Create a new test for rules
ast-grep new test

Testing Rules

bash
# Test all rules in project
ast-grep test

# Test with specific config
ast-grep test -c ./sgconfig.yml

Language Server

bash
# Start LSP for editor integration (use tmux for background)
tmux new -d -s ast-grep-lsp 'ast-grep lsp'

Tips

  • Start with simple patterns and refine
  • Use $_ for parts you don't care about capturing
  • Use $$$ for variable-length matches (arguments, statements)
  • Test patterns on a single file first: ast-grep run --pattern '...' --lang js path/to/file.js
  • Use JSON output for programmatic processing: ast-grep run --pattern '...' --json
  • Use ast-grep new to scaffold rules and tests

Related Skills

  • typescript: Use ast-grep for TypeScript-specific refactoring patterns.
  • jscpd: Combine with duplicate detection to find and consolidate similar code.