TeaRAGs is configured via environment variables passed to the MCP server. All
variables are optional unless specified otherwise.
Every index run records the indexing settings it used in the project registry,
and later runs on that project replay them. The MCP server's environment is the
default for every project it serves, so it never changes the index shape of a
project that already has a recorded value: chunk size, AST or hybrid mode, git
windows, codegraph resolution and the enable flags stay as recorded, while
runtime tuning (pool sizes, batch sizes, timeouts, endpoints) follows the
server. To change a recorded index-shaping value, export it in front of
tea-rags index-codebase --project <alias> — a CLI invocation's environment
overrides the registry for every setting — together with the --force or
--force-enrichments the change needs.
Server
| Variable | Description | Default |
|---|
SERVER_TRANSPORT | Transport mode: stdio or http | stdio |
SERVER_HTTP_PORT | Port for HTTP transport | 3000 |
SERVER_HTTP_TIMEOUT_MS | Request timeout for HTTP transport (ms) | 300000 |
SERVER_PROMPTS_FILE | Path to prompts configuration JSON | prompts.json |
Qdrant
| Variable | Description | Default |
|---|
QDRANT_URL | Qdrant connection mode. Unset = autodetect (probe localhost:6333 for external Qdrant, fallback to embedded). "embedded" = always use embedded Qdrant. "http://..." = use external Qdrant at that URL. | Autodetect |
QDRANT_API_KEY | API key for Qdrant authentication | - |
QDRANT_EMBEDDED_STORAGE_PATH | Override embedded Qdrant storage location | ~/.tea-rags/qdrant/storage |
QDRANT_TURBO_QUANT | Enable Qdrant 1.18 TurboQuant 8x dense quantization (rescored at search time, ~baseline recall). Applied to new and existing collections at startup — no reindex. | true |
QDRANT_MAX_RESIDENT_MEMORY_PERCENT | Reject memory-consuming writes when resident RAM exceeds N% (1-100). Strict-mode OOM guard applied to new and existing collections at startup — no reindex. Unset = off. | unset |
QDRANT_SEARCH_MAX_BATCHSIZE | Cap batch-search query size (strict mode). Unset = no cap. | unset |
QDRANT_LOW_MEMORY | Force the embedded daemon to keep storage on disk to minimize RAM (slower, OOM-safe). Takes effect on the next daemon start. | false |
Embedding
| Variable | Description | Default |
|---|
EMBEDDING_PROVIDER | Provider: onnx, ollama, llama-server, openai, cohere, voyage | ollama |
EMBEDDING_MODEL | Model name | jina-embeddings-v2-base-code |
EMBEDDING_BASE_URL | Custom API URL. llama-server accepts a comma-separated list: every URL is a peer that shares the load (one llama-server per GPU) | Provider-specific (llama-server: http://localhost:8080) |
EMBEDDING_FALLBACK_URL | Fallback endpoint(s) used while the primary is unreachable. Ollama: a fallback Ollama. llama-server: comma-separated llama-server URLs, typically a local one serving the same GGUF — never Ollama | - |
EMBEDDING_DIMENSIONS | Vector width. Ollama and ONNX report it at startup; other providers fall back to a built-in model table. Set it to pin the value. | Resolved |
OPENAI_API_KEY | OpenAI API key | - |
COHERE_API_KEY | Cohere API key | - |
VOYAGE_API_KEY | Voyage AI API key | - |
EMBEDDING_API_KEY | llama-server only: sent as Authorization: Bearer <key> to every peer and fallback; must match llama-server --api-key. Never written to the project registry | - |
EMBEDDING_AUTO_PULL | Ollama only: pull the configured model over /api/pull at startup when the server reports it missing. false restores the manual ollama pull | true |
OLLAMA_LEGACY_API | Use legacy single-request Ollama API | false |
OLLAMA_NUM_GPU | Ollama GPU count (0 = CPU only) | 999 |
Ingest
| Variable | Description | Default |
|---|
INGEST_CHUNK_SIZE | Maximum chunk size in characters | 2500 |
INGEST_CHUNK_OVERLAP | Overlap between chunks in characters | 300 |
INGEST_ENABLE_AST | Enable AST-aware chunking (tree-sitter) | true |
INGEST_ENABLE_HYBRID | Enable hybrid search (dense + sparse vectors) | true |
INGEST_DEFAULT_SEARCH_LIMIT | Default search result limit | 5 |
VCS Adapter
| Variable | Description | Default |
|---|
GIT_ADAPTER | Git history engine: git (system CLI) or es-git (in-process) | git |
GIT_ADAPTER selects how TeaRAGs reads git history (blame, log, blobs):
git — the system git binary, one process per operation. Right for small
projects and short histories.
es-git — the es-git library (napi-rs
over libgit2), reading history in-process with no per-operation process
spawn. Right for large projects, monorepos, and machines where security
tooling throttles process creation. Install with npm install -g es-git.
Selecting es-git without the binding installed makes every git-dependent
operation fail with an install hint — there is no silent fallback; set
GIT_ADAPTER=git to switch back. The value is pinned per-project: it is
always captured into the project registry at indexing time (even the default),
and tea-rags index-codebase / tea-rags tune replay it automatically with
env > registry > default precedence.
Trajectory: Git
| Variable | Description | Default |
|---|
TRAJECTORY_GIT_ENABLED | Enable git enrichment (file + chunk signals) | true |
TRAJECTORY_GIT_LOG_MAX_AGE_MONTHS | Git log depth for file-level signals (months) | 12 |
TRAJECTORY_GIT_LOG_TIMEOUT_MS | Timeout for git log --numstat (ms) | 60000 |
TRAJECTORY_GIT_CHUNK_CONCURRENCY | Parallel files for chunk-level churn analysis | 10 |
TRAJECTORY_GIT_CHUNK_MAX_AGE_MONTHS | Git log depth for chunk-level churn (months) | 6 |
TRAJECTORY_GIT_CHUNK_TIMEOUT_MS | Timeout for chunk churn CLI pathspec (ms) | 120000 |
TRAJECTORY_GIT_CHUNK_MAX_FILE_LINES | Skip chunk churn for files > N lines | 5000 |
TRAJECTORY_GIT_SQUASH_AWARE_SESSIONS | Group commits into sessions (squash noise reduction) | false |
TRAJECTORY_GIT_SESSION_GAP_MINUTES | Gap between commits to split sessions | 30 |
TRAJECTORY_GIT_ANCHOR | Clock git windows and ages are measured from: now (wall clock) or head (the HEAD commit's committer time) | now |
TRAJECTORY_GIT_ANCHOR=head is for indexing a historical snapshot (a pinned
benchmark checkout, an archived repository): with now, a tree whose last
commit is older than the windows has every file and chunk counter at zero.
Under head, every window, ageDays and recencyWeightedFreq written at index
time is measured from HEAD's committer time. Searches against that index use
the same clock: the recency / age rerank signals, the minAgeDays /
maxAgeDays filters and the age thresholds of filter presets measure from the
committer time of the commit the index was built at, so a file last changed at
that commit reads as fresh rather than years old. The mode a search uses is the
one recorded with the index, not the one in the searching shell; an index built
with now, or before this setting existed, keeps the wall clock. If the indexed
commit can no longer be read (garbage-collected, repository moved), searches
fall back to the wall clock. Changing the value is reported as env drift and
needs --force-enrichments git.
Trajectory: Codegraph
Codegraph enrichment (call graph + import graph signals) is on by default;
set CODEGRAPH_ENABLED=false to index without it. The value is recorded per
project and replayed on later runs. See
Codegraph Enrichments.
| Variable | Description | Default |
|---|
CODEGRAPH_ENABLED | Enable codegraph family (graph signals + get_callers/get_callees/find_cycles tools) | true |
CODEGRAPH_DB_PATH | Override graph-DB root dir (per-project .duckdb files live under it) | data dir |
CODEGRAPH_DB_MEMORY_LIMIT | Per-project DuckDB RAM ceiling before spilling to temp dir | 2GB |
CODEGRAPH_DB_THREADS | DuckDB worker threads per project | 2 |
CODEGRAPH_CUSTOM_EXCLUDE | Comma-separated .gitignore-shaped patterns to exclude from the graph | (empty) |
CODEGRAPH_AMBIGUOUS_RESOLVE_MODE | Short-name call resolution: strict (drop ambiguous) or first (pick first) | strict |
CODEGRAPH_TS_TYPECHECKER | TypeScript type checker for call resolution; 0 / false turns it off (see below) | on |
CODEGRAPH_RESIDUAL_KEV_URL | Kev base URL for residual call resolution; comma-separate several hosts (see Kev setup) | (unset) |
CODEGRAPH_RESIDUAL_KEV_THRESHOLD | Minimum Kev confidence for a pick to become an edge | 0.7 |
CODEGRAPH_RESIDUAL_CONCURRENCY | Residual requests in flight (one per enclosing method) | 16 |
CODEGRAPH_RESIDUAL_REQUEST_TIMEOUT_SEC | Seconds one residual request may run; a timed-out group is retried once at the end of the pass | 300 |
CODEGRAPH_RESIDUAL_MENU_LIMIT | Call sites with more candidates than this are not asked | 40 |
CODEGRAPH_RESIDUAL_MIN_MENU | Call sites with fewer candidates than this are neither asked nor given an edge | 1 |
CODEGRAPH_RESIDUAL_NONE_THRESHOLD | Minimum confidence of a "none of these" answer for its site to count as external, out of the recall denominator | 0.8 |
CODEGRAPH_RESIDUAL_VERDICT_RETENTION_DAYS | Cached verdicts unseen this many days are dropped | 180 |
CODEGRAPH_TS_TYPECHECKER. TypeScript call resolution builds a
ts.Program and asks the type checker what a call's receiver is. Setting it to
0 (or false) skips the Program entirely, so the resolve path reads no extra
files and holds no checker heap, and recall pays for it. Without a Program a
member call on a receiver the walker did not type resolves only through
structural evidence: a namespace or named import whose module (or the barrel it
goes through) declares the member, or, for this, the enclosing class and the
base classes its file declares or imports. A call on an untyped local or a
parameter stays unresolved, and JSX components, generics, overloads and
structural types lose their checker passes. On tea-rags' own 1,138 TypeScript /
JavaScript files that is 15,928 call edges with the checker and 12,771 without
(−20%).
The checker can go off without this variable. Before building a Program the
indexer projects its heap need against the enrichment worker's V8 heap ceiling,
and a project too large for it runs with the checker off and logs one
TypeScript type checker DISABLED for this run line. Raise
ENRICHMENT_WORKER_MEMORY_LIMIT_MB to keep it.
Debug
| Variable | Description | Default |
|---|
DEBUG | Enable debug timing logs (true or 1) | false |
These variables control batch sizes, concurrency, timeouts, and pool
sizes. Defaults work well for most setups. Tune only if you hit performance
bottlenecks.
Qdrant Tune
| Variable | Description | Default |
|---|
QDRANT_TUNE_UPSERT_BATCH_SIZE | Points per Qdrant upsert batch | 100 |
QDRANT_TUNE_UPSERT_FLUSH_INTERVAL_MS | Auto-flush buffer interval (0 to disable) | 500 |
QDRANT_TUNE_UPSERT_ORDERING | Ordering: weak, medium, strong | weak |
QDRANT_TUNE_DELETE_BATCH_SIZE | Paths per delete batch | 500 |
QDRANT_TUNE_DELETE_CONCURRENCY | Parallel delete requests | 8 |
QDRANT_TUNE_DELETE_FLUSH_TIMEOUT_MS | Flush timeout for delete accumulator (ms) | 1000 |
QDRANT_TUNE_WRITE_BARRIER_BUDGET_MS | Total wait for queued enrichment writes before terminal markers (ms); spent → degraded / barrier-timeout | 600000 |
Embedding Tune
Batch size and embedding concurrency are decided per run by adaptive embedding;
the values below bound it. See
Adaptive Embedding for how the
bounds are used and where the settled values are reported.
| Variable | Description | Default |
|---|
INGEST_PIPELINE_CONCURRENCY | Pipeline worker concurrency. With adaptive embedding an explicit value (either spelling, even 1) is the hard ceiling of the measured concurrency climb; unset, the climb starts at 1 and may reach an implicit ceiling of 8 while everything else stays at 1 | 1 (climb ceiling 8) |
EMBEDDING_TUNE_BATCH_SIZE | Chunks per embedding batch. With adaptive embedding this is the ceiling the throughput tuner works below | Provider-specific (Ollama 1024, llama-server 256) |
EMBEDDING_TUNE_MIN_BATCH_SIZE | Min chunks before timeout flush, and the floor of the adaptive batch size. When unset, the timeout flush uses batchSize × 0.5 and the adaptive floor batchSize / 16 | unset |
EMBEDDING_TUNE_STATIC | true pins the configured batch size and concurrency for the whole run. Default (false): the batch size drops for every later batch after one the server fails on size, recovers after a streak of successes, hill-climbs toward the fastest size by measured chars/s, then climbs concurrency by measured aggregate chars/s, and starts each run from the optimum the registry stored for the active endpoint + model | false |
EMBEDDING_TUNE_BATCH_TIMEOUT_MS | Flush partial batch after timeout (ms) | 2000 |
EMBEDDING_TUNE_MAX_REQUESTS_PER_MINUTE | Rate limit for embedding API | Provider-specific |
EMBEDDING_TUNE_RETRY_ATTEMPTS | Retry count for failed embedding calls | 3 |
EMBEDDING_TUNE_RETRY_DELAY_MS | Initial retry delay (ms) | 1000 |
EMBEDDING_TUNE_FAILOVER_CONSECUTIVE_FAILURES | Ollama (needs EMBEDDING_FALLBACK_URL): consecutive failed embed calls on the primary (transport error, timeout, 5xx, malformed response; never a 4xx input error) before switching to the fallback while the primary still answers its health check. The 60s recovery cooldown and background probe decide the way back. 0 disables. llama-server: consecutive failures after which one endpoint is taken out (a refused connection takes it out at once); a 30s /health probe re-admits it | 3 |
EMBEDDING_TUNE_UNAVAILABLE_RETRY_MAX_WAIT_MS | Ollama and llama-server: how long to keep retrying, with backoff, while no endpoint is reachable before the index aborts. 0 aborts on the first connection failure | 240000 |
EMBEDDING_TUNE_UNAVAILABLE_RETRY_BASE_DELAY_MS | First backoff step of that wait (ms); exponential, capped at 30s | 2000 |
Ingest Tune
| Variable | Description | Default |
|---|
INGEST_TUNE_CHUNKER_POOL_SIZE | Worker threads for parallel AST parsing | 4 |
INGEST_TUNE_FILE_CONCURRENCY | Parallel file read + chunk dispatch | 50 |
INGEST_TUNE_IO_CONCURRENCY | Max parallel file I/O during cache sync | 50 |
Data Directories
The server stores data in $TEA_RAGS_DATA_DIR (default ~/.tea-rags/).
| Variable | Description | Default |
|---|
TEA_RAGS_DATA_DIR | Root directory for all per-machine tea-rags state | ~/.tea-rags/ |
Layout under the data directory:
| Path | Purpose |
|---|
snapshots/ | Sharded file hash snapshots for incremental indexing |
logs/ | Debug logs when DEBUG=1 is enabled |
qdrant/ | Embedded Qdrant binary and storage (when QDRANT_URL is unset or embedded) |
registry.json | Project registry: aliases + collection metadata. See Project Registry |
update-check.json | Cached npm registry response used by tea-rags prime. Positive TTL 24h, negative TTL 5min. Safe to delete — regenerated on next prime. See Keeping tea-rags up to date. |