pattern
Match code by structural shape across 19 languages using AST metavariables, not text. Enables cross-language structural queries that grep cannot handle.
Instructions
Structural AST pattern matching: match code by shape, not text. Metavars: $NAME captures an identifier or balanced expression, $_ is a wildcard, $$$ is an anonymous ellipsis, $$$NAME / $$NAME is a named ellipsis that captures multi-line bodies or arg lists, repeated metavars enforce back-reference equality. Composition: space-flanked && and || join sub-patterns (AND requires both shapes in the file with shared captures agreeing; OR takes the union). Prefer over grep / ast-grep for cross-language structural queries — grep cannot match nested syntax, and ast-grep needs per-language scripts; vex pattern works on the cached tree-sitter parse with a skeleton prefilter (~10-50ms). Set why: true to inspect indexed vs live-scan mode. Supports diff scoping: since (rev), since_branched (since this branch diverged from main), changed_only (working-tree changes) — mutually exclusive.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| why | No | Surface a ScanTrace under `_meta.why` in the response: mode (indexed/live_scan), root_kind_inferred, candidate_files / total_files, fallback_reason. | |
| lang | Yes | Language: rust, python, typescript, go, java, csharp, ruby, kotlin, swift, cpp, php, sql, markdown | |
| limit | No | Max matches to return | |
| since | No | Restrict results to files changed between `<rev>..HEAD` (accepts anything `git diff` understands: `main`, `HEAD~3`, `origin/main`, SHA). Mutually exclusive with `since_branched` and `changed_only`. | |
| exclude | No | Blacklist results by path glob; wins over include (repeatable) | |
| include | No | Whitelist results by path glob, gitignore syntax (repeatable) | |
| pattern | Yes | Structural pattern with $METAVARS (e.g. `fn $NAME($$ARGS) -> Result<$T, $E> { $$$BODY }`, `interface $N || class $N`). NOT regex — see grep for regex. | |
| changed_only | No | Restrict results to working-tree changes (staged + unstaged + untracked). Mutually exclusive with `since` and `since_branched`. | |
| project_root | No | Absolute path to the project root (defaults to the MCP working directory) | |
| exclude_tests | No | Drop test files from the results (tests/ dirs, *_test.*, test_*.py, *.spec.ts, __tests__/, tests.rs, ...; same set as tests_for). Composes with include/exclude. Path-based only: Rust unit tests inside a `#[cfg(test)] mod tests` block of a non-test file are not excluded. | |
| since_branched | No | Restrict results to files changed since this branch diverged from `origin/main` (or `main`/`master`). Mutually exclusive with `since` and `changed_only`. |