Skip to content
cccskills
FreePublished on GitHubEnglish overview

ast-grep

Search and rewrite code by its syntax structure, such as function definitions or calls. Preview changes across files before applying them, and use YAML rules for repeatable checks and automatic fixes.

OriginalShow the original description

AST-aware structural code search and rewrite via ast-grep.

AI rating100/ 100See how to install

Good for

  • Finding functions or calls with a specific structure
  • Replacing matching code across multiple files
  • Previewing changes before applying them
  • Checking code with reusable YAML rules

Overview

What it does

Search and rewrite code in bulk based on its structure. It uses a syntax tree, which groups code into grammatical units, to find function definitions, calls, and import statements. The included scripts/ast_grep_helper.py supports checking search patterns in advance, previewing affected locations, and applying changes. You can also run checks and automatic fixes using YAML rules.

When it helps

Use it to replace the same kind of call across many files or find code with a particular shape, such as empty catch blocks. You can also save checks as rules when you need to reuse the same conditions. For changes across files, the workflow includes reviewing a preview before applying the rewrite.

Example requests

  • “Find console.log(x) and show me the proposed changes to logger.info(x) first.”
  • “Rewrite Python’s Optional[X] as X | None.”

Notes

The included helper requires Python 3 and the ast-grep executable. Search patterns are interpreted as code rather than regular expressions. The procedure requires reviewing a preview before rewriting. Use other tools to search comment or string contents, or to analyze meaning, such as determining what a variable refers to.

This overview was written by AI (OpenAI Codex) from the public SKILL.md. Check the original below for the exact behavior.

Objective evaluation

AI rated this skill on four points using only the contents of its SKILL.md. Stars and popularity are not taken into account.

Clear instructionsIs it clear when to use it and what it does?
AGoodStructural search and bulk rewriting are explained, with explicit distinctions from text search and semantic analysis.
Concrete stepsAre steps, inputs, outputs, and examples spelled out?
AGoodExamples cover search, replace, and scan, with validation, preview, and application steps.
SafetyAre sending data, deleting files, and running commands disclosed?
AGoodThe replace command defaults to preview only; file changes require the explicit --apply option.
Easy setupDoes it need few tools or API keys, and are they documented?
AGoodPython 3 and ast-grep are required; install, doctor, and platform-specific installation scripts are provided.

The total counts each point as A = 25, B = 15, C = 5. Rated by AI (OpenAI Codex) as of Oct 20, 2026. Treat it as a guide and read the original before installing.

Disagree? Request a re-evaluation

Tell us which point is wrong and why. No login needed. We will check it against the SKILL.md, redo the evaluation, and show the result here.

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

Files included (14)

  • SKILL.md12.8 KB
  • install.ps17.0 KB
  • install.sh7.4 KB
  • LICENSE1.0 KB
  • references/cli.md7.1 KB
  • references/install.md5.5 KB
  • references/patterns.md5.4 KB
  • references/pitfalls.md8.7 KB
  • references/recipes.md7.7 KB
  • references/sgconfig.md6.3 KB
  • references/yaml-rules.md11.1 KB
  • scripts/ast_grep_helper.py27.3 KB
  • tests/smoke.ps15.6 KB
  • tests/smoke.sh7.6 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

ast-grep

ast-grep (binary also named sg) is an AST-aware search and rewrite tool across 25 languages. It treats your pattern as code, parses it the same way it parses your project, and matches structurally. It is the right tool whenever your question depends on code shape rather than text bytes.

This skill ships a Python wrapper at scripts/ast_grep_helper.py and platform install scripts at install.sh (POSIX) and install.ps1 (Windows). The helper adds offline pattern validation, the two-pass write trick, and binary auto-resolution. Use it as your default entry point.

Upstream source: vendored from code-yeongyu/ast-grep-skill (MIT), as shipped in oh-my-openagent's shared-skills bundle.


When to use this skill

Use it whenever the question is about code structure, not bytes:

  • "Find every function that takes a Request parameter."
  • "Rewrite every console.log(x) to logger.info(x)."
  • "Strip every as any cast."
  • "Replace require(...) with import across the repo."
  • "Find empty catch blocks."
  • "Migrate Optional[X] to X | None."
  • "Apply this codemod across these 200 files."
  • "Run our YAML lint rules and surface violations."

Switch to search_files (or plain rg) when the question is text-shaped (string literal contents, comments, license headers, file names, cross-language regex). When in doubt, ask: "does the answer depend on the language's syntax tree, or just on the file's bytes?" If the former, ast-grep. If the latter, search_files.

Hermes integration notes:

  • Run the helper and sg through the terminal tool. Single-quote every pattern so the shell never expands $VAR.
  • For find→read chains around matches, use --json-out and process with execute_code rather than piping through interpreters.
  • This complements (does not replace) Hermes's patch tool: patch is for targeted edits you author; ast-grep is for pattern-driven bulk rewrites across many sites.

Three things the agent must internalize

1. ast-grep is NOT regex

The wildcards are $VAR (one AST node) and $$$ (zero or more nodes). Regex syntax fails silently:

You wroteWhat ast-grep sawWhat you wanted
foo|barbitwise-or of foo and barrun two separate searches
.*foonot parseable$$$ foo (if $$$ is a list of nodes) or use rg
\w+not parseable$VAR to capture any identifier
[a-z]character class, not parseableswitch to rg

The full anti-pattern table is in references/pitfalls.md §1. The helper's validate subcommand catches these mechanically — call it before debugging "no matches" by hand.

2. Patterns must be valid code

The pattern itself must parse. def $FN($$$): fails because the trailing : makes it incomplete; use def $FN($$$). function $NAME without params/body fails; use function $NAME($$$) { $$$ }. Full table per language in references/pitfalls.md §2.

3. --update-all and --json are mutually exclusive (silently)

This is the single biggest gotcha when scripting. sg run -p P -r R --json --update-all returns the JSON but does not mutate files. To both preview AND apply, run two passes:

sg run -p P -r R --json=compact .   # pass 1: see what would change
sg run -p P -r R --update-all .     # pass 2: actually apply

The helper does this automatically when you call replace --apply. Read references/pitfalls.md §9.


The helper script — scripts/ast_grep_helper.py

A single-file Python 3 stdlib wrapper. Same on every OS. The agent's default entry point.

search — find all matches of a pattern

python scripts/ast_grep_helper.py search 'console.log($MSG)' --lang ts src/

Validates the pattern offline first. If the pattern looks like regex (\w, .*, |, etc.) the helper exits with a hint and never calls sg — saves a round-trip. Pass --force to skip validation.

Flags:

  • --lang ts (or any of the 25 languages; aliases like js, py, rs, kt accepted)
  • --globs '!**/*.test.ts' (repeatable; prefix ! to exclude)
  • -C 3 (context lines)
  • --json-out (raw JSON instead of human format)

replace — rewrite by pattern, dry-run by default

# Dry-run preview (default — no files mutated)
python scripts/ast_grep_helper.py replace 'console.log($MSG)' 'logger.info($MSG)' --lang ts src/

# Actually apply
python scripts/ast_grep_helper.py replace 'console.log($MSG)' 'logger.info($MSG)' --lang ts src/ --apply

The helper:

  1. Validates both pattern and rewrite for hint-detectable mistakes.
  2. Runs pass 1 with --json=compact to collect matches and show a preview.
  3. If --apply is set, runs pass 2 with --update-all to mutate files.

scan — run YAML rules

# Discover sgconfig.yml from cwd and run all rules
python scripts/ast_grep_helper.py scan src/

# Run a single rule file
python scripts/ast_grep_helper.py scan -r rules/no-console.yml src/

# Apply auto-fixes
python scripts/ast_grep_helper.py scan -U src/

# CI-friendly GitHub annotations
python scripts/ast_grep_helper.py scan --report-style short src/

validate — offline pattern check (no sg call)

Useful for CI lints, pre-commit hooks, and quick sanity checks:

python scripts/ast_grep_helper.py validate '\w+' --lang ts
# → exit 2: regex \w not supported. Use $VAR for identifiers.

python scripts/ast_grep_helper.py validate 'console.log($MSG)' --lang ts
# → exit 0: pattern looks plausible for ast-grep.

langs / doctor / install

python scripts/ast_grep_helper.py langs       # list 25 supported languages and aliases
python scripts/ast_grep_helper.py doctor      # check ast-grep binary availability
python scripts/ast_grep_helper.py install     # delegate to install.sh / install.ps1

new and test subcommands proxy directly to sg new and sg test.


Direct sg use (when the helper isn't enough)

The helper is opinionated. For full control, drop to sg. The skill ships a CLI cheat sheet in references/cli.md. The minimal idioms:

# Search
sg run -p 'console.log($MSG)' --lang ts src/

# Search with JSON for scripting
sg run -p 'console.log($MSG)' --lang ts --json=compact src/

# Rewrite, dry-run
sg run -p 'console.log($MSG)' -r 'logger.info($MSG)' --lang ts --json=compact src/

# Rewrite, apply
sg run -p 'console.log($MSG)' -r 'logger.info($MSG)' --lang ts --update-all src/

# Pattern from stdin (great for ad-hoc experiments)
echo 'console.log("hi")' | sg run -p 'console.log($MSG)' --lang js --stdin

# Debug a pattern that returns 0 matches
sg run -p '<your pattern>' --lang <lang> --debug-query=ast --stdin <<< '<sample-code>'

# Run YAML rules
sg scan src/

# Inline YAML rule (one-off)
sg scan --inline-rules '
id: no-todo
language: TypeScript
severity: warning
rule: { pattern: TODO }' src/

When using sg directly in a shell, always single-quote patterns so $VAR is not expanded by the shell.


Decision tree — what to use, when

USER asks for "find/rewrite/codemod"
│
├─ structural pattern (function shape, call, class, import, control flow)
│  └→ ast-grep (this skill)
│
├─ text pattern (regex, alternation, character classes, file names)
│  └→ search_files / rg
│
├─ semantic question (what variable does this refer to? does this throw?)
│  └→ LSP tools, TypeScript compiler, Pyright, Semgrep with type inference
│
└─ multiple repos / federated search
   └→ a search engine + then ast-grep / rg / LSP per-repo

If the user says "find all" or "every", default to ast-grep when the target is shaped (function, class, call, import, statement). Default to search_files when the target is text (string content, comment, license header, file name, identifier substring).


Always run dry-run first when rewriting

A bad pattern silently rewrites the wrong thing. The helper's replace defaults to dry-run for this reason. The flow is:

  1. Search to confirm matches: helper search '<pattern>' --lang X .
  2. Dry-run rewrite: helper replace '<pattern>' '<rewrite>' --lang X . (no --apply)
  3. Inspect the dry-run summary: number of matches, files affected, the per-location preview.
  4. If wrong: refine pattern, go back to step 1.
  5. If right: helper replace '<pattern>' '<rewrite>' --lang X . --apply.

Never apply a rewrite that you have not first dry-run. After an --apply in a git repo, review with git diff --stat before committing.


When sg returns 0 matches but you know the code is there

In priority order:

  1. Run helper validate '<pattern>' --lang <lang> — catches regex misuse, missing function bodies, Python trailing colons.
  2. Check --lang — sg infers from extension; if you pass a .tsx file with --lang ts (not tsx), JSX won't parse.
  3. Inspect the parsed pattern: sg run -p '<pattern>' --lang <lang> --debug-query=ast --stdin <<< '<sample>'. If it shows ERROR nodes, the pattern is malformed.
  4. Check the AST of the target file: sg run -p '$_' --lang <lang> --debug-query=cst path/to/file | head -40 — find the kind you're trying to match.
  5. Try the playground: https://ast-grep.github.io/playground.html — paste code + pattern, see what's happening.

Do not blindly retry with variations. Each failure has a reason; surface it.


When to use YAML rules vs inline -p patterns

Use inline -p when:

  • One-off ad-hoc query.
  • The pattern is simple (no constraints, no fix template).
  • You're exploring.

Use YAML rules (file under rules/, run via sg scan) when:

  • The pattern is reused (lint rule, codemod that runs in CI).
  • You need constraints, transform, complex inside/has, or composite logic.
  • You want auto-fix (fix: field).
  • You want to test the rule (snapshot tests via sg test).

The full YAML rule schema is in references/yaml-rules.md. Project setup (sgconfig.yml, ruleDirs, utilDirs) is in references/sgconfig.md.


Output discipline

  • sg run --json=compact produces an array of match objects: { file, range: {start, end}, text, replacement?, lines, language, ... }.
  • Without --json, sg produces human-readable colored output suitable for terminals.
  • The helper's default output is human-readable (file:line:column + match preview). Pass --json-out for raw JSON.
  • The helper's replace always summarizes: number of matches, number of files, per-location preview.

When summarizing for the user, always include the count of files affected, not just the count of matches. Users care about blast radius.


Required reading (in order of priority)

  1. references/patterns.md — meta-variables, naming rules, strictness levels. Read when you're unsure why a pattern doesn't match.
  2. references/pitfalls.md — the failure-mode field guide. Read when 0 matches surprises you.
  3. references/recipes.md — copy-paste patterns by language. Read first when you start a new task.
  4. references/cli.md — sg run, sg scan, sg test, sg new, sg lsp. Read when the helper isn't enough.
  5. references/yaml-rules.md — YAML rule schema. Read when you outgrow inline patterns.
  6. references/sgconfig.md — project-level configuration. Read when you set up sg scan for a real project.
  7. references/install.md — per-OS install methods. Read only if install.sh / install.ps1 fail.

Invariants (do not break)

  • Validate before searching. When emitting a pattern programmatically, call helper validate first. It catches the regex-misuse class of mistakes that account for ~70% of "0 matches" debug sessions.
  • Dry-run before applying. Never run sg run -r ... --update-all without first inspecting the matches. The helper's replace enforces this by default.
  • Two-pass writes. When using sg directly to both preview and apply, run two invocations — --json ignores --update-all.
  • Single-quote patterns in shell. '$VAR' not "$VAR". The shell expands $VAR to the empty string in double quotes, breaking the pattern.
  • Pattern is code, not regex. When the pattern would need |, .*, \w, or [a-z], switch to search_files instead. Don't try to force ast-grep into a regex shape.
  • --lang is required for stdin. When piping with --stdin, set --lang explicitly; sg cannot infer from extension.
  • Linux: prefer ast-grep over sg because sg collides with setgroups from util-linux. The helper handles this; if you call sg directly, alias it: alias sg=ast-grep.

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

1password

FreeSummaryAI rating 100

Set up the 1Password CLI and use stored passwords or API keys in commands and configuration templates. Choose an authentication method, retrieve secret references, and pass credentials to processes through environment variables.

  • Installing and configuring the 1Password CLI
  • Running commands with stored API keys
  • Filling configuration templates with stored secrets
NousResearch/hermes-agent255.2KUpdated Oct 19, 2026

3-statement-model

FreeSummaryAI rating 90

Build an Excel workbook linking the income statement, balance sheet, and cash flow statement. Populate historical figures, create formula-based forecasts, compare scenarios, and check that balances and cash totals agree across all three statements.

  • Populating a financial model template with historical data
  • Building linked forecasts across three financial statements
  • Comparing base, upside, and downside scenarios
NousResearch/hermes-agent255.2KUpdated Oct 19, 2026

accelerate

FreeSummaryAI rating 80

Adapt existing PyTorch training scripts to use multiple GPUs or machines with limited code changes. The skill guides configuration, launch commands, mixed precision, which uses lower-precision numbers, and DeepSpeed or FSDP settings for distributing training work and memory.

  • Move a single-GPU training script to multiple GPUs
  • Configure mixed precision training
  • Set up DeepSpeed or FSDP to reduce memory use
NousResearch/hermes-agent255.2KUpdated Oct 19, 2026

actual-setup

FreeSummaryAI rating 100

Configure Hermes to run AI models through Actual Computer on your own hardware. Set up either the hosted relay or a local connection, select models, verify responses, and troubleshoot request errors or empty output.

  • Connecting Hermes with an Actual inference key
  • Running models through a local Actual daemon
  • Downloading and loading local models
NousResearch/hermes-agent255.2KUpdated Oct 19, 2026

adversarial-ux-test

FreeSummaryAI rating 80

Test an app from the perspective of a frustrated, less technical user. Find confusing steps and barriers, separate actionable usability problems from personal complaints, and produce screenshots, suggested fixes, and prioritized tickets.

  • Reviewing usability before a launch or demo
  • Checking the experience of a new user
  • Finding friction in signup and subscription flows
NousResearch/hermes-agent255.2KUpdated Oct 19, 2026

agent-merge-conflict-arbiter

FreeSummaryAI rating 100

Resolve Git merge conflicts between two agents by comparing both changes and their stated goals. Combine compatible work, explain choices where designs differ, and verify the merged result with project builds or tests.

  • Resolving conflicts between branches edited by two agents
  • Integrating changes from parallel worktrees
  • Reviewing reasons for conflicting design choices
NousResearch/hermes-agent255.2KUpdated Oct 19, 2026

See all skills by NousResearch

Report a problem with this skill