Structural code search: finding patterns instead of strings
Grep finds text. Structural search finds shapes: every call with a literal timeout, every catch that swallows the error. How AST queries beat a regex.
Structural search matches patterns in the syntax tree rather than characters in the file. It answers questions a regex cannot: every function longer than fifty lines, every catch that discards the error, every call to fetch without a timeout, every impl of a trait that does not override a given method.
Why regex runs out
Regular expressions do not nest. Matching a balanced block, an argument list that spans lines, or a call whose receiver is an expression means writing a pattern that is wrong in a way you will not find until it matters. The classic failure is a search for a function call that misses every instance where the arguments were wrapped onto a second line.
What a query looks like
With tree-sitter's query language, finding every catch block with an empty body:
(catch_clause
body: (statement_block) @body
(#eq? @body "{}"))With ast-grep, the same class of query is written in the syntax of the language itself, using metavariables:
ast-grep --pattern 'try { $$$ } catch ($E) { }'When to reach for it
| Task | Tool |
|---|---|
| Find a symbol by name | grep, and it is faster |
| Find every caller of a function | Structural search or a language server |
| Find a code shape across a codebase | Structural search |
| Rewrite a shape everywhere | Structural search with a rewrite rule, or a codemod |
| Resolve which overload is called | A language server; the syntax tree does not know |
Where it fits with agents
Agents grep. Given a large codebase and a vague instruction, a session will run a dozen text searches and read a lot of files that turn out to be irrelevant, spending context on each one. A structural query answers the same question in one call with a precise result set, which is cheaper in tokens and more accurate.
Aura exposes its index to agents over MCP for exactly this: definitions, references and the dependency graph, queried by structure rather than by string. See the MCP server for the tool list, and tree-sitter for the query language underneath.
What is structural code search?
Searching for shapes in the parsed code instead of strings in the text — every call with a hard-coded timeout, every catch block that swallows its error, every function returning a raw pointer. The query describes a pattern in the syntax tree.
How is structural search different from grep?
grep matches characters, so it finds your pattern in comments and strings and misses it whenever the code is spaced or wrapped differently. A structural query matches nodes, so formatting is irrelevant and a match is always real code.
When should you use structural search instead of grep?
When the thing you want has a shape rather than a spelling — an empty error handler, a specific argument position, a call inside a loop. For a symbol name or a literal string, grep is faster and entirely sufficient.
Aura Crew vs Claude Code Loops: the autonomous work-loop, compared
Claude Code names four loop types: turn-based, goal, time, proactive. Aura Crew is the same idea with proof, collision-safety and any agent you like.
Autonomous coding agent loops, explained: turn-based, goal, time, and proactive
An agent repeating cycles of work until a stop condition is met. The four loop types explained, when to use each, and how to keep the quality up.
How to run multiple coding agents in parallel without merge conflicts
Several AI agents at once collide on shared files. The fix: a worktree per agent, a live team radar, and zone claims so no two ever touch one symbol.
Goal-based agent loops: giving a coding agent a definition of done
A goal-based loop iterates until a success criterion is met. The trick is a deterministic definition of done — tests, a score, a proof — not a guess.