How it works

ctx is three pieces: an incremental indexer, a per-language resolver, and a ranker. Everything runs locally and everything is deterministic — the same repository and the same queries produce the same answers.

The index

ctx init walks the project and writes a SQLite database into .ctx/. The database holds files, symbols (kind, name, range, signature), and dependency edges between files. Parsing is done with tree-sitter grammars — not regex — so definitions, scopes, and boundaries are exact.

Re-indexing is incremental and content-hash based. Files that have not changed are left untouched; only changed files are re-parsed and their edges rebuilt, transactionally. The scanner skips the directories in [index].exclude, files over 2 MB, and symlinks.

Dependency resolution

ctx resolves imports to real files per language. Anything it cannot resolve is recorded as an external/unknown edge rather than a guess — so impact analysis never silently assumes a false dependency.

LanguageWhat is indexedImport resolution
TypeScript / JavaScriptFunctions, methods, classes, interfaces, enums, types, constants, fieldsimport / require / dynamic import() · ./ ../ @/ aliases · index files · workspace packages
PythonFunctions, methods, classes, constantsDotted, relative & from-import resolution
RustFns, methods, structs, traits, impls, enums, constants, modulesuse / crate:: / self:: / super:: / mod probing
GoFunctions, methods, structs, interfacesImport paths, module-relative resolution

Impact analysis

ctx impact runs a cycle-safe breadth-first search over the inverted graph starting from a symbol or file. It groups results into direct dependents, indirect dependents, test files, and unknown (unresolved) edges. Depth defaults to 3 and is bounded. When a name exists as both a production symbol and a test double, the production definition is preferred.

Context ranking

ctx context scores files against a task description. The signals, honestly stated:

  • Keyword match on symbol names, signatures, and paths, weighted by an inverse-document-frequency term so common words matter less. A small synonym vocabulary maps common task words.
  • Hub centrality — files many others depend on get a bonus, but dependents of hubs are capped so they do not flood the package.
  • Recency and path depth — surface-level files and recently modified files score slightly higher.
  • Git activity — files changed in the working tree get a bump unless --no-git is passed.

Files are selected up to a token budget (default 12,000, ≤ 25 files), and every selection carries the reason it was chosen, so the output is explainable rather than a black box.

Git awareness

ctx changed and ctx diff compare symbol sets between the working tree, a ref, or two refs — reporting which definitions were added, removed, or modified, not just which files changed status. ctx diff uses merge-base resolution so a single ref compares your branch against where it forked.

Storage & privacy

The index lives entirely inside .ctx/ in your repository. ctx makes no network connections, sends no telemetry, and never executes project code. What it reads stays on your machine.