kontext-engine
v0.1.6
Published
Context engine for AI coding agents — semantic code search via CLI
Downloads
813
Maintainers
Readme
ctx - Context Engine for AI Coding Agents
Give your AI coding agent deep understanding of any codebase. No plugins, no MCP - just a CLI.
Any agent that can run bash can use ctx. Zero integration required.
ctx init # Index your codebase (~5s for 1K files)
ctx query "authentication middleware" # Multi-strategy code search
ctx ask "how does the auth middleware validate tokens?" # LLM-steered natural language searchWhy
AI coding agents are blind. They either read the whole codebase (blows context windows), rely on grep (misses semantic meaning), or need hand-crafted AGENTS.md files that don't scale.
ctx fixes this. One command indexes your codebase into a local SQLite database. Every search combines five strategies - vector similarity, full-text, AST symbol lookup, path matching, and dependency tracing - then fuses the results with Reciprocal Rank Fusion.
The result: your agent gets exactly the right files and line ranges, in milliseconds.
Features
- Multi-strategy search - five search strategies fused with Reciprocal Rank Fusion (RRF)
- Semantic search - vector embeddings via
all-MiniLM-L6-v2(runs 100% locally) - Full-text search - SQLite FTS5 with BM25 ranking, sanitized query handling for special characters
- AST-aware symbol lookup - Tree-sitter parsing for functions, classes, types, imports across 30+ languages
- Path and dependency tracing - glob matching + BFS dependency graph traversal
- LLM-steered queries - Gemini / OpenAI / Anthropic turn natural language into precise multi-strategy search plans
- Smart result ranking - import deprioritization, test file penalty, small snippet penalty, file diversity, export/public API boost
- Incremental indexing - SHA-256 hash comparison, only re-indexes changed files
- File watching -
ctx watchauto re-indexes on save - 100% local - your code never leaves your machine (unless you opt into API embeddings or LLM steering)
Installation
npm install -g kontext-engine
# Or run directly (any of these work)
npx kontext-engine init
npx ctx initRequires Node.js 20+.
Quickstart
# 1. Index your project
cd my-project
ctx init
# 2. Search (JSON output - perfect for agents)
ctx query "error handling"
# 3. Search (human-readable text)
ctx query "error handling" -f text
# 4. LLM-steered natural language search (needs API key)
export CTX_GEMINI_KEY=your-key # or CTX_OPENAI_KEY / CTX_ANTHROPIC_KEY
ctx ask "how does the payment flow handle failed charges?"
# 5. Watch mode - auto re-index on file changes
ctx watchSearch Quality
ctx goes beyond basic search fusion. Results are ranked through multiple passes to surface the most relevant code:
Reciprocal Rank Fusion (RRF)
Results from all active strategies (vector, FTS, AST, path, dependency) are combined using RRF with K=60 and per-strategy weights. This produces a unified ranking without needing to normalize scores across different metrics.
Path Boosting
Files whose path matches the query terms get a boost:
- 1.5x for directory name matches (e.g., querying "indexer" boosts files in
src/indexer/) - 1.4x for filename matches
Import Deprioritization
Import blocks (import statements, require calls) receive a 0.5x penalty when non-import results exist. This prevents import blocks from outranking actual implementations.
Test File Deprioritization
Test files (tests/, __tests__/, *.test.*, *.spec.*) receive a 0.65x penalty when non-test results exist. Test code is useful but rarely the primary answer to "how does X work?"
Small Snippet Penalty
Results spanning only 1-3 lines (bare constants, trivial type aliases) get a mild penalty. A const MAX_RETRIES = 3 should not outrank the retry logic itself.
File Diversity
Diminishing returns per file prevent one file from dominating results:
- 1st result from a file: 1.0x
- 2nd result: 0.9x
- 3rd result: 0.8x
- 4th+: 0.7x
This ensures results spread across the codebase, giving broader context.
Export Boost
Exported/public API symbols get a mild boost over internal helpers. When you ask about "chunking", the exported chunkFile() function ranks higher than the private canMerge() helper.
CLI Reference
ctx init [path]
Index a codebase. Discovers files, parses ASTs, creates chunks, generates embeddings, stores everything in .ctx/index.db.
ctx init # Index current directory
ctx init ./my-project # Index specific pathRuns incrementally on subsequent calls - only processes changed files.
ctx query <query>
Multi-strategy code search. Default output is JSON (agent-friendly).
ctx query "authentication"
ctx query "auth" -f text # Human-readable output
ctx query "auth" -s fts,ast # Specific strategies
ctx query "auth" -l 20 # Limit results
ctx query "auth" --language typescript # Filter by languageOptions:
| Flag | Description | Default |
|---|---|---|
| -f, --format <fmt> | Output format: json or text | json |
| -s, --strategy <list> | Comma-separated: vector,fts,ast,path | fts,ast,path |
| -l, --limit <n> | Maximum results | 10 |
| --language <lang> | Filter by language | all |
| --no-vectors | Skip vector search | - |
JSON output (for agents):
{
"query": "authentication",
"results": [
{
"file": "src/middleware/auth.ts",
"lineStart": 14,
"lineEnd": 89,
"name": "validateToken",
"type": "function",
"score": 0.94,
"language": "typescript",
"text": "export async function validateToken(token: string) { ... }"
}
],
"searchTimeMs": 12,
"totalResults": 3
}Text output (for humans):
Query: "authentication"
src/middleware/auth.ts L14-L89 (0.94)
validateToken [function]
export async function validateToken(token: string) { ... }
src/routes/login.ts L45-L112 (0.87)
handleLogin [function]
...
3 results in 12msctx find <query>
Alias for ctx query. Identical behavior.
ctx ask <query>
LLM-steered natural language search. Sends your query to a steering LLM that creates a search plan, executes multi-strategy search, then synthesizes an explanation.
ctx ask "how does the auth middleware validate tokens?"
ctx ask "what happens when a payment fails?" -f json
ctx ask "find all database models" --no-explain
ctx ask "auth flow" -p openai # Force specific providerOptions:
| Flag | Description | Default |
|---|---|---|
| -f, --format <fmt> | Output format: json or text | text |
| -l, --limit <n> | Maximum results | 10 |
| -p, --provider <name> | LLM provider: gemini, openai, anthropic | auto-detect |
| --no-explain | Skip explanation, return raw search results | - |
Requires an API key (set via environment variable):
export CTX_GEMINI_KEY=your-key # Gemini 2.0 Flash (cheapest)
export CTX_OPENAI_KEY=your-key # GPT-4o-mini
export CTX_ANTHROPIC_KEY=your-key # Claude 3.5 HaikuFalls back to keyword-based multi-strategy search if no API key is available. A warning is shown when no LLM provider is detected.
Natural language handling: Queries like "how does the indexer work?" are automatically processed - stop words are stripped, code identifiers (camelCase, snake_case, dotted names like fs.readFileSync) are preserved, and the cleaned terms are used across all search strategies.
ctx watch [path]
Watch mode - monitors files and re-indexes automatically when you save.
ctx watch # Watch current directory
ctx watch --init # Run full init first, then watch
ctx watch --debounce 1000 # Custom debounce (ms)
ctx watch --embed # Re-embed on changes (slower)Options:
| Flag | Description | Default |
|---|---|---|
| --init | Run ctx init before starting watch | off |
| --debounce <ms> | Debounce interval | 500 |
| --embed | Enable embedding during watch | off |
Press Ctrl+C to stop gracefully.
ctx status [path]
Show index statistics.
ctx statusKontext Status - /path/to/project
Initialized: Yes
Database: .ctx/index.db (14.2 MB)
Last indexed: 2025-01-15 14:30:22
Files: 847
Chunks: 3,241
Vectors: 3,241
Languages:
Typescript 420 files
Python 200 files
Javascript 127 files
Go 50 files
Rust 50 files
Embedder: local (all-MiniLM-L6-v2, 384 dims)ctx config <subcommand>
Manage project configuration stored in .ctx/config.json.
ctx config show # Show full config
ctx config get search.defaultLimit # Get specific value
ctx config set search.defaultLimit 20 # Set value
ctx config set embedder.provider voyage # Switch embedder
ctx config set search.strategies '["fts","ast","vector"]'
ctx config reset # Reset to defaultsSupports dot-notation for nested keys. Values are auto-parsed (numbers, booleans, JSON arrays, null).
Global Options
| Flag | Description |
|---|---|
| --verbose | Enable debug output (stderr) |
| --version | Show version |
| --help | Show help |
Debug logging is also enabled via CTX_DEBUG=1.
Configuration
Configuration lives in .ctx/config.json, created automatically by ctx init.
{
"embedder": {
"provider": "local",
"model": "Xenova/all-MiniLM-L6-v2",
"dimensions": 384
},
"search": {
"defaultLimit": 10,
"strategies": ["vector", "fts", "ast", "path"],
"weights": {
"vector": 1.0,
"fts": 0.8,
"ast": 0.9,
"path": 0.7,
"dependency": 0.6
}
},
"watch": {
"debounceMs": 500,
"ignored": []
},
"llm": {
"provider": null,
"model": null
}
}Embedder providers
| Provider | Model | Dimensions | Cost | Notes |
|---|---|---|---|---|
| local | all-MiniLM-L6-v2 | 384 | Free | Default. Runs on CPU via ONNX Runtime. |
| voyage | voyage-code-3 | 1024 | API pricing | Higher quality for code search. |
| openai | text-embedding-3-large | 1024 | API pricing | OpenAI embedding model (dimension truncated for efficiency). |
Remote embedders require API keys:
export CTX_VOYAGE_KEY=your-key
export CTX_OPENAI_KEY=your-keySearch strategies
| Strategy | What it does | Best for |
|---|---|---|
| vector | KNN cosine similarity on embeddings | Semantic/conceptual search |
| fts | SQLite FTS5 full-text search with BM25 | Keyword/exact term search |
| ast | Symbol name/type/parent matching | Finding specific functions, classes, types |
| path | Glob-pattern and keyword file path matching | Finding files by name or directory |
| dependency | BFS traversal of import/require graph | Tracing what depends on what |
Default strategies are fts,ast,path. Vector search is opt-in (add vector to the strategy list or configure in .ctx/config.json). Dependency tracing runs when queries match dependency patterns.
Results from all strategies are fused using Reciprocal Rank Fusion (RRF) with K=60 and per-strategy weights, then re-ranked with path boosting, import/test deprioritization, file diversity, and export boosting.
Architecture
| Layer | Components |
|---|---|
| CLI | ctx init / ctx query / ctx ask / ctx watch / ctx status / ctx config |
| Engine | Indexer - Search Engine - Steering LLM - File Watcher |
| Storage | SQLite (sqlite-vec vectors + FTS5 full-text + metadata) |
Indexing pipeline
| Stage | What it does | Output |
|---|---|---|
| Discovery | Recursive file scan, respects .gitignore / .ctxignore, 30+ language extensions | File list |
| Parsing | Tree-sitter extracts functions, classes, methods, types, imports, constants | AST nodes with line ranges |
| Chunking | Groups nodes into logical code units, merges small chunks, keeps functions whole | Chunks with metadata |
| Embedding | all-MiniLM-L6-v2 via ONNX Runtime (384-dim vectors, runs locally) | Vector embeddings |
| Storage | Writes to SQLite: sqlite-vec for KNN, FTS5 for full-text, plus file hashes | .ctx/index.db |
- Discovery - recursive file scan, respects
.gitignoreand.ctxignore, filters by 30+ language extensions - Parsing - Tree-sitter extracts functions, classes, methods, types, imports, constants with line ranges and docstrings
- Chunking - splits files into logical code units (not arbitrary line windows). Functions stay whole. Related imports group together. Small constants merge.
- Embedding -
all-MiniLM-L6-v2via ONNX Runtime (384-dimensional vectors, runs locally) - Storage - SQLite with sqlite-vec for vector KNN, FTS5 for full-text, plus metadata tables
Search pipeline
| Step | Description | |---|---| | 1. Query input | Raw user query (natural language or code terms) | | 2. Steering (optional) | LLM interprets query, selects strategies, optimizes search terms | | 3. Parallel search | Runs selected strategies simultaneously: Vector (KNN), FTS (BM25), AST (symbol lookup), Path (glob/keyword), Dependency (BFS) | | 4. RRF Fusion | Reciprocal Rank Fusion combines results across strategies (K=60, per-strategy weights) | | 5. Re-ranking | Path boosting, import penalty, test file penalty, snippet penalty, file diversity, export boost | | 6. Synthesis (optional) | LLM generates a concise explanation referencing specific files and line numbers |
Key design decisions
- SQLite for everything - vectors, FTS, metadata, all in one file (
.ctx/index.db). Zero infrastructure. - Tree-sitter for AST - language-agnostic parsing via WebAssembly grammars. Supports TypeScript, JavaScript, Python, Go, Rust, Java, C, C++, and more.
- Logical chunking - chunks follow code structure (functions, classes, type blocks), not arbitrary line windows. This gives better search quality and more useful results.
- RRF fusion - combines results from multiple strategies without needing to normalize scores across different metrics. Simple, effective, well-studied.
- Multi-pass re-ranking - after fusion, results go through path boosting, import/test/snippet deprioritization, file diversity balancing, and export boosting for consistently relevant output.
- Incremental by default - SHA-256 content hashing means re-indexing only processes files that actually changed.
For AI Agent Authors
ctx is designed to be called from any AI coding agent via shell. No SDK, no API server, no MCP protocol needed.
Integration pattern
# Your agent runs this in bash:
ctx query "authentication middleware" -f json
# Parse the JSON output, use the file paths and line ranges
# to read exactly the right code into the agent's context window.Recommended agent workflow
1. Agent receives a task involving unfamiliar code
2. Agent runs: ctx query "<relevant terms>" -f json
3. Agent reads the top results (file paths + line ranges)
4. Agent now has targeted context instead of the whole codebase
5. Agent completes the task with precisionTips for agent integration
- Always use
-f jsonfor machine-readable output - Default strategies (
fts,ast,path) work great without embeddings - Use
ctx askwhen the query is natural language and an LLM key is available - Run
ctx initonce, thenctx watchin the background to keep the index fresh - The index is stored in
.ctx/- add it to.gitignore(done automatically byctx init)
Works with
- OpenAI Codex (CLI)
- Claude Code (Anthropic)
- Cursor (AI IDE)
- Aider (terminal)
- Windsurf (AI IDE)
- LXT (coding agent)
- Any tool that can execute shell commands
Supported Languages
TypeScript, JavaScript, Python, Go, Rust, Java, C, C++, C#, Ruby, PHP, Swift, Kotlin, Scala, Haskell, Lua, R, Dart, Elixir, Shell, SQL, HTML, CSS, SCSS, Vue, Svelte, JSON, YAML, TOML, Markdown, and more.
Project Structure
src/
cli/ # CLI commands (init, query, ask, watch, status, config)
indexer/ # File discovery, Tree-sitter parsing, chunking, embedding
search/ # Vector, FTS, AST, path, dependency search + RRF fusion + re-ranking
steering/ # LLM integration and prompts (Gemini, OpenAI, Anthropic)
storage/ # SQLite database, sqlite-vec vectors
watcher/ # File watching with chokidar
utils/ # Error handling, loggingDevelopment
git clone https://github.com/LuciferMornens/context-engine.git
cd context-engine
npm install
npm run build # Build with tsup
npm run test # Run tests (vitest) - 369 tests
npm run lint # Lint (eslint)
npm run typecheck # Type check (tsc --noEmit)
npm run check # All of the aboveLicense
MIT
