config/agents/skills/ast-grep/SKILL.md
Structural code search and refactoring using AST patterns. Use when searching for code patterns (not text), finding deprecated patterns, or systematic refactoring. Supports Nextflow, JavaScript, Python, and more.
npx skillsauth add edmundmiller/dotfiles ast-grepInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
ast-grep is a structural code search and rewriting tool. Use it when you need to find or modify code based on its AST structure rather than text patterns.
Use ast-grep when:
Use grep/ripgrep when:
| Task | Command |
| ------------------ | ---------------------------------------------- |
| Find pattern | ast-grep run --pattern 'PATTERN' --lang LANG |
| Scan with rule | ast-grep scan --rule file.yaml |
| Debug AST | --debug-query=ast |
| Test pattern match | --debug-query=pattern |
| Use inline rule | --inline-rules 'YAML' |
| Nextflow patterns | Use _VAR instead of $VAR |
# Find all console.log calls
ast-grep run --pattern 'console.log($$$ARGS)' --lang js
# Find Channel.from() calls in Nextflow
ast-grep run --pattern 'Channel.from(___)' --lang nextflow
# Scan with a rule file
ast-grep scan --rule path/to/rule.yaml
# Quick inline rule test
ast-grep scan --inline-rules '
id: test-rule
language: javascript
rule:
pattern: console.log($$$ARGS)
'
# See AST structure of code
ast-grep run --pattern '$$$' --debug-query=ast path/to/file.js
# See how pattern matches
ast-grep run --pattern 'your_pattern' --debug-query=pattern path/to/file.js
| Syntax | Matches | Example |
| ---------- | --------------------------------- | --------------------------------------- |
| $VAR | Single named node | console.$METHOD matches console.log |
| $$VAR | Single node (including anonymous) | $$OP matches operators |
| $$$VAR | Zero or more nodes | func($$$ARGS) matches any args |
| _ prefix | Non-capturing (Nextflow) | _VAR instead of $VAR |
Note: In Nextflow, use _ instead of $ for metavariables (configured via expandoChar in sgconfig.yml).
id: rule-name
language: javascript # or nextflow, python, etc.
severity: warning # error, warning, hint, off
message: "Human-readable message"
note: |
Additional context and fix suggestions
rule:
pattern: code_pattern_here
--debug-query=ast to see structure--debug-query=pattern to debug matchesinside, has) as neededrule:
all:
- pattern: function $NAME($$$PARAMS) { $$$ }
- has:
pattern: console.log($$$)
stopBy: end
rule:
all:
- pattern: await $PROMISE
- inside:
kind: try_statement
stopBy: end
rule:
all:
- pattern: function $NAME($$$) { $$$ }
- not:
has:
pattern: return $$$
stopBy: end
stopBy: end for relational rules (inside, has, precedes, follows) to search the full subtree$ in shell - Use \$VAR or single quotes when running from bashall for order - When metavariables depend on each other, all processes rules in orderThis repository includes nf-ast-grep MCP tools for Nextflow-specific searches:
nf-ast-grep_find_processes - Find all process definitionsnf-ast-grep_find_workflows - Find workflow definitionsnf-ast-grep_find_channels - Find channel factory operationsnf-ast-grep_find_deprecated - Find deprecated patternsnf-ast-grep_lint - Run lint rules on Nextflow codenf-ast-grep_search - Search with custom patternsUse these tools for Nextflow work instead of raw ast-grep commands when available.
When running ast-grep from bash:
$ metavariables: ast-grep run --pattern 'console.$METHOD'ast-grep run --pattern "console.\$METHOD"--inline-rules with a heredoc or rule files--debug-queryCause: Pattern syntax doesn't match AST structure.
Solution:
ast-grep run --pattern '$$$' --debug-query=ast file.extCause: ast-grep not installed or not in PATH.
Solution:
# Install via cargo
cargo install ast-grep
# Or via npm
npm install -g @ast-grep/cli
# Or via nix
nix shell nixpkgs#ast-grep
Cause: Trying to use an unsupported or unconfigured language.
Solution:
ast-grep --helpsgconfig.yml is present with customLanguages configuredCause: Relational rules (inside, has, precedes, follows) default to stopBy: neighbor which only checks immediate children.
Solution: Always add stopBy: end to search the full subtree:
rule:
has:
pattern: target_pattern
stopBy: end # Don't forget this!
Cause: Using _ prefix makes metavariables non-capturing, or metavariable used before it's defined.
Solution:
$VAR (or _VAR in Nextflow) for capturingall blocks, define metavariables before using them (rules process in order)Cause: $ in patterns gets interpreted as shell variable.
Solution:
# Use single quotes (preferred)
ast-grep run --pattern 'console.$METHOD'
# Or escape in double quotes
ast-grep run --pattern "console.\$METHOD"
# Or use rule files to avoid shell entirely
ast-grep scan --rule my-rule.yaml
Cause: Invalid YAML syntax or wrong file path.
Solution:
--inline-rules first before creating rule fileUser request: "Find all uses of the deprecated Channel.from() in our Nextflow pipeline"
Workflow:
# Step 1: Quick search to see scope of problem
ast-grep run --pattern 'Channel.from(___)' --lang nextflow
# Step 2: If many results, use the lint tool for structured output
# (uses existing deprecated-channel-from.yaml rule)
Rule used (deprecated-channel-from.yaml):
id: deprecated-channel-from
language: nextflow
severity: warning
message: "Channel.from() is deprecated in DSL2"
note: |
Use Channel.of() for simple values or Channel.fromList() for lists.
Before: Channel.from(1, 2, 3)
After: Channel.of(1, 2, 3)
rule:
pattern: Channel.from(___)
Result: Found 3 instances in main.nf, updated to use Channel.of().
User request: "Replace all console.log calls with our custom logger"
Workflow:
# Step 1: Find all console.log calls
ast-grep run --pattern 'console.log($$$ARGS)' --lang js
# Step 2: Create a rewrite rule
cat > /tmp/replace-console.yaml << 'EOF'
id: replace-console-log
language: javascript
rule:
pattern: console.log($$$ARGS)
fix: logger.info($$$ARGS)
EOF
# Step 3: Preview changes
ast-grep scan --rule /tmp/replace-console.yaml
# Step 4: Apply changes (with --update-all)
ast-grep scan --rule /tmp/replace-console.yaml --update-all
Key insight: The fix field in rules enables automatic refactoring, not just finding.
User request: "Create a rule that warns when async functions don't have error handling"
Workflow:
# Step 1: Create example code to understand the AST
cat > /tmp/example.js << 'EOF'
async function good() {
try {
await fetch('/api');
} catch (e) {
console.error(e);
}
}
async function bad() {
await fetch('/api'); // No try-catch!
}
EOF
# Step 2: Inspect AST structure
ast-grep run --pattern '$$$' --debug-query=ast /tmp/example.js
# Step 3: Write initial pattern for async functions with await
ast-grep run --pattern 'async function $NAME($$$) { $$$ }' /tmp/example.js
# Step 4: Add constraint: must have await but no try statement
cat > /tmp/async-error-handling.yaml << 'EOF'
id: async-needs-error-handling
language: javascript
severity: warning
message: "Async function '$NAME' has await but no try-catch"
note: |
Async functions with await should have error handling.
Wrap await calls in try-catch blocks.
rule:
all:
- pattern: async function $NAME($$$PARAMS) { $$$BODY }
- has:
pattern: await $$$
stopBy: end
- not:
has:
kind: try_statement
stopBy: end
EOF
# Step 5: Test the rule
ast-grep scan --rule /tmp/async-error-handling.yaml /tmp/example.js
Result: Rule correctly flags bad() but not good().
User request: "Find closures that use implicit 'it' parameter - we want explicit parameters for readability"
Workflow:
# Use the existing rule via nf-ast-grep tools
# Or run directly:
ast-grep scan --rule config/opencode/skills/ast-grep/rules/implicit-it-closure.yaml
Rule explanation (implicit-it-closure.yaml):
id: implicit-it-closure
language: nextflow
severity: hint
message: "Consider using explicit closure parameter instead of implicit 'it'"
rule:
all:
- kind: closure
- has:
pattern: it
stopBy: end
- not:
has:
kind: closure_parameter
stopBy: end
This uses kind matching (AST node type) combined with has/not has to find closures that reference it but don't declare a parameter.
User request: "Find all React components that use useState but don't have a useEffect cleanup"
Workflow:
cat > /tmp/missing-cleanup.yaml << 'EOF'
id: missing-useeffect-cleanup
language: typescript
severity: warning
message: "Component uses useState but may be missing useEffect cleanup"
rule:
all:
- kind: function_declaration
- has:
pattern: useState($$$)
stopBy: end
- has:
pattern: useEffect($$$)
stopBy: end
- not:
has:
pattern: |
useEffect(() => {
$$$SETUP
return $$$CLEANUP
}, $$$DEPS)
stopBy: end
EOF
ast-grep scan --rule /tmp/missing-cleanup.yaml src/
Key insight: Complex patterns can combine multiple has and not has clauses to express sophisticated constraints.
For detailed syntax and advanced features, see:
This skill document provides a practical introduction to ast-grep. For deeper understanding:
development
Read-only Linear issue access via the Linear GraphQL API.
data-ai
## <!-- Purpose: Teach agents fast day-to-day memory browse/search/read/sync workflows in pi-context-repo. --> name: searching-memory description: > Search, browse, and inspect memory quickly in pi-context-repo. Use when asked to find prior notes, inspect memory files, locate preferences, or sync recent memory updates. Trigger phrases: "search memory", "list memory files", "find in memory", "read memory file", "memory status", "sync memory". --- # Searching Memory Use this workflow for fast
development
Comprehensive guide for initializing or reorganizing agent memory into a deeply hierarchical file structure. Use when running /init, when user asks to set up memory, or when memory needs a major reorganization. Trigger phrases: "initialize memory", "set up memory", "populate memory", "build my memory", "memory init".
data-ai
Decomposes and reorganizes agent memory files into focused, single-purpose components. Use when memory has large multi-topic blocks, redundancy, or poor organization. Trigger phrases: "defrag memory", "reorganize memory", "clean up memory files", "split memory blocks".