Skip to content

WebAssembly (WASM)

WASM shows up in two subsystems: Tree-sitter for code parsing across 7 languages, and sql.js for local SQLite. Both ship as portable .wasm — no native compilation, one bundle works on macOS, Linux, and Windows.

Why WASM here:

ApproachPlatform buildsInstall frictionPerf
Native addon6+ (os × arch)node-gyp + Python + C++ toolchainFastest
Pure JS1None10–100× slower
WASM1NoneNear-native (1.2–2×)

web-tree-sitter wraps the Tree-sitter C library as WASM. Grammars are loaded lazily — only when a file of that language is first opened.

GrammarExtensionsExtracts
tree-sitter-javascript.wasm.js, .jsx, .mjs, .cjsFunctions, classes, methods, Express/Fastify routes
tree-sitter-tsx.wasm.ts, .tsx, .mts, .ctsFunctions, classes, methods, NestJS + React
tree-sitter-python.wasm.pyFunctions, classes, FastAPI / Flask / Django
tree-sitter-java.wasm.javaMethods, classes, Spring / JAX-RS annotations
tree-sitter-go.wasm.goFunctions, structs, Gin / Chi / Echo handlers
tree-sitter-rust.wasm.rsFunctions, structs, Actix / Axum / Rocket macros
tree-sitter-php.wasm.php, .phtmlFunctions, classes, interfaces, Laravel / Symfony

Runtime path resolution. Parser.init searches for tree-sitter.wasm in dist/grammars/, grammars/, out/grammars/, then node_modules/web-tree-sitter/. Handles different bundling strategies.

Parser pool. Per-language Map<language, { available: Parser[], inUse: Set<Parser> }>. Checks out a parser per file → returns after use. Avoids new Parser() + setLanguage() per file when analyzing many.

Fallback. If WASM fails to load, AstAnalyzerWorker + TreeSitterAnalyzer fall back to regex extraction covering the same languages with less accuracy (no nested structures, no multi-line signatures). Analysis always produces a result.

Every persistent store the extension owns:

DB fileServicePurpose
.codebuddy/codebase_analysis.dbSqliteDatabaseServiceCodebase snapshots, git state, and chat history (table chat_history)
.codebuddy/vector_store.dbSqliteVectorStoreVector embeddings + FTS index + file metadata
~/.codebuddy/telemetry/traces.dbTelemetryPersistenceServiceOTel spans + metrics (global, not per-workspace)
.codebuddy/checkpoints.dbSqljsCheckpointSaverLangGraph state checkpoints
.codebuddy/team_graph.dbTeamGraphStoreTeam collaboration graph

Vector store schema:

ColumnTypePurpose
idTEXTChunk ID (filePath::offset)
textTEXTSource chunk
vectorBLOBFloat32 embedding (3072 bytes for 768-dim)
filePathTEXTSource file
startLineINTEGERChunk start
endLineINTEGERChunk end
chunkTypeTEXTfunction, class, method, text_chunk
languageTEXTProgramming language

FTS4 virtual table auto-synced via SQLite triggers. Cosine similarity computed in JavaScript with event-loop yielding for large result sets.

Persistence strategy — dirty-flag debounce:

  1. Any write sets isDirty = true.
  2. 5-second debounce timer (resets on subsequent writes).
  3. On fire: db.export()fs.writeFileSync (atomic write-temp-rename).
  4. Extension deactivation triggers a final flush.

Batches rapid writes (e.g. indexing 200 files) into one disk write.

Memory model. sql.js runs entirely in memory. Fast reads, no disk I/O for queries. Memory proportional to data — a 50 MB vector store uses ~50 MB of heap. No WAL — concurrency handled at the JS layer via singletons + the chat-history worker’s concurrency guard.

Tree-sitter WASM runs in main thread AND worker threads:

ContextServiceWASM loaded
MainTreeSitterParsertree-sitter.wasm + language grammars
Codebase Analysis WorkerTreeSitterAnalyzertree-sitter.wasm + language grammars
AST Analyzer Workerweb-tree-sittertree-sitter.wasm (grammar loading optional)

Each worker initializes its own WASM instance — memory isn’t shared across threads. grammarsPath passed via workerData so workers locate .wasm relative to the install dir.

WASM memory isn’t GC’d by V8. Explicit disposal is required:

  • TreeSitterAnalyzer.dispose() in a finally after analysis completes
  • Parser pool entries cleaned on service deactivation
  • worker.terminate() releases all WASM allocations for that worker
dist/
grammars/
tree-sitter.wasm (~400 KB core runtime)
tree-sitter-javascript.wasm
tree-sitter-tsx.wasm
tree-sitter-python.wasm
tree-sitter-java.wasm
tree-sitter-go.wasm
tree-sitter-rust.wasm
tree-sitter-php.wasm
sql-wasm.wasm (~1.2 MB SQLite runtime)

Excluded from the esbuild bundle (loaded at runtime via fs.readFileSync), copied as static assets during build.

  • Workers — worker-thread architecture that uses these WASMs
  • Semantic search — the primary consumer of sql-wasm.wasm