| name | sg |
|---|---|
| description | Use when the user asks for AST-aware search or safe structural refactors using ast-grep (sg). |
This skill uses ast-grep (CLI: sg) for structural, AST-aware code search and safe refactoring. It complements text search by matching syntax nodes, enabling precise queries and replacements across languages.
Tested Versions: ast-grep 0.19+ (JSON/stream output supported)
Goals:
- Verify
sgis installed and detect version. - Confirm basic commands and JSON output availability.
- Ensure CLI flags reflect current
sg runsyntax (--globs,--lang,--no-ignorefamily).
Commands:
command -v sg >/dev/null || { echo "ERROR: ast-grep (sg) not installed"; exit 1; }
sg --version
sg --help | head -n 1Install Hints:
- macOS:
brew install ast-grep(orbrew tap ast-grep/ast-grep && brew install ast-grep) - Debian/Ubuntu:
curl -fsSL https://ast-grep.github.io/install.sh | shor use package if available - Cargo:
cargo install ast-grep
Exit Conditions:
- Proceed only if
sgis present; otherwise guide installation and stop.
Intent Dimensions:
- Match style: simple pattern (
-p) vs rule file (-r rules/*.yml). - Languages: explicit
--lang <lang>or infer by extension. - Scope and ignores: include globs (
-g), hidden files, or bypass ignores on request. - Output: streaming JSON for programmatic parsing; optional preview context.
- Refactoring: structural replace with
--rewriteor rulefix:sections.
Safe Defaults:
- Read-only search unless refactor requested.
- Respect ignores and exclude heavy dirs by default:
--globs '!{.git,node_modules,.venv,dist,build,.next,.cache,coverage}'
- Stream results as JSON events with file, range, and snippet.
Canonical Shapes:
# Pattern-based search (regex-like but AST-aware per language grammar)
sg run -p '<pattern>' \
--json=stream \
--globs '!{.git,node_modules,.venv,dist,build,.next,.cache,coverage}' \
[--lang <lang>] [--hidden] [--no-ignore] [--globs '<glob>'] [<paths...>]
# Rule-based search
sg run -r rules/ \
--json=stream \
--globs '!{.git,node_modules,.venv,dist,build,.next,.cache,coverage}' \
[--lang <lang>] [--hidden] [--no-ignore] [<paths...>]
# Structural replace (explicit)
sg run -p '<pattern>' --rewrite '<replacement>' --dry-run \
--json=stream [scoping flags...] [<paths...>]Notes:
- Prefer
--json=streamfor line-delimited events; fall back to compact JSON if needed. - Always quote the pattern to avoid shell expansion.
- Use
--dry-runby default for refactors; require explicit confirmation to apply. - For complex patterns, encourage rule YAML with
rule:/fix:blocks and tests. - Scope directories by passing them as final positional arguments (defaults to the current working directory). Example:
sg run -p 'pattern' --json=stream ./src ./services/api. - Language selection: prefer
--lang <lang>(e.g.,--lang typescript,--lang python) over file globs when possible. - Debugging:
--inspectprints rule/pattern diagnostics;--strictness <level>controls match leniency.
Approach:
- Execute
sgand stream JSON events. - Detect “no matches” as a successful empty result set.
- Impose a soft timeout for giant repos and suggest narrowing scope on timeout.
Parsing:
- Parse streaming JSON. Match payload typically includes:
- file path, language, range (start line/col, end line/col), and code snippet.
- Capture captures for named pattern variables if present.
Aggregation:
- Group results by file; sort by line number.
- Provide concise previews:
file:line:column: code… - Offer follow-ups: open file at range, show N lines context, export to a rule file.
User Summary:
- Totals: matches and files.
- Top files by match count with snippets.
- “Repro” command emitted for transparency.
Machine-Readable (internal):
{
\"matches\": [
{
\"file\": \"src/app.ts\",
\"lang\": \"typescript\",
\"line\": 42,
\"column\": 7,
\"endLine\": 42,
\"endColumn\": 19,
\"text\": \"console.log(user)\",
\"captures\": {\"ident\": \"user\"}
}
],
\"command\": \"sg run -p 'console.log($X)' --json=stream\",
\"stats\": {\"files\": 6, \"matches\": 9}
}Common Issues:
sg: command not found: provide install steps.- Invalid pattern or language: suggest adding
--langor using a rule file with explicitlanguage. - Large matches or binary files: scope with
-g 'src/**'or use file types.
Recovery Strategies:
- Move from simple
-pto rule YAML for complex matching or rewrites. - Narrow search with language and globs.
- For refactors, keep
--dry-run; then apply with confirmation.
- Read-only by default; structural rewrite runs with
--dry-rununless explicitly confirmed. - Respects ignores by default;
--hidden/--no-ignoreonly when user requests. - Emits exact command used for transparency and reproducibility.
- Pattern:
-p '<pattern>'(uses language grammar; add--lang <lang>when ambiguous). - Rule directory:
-r rules/(supportsfix:for rewrite). - JSON:
--json=streamfor NDJSON-style events. - Scope: append directories as positional args (default
.) and use--globs '<glob>',--hidden,--no-ignorefor finer control. - Dry run:
--dry-runfor safe preview of rewrites. - Inspect:
--inspectto see how patterns/rules are interpreted.
# 1) Find console logs in TS/JS
sg run -p 'call_expression(callee: identifier(name: \"console\"))' \
--json=stream --lang javascript --globs 'src/**' .
# 2) Rename identifier via rewrite (preview)
sg run -p 'identifier(name: \"foo\")' --rewrite 'bar' \
--dry-run --json=stream --lang typescript .
# 3) Use a rule directory with fixes (preview)
sg run -r rules/ --json=stream --lang typescript src/
# 4) Run the built-in example rule (no-console) from this repo
sg run -r plugins/ast-grep-explorer/examples/rules \
--json=stream --lang typescript . \
--globs '!{.git,node_modules,.venv,dist,build,.next,.cache,coverage}'
# 5) Apply fixes (dangerous): remove --dry-run to write changes
# Always commit or back up first. Run on a scoped directory and review diff.
sg run -p 'identifier(name: \"foo\")' --rewrite 'bar' \
--json=stream --lang typescript . # note: no --dry-run hereSee REFERENCES.md in this directory for authoritative docs and best practices.