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.
| Language | What is indexed | Import resolution |
|---|---|---|
| TypeScript / JavaScript | Functions, methods, classes, interfaces, enums, types, constants, fields | import / require / dynamic import() · ./ ../ @/ aliases · index files · workspace packages |
| Python | Functions, methods, classes, constants | Dotted, relative & from-import resolution |
| Rust | Fns, methods, structs, traits, impls, enums, constants, modules | use / crate:: / self:: / super:: / mod probing |
| Go | Functions, methods, structs, interfaces | Import 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-gitis 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.