tree-sitter-bash stubbed out in Bun single-file binary — all Bash permission checks use legacy fallback

Resolved 💬 2 comments Opened Mar 14, 2026 by d33disc Closed Apr 12, 2026

Description

Every Bash tool invocation logs:

bashToolHasPermission: tree-sitter unavailable, using legacy shell-quote path

The tree-sitter-bash parser is completely non-functional in the compiled CLI binary. All Bash permission checks fall back to the legacy shell-quote path, which provides less accurate command parsing.

Root Cause

The CLI is compiled with bun build --compile into a single Mach-O executable. The tree-sitter-bash NAPI native addon (tree-sitter-bash.node) is referenced in the Bun virtual filesystem (/$bunfs/root/tree-sitter-bash.node) but cannot be loaded because dlopen() cannot open files from Bun's in-memory $bunfs.

As a result, the parser functions are stubbed out in the compiled binary:

async function parseCommandRaw(_) { if (!_ || _.length > limit) return null; return null }
async function parseCommand(_)    { if (!_ || _.length > limit) return null; return null }
async function ensureInitialized() {}

These always return null, which triggers {kind: "parse-unavailable"} → legacy shell-quote fallback for every single Bash tool call.

Environment

  • Claude Code version: 2.1.75 (also confirmed on 2.1.72, 2.1.73, 2.1.74)
  • Platform: macOS 15.5, Apple M1 Max (darwin-arm64)
  • Binary: /Users/<user>/.local/share/claude/versions/2.1.75 (Bun-compiled single-file executable, ~190MB)

Reproduction

  1. Open Claude Code in VSCode or terminal
  2. Run any Bash command
  3. Check logs: grep 'tree-sitter unavailable' "<log path>"
  4. Every Bash invocation will show the fallback message

Impact

  • Bash permission parsing runs in a less capable mode for all users on compiled binaries
  • Potential for less accurate command safety analysis (the tree-sitter parser handles complex shell syntax that regex/shell-quote cannot)

Suggested Fix

Ship tree-sitter-bash.node as a sidecar file alongside the binary rather than embedding it in $bunfs, or use the tree-sitter WASM build (tree-sitter-bash.wasm) which doesn't require dlopen().

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗