ast-grep · git:20260916.50d6810 · 2026-09-16 · sha256 62138cb71c091a04
ast-grep git:20260916.50d6810A
Immutable. This exact content is served forever at /api/v1/blob/62138cb71c091a04.
--- name: ast-grep description: "Find and safely rewrite Python syntax with ast-grep patterns and rules." license: MIT metadata: kind: task author: Médéric HURIER (Fmind) source: github.com/fmind/dot/tree/main/skills/ast-grep created: "2026-09-03" updated: "2026-09-16" --- # ast-grep Structural code search and rewrite: a pattern is real code with meta-variables, matched against the syntax tree, so it ignores formatting and never matches inside strings or comments. Use it where `rg` gives false positives and where a refactor must touch every call site exactly once; plain text search stays with `rg`. ## Commands ```bash ast-grep run -p 'print($$$ARGS)' -l python # search; run is the default subcommand ast-grep run -p 'print($$$ARGS)' -r 'logger.info($$$ARGS)' -l python # dry run: prints the diff, changes nothing ast-grep run -p 'print($$$ARGS)' -r 'logger.info($$$ARGS)' -l python --update-all # apply after reviewing the dry run (-i to confirm per hunk) ast-grep run -p 'os.getenv($KEY)' -l python --json=compact # structured output; --json=stream gives one object per line ast-grep scan # every rule in sgconfig.yml ast-grep scan -r rules/no-print.yml --format github # one rule file; GitHub annotations in CI ``` ## Workflow 1. **Write the pattern as code**: `$NAME` matches one node, `$$$NAME` a sequence (arguments, statements), `$_` a node without binding; always pass `-l <lang>` so the pattern parses in the right grammar, and use `--debug-query=ast` when a pattern that should match does not. 1. **Search first**: run without `-r`, read the matches with `-C 2` for context, and tune `--globs` or `--no-ignore` when files are skipped. 1. **Rewrite in two steps**: add `-r` to see the diff, then `--update-all` (or `-i` for an interactive session); captured meta-variables are reused in the replacement. 1. **Promote to a rule**: for a lint or a repeated refactor, `ast-grep new project` scaffolds `sgconfig.yml` and `rules/`; a rule file has `id`, `language`, `rule` (`pattern`, `kind`, `inside`, `has`, `not`), optional `fix`, `severity`, and `message`; `ast-grep test` runs its `valid` and `invalid` cases. 1. **Wire into the gate**: run `ast-grep scan` inside `check:lint` (see [mise](../mise/SKILL.md)) so hooks and CI apply the same rules. ## Gotchas - **Meta-variables are uppercase**: `$a` is plain text; `$A`, `$ARGS`, `$_` are meta-variables. - **Pattern must be a complete node**: `foo(` does not parse; match `foo($$$)` and narrow with `--selector`. - **Rewrite scope**: `-r` replaces the whole matched node, not a substring inside it. - **Language id**: pass `-l python` for inline patterns; under `scan`, the `.py` extension selects the grammar. ## Official Skills Upstream: `ast-grep/agent-skill`; follow the shared [vendor-skill policy](../agent-project/references/vendor-skills.md) and select the structural-search guidance. ## Documentation - [ast-grep guide](https://ast-grep.github.io/guide/introduction.html) · [Pattern syntax](https://ast-grep.github.io/guide/pattern-syntax.html) · [Rule reference](https://ast-grep.github.io/reference/rule.html) · [Languages](https://ast-grep.github.io/reference/languages.html) - Releases: [ast-grep](https://github.com/ast-grep/ast-grep/releases) · [changelog](https://github.com/ast-grep/ast-grep/blob/main/CHANGELOG.md) - Companion skills: [repository-maintenance](../repository-maintenance/SKILL.md) (repository simplification), [python-stack](../python-stack/references/foundation/GUIDE.md) (Python quality gate).