# Copy to .env and fill in. All variables are optional; defaults match deploy/docker-compose.yml. # Read by bce.config.Settings (prefix BCE_). .env is gitignored. # --- PostgreSQL (single DB: AGE + pgvector + SQL) --- BCE_DB_HOST=localhost BCE_DB_PORT=5432 BCE_DB_NAME=bce BCE_DB_USER=bce BCE_DB_PASSWORD=bce # Name of the Apache AGE graph holding the code graph. BCE_GRAPH_NAME=code_graph # --- i18n (presentation only; never affects payload) --- BCE_DEFAULT_LOCALE=en # Locales the API and UI accept, as a JSON array. Anything else falls back to the default. BCE_SUPPORTED_LOCALES=["en","tr"] # --- CORS --- # Browser origins allowed to call the API, as a JSON array. The bundled UI is served from the # API's own origin and needs no entry here; this only matters for a separately hosted frontend # such as the Vite dev server. Use ["*"] for development only. BCE_CORS_ORIGINS=["http://localhost:5173","http://127.0.0.1:5173"] # --- Embedding (Phase 2; anchor finding only, pinned for determinism P2) --- # Provider: "hashing" (default, dependency-free deterministic fallback), "voyage" (Voyage AI) or # "openai" (any OpenAI-compatible /v1/embeddings server: vLLM, TEI, Ollama, OpenAI - this is how # an open model such as jinaai/jina-code-embeddings-1.5b runs on-prem). BCE_EMBEDDING_PROVIDER=hashing # Model name + dimension are pinned together as the stored model_id; changing either is a reindex. # `bce migrate` re-types the pgvector column to BCE_EMBEDDING_DIM (refusing to drop stored vectors # unless run with --reset-embeddings). # Supported (see README "Supported models"); the retrieval profiles were fitted on these two: # voyage: BCE_EMBEDDING_MODEL=voyage-code-4 BCE_EMBEDDING_DIM=1024 # openai: BCE_EMBEDDING_MODEL=jina-code-embeddings-1.5b BCE_EMBEDDING_DIM=1536 # (voyage-code-3, 1024, still works and stays the code default for indexes built with it.) BCE_EMBEDDING_MODEL=voyage-code-4 BCE_EMBEDDING_DIM=1024 # Required when BCE_EMBEDDING_PROVIDER=voyage, which also needs the optional 'voyageai' package: # pip install "bgts-context-engine[embed]". Selecting voyage without both is an error, not a # silent fall back to hashing -- index and query vectors have to come from the same encoder. BCE_VOYAGE_API_KEY= # --- provider "openai" only --- # e.g. vllm serve ~/models/jina-code-embeddings-1.5b --runner pooling --port 8001 \ # --served-model-name jina-code-embeddings-1.5b BCE_EMBEDDING_BASE_URL=http://127.0.0.1:8001/v1 # Bearer token; leave empty for a local server. BCE_EMBEDDING_API_KEY= # Instruction prefixes for instruction-tuned models. Unset = built-in default from the model name # (jina-code-* gets its nl2code query/passage prompts; anything else none). Set to override. # BCE_EMBEDDING_QUERY_PREFIX= # BCE_EMBEDDING_DOCUMENT_PREFIX= # Extra JSON merged into every request. The default makes vLLM truncate inputs longer than its # --max-model-len instead of rejecting the batch. OpenAI's own API rejects unknown fields: use {}. BCE_EMBEDDING_EXTRA_BODY={"truncate_prompt_tokens": -1} # Seconds per embedding request while indexing (a local model can take minutes on a large batch). BCE_EMBEDDING_TIMEOUT=600 # Seconds per *query* embedding at search time (one short text; two attempts). Kept short so a tool # call returns - without its semantic anchor, lexical/structural anchors still answer - before an # agent's own MCP timeout (Cursor: 60 s) kills it. BCE_EMBEDDING_QUERY_TIMEOUT=10 # --- Retrieval profile: engine constants that depend on the embedding model --- # "auto" picks the profile fitted for BCE_EMBEDDING_MODEL: voyage-* -> "voyage" (the historical # constants), jina-* -> "jina" (model's top-10 ranks guarded in narrowing), anything else -> the # voyage set. Name one to force it. The BCE_RETRIEVAL_SEMANTIC_* knobs override single values of the # chosen profile and exist for fitting runs (local_bench/bench40_jina.py rerun); leave them unset. BCE_RETRIEVAL_PROFILE=auto # BCE_RETRIEVAL_SEMANTIC_GUARD_RANKS= # BCE_RETRIEVAL_SEMANTIC_RESERVE_SHARE= # BCE_RETRIEVAL_SEMANTIC_RANK_SCALE= # --- Context selector (optional; see docs/selector.md) --- # A decision model that tiers the ranked answer after retrieval: the files the task most likely # edits in full, likely related files as one line each, the rest dropped. Values: # off (default) no selector: get_context_for_task returns the plain ranking at K=20 # jev TypeSafe's Jev, hosted (OpenRouter or TypeSafe's own API) # decider-2b open-weight https://huggingface.co/Mapika/decider-2b on your own GPU # decider-4b open-weight https://huggingface.co/Mapika/decider-4b on your own GPU # With a selector set, the server ranks K=50 and the model cuts it down. It is fail-open: an # error or timeout returns the plain ranking, and coverage.selector says so. BCE_SELECTOR=off # # Example 1 - Jev over OpenRouter (no TypeSafe account; billed to the OpenRouter account): # BCE_SELECTOR=jev # OPENROUTER_API_KEY=sk-or-v1-... # (defaults: BCE_SELECTOR_MODEL=typesafe/jev-1.13 # BCE_SELECTOR_URL=https://openrouter.ai/api/alpha/decisions BCE_SELECTOR_TIMEOUT=3) # # Example 2 - Jev on TypeSafe's own API (BCE_SELECTOR_API_KEY wins over the OpenRouter key): # BCE_SELECTOR=jev # BCE_SELECTOR_URL=https://api.typesafe.ai/v1/systemone # BCE_SELECTOR_API_KEY= # BCE_SELECTOR_MODEL=jev-latest # # Example 3 - decider-4b (or decider-2b) behind `uvicorn decider.serve:app` on a GPU host, e.g. a # RunPod TCP port mapping. No key; the value must match the model the server loaded. # BCE_SELECTOR=decider-4b # BCE_SELECTOR_URL=http://:/v1/systemone # (defaults: BCE_SELECTOR_URL=http://127.0.0.1:8000/v1/systemone BCE_SELECTOR_TIMEOUT=10) # # OpenRouter key for Jev. Set either name, not both: an empty BCE_OPENROUTER_API_KEY= line in this # file hides an OPENROUTER_API_KEY below it. # OPENROUTER_API_KEY= # Bearer token for the selector endpoint: TypeSafe's key, or an auth proxy's in front of a decider. # BCE_SELECTOR_API_KEY= # Empty = the default of the chosen selector (see above). BCE_SELECTOR_MODEL= BCE_SELECTOR_URL= # Seconds per request, also the worst-case latency the selector adds. Unset = 3 (jev) / 10 (decider). # BCE_SELECTOR_TIMEOUT= # Tiering policy, fitted on Jev and shared by every model. Leave unset unless re-fitting. # BCE_SELECTOR_FULL_THRESHOLD=0.5 # BCE_SELECTOR_STUB_THRESHOLD=0.05 # BCE_SELECTOR_MAX_FILES=12 # BCE_SELECTOR_SYMBOL_MIN_SCORE=1.0 # --- Bitbucket Cloud remote indexing (bce index-remote / POST /v1/index-remote) --- # Access token (recommended): leave username empty; we clone as x-token-auth:. # App password: also set BCE_BITBUCKET_USERNAME to your Bitbucket username. BCE_BITBUCKET_USERNAME= BCE_BITBUCKET_TOKEN= # Where cloned repos are cached (re-index does a fast git fetch). Gitignored. BCE_REPO_CACHE_DIR=.bce_data/repos # Set to false ONLY behind a TLS-intercepting corporate proxy. BCE_GIT_SSL_VERIFY=true # --- Logging (JSON lines to stdout; optional rotating file sink) --- # DEBUG logs request start, body, response and every pipeline stage; INFO logs summaries only. BCE_LOG_LEVEL=INFO # Set to true to ALSO write logs to a rotating file (path below). BCE_LOG_FILE_ENABLED=false BCE_LOG_FILE_PATH=.bce_data/logs/bce.log BCE_LOG_FILE_MAX_BYTES=10485760 BCE_LOG_FILE_BACKUP_COUNT=5 # --- Background jobs (async indexing via POST /v1/jobs/* and the MCP indexing tools) --- # Worker threads running inside the API server process (1 = jobs run strictly in order). BCE_JOB_WORKERS=1 # Seconds a worker sleeps between queue polls when idle. BCE_JOB_POLL_INTERVAL=2.0 # --- MCP (bce serve-mcp) --- # Off: the server advertises read-only tools only. On: it also exposes index_repo and # reindex_repo (local working trees; cloning stays on REST/CLI), and runs its own job workers so # queued indexing progresses without a separate `bce serve`. BCE_MCP_ALLOW_WRITE=false # Comma-separated tool names the MCP server advertises; empty = all read tools. Agents fetch a # tool's schema before first use and chain small calls when many tools are offered, so a narrow # catalog costs fewer model turns. The agent benchmark ran with the single primary tool: # BCE_MCP_TOOLS=get_context_for_task BCE_MCP_TOOLS= # How the agent uses the get_context_for_task answer; the server states the workflow in the tool # description and in every answer's payload.workflow. hint (empty = default): the answer is the # starting point - add the files of uncovered identifiers, search only when the engine says the # answer is likely incomplete. trust: the answer is the set of locations - no searching the tree. # The init commands write it into the editor's MCP config, which wins over this file. BCE_AGENT_MODE= # Not a setting, but worth knowing: BCE_ENV_FILE (or `bce --env-file PATH`) points the engine at an # explicit .env. Editors spawn `bce serve-mcp` from their own working directory, so without it the # MCP server never reads this file. `bce --env-file PATH cursor-init` / `claude-init` write the # editor config (and the agent rule) for a project with that path filled in.