tree_sitter_typescript::language_tsx in Rust — the right way to wire it up
How to use tree_sitter_typescript::language_tsx() from Rust without crashing on JSX-heavy files. Crate version compatibility, parser init, and how Aura uses it.
The tree-sitter-typescript crate exposes two grammars: language_typescript() for plain .ts files, and tree_sitter_typescript::language_tsx() for .tsx files containing JSX. Pick the wrong one and the parser silently truncates every JSX subtree to ERROR nodes, which is exactly what Aura\'s AST-diff engine handled wrong in v0.4 and now treats as a hard precondition.
Cargo.toml
[dependencies] tree-sitter = "0.22" tree-sitter-typescript = "0.21"
Minimal parser setup
use tree_sitter::Parser;
fn parse_tsx(source: &str) -> tree_sitter::Tree {
let mut parser = Parser::new();
parser
.set_language(&tree_sitter_typescript::language_tsx())
.expect("load tsx grammar");
parser.parse(source, None).expect("parse")
}Pitfalls Aura hit (so you don\'t have to)
- One parser, one grammar. Re-using the same
Parseracross.tsand.tsxfiles without callingset_languageagain leaves you parsing TSX with the TypeScript grammar: most JSX becomesERRORnodes and your diff is meaningless. - Version skew.
tree-sitter0.22 ABI requires atree-sitter-typescriptbuilt against the same major. Mixing 0.20 + 0.22 compiles fine, then segfaults at runtime when the parser walks a sufficiently deep tree. - UTF-16 source.
parseassumes UTF-8. If you\'re feeding it bytes from VS Code over LSP, decode first or useparse_with_options. - Cancellation timeouts. Set
parser.set_timeout_micros(…)for adversarial inputs: a hand-crafted JSX file can blow up the parser for > 30s otherwise.
How Aura uses it
Aura\'s AST-diff engine runs language_tsx() against every .tsx commit, extracts named function nodes, and hashes their structural skeleton (rename-proof identity). When Claude rewrites <UserCard> from a class component to a functional one, Aura sees one node updated, not 200 lines deleted + 180 added, and the intent log says exactly that.
Reference
The grammar source lives at tree-sitter/tree-sitter-typescript. The Aura wrapper that picks the right grammar per file extension is in aura-stackgraph/src/lang/typescript.rs (Apache 2.0).
How do you parse TSX with Tree-sitter in Rust?
Use the language_tsx() function from the tree-sitter-typescript crate rather than the plain TypeScript grammar — TSX is a separate grammar because JSX syntax is ambiguous with type assertions. Set it on the parser before parsing any .tsx source.
Why does Tree-sitter fail on JSX-heavy TypeScript files?
Almost always because the TypeScript grammar was set instead of the TSX one. They are distinct languages in the crate, and the TypeScript grammar reads a JSX element as a comparison, producing error nodes rather than a usable tree.
What causes a Tree-sitter version mismatch panic in Rust?
A grammar crate compiled against a different tree-sitter ABI than the runtime you linked. The versions must be compatible; pinning both in Cargo.toml and rebuilding cleanly is the fix, since a stale build artefact will keep reproducing it.
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.