npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

codebase-contextualizer-cli

v1.0.0

Published

Local semantic code search CLI using Tree-sitter, worker threads, local embeddings, and SQLite vector storage.

Readme

Codebase Contextualizer CLI

Query your codebase in plain English, completely offline. Codebase Contextualizer CLI indexes local JavaScript-family projects with Tree-sitter, creates local embeddings with @xenova/transformers, stores vectors in SQLite, and searches code semantics from your terminal without sending source code to external APIs.

npx codebase-contextualizer-cli index .
npx codebase-contextualizer-cli search "where are files hashed with sha256" .

Highlights

  • Zero external API dependencies: embeddings and search run locally.
  • Sub-0.08ms p95 vector retrieval latency over 1,000 local benchmark queries.
  • Worker-thread indexing keeps parsing and embedding work off the main V8 event loop.
  • Tree-sitter semantic chunks for JavaScript-family files.
  • SQLite vector storage in .contextualizer/vector.db.
  • JSON output for scripts, demos, and CI-friendly inspection.

Installation

Run without installing:

npx codebase-contextualizer-cli <command> [arguments]

Install globally:

npm install -g codebase-contextualizer-cli
codebase-contextualizer <command> [arguments]

Requirements:

  • Node.js 20 or newer
  • npm 10 or newer recommended

Usage

Index a codebase:

codebase-contextualizer index .

Index with a fixed worker count:

codebase-contextualizer index . --workers 4

Check cache drift without writing updates:

codebase-contextualizer status .

Search indexed code:

codebase-contextualizer search "hash files with sha256" .

Return machine-readable output:

codebase-contextualizer search "worker pool queue" . --json

CLI Examples

$ codebase-contextualizer index .
Index complete: C:\projects\my-app
Cache: C:\projects\my-app\.contextualizer\cache.json
Scanned files: 42
New: 42
Modified: 0
Unchanged: 0
Removed: 0
Embedded chunks: 118
Vector database: C:\projects\my-app\.contextualizer\vector.db
Persisted chunks: 118
$ codebase-contextualizer search "where is the worker queue drained" .
Search: where is the worker queue drained
Target: C:\projects\my-app
Database: C:\projects\my-app\.contextualizer\vector.db

1. drainQueue (function)
Score: 0.8124
File: src/worker-pool.js
Line: 74-118
Code:
function drainQueue() {
  ...
}
$ codebase-contextualizer status . --json
{
  "root": "C:\\projects\\my-app",
  "cacheExists": true,
  "saved": false,
  "counts": {
    "scanned": 42,
    "new": 0,
    "modified": 1,
    "unchanged": 41,
    "removed": 0
  }
}

Features

  • Offline semantic code search with no SaaS API calls.
  • Incremental indexing with SHA-256 file hashes.
  • .gitignore-aware traversal.
  • Worker pool architecture for CPU-heavy parsing and embedding.
  • Zero-copy transfer of Float32Array embeddings from workers to the main thread.
  • SQLite persistence with WAL mode and transactional writes.
  • Graceful Ctrl+C cleanup for workers and database handles.

System Architecture

The CLI is split into two execution planes.

Main thread

  • Parses commands with commander.
  • Walks directories asynchronously while respecting .gitignore.
  • Hashes source files with streamed SHA-256.
  • Uses the cache at .contextualizer/cache.json to process only new or modified files.
  • Owns all SQLite writes through better-sqlite3.

Worker pool

  • Uses native Node.js worker_threads.
  • Defaults to Math.min(4, Math.max(1, os.cpus().length - 1)) workers.
  • Each worker initializes its own Tree-sitter parser and singleton local embedding pipeline.
  • Workers read files, extract JavaScript functions/classes/methods, build semantic payloads, and return chunk metadata plus vector tensors.

This design avoids the primary Node.js performance trap: running CPU-heavy AST parsing and ONNX inference on the main V8 event loop. The main thread remains responsible for orchestration and storage, while worker threads absorb the expensive compute path.

Memory Management

Embeddings are represented as Float32Array instances end to end. Workers convert model output into compact typed arrays before returning results to the main process.

The worker response uses zero-copy transfer:

parentPort.postMessage(payload, transferList);

Each vector's underlying ArrayBuffer is included in transferList, so ownership moves from the worker to the main thread instead of cloning megabytes of embedding data. This prevents avoidable garbage collection pressure and keeps large-codebase indexing predictable.

Storage Engine

Vectors are persisted in .contextualizer/vector.db with better-sqlite3.

The database uses:

  • PRAGMA journal_mode = WAL for concurrent-friendly write behavior.
  • A files table keyed by path and hash.
  • A chunks table containing symbol metadata, line ranges, source snippets, and vector BLOBs.
  • Bulk transactional writes with db.transaction() so chunk inserts are committed as a batch.
  • Binary vector storage via Buffer.from(embedding.buffer).

At search time, BLOBs are reconstructed as typed arrays:

new Float32Array(
  row.embedding.buffer,
  row.embedding.byteOffset,
  row.embedding.byteLength / Float32Array.BYTES_PER_ELEMENT
);

Cosine similarity is computed over typed arrays and the top matches are ranked in memory.

Benchmark

Run the search latency benchmark against the current directory:

node scripts/benchmark.js

Run against another indexed target:

node scripts/benchmark.js ./src "authentication logic"

The benchmark opens .contextualizer/vector.db, embeds a dummy query once, runs 1,000 cosine-similarity scans, and reports average, p50, p90, and p95 latency in milliseconds.

Performance: achieves sub-0.0763ms p95 vector retrieval latency over 1,000 local queries.

Current Language Support

The parser dispatch layer currently routes JavaScript-family files:

  • .js
  • .jsx
  • .mjs
  • .cjs

Unsupported source extensions are skipped gracefully. The architecture is ready for additional Tree-sitter grammars through the parser router.

Local Package Testing

From the repository root:

npm install
npm link
codebase-contextualizer --help
codebase-contextualizer status . --json
npm pack --dry-run
npx --yes . --help

Remove the global link when finished:

npm unlink -g codebase-contextualizer-cli

Engineering Notes

  • No external embedding APIs are used.
  • Unchanged files are not re-parsed or re-embedded.
  • Indexing skips source files over 1 MB, common binary extensions, and obvious minified bundles before they reach the parser.
  • Ctrl+C aborts active indexing, terminates worker threads, and closes open SQLite handles.
  • SQLite writes happen on the main thread after worker results return.
  • Search loads the local embedding model as a singleton for query vectors.
  • The system favors explicit typed-array and BLOB boundaries over generic JavaScript arrays.