Claude
Skills
Sign in
Back

ast-grep

Included with Lifetime
$97 forever

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.

General

What this skill does


# ast-grep Skill

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.

## When to Use ast-grep

**Use ast-grep when:**

- Searching for code patterns (function calls, imports, specific constructs)
- Refactoring code systematically
- Finding deprecated patterns or anti-patterns
- The pattern involves code structure, not just text

**Use grep/ripgrep when:**

- Searching for literal strings, comments, or documentation
- Simple text matching is sufficient

## Quick Reference

| 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`                   |

## Quick Start

### Simple Pattern Search

```bash
# 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
```

### Using Rules for Complex Patterns

```bash
# 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)
'
```

### Debugging Patterns

```bash
# 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
```

## Core Concepts

### Metavariables

| 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).

### Rule Structure

```yaml
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
```

## Workflow for Writing Rules

1. **Understand the query** - What code pattern are you looking for?
2. **Create example code** - Write a small file with the pattern
3. **Inspect the AST** - Use `--debug-query=ast` to see structure
4. **Write initial pattern** - Start simple, use metavariables
5. **Test and refine** - Use `--debug-query=pattern` to debug matches
6. **Add constraints** - Use relational rules (`inside`, `has`) as needed

## Common Patterns

### Match function with specific content

```yaml
rule:
  all:
    - pattern: function $NAME($$$PARAMS) { $$$ }
    - has:
        pattern: console.log($$$)
        stopBy: end
```

### Match code inside a context

```yaml
rule:
  all:
    - pattern: await $PROMISE
    - inside:
        kind: try_statement
        stopBy: end
```

### Match missing pattern (lint for absence)

```yaml
rule:
  all:
    - pattern: function $NAME($$$) { $$$ }
    - not:
        has:
          pattern: return $$$
          stopBy: end
```

## Key Principles

1. **Always use `stopBy: end`** for relational rules (`inside`, `has`, `precedes`, `follows`) to search the full subtree
2. **Start simple** - Get a basic pattern working before adding complexity
3. **Escape `$` in shell** - Use `\$VAR` or single quotes when running from bash
4. **Use `all` for order** - When metavariables depend on each other, `all` processes rules in order

## Integration Notes

### OpenCode Tools

This repository includes **nf-ast-grep MCP tools** for Nextflow-specific searches:

- `nf-ast-grep_find_processes` - Find all process definitions
- `nf-ast-grep_find_workflows` - Find workflow definitions
- `nf-ast-grep_find_channels` - Find channel factory operations
- `nf-ast-grep_find_deprecated` - Find deprecated patterns
- `nf-ast-grep_lint` - Run lint rules on Nextflow code
- `nf-ast-grep_search` - Search with custom patterns

Use these tools for Nextflow work instead of raw ast-grep commands when available.

### Shell Execution

When running ast-grep from bash:

- **Single quotes** preserve `$` metavariables: `ast-grep run --pattern 'console.$METHOD'`
- **Escape in double quotes**: `ast-grep run --pattern "console.\$METHOD"`
- For complex patterns, use `--inline-rules` with a heredoc or rule files

### When to Delegate

- **Large searches**: Use explore agents for searching across large codebases
- **Simple patterns**: Run ast-grep directly for quick one-off searches
- **Rule development**: Use iterative bash commands with `--debug-query`

## Error Handling

### "Pattern not matching expected code"

**Cause**: Pattern syntax doesn't match AST structure.

**Solution**:

1. Inspect actual AST: `ast-grep run --pattern '$$$' --debug-query=ast file.ext`
2. Check node kinds match what you expect
3. Simplify pattern and add constraints incrementally

### "ast-grep: command not found"

**Cause**: ast-grep not installed or not in PATH.

**Solution**:

```bash
# Install via cargo
cargo install ast-grep

# Or via npm
npm install -g @ast-grep/cli

# Or via nix
nix shell nixpkgs#ast-grep
```

### "Language not supported"

**Cause**: Trying to use an unsupported or unconfigured language.

**Solution**:

- Check supported languages: `ast-grep --help`
- For custom languages (like Nextflow), ensure `sgconfig.yml` is present with `customLanguages` configured
- See [Nextflow Reference](references/nextflow.md) for custom language setup

### "Missing stopBy in relational rule"

**Cause**: 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:

```yaml
rule:
  has:
    pattern: target_pattern
    stopBy: end # Don't forget this!
```

### "Metavariable not captured"

**Cause**: Using `_` prefix makes metavariables non-capturing, or metavariable used before it's defined.

**Solution**:

- Use `$VAR` (or `_VAR` in Nextflow) for capturing
- In `all` blocks, define metavariables before using them (rules process in order)

### Shell escaping issues

**Cause**: `$` in patterns gets interpreted as shell variable.

**Solution**:

```bash
# 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
```

### "Rule file not found" or YAML errors

**Cause**: Invalid YAML syntax or wrong file path.

**Solution**:

1. Validate YAML syntax (check indentation, colons, quotes)
2. Use absolute paths or run from correct directory
3. Test with `--inline-rules` first before creating rule file

## Examples

### Example 1: Finding and Fixing Deprecated Nextflow Patterns

**User request**: "Find all uses of the deprecated Channel.from() in our Nextflow pipeline"

**Workflow**:

```bash
# 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`):

```yaml
id: deprecated-channel-from
language: 
Files: 11
Size: 179.0 KB
Complexity: 59/100
Category: General

Related in General