diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md
index f229a323c..9f8533968 100644
--- a/packages/coding-agent/CHANGELOG.md
+++ b/packages/coding-agent/CHANGELOG.md
@@ -1,6 +1,7 @@
# Changelog
## [Unreleased]
+
### Added
- Added `glob` parameter to `ast_grep` and `ast_edit` tools for additional glob filtering relative to the `path` parameter
@@ -8,6 +9,9 @@
### Changed
+- Renamed `patterns` parameter to `pat` in `ast_grep` tool for consistency
+- Renamed `selector` parameter to `sel` in `ast_grep` and `ast_edit` tools for brevity
+- Updated tool documentation with expanded guidance on AST pattern syntax, metavariable usage, and contextual matching strategies
- Updated `grep` tool to combine glob patterns from `path` and `glob` parameters instead of throwing an error when both are provided
## [13.9.4] - 2026-03-07
diff --git a/packages/coding-agent/src/prompts/tools/ast-edit.md b/packages/coding-agent/src/prompts/tools/ast-edit.md
index 17bca6b78..f6963e2e9 100644
--- a/packages/coding-agent/src/prompts/tools/ast-edit.md
+++ b/packages/coding-agent/src/prompts/tools/ast-edit.md
@@ -4,8 +4,13 @@ Performs structural AST-aware rewrites via native ast-grep.
- Use for codemods and structural rewrites where plain text replace is unsafe
- Narrow scope with `path` before replacing (`path` accepts files, directories, or glob patterns; use `glob` for an additional filter relative to `path`)
- Default to language-scoped rewrites in mixed repositories: set `lang` and keep `path`/`glob` narrow
-- Treat parse issues as a scoping signal: tighten `path`/`lang` before retrying
+- Treat parse issues as a scoping or pattern-shape signal: tighten `path`/`lang`, or rewrite the pattern into valid syntax before retrying
- Metavariables captured in each rewrite pattern (`$A`, `$$$ARGS`) are substituted into that entry's rewrite template
+- For variadic captures, use `$$$NAME` (not `$$NAME`)
+- Rewrite patterns must parse as valid AST for the target language; if a method or declaration does not parse standalone, wrap it in valid context or switch to a contextual `sel`
+- For TypeScript declarations, prefer patterns that tolerate annotations you do not care about, e.g. `async function $NAME($$$ARGS): $_ { $$$BODY }`
+- Metavariables must be the sole content of an AST node; partial-text metavariables like `prefix$VAR` or `"hello $NAME"` do NOT work in patterns or rewrites
+- To delete matched code, use an empty `out` string: `{"pat":"console.log($$$)","out":""}`
- Each matched rewrite is a 1:1 structural substitution; you cannot split one capture into multiple nodes or merge multiple captures into one node
@@ -17,14 +22,25 @@ Performs structural AST-aware rewrites via native ast-grep.
- Rename a call site across a directory:
`{"ops":[{"pat":"oldApi($$$ARGS)","out":"newApi($$$ARGS)"}],"lang":"typescript","path":"src/"}`
-- Multi-op codemod:
- `{"ops":[{"pat":"require($A)","out":"import $A"},{"pat":"module.exports = $E","out":"export default $E"}],"lang":"javascript","path":"src/"}`
+- Delete all matching calls (empty `out` removes the matched node):
+ `{"ops":[{"pat":"console.log($$$ARGS)","out":""}],"lang":"typescript","path":"src/"}`
+- Rewrite an import source path:
+ `{"ops":[{"pat":"import { $$$IMPORTS } from \"old-package\"","out":"import { $$$IMPORTS } from \"new-package\""}],"lang":"typescript","path":"src/"}`
+- Modernize to optional chaining (same metavariable enforces identity):
+ `{"ops":[{"pat":"$A && $A()","out":"$A?.()"}],"lang":"typescript","path":"src/"}`
- Swap two arguments using captures:
`{"ops":[{"pat":"assertEqual($A, $B)","out":"assertEqual($B, $A)"}],"lang":"typescript","path":"tests/"}`
+- Rename a TypeScript function declaration while tolerating any return type annotation:
+ `{"ops":[{"pat":"async function fetchData($$$ARGS): $_ { $$$BODY }","out":"async function loadData($$$ARGS): $_ { $$$BODY }"}],"sel":"function_declaration","lang":"typescript","path":"src/api.ts"}`
+- Rewrite a class method by matching it through valid class context:
+ `{"ops":[{"pat":"class $_ { execute($$$ARGS) { $$$BODY } }","out":"class $_ { run($$$ARGS) { $$$BODY } }"}],"sel":"method_definition","lang":"typescript","path":"src/runner.ts"}`
+- Convert Python print calls to logging:
+ `{"ops":[{"pat":"print($$$ARGS)","out":"logger.info($$$ARGS)"}],"lang":"python","path":"src/"}`
- `ops` **MUST** contain at least one concrete `{ pat, out }` entry
- If the path pattern spans multiple languages, set `lang` explicitly for deterministic rewrites
+- Parse issues mean the rewrite request is malformed or mis-scoped; do not assume a clean no-op until the pattern parses successfully
- For one-off local text edits, prefer the Edit tool instead of AST edit
\ No newline at end of file
diff --git a/packages/coding-agent/src/prompts/tools/ast-grep.md b/packages/coding-agent/src/prompts/tools/ast-grep.md
index f41609f92..90a5f5974 100644
--- a/packages/coding-agent/src/prompts/tools/ast-grep.md
+++ b/packages/coding-agent/src/prompts/tools/ast-grep.md
@@ -4,12 +4,19 @@ Performs structural code search using AST matching via native ast-grep.
- Use this when syntax shape matters more than raw text (calls, declarations, specific language constructs)
- Prefer a precise `path` scope to keep results targeted and deterministic (`path` accepts files, directories, or glob patterns; use `glob` for an additional filter relative to `path`)
- Default to language-scoped search in mixed repositories: pair `path` + `glob` + explicit `lang` to avoid parse-noise from non-source files
-- `patterns` is required and must include at least one non-empty AST pattern; `lang` is optional (`lang` is inferred per file extension when omitted)
+- `pat` is required and must include at least one non-empty AST pattern; `lang` is optional (`lang` is inferred per file extension when omitted)
- Multiple patterns run in one native pass; results are merged and then `offset`/`limit` are applied to the combined match set
-- Use `selector` only for contextual pattern mode; otherwise provide direct patterns
+- Use `sel` only for contextual pattern mode; otherwise provide direct patterns
- For variadic arguments/fields, use `$$$NAME` (not `$$NAME`)
+- Patterns must parse as a single valid AST node for the target language; if a bare pattern fails, wrap it in valid context or use `sel`
- Patterns match AST structure, not text — whitespace/formatting differences are ignored
- When the same metavariable appears multiple times, all occurrences must match identical code
+- For TypeScript declarations, prefer shapes that tolerate annotations you do not care about, e.g. `async function $NAME($$$ARGS): $_ { $$$BODY }` instead of omitting the return type entirely
+- Metavariables must be the sole content of an AST node; partial-text metavariables like `prefix$VAR`, `"hello $NAME"`, or `a $OP b` do NOT work — match the whole node instead
+- `$$$` captures are lazy (non-greedy): they stop when the next element in the pattern can match; place the most specific node after `$$$` to control where capture ends
+- `$_` is a non-capturing wildcard (matches any single node without binding); use it when you need to tolerate a node but don't need its value
+- Search the right declaration form before concluding absence: top-level function, class method, and variable-assigned function are different AST shapes
+- If you only need to prove a symbol exists, prefer a looser contextual search such as `pat: ["executeBash"]` with `sel: "identifier"`