{"slug":"ast-grep","title":"ast-grep","summary":"Use ast-grep (sg) for AST-aware code search and rewrite across 25 languages. Trigger for structural code matching or deterministic codemods: find every function/call/class/import shaped like X, rewrite console.log to logger.info, strip `as any`, migrate require() to import, find ","platform":"Claude","tags":[],"authorName":"LLM Mart","authorSlug":"llm-mart","score":0,"source":"github","price":null,"verified":false,"createdAt":"2026-08-23T08:58:16.221168Z","repo":{"url":"https://github.com/code-yeongyu/oh-my-openagent","stars":69391,"forks":5715,"license":null,"updatedAt":"2026-09-24T23:30:44Z"},"bodyHtml":"<h1>ast-grep-skill</h1>\n<p>LLM-neutral skill for <strong>AST-aware search and rewrite</strong> across 25 languages. Wraps the <a href=\"https://ast-grep.github.io/\"><code>ast-grep</code></a> (<code>sg</code>) CLI with offline pattern validation, the two-pass write trick, binary auto-resolution, and a per-OS installer.</p>\n<p>Same shape as <a href=\"https://github.com/code-yeongyu/web-fetch\"><code>web-fetch</code></a> and <a href=\"https://github.com/code-yeongyu/web-search\"><code>web-search</code></a>, packaged as a standalone skill that any Bash-capable agent (Claude Code, OpenCode, pi, hermes, openclaw) can load.</p>\n<h2>Install</h2>\n<pre><code>git clone https://github.com/code-yeongyu/ast-grep-skill ~/.agents/skills/ast-grep\nbash ~/.agents/skills/ast-grep/install.sh        # installs the ast-grep binary\n</code></pre>\n<p>That is it. The wrapper script is single-file Python 3 stdlib; no <code>pip install</code> needed. The installer tries <code>brew</code> → <code>npm</code> → <code>cargo</code> → <code>pip</code> → <code>nix</code> → <code>mise</code> → GitHub release in priority order, picks the first that works, and falls back to a cached binary at <code>&lt;skill&gt;/bin/sg</code>.</p>\n<h3>Symlink for active development</h3>\n<pre><code>ln -s /path/to/your/clone ~/.agents/skills/ast-grep\n</code></pre>\n<h3>Other agents</h3>\n<ul>\n<li><strong>Claude Code / OpenCode</strong>: drop the directory under <code>~/.agents/skills/</code> (or <code>~/.config/opencode/skills/</code>) and the skill auto-registers via the <code>name</code> + <code>description</code> in <code>SKILL.md</code> frontmatter.</li>\n<li><strong>pi (<code>~/.senpi/agent</code>)</strong>: not a <code>pi</code> extension — this is a skill. Pi consumes skills via <code>~/.agents/skills/</code> symlinks; the actual <code>pi-ast-grep</code> extension is at <a href=\"https://github.com/code-yeongyu/pi-extensions\">https://github.com/code-yeongyu/pi-extensions</a>.</li>\n<li><strong>Direct CLI use</strong>: <code>python3 ~/.agents/skills/ast-grep/scripts/ast_grep_helper.py &lt;subcommand&gt;</code>.</li>\n</ul>\n<h2>Usage</h2>\n<pre><code># Search by AST pattern (the helper validates patterns offline first)\npython3 scripts/ast_grep_helper.py search 'console.log($MSG)' --lang ts src/\n\n# Rewrite (dry-run preview by default)\npython3 scripts/ast_grep_helper.py replace 'console.log($MSG)' 'logger.info($MSG)' --lang ts src/\n\n# Apply the rewrite (two-pass: preview JSON + then --update-all)\npython3 scripts/ast_grep_helper.py replace 'console.log($MSG)' 'logger.info($MSG)' --lang ts src/ --apply\n\n# Run YAML lint rules from sgconfig.yml\npython3 scripts/ast_grep_helper.py scan src/\n\n# Validate a pattern OFFLINE (no sg call, no filesystem)\npython3 scripts/ast_grep_helper.py validate '\\w+' --lang ts\n# → exit 2: regex \\w not supported. Use $VAR for identifiers.\n\n# Doctor: check ast-grep binary availability\npython3 scripts/ast_grep_helper.py doctor\n\n# List 25 supported languages\npython3 scripts/ast_grep_helper.py langs\n\n# Install / re-install the ast-grep binary\npython3 scripts/ast_grep_helper.py install\n</code></pre>\n<p>See <a href=\"./SKILL.md\">SKILL.md</a> for full agent-facing usage and the <a href=\"./references/\"><code>references/</code></a> directory for deep dives.</p>\n<h2>Project layout</h2>\n<pre><code>ast-grep-skill/\n├── SKILL.md                       agent-facing skill (loaded by Claude Code, OpenCode, pi, etc.)\n├── README.md                      this file\n├── LICENSE                        MIT\n├── install.sh                     POSIX installer (macOS / Linux / WSL / Git Bash)\n├── install.ps1                    Windows PowerShell installer\n├── scripts/\n│   └── ast_grep_helper.py         single-file Python 3 stdlib wrapper\n├── references/\n│   ├── install.md                 per-OS install methods + manual fallback\n│   ├── patterns.md                meta-variables ($VAR, $$$) and pattern syntax\n│   ├── pitfalls.md                regex anti-patterns + language-specific traps\n│   ├── recipes.md                 copy-paste patterns by language (TS/JS/Py/Go/Rust/...)\n│   ├── cli.md                     sg run / scan / test / new / lsp reference\n│   ├── yaml-rules.md              YAML rule schema (atomic / relational / composite / transform / fix)\n│   └── sgconfig.md                project configuration (ruleDirs, testConfigs, utilDirs)\n├── tests/\n│   ├── smoke.sh                   POSIX self-test\n│   └── smoke.ps1                  PowerShell self-test (Windows CI)\n└── .github/workflows/ci.yml       matrix CI: macos / ubuntu / windows × py 3.9-3.13\n</code></pre>\n<h2>What it does</h2>\n<ol>\n<li><strong>Wraps <code>sg</code></strong> with a single Python 3 stdlib script that works the same on macOS, Linux, Windows, WSL, Git Bash.</li>\n<li><strong>Validates patterns offline</strong> before calling <code>sg</code> — catches the regex-misuse class of mistakes (<code>\\w</code>, <code>.*</code>, <code>|</code>, <code>[a-z]</code>) plus language-specific traps (Python trailing colons, JS/Go/Rust missing function bodies).</li>\n<li><strong>Resolves the binary</strong> through 6 candidate paths: cached → PATH (with Linux <code>setgroups</code> collision detection) → Homebrew. Falls through to a clear install hint with copy-paste commands.</li>\n<li><strong>Runs the two-pass write trick</strong> when applying rewrites — <code>sg run</code> silently ignores <code>--update-all</code> when <code>--json</code> is set, so <code>replace --apply</code> runs two invocations: pass 1 collects JSON matches, pass 2 mutates files.</li>\n<li><strong>Ships per-OS installers</strong> that try every reasonable package manager and fall back to a GitHub release tarball.</li>\n<li><strong>Documents the failure modes</strong> the model will hit (regex misuse, incomplete patterns, <code>--update-all</code> + <code>--json</code> trap, scope/type questions ast-grep can't answer) in <code>references/pitfalls.md</code>.</li>\n</ol>\n<h2>What it does NOT do</h2>\n<ul>\n<li>No type inference, scope analysis, or data flow. ast-grep is a structural matcher; for type-aware questions use TypeScript LSP, Pyright, Semgrep with type inference, or CodeQL.</li>\n<li>No multi-repo federation. Run the helper once per repo.</li>\n<li>No automatic <code>sgconfig.yml</code> discovery — it does what <code>sg scan</code> does (walk up from cwd looking for one).</li>\n<li>No JS/Python rewriter authoring environment — for that, write YAML rules and use <code>sg test</code> for snapshot testing (see <a href=\"./references/yaml-rules.md\"><code>references/yaml-rules.md</code></a>).</li>\n</ul>\n<h2>Limits</h2>\n<ul>\n<li>5-minute timeout per <code>sg</code> invocation (configurable in the helper).</li>\n<li>ast-grep itself supports 25 languages out-of-the-box. For anything else, use <a href=\"./references/sgconfig.md#customlanguages-experimental\"><code>customLanguages</code></a> in <code>sgconfig.yml</code>.</li>\n<li>Pattern hint detection is heuristic; pass <code>--force</code> to skip validation when you know the pattern is correct.</li>\n</ul>\n<h2>Requirements</h2>\n<ul>\n<li>Python ≥ 3.9 (stdlib only — no pip install).</li>\n<li><code>ast-grep</code> binary, installed via <code>install.sh</code> / <code>install.ps1</code> or one of:\n<ul>\n<li><code>brew install ast-grep</code> (macOS / linuxbrew)</li>\n<li><code>npm install -g @ast-grep/cli</code> (any OS with Node)</li>\n<li><code>cargo install ast-grep --locked</code> (any OS with Rust)</li>\n<li><code>pip install ast-grep-cli</code> (any OS with Python)</li>\n<li><code>scoop install main/ast-grep</code> (Windows)</li>\n</ul>\n</li>\n</ul>\n<p>For older systems and Windows-specific setup, see <a href=\"./references/install.md\"><code>references/install.md</code></a>.</p>\n<h2>Testing</h2>\n<pre><code>bash tests/smoke.sh        # POSIX (macOS / Linux / WSL / Git Bash)\npwsh tests/smoke.ps1       # Windows (PowerShell 5.1+ or 7+)\n</code></pre>\n<p>CI runs the matrix on every push: <code>{macos-latest, ubuntu-latest, ubuntu-22.04, windows-latest}</code> × <code>{Python 3.9, 3.10, 3.11, 3.12, 3.13}</code> plus a syntax-floor check on Python 3.9 and 3.10.</p>\n<h2>License</h2>\n<p><a href=\"./LICENSE\">MIT</a>.</p>\n<h2>Acknowledgments</h2>\n<ul>\n<li><a href=\"https://github.com/code-yeongyu/oh-my-opencode\"><code>omo</code> (oh-my-opencode)</a> — <code>src/tools/ast-grep/</code> is the original tool implementation; this skill is a port of its pattern-hint detection and two-pass-write strategy.</li>\n<li><a href=\"https://github.com/code-yeongyu/pi-extensions\"><code>pi-extensions/pi-ast-grep</code></a> — sibling Node port; the helper's binary-resolution cascade is modelled on it.</li>\n<li><a href=\"https://github.com/ast-grep/ast-grep\">ast-grep</a> — the CLI. All structural matching power comes from it.</li>\n<li><a href=\"https://docs.anthropic.com/en/docs/claude-code/skills\">Anthropic skills</a> — the <code>SKILL.md</code> + <code>references/</code> packaging convention.</li>\n</ul>\n","files":[{"path":"AGENTS.md","sizeBytes":3163,"isText":true},{"path":".gitignore","sizeBytes":343,"isText":false},{"path":"install.ps1","sizeBytes":7165,"isText":false},{"path":"install.sh","sizeBytes":7581,"isText":true},{"path":"LICENSE","sizeBytes":1068,"isText":false},{"path":"README.md","sizeBytes":7675,"isText":true},{"path":"references/cli.md","sizeBytes":7273,"isText":true},{"path":"references/install.md","sizeBytes":5597,"isText":true},{"path":"references/patterns.md","sizeBytes":5538,"isText":true},{"path":"references/pitfalls.md","sizeBytes":8914,"isText":true},{"path":"references/recipes.md","sizeBytes":7870,"isText":true},{"path":"references/sgconfig.md","sizeBytes":6413,"isText":true},{"path":"references/yaml-rules.md","sizeBytes":11383,"isText":true},{"path":"scripts/ast_grep_helper.py","sizeBytes":26972,"isText":true},{"path":"SKILL.md","sizeBytes":13371,"isText":true},{"path":"SOURCE","sizeBytes":125,"isText":false},{"path":"tests/smoke.ps1","sizeBytes":5701,"isText":false},{"path":"tests/smoke.sh","sizeBytes":7765,"isText":true}],"reviewScore":null,"reviewSummary":null,"trust":{"provenance":"trusted-source-unreviewed","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow.","bodySource":null},"bodyLocked":false,"purchaseUrl":null,"sourceUrl":null,"report":{"provenance":"trusted-source-unreviewed","screen":{"ran":true,"outcome":"clean","suspicious":0,"notes":0,"hiddenCharacters":false},"virusScan":{"engine":"clamav","status":"clean","scannedAt":"2026-09-25T07:38:19.398381Z","sha256":"98028FE36F619B599F4A40BC6F13AFECCC50DE78B780DCAAA292C5DE617793AC","sizeBytes":52800},"review":null,"source":{"repositoryUrl":"https://github.com/code-yeongyu/oh-my-openagent","path":"packages/shared-skills/skills/ast-grep","license":null,"commit":"05dcba64b749e7666dcd0296c079d31cf3c298f1","subtreeSha":"B4880687043F5762A3EAB25474BA8AEA85DC223E0683B9DF02DD8A9A31F726FF","lastSyncedAt":"2026-09-25T07:37:33.26442Z"},"reviewedAt":"2026-09-25T07:39:04.121964Z","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow."},"install":[{"target":"skills-cli","command":"npx skills add https://github.com/code-yeongyu/oh-my-openagent/tree/dev/packages/shared-skills/skills/ast-grep"},{"target":"claude-code","command":"claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install code-yeongyu-oh-my-openagent@llmmart"},{"target":"git","command":"git clone https://github.com/code-yeongyu/oh-my-openagent.git"}]}