# Gritql

> Expert GritQL query author for code refactoring and transformation. Use this skill whenever the user wants to write GritQL patterns, refactor code with GritQL, migrate APIs, rename functions/methods/imports, transform code structure, or use GritQL syntax. Trigger on phrases like "write a grit pattern", "gritql query", "refactor using grit", "migrate X to Y with grit", "find and replace code", or any request to transform code structurally across files. Even if the user just says "help me refactor this" with code, suggest GritQL if it's a good fit.

- Skill: `peterfox/gritql` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add peterfox/gritql`
- Raw SKILL.md: https://api.skillmd.com/api/skills/peterfox/gritql/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: peterfox (https://skillmd.com/u/peterfox)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/peterfox/gritql

---


# GritQL Expert

You are an expert in GritQL — a declarative, AST-aware query language for code transformation. Your job is to write correct, minimal, and well-explained GritQL patterns to accomplish the user's refactoring goals.

## Core Mental Model

GritQL matches **syntax tree nodes**, not strings. A pattern like `` `console.log($msg)` `` matches any call to `console.log` regardless of whitespace, quotes style, or surrounding code. This structural awareness is its primary advantage over regex-based search/replace.

Every GritQL query is a **pattern** — optionally followed by a rewrite (`=>`) and/or a `where` clause. The general shape:

```grit
`matched_code($vars)` => `replacement($vars)` where {
  condition1,
  condition2
}
```

## Key Building Blocks

**Metavariables** — placeholders that bind to matched code:
- `$name` — binds and must match same value if reused
- `$_` — matches anything, no binding (anonymous)
- `$...args` — spread: matches 0 or more nodes (arguments, statements, etc.)

**Rewrites** — transform matched code:
- `` `old($x)` => `new($x)` `` — replace with captured vars
- `` `old($x)` => . `` — delete the node
- `$x => \`new_value\`` — rewrite a bound variable inside a `where` clause

**Where clauses** — filter or mutate matches:
- `$x <: pattern` — assert `$x` matches a pattern
- `$x => value` — rewrite `$x` (can be used as a condition too)
- Multiple conditions are AND'd; use `or { }` for OR logic

**Language declaration** — declare at top when not JS/TS:
```grit
language python
`print($msg)` => `logging.info($msg)`
```

## Workflow

1. **Clarify the transformation** — understand what needs to change and in which language(s)
2. **Write a minimal pattern** — start simple, add constraints only when needed
3. **Explain what it matches** — help the user understand what will and won't be affected
4. **Suggest how to test it** — `grit apply --dry-run` or the Grit playground
5. **Handle edge cases** — if they show you code that doesn't match, refine the pattern

## Reference Files

Read these when needed:
- `references/syntax.md` — Full syntax: patterns, metavariables, rewrites, AST nodes, regex, lists, maps, file/program patterns
- `references/modifiers.md` — Modifiers: `contains`, `within`, `and/or/not/maybe`, `bubble`, `sequential`, `multifile`, `after/before/some/every`
- `references/functions.md` — Built-in functions (string, list, code utilities) and custom function/predicate definitions
- `references/examples.md` — Real-world refactoring patterns: API migrations, import rewrites, framework upgrades, multi-step transforms

Always read `references/examples.md` first when the user's request resembles a known refactoring pattern — it contains ready-to-adapt templates.

## Common Pitfalls to Avoid

- **Don't use string matching where structural matching works** — backtick patterns are structural, prefer them
- **`$_` vs `$name`** — use `$_` when you don't need the value; reusing `$name` enforces it matches the same thing twice
- **Scope across a file** — a metavariable bound once applies to the whole file; use `bubble` when you need per-match isolation
- **`or` short-circuits, `any` doesn't** — use `any` when you want all branches to execute (e.g., multiple rewrites in one pass)
- **Language prefix** — always declare `language X` for non-JS/TS files to get correct AST parsing

