Install
$ agentstack add skill-outlinedriven-odin-claude-plugin-ast-grep ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
ast-grep (sg)
ast-grep is a fast and polyglot tool for code searching, linting, and rewriting based on Abstract Syntax Trees (AST). It excels at structural search and replace where regex fails.
When to use
- Structural Search: Finding code based on structure (e.g., "all function calls to
foowith 2 arguments") regardless of whitespace. - Refactoring: Renaming variables, changing function signatures, or transforming code patterns safely.
- Linting: Creating custom rules to enforce code style or best practices.
- Code Analysis: Extracting information from codebases.
Quick Start
CLI Basics
# Search (pattern must be in single quotes)
ast-grep -p '$A + $B' --lang ts
# Rewrite (dry run)
ast-grep -p '$A != null' --rewrite '$A' --lang ts
# Interactive Rewrite
ast-grep -p 'var $A = $B' --rewrite 'const $A = $B' --interactive
Pattern Syntax
- Meta-variables:
$VARmatches any single node. - Multi-meta-variables:
$$$ARGSmatches zero or more nodes (list of items). - Wildcard:
$_matches any node (non-capturing). - Anonymous:
$$matches any list of nodes (non-capturing).
See [Pattern Syntax](references/pattern-syntax.md) for details.
The helper — validate first, dry-run first
scripts/ast_grep_helper.py wraps two safety gates:
# Lint a pattern before you search with it (exit 0 valid / exit 2 malformed; flags regex-smell)
python3 scripts/ast_grep_helper.py validate '$A + $B' --lang ts
# Preview a rewrite — diff + "N matches across M files", mutates nothing without --apply
python3 scripts/ast_grep_helper.py replace '$A != null' '$A' --lang ts src/
python3 scripts/ast_grep_helper.py replace '$A != null' '$A' --lang ts src/ --apply
validate compiles the pattern through ast-grep's own parser, so it catches malformed queries in every language (including Go/Python where $ is not an identifier char). replace is two-pass: dry-run prints the blast radius, --apply writes.
Rule: emit a pattern → validate it; emit a rewrite → replace dry-run, inspect the diff + match count, only then re-run with --apply.
What to use, when
structural shape (call/func/class/import shaped like X) → ast-grep
text / regex / filenames / comments / string contents → rg / grep
semantic (types, references, "who calls this symbol") → LSP / compiler
across many repos → search engine, then ast-grep per-repo
ast-grep matches syntax, not bytes. The moment you reach for |, .*, \w, or [...], you want rg, not a pattern.
When a rewrite or search surprises you
Rewrite flow (never skip the dry-run):
searchthe pattern to confirm it matches what you think.replacedry-run — read the diff.- Inspect the
N matches across M filescount; if the blast radius is wrong, stop. - Refine the pattern (tighten meta-vars, add
--lang, add context). - Re-run with
--apply.
0-matches ladder (in order):
python3 scripts/ast_grep_helper.py validate '' --lang L— is the pattern even well-formed?- Check
--lang—tsx≠ts; the wrong dialect silently matches nothing. ast-grep run -p '' -l L --debug-query=pattern— look forERRORin the dumped query tree.- Inspect the target's actual tree (
--debug-query=aston a known-matching snippet) — your node kinds may differ from your guess. - Reproduce in the online playground.
references/pitfalls.md is the deep field guide — read it when 0 matches surprises you.
Invariants (do not break)
- Validate before you search — lint the pattern via the helper first.
- Dry-run before you apply — never
--apply(or--update-all) without reading the diff. - Writes are two-pass —
--jsonand--update-allconflict: combine them and--jsonsilently wins, so the write is dropped with no error. Preview with--json, then apply with--update-allseparately. - Single-quote patterns in the shell —
$VARmust reach ast-grep unexpanded. --langis required for stdin — piped input has no filename to infer the dialect from.- A pattern is code, not regex — switch to rg the moment you'd need
|,.*,\w, or[...]. - Invoke
ast-grep, neversg—sgcollides with thesetgroupsbinary on many systems.
Core Concepts
Understanding Named vs Unnamed nodes and Matching Strictness is crucial for precise patterns.
- Named Nodes:
identifier,function_definition(matched by$VAR). - Unnamed Nodes:
(,),;(skipped by default insmartmode). - Strictness: Control matching precision (
smart,cst,ast,relaxed,signature).
See [Core Concepts](references/core-concepts.md) for details.
Rule Configuration (YAML)
For complex tasks, use YAML configuration files.
id: no-console-log
language: TypeScript
rule:
pattern: console.log($$$ARGS)
inside:
kind: function_declaration
stopBy: end
fix: '' # Remove the log
See [Rule Configuration](references/rule-config.md) for details.
Advanced Rewriting
ast-grep supports complex transformations (regex replace, case conversion) and rewriters for sub-node transformation.
See [Rewriting & Transformations](references/rewriting.md) for details.
Project Setup & Testing
For larger projects, organize rules and tests using sgconfig.yml.
- Scaffold:
ast-grep new project - Config:
sgconfig.ymldefines rule and test directories. - Testing: Define
validandinvalidcases to ensure rule accuracy.
See [Project Setup & Testing](references/project-setup.md) for details.
Utility Rules
Reuse logic with local or global utility rules. Enables recursive matching.
utils:
is-literal:
any: [{kind: string}, {kind: number}]
rule:
matches: is-literal
See [Utility Rules](references/utility-rules.md) for details.
Configuration Reference
Full reference for YAML fields (id, severity, files, ignores) and supported languages.
See [Configuration Reference](references/yaml-reference.md) for details.
CLI Reference
Common commands: scan, run, new, test, lsp.
See [CLI Reference](references/cli.md) for details.
Required reading
- [Recipes](references/recipes.md) — per-language copy-paste patterns (TS/JS, Python, Rust, Go, Java, Kotlin, C, C++). Read this first when starting a task in a given language.
- [Pitfalls](references/pitfalls.md) — failure-mode field guide (regex-vs-AST, incomplete patterns, the two-pass write, named/unnamed nodes, meta-var naming, stdin/tsx,
sg↔setgroups, and the 0-matches debug ladder). Read this when 0 matches surprises you.
Use the per-topic references linked above only when that topic is relevant.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: OutlineDriven
- Source: OutlineDriven/odin-claude-plugin
- License: Apache-2.0
- Homepage: https://outlinedriven.github.io
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.