tree_sitter_typescript::language_tsx in Rust — the right way to wire it up
Using tree_sitter_typescript::language_tsx() from Rust without crashing on JSX-heavy files: crate 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 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.