bonsai

Language intelligence

Three layers give the agent code understanding: built-in tree-sitter parsing (offline, always available), managed language servers (when installed), and web research for everything outside the repository.

Tree-sitter symbols

Grammars for Rust, TypeScript/TSX, JavaScript/JSX, Python, and Go are compiled into the binary — no network, no server. They power symbol_search, read_symbol, and the startup repository map.

What the extractors index per language: functions, methods, structs/classes, enums, traits/interfaces, impls, modules, type aliases, constants and public/exported variables — each with kind, name, one-line signature, position, and visibility (Rust pub, JS/TS exports and #private, Python underscore convention, Go capitalization).

The repository map

At startup bonsai builds a ranked, token-budgeted outline of the repository (~1,500 tokens): files scored by public-symbol count with entry-point bonuses (main.rs, lib.rs, index.ts, main.go, __init__.py, …), up to 12 symbols per file, 5,000-file scan cap. The output is deliberately byte-stable (sorted, deterministic) so it lives in the cacheable prompt prefix. The TUI builds it in the background and injects it before the first turn; headless builds it eagerly. Smol mode omits it.

Language servers

Definition, references, hover, workspace-symbol, rename, and diagnostics use a managed server when its command is installed:

Language Server Install Override
Rust rust-analyzer rustup component add rust-analyzer BONSAI_RUST_ANALYZER
TypeScript/JavaScript typescript-language-server --stdio npm i -g typescript-language-server typescript BONSAI_TYPESCRIPT_LANGUAGE_SERVER
Python pyright-langserver --stdio npm i -g pyright or pip install pyright BONSAI_PYRIGHT_LANGSERVER
Go gopls go install golang.org/x/tools/gopls@latest BONSAI_GOPLS

Mechanics:

Web research

websearch

Providers: Brave Search, Tavily, or a self-selected SearXNG instance (its JSON format must be enabled). Configure before startup:

When several are configured the order is Brave → Tavily → SearXNG; BONSAI_WEB_SEARCH_PROVIDER=brave|tavily|searxng chooses explicitly. Supports recency filters (day/week/month/year) and up-to-8 primary-domain filters; returns bounded titles, source URLs, dates when available, and snippets (≤10 results). Results are untrusted data; URLs are preserved in the transcript and headless event stream. Search never fetches a result page implicitly — the search-provider domain and every source domain go through separate network permission checks. Queries containing something that looks like a live secret are refused.

webfetch

Fetches one URL as markdown (HTML converted, text/JSON/XML passed through, binary refused) with hard security properties: public-address validation with per-request DNS pinning (anti-rebinding), manual redirect following (≤5) with re-validation and re-authorization per hop, per-domain permission prompts at High risk, 5 MiB body cap, 30 s total deadline, and untrusted framing of everything returned. Details in Tools and Security model.

Background tasks and PTY terminals

The execution side of “run, debug, verify”:

Where this lives in the code

Concern Location
Tree-sitter extractors src/symbol/
Repository map src/tool/repo_map.rs
LSP hub, clients, specs src/lsp/
LSP tools & diagnostics src/tool/lsp.rs, src/tool/diagnostics.rs
Web tools src/tool/webfetch.rs, src/tool/websearch.rs
Background tasks & PTYs src/background.rs, src/terminal.rs