Tree-sitter and the AST: how tools read your code
Tree-sitter parses source into a concrete syntax tree fast enough to run on every keystroke, and keeps working on code that does not compile. What the tree contains, and what it is used for.
Tree-sitter is a parser generator and an incremental parsing library: it turns source code into a syntax tree, updates that tree as you type, and keeps producing a usable tree when the code is broken. It is what sits underneath syntax highlighting in Neovim, code navigation on GitHub, and most tools that need to understand code structure without running a compiler.
What the tree looks like
For function add(a, b) { return a + b; } a tree-sitter tree contains afunction_declaration with a name, a formal_parameters node holding two identifiers, and a statement_block holding a return_statement holding a binary_expression. Every node carries its byte range in the file, so a node maps back to exactly the text it came from.
Strictly this is a concrete syntax tree: it keeps every token, including punctuation. Named nodes are the interesting ones, and most tools query those. The distinction from an abstract syntax tree matters when you are writing queries and wondering why a comma has a node.
The three properties that matter
- Incremental. Editing one line re-parses that region rather than the file, which is what makes per-keystroke use possible.
- Error tolerant. A missing brace produces a tree with an error node, not a failure. Half-written code still highlights and still indexes.
- Uniform across languages. One query language works over every grammar, so a tool supports a new language by adding a grammar rather than by writing a parser.
Queries
Tree-sitter ships an s-expression query language for matching patterns in the tree. Finding every function declaration with its name looks like this:
(function_declaration
name: (identifier) @name
body: (statement_block) @body)That is the whole mechanism behind structural search, syntax highlighting and most code-mod tooling. See structural code search for what you can do with it.
What it does not do
Tree-sitter parses. It does not resolve types, imports or overloads, and it does not know that the foo in one file is the foo defined in another. Tools that need that build a resolution layer on top, or fall back to a language server. Knowing the boundary keeps expectations right: a syntax tree gives structure, and structure covers a surprising amount of what review and diffing need.
Where Aura uses it
Every file Aura indexes is parsed with tree-sitter, each node is hashed into a Merkle graph, and the graph is what the semantic diff, the impact analysis and the goal proof read from. Grammar packages differ in shape between languages, which is a common source of confusion; the TypeScript and Rust grammar note covers the two that trip people up most.
What is Tree-sitter?
A parser generator and incremental parsing library that turns source code into a concrete syntax tree. It is fast enough to reparse on every keystroke and it keeps producing a usable tree from code that does not compile, which is why editors and code tools use it.
What is an AST?
An abstract syntax tree — the structure of a program as a tree of nested constructs rather than a sequence of characters. Functions contain statements, statements contain expressions. Tools that need to know what code means rather than how it is spelled work on this.
What is the difference between a concrete and an abstract syntax tree?
A concrete tree keeps everything in the source, punctuation and comments included, so you can reconstruct the file exactly. An abstract tree drops what is only there for the parser. Tree-sitter produces a concrete tree, which is why it can rewrite code without reformatting it.
Why do code tools use Tree-sitter instead of a compiler?
A compiler front end is accurate, slow, per-language, and gives up on broken input. Tree-sitter is approximate, fast, uniform across languages, and returns a tree with an error node where the mistake is — which is the right trade for an editor or a diff.
Aura Crew vs Claude Code Loops: the autonomous work-loop, compared
Claude Code defines four loop types — turn-based, goal, time, and proactive. Aura Crew is the same idea productized: a dependency-ordered work-loop with proof, collision-safety, and any agent. Full comparison.
Autonomous coding agent loops, explained: turn-based, goal, time, and proactive
A coding agent loop is an agent repeating cycles of work until a stop condition is met. The four types explained — turn-based, goal-based, time-based, proactive — with when to use each and how to keep quality high.
How to run multiple coding agents in parallel without merge conflicts
Running several AI coding agents at once collides on shared files. The fix: a worktree per agent, a live team radar, and soft-to-hard zone claims so parallel agents never touch the same symbol. How Aura Crew does it.
Goal-based agent loops: giving a coding agent a definition of done
A goal-based loop keeps a coding agent iterating until a success criterion is met. The trick is a deterministic definition of done — tests, a score, a proof — not an LLM guessing at "good enough." How to write one.