vinhnx/vtcode/ast-grep
Claude Code and agent skill by vinhnx/vtcode
- community
Checking that the SKILL.md file is still in the repository.
Use for ast-grep project setup, rule authoring, rule debugging, and structural search workflows.
Install
npx vskill@latest install vinhnx/vtcode/ast-grepSKILL.md
Ast-Grep
Use this skill for ast-grep project setup, rule authoring, rule debugging, and CLI workflows that go beyond a single structural query.
Routing
- Use
exec_commandfor ast-grep queries, project scans, rule tests, debug output, and rewrite previews. - Use
ast-grep scanfor project rules andast-grep testfor rule tests. - Use
ast-grep run --pattern=... --rewrite=... --json=compact --color=neverfor dry-run rewrite previews. Review every
replacement before applying changes.
- Use
ast-grep run --debug-querywhen a query matches an unexpected syntax node. - Use
--kindto match node kinds. Ast-grep supports ESQuery-style compound selectors and pseudo-selectors in supported
releases.
- Keep this skill read-only unless the user explicitly authorises applying a rewrite.
Quick Start
- In VT Code, prefer
vtcode dependencies install ast-grepbefore suggesting system package managers. - External install routes such as Homebrew, Cargo, npm, pip, MacPorts, or Nix are fallback options when the user
explicitly wants a system-managed install.
- After installation, validate availability with
ast-grep --help. - On Linux, prefer the full
ast-grepbinary name oversgbecausesgmay already refer tosetgroups. - When running CLI patterns with shell metavariables like
$PROP, use single quotes so the shell does not expand them
before ast-grep sees the pattern.
- A good first rewrite example is optional chaining, for example rewriting
$PROP && $PROP()to$PROP?.().
Command Overview
ast-grep run: ad-hoc query execution and one-off rewrites.ast-grep scan: project rule scanning.ast-grep new: scaffold and rule generation.ast-grep test: rule-test execution.ast-grep lsp: editor integration via language server.
Built-In Languages
- ast-grep ships many built-in languages. Common aliases include
bash,c,cc/cpp,cs,css,ex,go/
golang, html, java, js / javascript / jsx, json, kt, lua, md / markdown, php, py / python, rb, rs / rust, swift, ts / typescript, tsx, and yml.
--lang <alias>and YAMLlanguage: <alias>use those built-in aliases. File-system scans infer language from
built-in extensions unless the project overrides them.
- Pass
--lang <alias>to the CLI when extension inference is insufficient. - Use
languageGlobswhen the repository needs a different extension mapping than ast-grep’s built-in defaults.
How Ast-Grep Works
- ast-grep accepts several query formats: pattern queries, YAML rules, and programmatic API usage.
- The core pipeline is parse first, match second. Tree-Sitter builds the syntax tree, then ast-grep’s Rust matcher finds
the target nodes.
- The main usage scenarios are search, rewrite, lint, and analyze.
- ast-grep processes many files in parallel and is built to use multiple CPU cores on larger codebases.
- In VT Code, run ast-grep through
exec_commandand use this skill for YAML authoring, rule tests, rewrites, and
API-level work.
Project Scaffolding
- A scan-ready ast-grep project needs workspace
sgconfig.ymlplus at least one rule directory, usuallyrules/. rule-tests/andutils/are optional scaffolding thatast-grep newcan create for rule tests and reusable utility
rules.
- If the repository already has
sgconfig.ymlandrules/, prefer working with the existing layout instead of
recreating scaffolding.
- Use
ast-grep newwhen the repository does not have ast-grep scaffolding yet. - Use
ast-grep new rulewhen the scaffold exists and the task is creating a new rule plus optional test case.
sgconfig.yml
sgconfig.ymlis the project-level ast-grep config file, not a rule file. Treat it like the repository root for rule
discovery, tests, parser overrides, and embedded-language behavior.
ruleDirsis required and is resolved relative to the directory containingsgconfig.yml.testConfigsis optional and configures ast-grep test discovery. Each entry needstestDir;snapshotDiris
optional and otherwise defaults to __snapshots__ under that testDir.
utilDirsdeclares directories for global utility rules shared across multiple rule files.languageGlobsremaps files to parsers and takes precedence over ast-grep’s default extension mapping, which is
useful for similar-language reuse like TS -> TSX or C -> Cpp.
customLanguagesregisters project-local parsers.libraryPathcan be one relative library path or a target-triple
map, extensions is required, expandoChar is optional, and languageSymbol defaults to tree_sitter_{name}.
languageInjectionsis experimental. Each entry needshostLanguage,rule, andinjected.- Use dynamic
injectedcandidates when the rule captures$LANGand the embedded language must be chosen from a list
such as css, scss, or less.
- Raw ast-grep project discovery walks upward from the current working directory until it finds
sgconfig.yml, and
--config <file> overrides that discovery with an explicit root config path.
ast-grep scanrequires project config and will error if nosgconfig.ymlis found.ast-grep runcan still search
without project config, though it also benefits from discovered config for things like customLanguages and languageGlobs.
ast-grep scan --inspect summaryis the quickest way to confirm which project directory and config file ast-grep
actually selected during discovery.
- ast-grep also recognizes a home-directory
sgconfig.ymlas a global fallback config. XDG config directories are not
part of this behavior.
- Keep
sgconfig.ymlauthoring on the skill path and pass the project config to ast-grep commands where needed.
Rule Catalog
- Use the ast-grep catalog as inspiration when the user wants existing example rules, not as something to copy blindly.
- Start from examples in the same language family when possible.
- Read catalog markers as hints about rule complexity:
- simple pattern examples are good starting points
Fixmeans the example includes a rewrite pathconstraints,labels,utils,transform, andrewritersmean the example depends on more advanced rule
features
- When adapting a catalog example, translate it to the current repository’s language, style, and safety constraints
instead of preserving the example verbatim.
- Prefer the bundled skill workflow when the user asks to explain, adapt, or combine catalog examples.
VT Code Bundled Rules
VT Code ships a set of curated ast-grep rules under rules/ with matching tests under rule-tests/. Run them with vtcode check ast-grep. The bundled rules are organised by language:
Python (rules/python/)
no-print: flagsprint()calls in production codeno-walrus-source: flags walrus operators that harm readabilityno-unnecessary-list: flagslist(...)wrapping an already-list expressionno-identity-check-with-type: flagstype(x) is Tin favor ofisinstance(x, T)optional-to-union: flagsOptional[X]in favor ofX | Noneprefer-dict-get: flagsif k in d: d[k]in favor ofd.get(k)prefer-generator-expression: flags list comprehensions passed tosum/any/all/min/maxprefer-isinstance-tuple: flagsisinstance(x, A) or isinstance(x, B)in favor ofisinstance(x, (A, B))
Rust (rules/rust/)
no-unsafe-fn-without-unsafe: flagsunsafe fnbodies that contain nounsafeblockavoid-duplicate-export: flagspub usewhenpub modalready exposes the moduleno-iterator-for-each: flags.iter().for_each()in favor offorloopsno-redundant-closure: flags|x| foo(x)in favor offoodirectlylet-chain-candidate: flags nestedifthat could be collapsed withlet-chainsno-chars-enumerate: flags.chars().enumerate()when.char_indices()is more idiomaticno-alloc-digit-count: flags digit-count loops that allocate instead of using repeated divisionprefer-iterator-sum: flags manual accumulator loops in favor of.sum()prefer-retain-over-filter-collect: flags.filter().collect()on aVecin favor of.retain()prefer-unwrap-or-default: flags.unwrap_or(Default::default())in favor of.unwrap_or_default()
Kotlin (rules/kotlin/)
no-var: flags mutablevardeclarationsno-println: flagsprintln/printcallsno-lateinit: flagslateinit varusageno-unsafe-cast: flagsascasts without null-safeas?no-unnecessary-let: flagsletblocks that add no valueprefer-is-empty: flags.count() == 0in favor of.isEmpty()prefer-data-class: flags classes that should bedata classclean-architecture-imports: flags imports that violate clean architecture layer boundaries
Ruby (rules/ruby/)
no-path-traversal: flags string concatenation inFile.join/Pathnamethat may cause traversalprefer-action-over-filter: flagsbefore_filter/after_filterin favor ofbefore_action/after_actionprefer-symbol-over-proc: flagsProc.newwith a symbol when(&:method)is cleaner
TypeScript (rules/typescript/)
no-await-in-promise-all: flagsawaitinsidePromise.all()arrays (defeats parallelism)no-console-except-error: flagsconsole.log/debug/warn/info/trace(allowsconsole.errorin catch blocks)no-debugger: flagsdebuggerstatementsno-unnecessary-boolean-literal-compare: flagsx === trueorx === falseno-useless-promise-resolve: flagsreturn Promise.resolve(...)in async functionsprefer-array-flat-map: flags.map(fn).flat()in favor of.flatMap(fn)prefer-nullish-coalescing: flags||in assignments/returns where??is more preciseuse-logical-assignment: flags$A = $A || $Bin favor of$A ||= $Bprefer-optional-chaining: flagsa && a.bin favor ofa?.bno-return-in-forEach: flagsreturninside.forEach()callbacks (does not return from caller)no-array-delete: flagsdelete arr[i]in favor of.splice()
TSX (rules/tsx/)
avoid-jsx-short-circuit: flags{cond && <Elem />}in favor of{cond ? <Elem /> : null}(prevents rendering0)no-nested-links: flags<a>elements nested inside other<a>elements (invalid HTML)no-unnecessary-usestate-type: flagsuseState<string>('hello')when TypeScript can infer the typerename-svg-attribute: flags hyphenated SVG attributes likestroke-linecapin favor of camelCasestrokeLinecap
Examples (rules/examples/)
no-console-log: starter rule scoped to__ast_grep_examples__/for scaffold validation
Rust Catalog Highlights
- Avoid duplicated exports: a Rust lint-style rule can detect
pub use foo::Bar;in the same source file that already
exposes pub mod foo;. Treat this as API-surface cleanup, not a mechanical rewrite. The rule uses all to combine a pub use $A::$B; pattern with inside: { kind: source_file } and a has check for pub mod $A; with stopBy: end:
- Beware
chars().enumerate(): the Rust catalog rewrite from$A.chars().enumerate()to$A.char_indices()is valid
when the code needs byte offsets instead of character indexes. Do not apply blindly if the caller intentionally wants character positions:
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 90 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingcrates/codegen/vtcode-skills/src/skills/assets/samples/ast-grep/SKILL.md
Popularity
- 7-day trend score
- 5
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/vinhnx/vtcode/ast-grep)