How it works
- Resolve. Every lockfile in the project directory, and in monorepo roots above it for ecosystems not found yet, becomes a list of exact
(ecosystem, name, version)triples. Direct dependencies are marked. - Locate. Each package's files are found on disk (see Ecosystems). If the installed version differs from the lockfile, the answer says so and shows the installed one; with fetching enabled it reads the pinned version instead.
- Extract. Markdown and reStructuredText are split into heading-scoped sections (long ones at paragraph boundaries, never inside code fences). Source files are parsed with tree-sitter (TypeScript, Python, Rust, Go) into symbols with a signature (the declaration without its body), a cleaned doc comment, a qualified path and a line number.
- Index. Each entry becomes weighted terms: names and headings count most, doc prose next, signatures and code examples least. The tokenizer keeps identifiers whole and also splits camelCase, snake_case and digits; a light stemmer and a short programming synonym table (dict/dump, parse/validate, error/exception, ...) bridge wording. The index is cached on disk per package, version and source location, so a version is indexed once.
- Rank. BM25 fused with embedding similarity (a static model2vec model: a text's vector is the mean of its WordPiece token vectors, so embedding every symbol of Next.js takes well under a second), each normalized to its best hit. Then signals that matter for docs: entries whose name or heading contains a query word, identifiers written in the question (
model_dump,z.object), changelog sections only when the question is about changes, and lower weight for private modules, bundled tooling and legacy copies. Deprecation notes among the top results ("usemodel_validateinstead") lift the API they point to. - Pack. Results are added in rank order until the token budget is spent (the last one trimmed at a line boundary), each with a
package@version path:linecitation.
api is exact rather than ranked: it finds entries whose name matches the last segment of the symbol, scores qualifiers (Router in axum::Router::route), follows re-exports, and adds overloads, members and other matches.