Skip to main content

cxc-ast-grep

Use for AST search and codemods. Triggers: ast-grep, sg, function/call/class/import, empty catch, missing await, YAML rules.

Source facts

Repository
lidge-jun/codexclaw
Last source activity
October 9, 2026 at 04:32
Detected SKILL.md language
English
Stars
48
Forks
10

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
6 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
cxc-ast-grep
description
Use for AST search and codemods. Triggers: ast-grep, sg, function/call/class/import, empty catch, missing await, YAML rules.
metadata
{"short-description":"AST-aware structural search + deterministic codemods (ast-grep/sg) across 25 languages."}
# ast-grep `sg` (also installed as `ast-grep`) 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. Reach for it whenever the question depends on **code shape** rather than text bytes. This skill ships a Python wrapper at `scripts/ast_grep_helper.py` and an install reference at `references/install.md`. The helper adds offline pattern validation, the two-pass write trick, and binary auto-resolution. Use it as the default entry point. ## rg first — do not use ast-grep for ordinary grep Plain filename, literal text, regex, comment, and simple callsite searches use `rg` / `rg --files` first. ast-grep is for syntax-tree questions only. The test: "does the answer depend on the language's syntax tree, or just on the file's bytes?" Tree → ast-grep. Bytes → `rg`. For a whole-repo structure OVERVIEW (which files own which symbols, ranked), use `cxc map` (repo-map skill) instead; ast-grep is for shape SEARCH within known scope. ## When to use this skill - "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" / "find missing `await`." - "Apply this codemod across these 200 files." - "Run our YAML lint rules and surface violations." ## Three things to internalize ### 1. ast-grep is NOT regex The wildcards are `$VAR` (one AST node) and `$$$` (zero or more nodes). Regex syntax (`|`, `.*`, `\w`, `[a-z]`) fails silently — the helper's `validate` subcommand catches the common misuses offline before you run a search. ### 2. Always preview before you write `replace` is a dry-run by default and prints the would-change diff. Add `--apply` only after you have inspected the preview. The helper runs a two-pass write (JSON match pass, then a separate `--update-all` pass) because ast-grep ignores `--update-all` when `--json` is set. ### 3. Language matters Pass `--lang` so the correct parser is used; the same pattern parses differently across languages. `langs` lists the 25 supported languages with extensions. ## Verification loop (MUST) Never trust a pattern you have not seen match. The loop: 1. `validate PATTERN --lang LANG` — offline sanity check (catches regex syntax and other common misuses; it can NOT catch every silent miss — see step 3). 2. `search PATTERN --lang LANG` — read the match list: is the COUNT plausible, and do 2-3 spot-checked sites look right? 3. **0 matches where you expected some = pattern bug first**, not "no occurrences". The two reproduced causes: a glued metavariable (`use$HOOK(...)` — a metavar must be a whole token) and a pattern that does not parse as ONE node (`catch ($E) {}`). Consult `references/patterns.md` (verified examples + pitfalls) and refine. 4. `replace PATTERN REWRITE` — inspect the dry-run diff for every file, or at minimum every distinct shape in it. 5. Only then `--apply`. Never `--apply` a pattern whose match list you have not read. ## Helper usage ``` ast_grep_helper.py search PATTERN [PATH...] [--lang LANG] [--globs GLOB ...] [-C N] ast_grep_helper.py replace PATTERN REWRITE [PATH...] [--lang LANG] [--apply] ast_grep_helper.py scan [PATH...] --rule RULE_FILE [--apply] # rule file via --rule, NOT positional ast_grep_helper.py validate PATTERN [--lang LANG] # offline pattern check ast_grep_helper.py langs # list languages ast_grep_helper.py doctor # binary availability + version ast_grep_helper.py install # lazy-provision sg ``` Verified per-language pattern examples (call rewrite, cast strip, CJS→ESM, empty catch, bare except, relational YAML rules) and the reproduced pitfall table live in `references/patterns.md` — read it before writing a non-trivial pattern. ## Binary resolution + lazy provisioning The helper resolves `sg` in priority order: `CODEXCLAW_AST_GREP_SG_PATH` override (`OMO_AST_GREP_SG_PATH` fallback) → codexclaw runtime (`$CODEX_HOME/runtime/ast-grep` or `~/.codexclaw/runtime/ast-grep`) → a cached binary under the skill `bin/` → `PATH` → Homebrew defaults. When `sg` is missing, `doctor`/`install` exit with a clear install hint rather than crashing. See `references/install.md`. Provisioning is lazy, evidence-bound, and idempotent. ## Notes - On-demand skill (`allow_implicit_invocation: false`); reached by trigger or `dev`-hub routing. - No MCP server, no daemon, no workspace side-effects — this honors the core no-server contract. LSP and codegraph are deferred to a separate, isolated post-MVP extension and are deliberately not shipped here.
View on GitHub