Most things are configured via .repowise/config.yaml (see
Configuration; repowise init
generates one for you). The handful of settings that make sense as
environment variables are below.
LLM provider keys
All optional. repowise init never requires one: with no provider
resolvable it renders the wiki from your code's structure and exits 0. Set
a key when you want model-written prose instead. See
Deterministic wiki.
Pick one. Pass --provider <name> on init / update / mcp to switch,
or set REPOWISE_PROVIDER / REPOWISE_MODEL for repos whose config.yaml
names no provider.
| Variable | Used by |
|---|---|
ANTHROPIC_API_KEY | Default provider |
OPENAI_API_KEY | --provider openai |
GEMINI_API_KEY / GOOGLE_API_KEY | --provider gemini |
OPENROUTER_API_KEY | --provider openrouter |
DEEPSEEK_API_KEY | --provider deepseek |
KIMI_API_KEY | --provider kimi |
LITELLM_API_KEY / LITELLM_API_BASE | --provider litellm |
EDENAI_API_KEY / EDENAI_BASE_URL | --provider edenai |
OLLAMA_BASE_URL | --provider ollama (default http://localhost:11434) |
Base URLs can also be overridden per provider: ANTHROPIC_BASE_URL,
OPENAI_BASE_URL (used for vLLM/SGLang-compatible endpoints),
GEMINI_BASE_URL, DEEPSEEK_BASE_URL, KIMI_BASE_URL, LITELLM_BASE_URL,
EDENAI_BASE_URL. A base_url in config.yaml takes precedence over all of
them.
Provider, model and base URL order
The CLI, repowise serve chat and jobs, and the MCP server resolve the
provider, model and base URL the same way. The first match wins:
| # | Source |
|---|---|
| 1 | --provider / --model, or a per-request choice in the web UI |
| 2 | provider, model and <provider>: {base_url: ...} in .repowise/config.yaml |
| 3 | The global default saved from the web UI settings (~/.repowise/provider_config.json) |
| 4 | REPOWISE_PROVIDER / REPOWISE_MODEL and the provider's *_BASE_URL variable |
| 5 | API key variables, in order: ANTHROPIC_API_KEY, OPENAI_API_KEY, OPENROUTER_API_KEY, OLLAMA_BASE_URL, GEMINI_API_KEY, DEEPSEEK_API_KEY, KIMI_API_KEY, EDENAI_API_KEY |
Picking a model or base URL for a repo in the web UI writes that repo's
config.yaml, so the CLI uses it too. The repo's Settings page lists the
provider's live models, accepts any typed id, and has a Test connection
button for a base URL.
Local and OpenAI-compatible gateways
The openai adapter talks to anything that speaks the OpenAI API, so a
local model server needs no separate provider. An OpenAI-compatible server
on this machine (LM Studio, Ollama, vLLM) needs no API key. The simplest
setup is a base URL in the repo's config.yaml:
provider: openai
model: qwen3-coder
openai:
base_url: http://localhost:1234/v1Or point OPENAI_BASE_URL at the gateway's /v1 endpoint, put the gateway's key (if it wants one) in
OPENAI_API_KEY, and pass the model id that endpoint's /models
response returns:
export OPENAI_BASE_URL="http://localhost:8000/v1"
repowise init --provider openai --model qwen3 --reasoning offexport OPENAI_API_KEY="your-gateway-key"
export OPENAI_BASE_URL="http://localhost:20128/v1"
repowise init --provider openai --model ag/gemini-3.7-flash-mediumNamespaced model ids are discovered as-is, so the model does not need to
start with gpt-. This covers vLLM, SGLang, LM Studio and gateways such
as 9router. In an interactive repowise init, the menu row is
OpenAI-compatible (Custom / local gateway): repowise validates the
endpoint, takes the key without echoing it, checks /models, and lets
you search the discovered models or type an exact id. The endpoint is
written to the repo's gitignored .repowise/.env, and the key is saved
there only after you confirm; --no-save-key keeps it process-local.
Pick the plain openai row instead for the official OpenAI endpoint.
Eden AI
Eden AI is a hosted gateway with an EU endpoint, so inference can stay in the EU without self-hosting anything. Every other hosted provider listed above terminates in the US; the alternatives for a team working under a DPA are Ollama or LiteLLM on your own infrastructure.
export EDENAI_API_KEY="..."
export EDENAI_BASE_URL="https://api.eu.edenai.run/v3"
repowise init --provider edenai --model mistral/mistral-small-latestWithout EDENAI_BASE_URL the requests go to the global endpoint. One key
reaches Mistral, GPT, Claude, Gemini, Cohere, DeepSeek and Llama through
a single OpenAI-compatible endpoint, with models addressed as
vendor/model. The catalogue is public and needs no authentication:
api.edenai.run/v3/models.
EDENAI_BASE_URL covers the embedder too, since both read the same
variable. The same key selects edenai as the embedder, defaulting to
amazon/amazon.titan-embed-text-v2:0, which is served from an EU region
and is the cheapest per token of the models this adapter declares.
Override it with REPOWISE_EMBEDDING_MODEL. Only the models the adapter
declares dimensions for are accepted, because a wrong dimension count
would silently mis-size stored vectors.
The default Kimi Code endpoint supports kimi-for-coding and
kimi-for-coding-highspeed. K2.x models use the separate Kimi Open
Platform: supply a key from that platform together with
KIMI_BASE_URL=https://api.moonshot.ai/v1. Repowise selects the
required sampling parameters for either endpoint automatically.
| Variable | Purpose |
|---|---|
REPOWISE_PROVIDER | Provider when no flag, config.yaml or saved web UI default names one; skips auto-detection. An empty value (REPOWISE_PROVIDER="", common in CI matrices) is treated as unset |
REPOWISE_MODEL | Model when no flag, config.yaml or saved web UI default names one |
REPOWISE_DOC_MODEL | Override the model used for get_answer synthesis specifically |
REPOWISE_REASONING | Override reasoning (auto, off, none, minimal, low, medium, high, xhigh, max) |
REPOWISE_ANSWER_LEAN_HIGH | Set to 1/true/yes/on to strip re-read evidence (symbol_bodies, quotes, flow_path, best_guesses, code_rationale) from high-confidence get_answer responses, shrinking the payload. Off by default; the citation and prose still carry the answer, but an agent that needs the dropped body pays a get_symbol round-trip. Grounded fast paths and why-questions are exempt, since their evidence is the answer. |
REPOWISE_CODEX_CLI_CONCURRENCY / REPOWISE_OPENCODE_CONCURRENCY / REPOWISE_CLAUDE_CLI_CONCURRENCY / REPOWISE_COPILOT_CLI_CONCURRENCY | How many codex_cli / opencode / claude_cli / copilot_cli subprocesses run at once. Default 4, minimum 1. |
REPOWISE_OLLAMA_NUM_CTX | Pin Ollama's context window (num_ctx). Unset sizes it per prompt. |
OLLAMA_NUM_PARALLEL | How many requests repowise sends to Ollama at once. Default 1; match the value the Ollama server was started with. |
REPOWISE_ANSWER_TIMEOUT_S | Seconds get_answer waits for synthesis before giving up. Defaults to a per-provider budget: 60s for the remote API providers, 120s for ollama and litellm, 180s for codex_cli and opencode. Capped at 600s. Your MCP client enforces its own tool timeout underneath this one, so a value above it produces a client-side error instead of repowise's diagnosable timeout response. |
Repowise also persists provider/model choice into .repowise/state.json
during init, so the MCP server and update runs reuse the same
provider without you re-specifying.
Embedder overrides
The embedder powers semantic search and the RAG behind get_answer. It's
separate from the LLM provider, and defaults to mock (no semantic
search) when no key is detected.
| Variable | Notes |
|---|---|
REPOWISE_EMBEDDER | Embedder: gemini, openai, ollama, openrouter, edenai, or mock |
REPOWISE_EMBEDDING_MODEL | Embedding model, applies to whichever embedder is active |
REPOWISE_EMBEDDING_DIMS | Embedding output dimensions (optional; inferred from the model otherwise) |
REPOWISE_EMBEDDING_TIMEOUT | Embed request timeout in seconds |
OLLAMA_EMBEDDING_MODEL | Ollama embedding model (also selects the ollama embedder) |
OLLAMA_EMBEDDING_DIMS | Ollama embedding output dimensions (optional) |
OLLAMA_EMBEDDING_TIMEOUT | Ollama embed request timeout in seconds (default: 30). Raise it for long wiki pages on slow local models, otherwise those pages can silently drop out of the vector store. |
When nothing names an embedder, repowise takes the first one with a key set, in the order gemini, openai, openrouter, ollama, edenai, and every model run prints which embedder it uses. The full order, flags and config included, is in Configuration.
Server and database
| Variable | Default | Purpose |
|---|---|---|
REPOWISE_DB_URL | SQLite | Use PostgreSQL instead of SQLite (e.g. postgresql+asyncpg://...) |
REPOWISE_DATABASE_URL | none | Legacy alias for REPOWISE_DB_URL, still honored |
REPOWISE_HOST | 127.0.0.1 | API server host |
REPOWISE_PORT | 7337 | API server port |
REPOWISE_MCP_PORT | 7338 | MCP SSE server port |
REPOWISE_API_URL | http://localhost:7337 | Frontend only; backend URL for the web UI |
REPOWISE_API_KEY | none | Bearer token required by clients calling the server API. Without it the server answers local callers only |
REPOWISE_TOKENS_FILE | ~/.repowise/tokens.yaml | Scoped bearer tokens file (see below) |
REPOWISE_PUBLIC_URL | none | Externally visible base URL (https://host[/prefix]) for the MCP HTTP protected-resource document and the 401 challenge, when serving behind a proxy |
REPOWISE_CORS_ORIGINS | any origin, no credentials | Comma-separated origins the API server allows. Setting it also allows credentials. |
REPOWISE_CONFIG_DIR | none | Override where repowise looks for its config directory |
REPOWISE_GITHUB_WEBHOOK_SECRET | none | Secret for verifying GitHub webhook signatures |
REPOWISE_GITLAB_WEBHOOK_TOKEN | none | Token for verifying GitLab webhook requests |
REPOWISE_GITEA_WEBHOOK_SECRET | none | HMAC-SHA256 secret for POST /api/webhooks/gitea, which syncs on push from Gitea and Forgejo |
Scoped tokens
REST, MCP streamable HTTP and SSE, and webhooks all resolve a caller to a
principal with repository and tool scope. Besides the shared
REPOWISE_API_KEY, you can list scoped tokens, stored as SHA-256 digests:
# ~/.repowise/tokens.yaml
tokens:
- id: ci-reader
sha256: "<hex SHA-256 of the token>" # printf %s "$TOKEN" | sha256sum
repos: [backend] # repository ids or names
tools: [get_context, get_risk] # MCP tool names
expires_at: 2027-01-01T00:00:00ZA token with tools is refused on every REST route except chat, which runs
only the tools in its scope. With no key and no tokens file, local callers are
served without a credential and every other caller is refused.
Workspace MCP
| Variable | Default | Purpose |
|---|---|---|
REPOWISE_WORKSPACE_CONCURRENCY | 4 | Workspace repositories a repo="all" call queries at once |
REPOWISE_WORKSPACE_REPO_TIMEOUT_S | 60 | Seconds each repository may take before the call answers without it (named in repos_failed). Capped at 300 |
Plugins and seams
| Variable | Purpose |
|---|---|
REPOWISE_PLUGINS | Comma-separated plugins to load (module or module:attr), on top of installed repowise.plugins entry points |
REPOWISE_SEAM_<NAME> | Pick the implementation of a named seam, e.g. REPOWISE_SEAM_AUTHENTICATOR, REPOWISE_SEAM_CHANGE_METADATA |
Both are read from the real process environment only, never from a
repository's .repowise/.env. repowise plugins shows what loaded and which
implementation each seam uses.
Telemetry
Anonymous usage telemetry is enabled by default (opt-out).
| Variable | Purpose |
|---|---|
DO_NOT_TRACK | Any truthy value disables telemetry (respects the cross-tool convention) |
REPOWISE_TELEMETRY_DISABLED | Disables telemetry, repowise-specific |
REPOWISE_TELEMETRY_DEBUG | Prints the telemetry payload to stderr instead of sending it |
Misc
| Variable | Purpose |
|---|---|
REPOWISE_GIT_WINDOW_ANCHOR | Git history windows (churn, prior fixes, age) are measured from the indexed commit, so re-indexing an unchanged tree later gives the same scores. Set to now to measure from wall-clock time instead. |
REPOWISE_HOOK_COVERAGE_REINGEST | Set to 1 to turn on the coverage re-ingest hook for one session (see hooks.coverage_reingest in Configuration). |
REPOWISE_SKIP_EDITOR_SETUP | Stop init writing machine-wide editor config (same as init --no-editor-setup). Use it for CI, sandboxes and benchmark runs |
REPOWISE_NO_SAVE_KEY | Same as init --no-save-key: keep the provider key process-local |
REPOWISE_NO_HINTS | Turn off the occasional repowise.dev hint line (also repowise config hints off) |
REPOWISE_FORGE_HOSTS | Self-managed git hosts as host=forge pairs (git.corp.com=gitlab,tfs.corp.com=azure). Wins over forges.hosts in config.yaml |
REPOWISE_MCP_DEBUG_META | Set to 1 to restore the full _meta diagnostics on every MCP response |
REPOWISE_MCP_PRETTY_JSON | Set to 1 for indented JSON in MCP text results |
REPOWISE_CHANGELOG | Override the changelog source used by the "what's new" check |
REPOWISE_PARSE_WORKERS | How many processes parse files during indexing. Defaults to your CPU count capped at 8, and never exceeds the number of files to parse. Each worker is a separate interpreter holding roughly 50 MB, so lower it on a memory-constrained machine; raising it above 8 is not measurably faster. |
PYTHONIOENCODING | On Windows PowerShell, set to utf-8 if you see codec errors during indexing |
Hosted version
If you're using repowise.dev, none of the above apply, because the platform manages keys for you. The only env var you'd set client-side is the API key your editor uses to talk to the hosted MCP endpoint, which the Settings → Editor page generates automatically.
Model keys on hosted. Hosted plans run on the platform's model, and AI use is paid from credits. To use your own Anthropic, OpenAI, or Gemini key, run the open-source CLI or a self-hosted deployment.