Environment variables reference
Almost everything Loom is configured with is a settings field: the
environment variable LOOM_<FIELD> of a field on server.settings.Settings,
listed with its default and meaning in the generated
configuration reference. This page covers the rest: the
variables read directly with os.environ (or a shell ${VAR}) by the server,
the CLI, the SDKs, the plugins, the container image, the compose files and the operator
scripts. The LOOM_* ones are listed in NON_SETTINGS_ENV (server/settings/_env.py),
or, for a family such as the webhook signing secrets, in NON_SETTINGS_ENV_PREFIXES, and
the server's unknown-variable warning skips them;
tests/unit/test_environment_reference.py keeps those lists and this page the same.
Server
| Variable | Read by | Default | Meaning |
|---|---|---|---|
OPENAI_API_KEY |
server/embedding/openai.py, server/llm/openai.py |
unset | Key for the OpenAI embedder and LLM. Missing while an OpenAI model is configured: the embedder falls back to the fake n-gram embedder with an ERROR log, the LLM to the fake client, and loom doctor warns. |
ANTHROPIC_API_KEY |
server/llm/anthropic.py |
unset | Key for the Anthropic LLM provider (LOOM_LLM_PROVIDER=anthropic, or inferred from a claude* model). |
GEMINI_API_KEY, GOOGLE_API_KEY |
server/embedding/gemini.py |
unset | Key for the Gemini embedder; the first one set wins. |
COHERE_API_KEY |
server/core/provider_keys.py |
unset | Key for the hosted rerank provider. Without it the reranker logs a warning and returns candidates in their input order (fail-open). |
LOOM_EMBEDDING_API_KEY |
server/core/provider_keys.py |
unset | Key for the compatible embedding provider (LOOM_EMBEDDING_PROVIDER=compatible); /v1/health and loom doctor report it missing. |
LOOM_ENV_FILE |
server/core/env_file.py, server/cli/app.py |
.env |
The env file Settings reads, and the one the loom CLI loads into the environment. Empty for none. |
LOOM_SETTINGS_FILE |
server/core/env_file.py |
unset (none) | The YAML settings file Settings reads below the env file and the environment (configuration reference). A named file that does not exist refuses to start. Read from the environment, else from the env file; an empty value in the environment reads none, whatever the env file says. |
LOOM_INSTANCE_LABEL |
server/observability/instance.py |
unset | A label for this process on every ledger row (up to 64 characters). A process started without it and without LOOM_DEPLOYMENT=1 (a settings field the shipped compose files set) refuses to boot, so every row is attributable. |
XDG_RUNTIME_DIR |
server/core/runtime_files.py |
unset | Where one server's web processes keep their shared files (the rate-limit table) when LOOM_RUNTIME_DIR is unset: the first of $XDG_RUNTIME_DIR/loom, /run/loom and /tmp/loom-<uid> that is, or can be made, a directory only that user can enter; with several web processes and none, scripts/serve.sh starts one when it chose the count itself, and otherwise stops and names them. scripts/serve.sh makes this choice once and exports it as LOOM_RUNTIME_DIR. |
HOSTNAME |
server/observability/instance.py |
the system host name | Fallback host name in the hostname:pid instance id. |
POD_NAMESPACE, POD_NAME |
server/core/provider_process.py |
unset | This pod's namespace and name (the chart sets them from the downward API). The workers leader retires a lost pod's provider participant once the API in that namespace no longer has the pod, or has it failed. |
KUBERNETES_SERVICE_HOST, KUBERNETES_SERVICE_PORT |
server/core/provider_process.py |
set by Kubernetes | The API server the lost-pod check asks, with the service-account token. |
NODE_OPTIONS |
server/code/workers/scip_ts_delta.py, scip_py_delta.py |
unset | Passed through to the compiler-tier indexer subprocess; every other variable of that subprocess is set by the worker. |
SCIP_ENV_JSON |
server/code/workers/scip_py_delta.py |
unset | Passed through to the Python compiler-tier indexer. |
PATH |
server/code/workers/scip_go_delta.py |
inherited | Searched for the Go toolchain and indexer binaries; the subprocess gets its own PATH. |
LOOM_WEBHOOK_SECRET_<ORG>__<NAME> |
server/core/webhooks.py |
unset | A webhook signing secret, named by a memory webhook's secret_ref or a task inbox's webhook_secret_ref; ORG is the org id encoded as in task inbox webhooks. A whsec_ prefix marks a base64 key, whose whitespace is dropped. Unset, a whsec_ value that is empty or not base64, or a value that is not UTF-8, the secret is not usable: memory webhook events wait (dead after 2.5 days) and a task inbox's notices are held; the server warns once, naming the variable. The unknown-variable warning skips every name with this prefix. |
Provider selection itself (LOOM_EMBEDDING_MODEL, LOOM_LLM_PROVIDER,
LOOM_LLM_MODEL) is settings; see
Deployment and
LLM architecture.
Container image and uvicorn
Read by scripts/serve.sh, the image's command, which starts uvicorn. It takes
them from its environment only, not from .env or LOOM_ENV_FILE (compose's
env_file: sets them in the environment), except the settings fields
LOOM_WEB_WORKERS, LOOM_TRUSTED_PROXIES and LOOM_RUNTIME_DIR, which it
resolves as the server loads them: the environment, then the env file, then the
settings file:
| Variable | Default | Meaning |
|---|---|---|
PORT |
7777 |
The port uvicorn binds inside the container. |
LOOM_LISTEN_HOST |
127.0.0.1 |
uvicorn --host: the address it listens on. The image sets 0.0.0.0; LOOM_BIND_HOST stays the address the startup checks read, and scripts/serve.sh sets it to a non-loopback listen address when the environment does not set it (overriding an env-file or settings-file value). |
LOOM_WEB_WORKERS |
one per CPU, up to 8 | uvicorn --workers. Unset, one per CPU the container may use (its cpuset, lowered by a CPU quota), at most one per GiB of memory and at most 8. The compose files set it unless .env names a count: 2 in deploy/standalone and the dev stack, 1 in the cloud and colour stacks. Also a settings field, which the rate limiter divides budgets by. |
LOOM_UVICORN_LOOP |
asyncio |
uvicorn --loop: asyncio, auto or uvloop. uvloop forks the whole process for each git spawn, which stalls its loop. |
LOOM_TRUSTED_PROXIES |
127.0.0.1 |
uvicorn --forwarded-allow-ips: the peers whose X-Forwarded-For/-Proto are applied. |
LOOM_GRACEFUL_SHUTDOWN_S |
10 |
uvicorn --timeout-graceful-shutdown: how long a stopping process drains requests. |
LOOM_KEEP_ALIVE_S |
5 |
uvicorn --timeout-keep-alive: how long an idle connection stays open. Behind a load balancer that reuses connections, longer than its idle timeout. |
Build argument: LOOM_BUILD_COMMIT (baked into the image as LOOM_BUILD_COMMIT,
reported as build_commit). The image always carries the local CPU embedder and its
default model, and sets LOOM_LOCAL_EMBEDDING_MODEL_DIR=/app/models. The remaining
ARGs pin toolchain versions and checksums for the compiler-tier indexers
(GO_VERSION, NODE_VERSION, SCIP_GO_VERSION, SCIP_CLANG_VERSION, their
*_SHA256* values and LLVM_SIGNER_FPR, the LLVM signing key's fingerprint);
scripts/install-code-toolchains.sh pins the tools it installs with npm
(scip-typescript, scip-python and the package managers).
Compose files
| Variable | Read by | Default | Meaning |
|---|---|---|---|
LOOM_CH_HOST_PORT, LOOM_CH_NATIVE_HOST_PORT |
dev/docker-compose.dev.yml, dev/ci_start_clickhouse.sh |
8123, 9000 |
Host ports the local ClickHouse publishes (HTTP and native). |
LOOM_CH_CONTAINER |
dev/ci_start_clickhouse.sh |
loom-ch |
Container name, so a second ClickHouse (one per worktree) runs beside the first. |
LOOM_COLOUR, LOOM_COLOUR_PORT |
dev/docker-compose.colour.yml |
required | Which colour (blue or green) and host port (7781 or 7782) a blue/green project runs. |
LOOM_CLICKHOUSE_IMAGE |
compose.yaml, dev/ci_start_clickhouse.sh |
clickhouse/clickhouse-server:latest |
The ClickHouse image the stack runs. A release bundle's compose file defaults it to the release the bundle was built and schema-checked with. |
LOOM_IMAGE_REPOSITORY, LOOM_VERSION |
compose.yaml, install.sh |
ghcr.io/clickhouse/loom, latest |
The image and tag the standalone stack runs; the installer pins the tag in .env. |
LOOM_EXTRACTOR_IMAGE_REPOSITORY |
compose.yaml, install.sh |
ghcr.io/clickhouse/loom-extractor |
The document extractor service's image, run at LOOM_VERSION. |
LOOM_PORT |
compose.yaml, install.sh |
7777 |
The host port the standalone stack publishes. |
LOOM_REPOSITORY |
install.sh |
ClickHouse/loom |
The GitHub repository whose releases the installer downloads. |
LOOM_RELEASES_URL |
install.sh |
GitHub | Where the installer downloads release files, an https:// URL; by default https://github.com/$LOOM_REPOSITORY/releases. |
LOOM_CONNECT |
install.sh |
unset | The coding agents to connect without asking, a comma list of claude-code, codex and vscode, all, or none alone; unset, a terminal is asked and a run without one connects none (quickstart). |
LOOM_NO_OPEN |
install.sh |
unset | 1 keeps the installer from opening the dashboard in a browser. |
Given to the installer, LOOM_VERSION installs the release it names. Without it, a release's
install.sh installs its own release and the repository's copy installs latest; an older
release over a newer install is refused unless LOOM_VERSION names it
(pin ClickHouse first:
downgrading an installer install).
Other ${LOOM_*} references in the compose files are settings fields given a
compose-level default and the uvicorn variables above. The installer keeps the two image
repositories (LOOM_IMAGE_REPOSITORY, LOOM_EXTRACTOR_IMAGE_REPOSITORY), the tag, the
port, the bind host and LOOM_CLICKHOUSE_IMAGE in .env when given; the
quickstart describes what the stock .env sets.
loom CLI
| Variable | Read by | Default | Meaning |
|---|---|---|---|
LOOM_BASE_URL |
server/cli/_client.py and the client commands |
http://localhost:7777 |
The server the client commands (install, demo, export-okf, …) talk to. |
LOOM_API_KEY |
server/cli/_client.py and the client commands |
unset, then ~/.loom/token |
The token they present. A stale value here wins over ~/.loom/token. |
LOOM_BIND_HOST, LOOM_BIND_PORT |
server/cli/serve.py |
0.0.0.0, 7777 |
Defaults for loom serve --host and --port. |
LOOM_CONFIG_FILE |
server/cli/_client.py |
~/.loom/config.json |
The client config loom doctor --client reads (the file loom init writes). |
LOOM_API_KEY_FILE |
server/cli/_client.py, the plugins' lib/loom-client.mjs, the grep shim |
~/.loom/token |
The token file read when LOOM_API_KEY is unset. |
See CLI reference.
SDKs
| Variable | Read by | Default | Meaning |
|---|---|---|---|
LOOM_BASE_URL |
Python and TypeScript SDKs | http://localhost:7777 |
The server, when the constructor gives none. |
LOOM_API_KEY |
Python and TypeScript SDKs | the loom login session, then ~/.loom/token |
The bearer token, when the constructor gives none. Blank counts as unset. |
LOOM_PROFILE |
Python and TypeScript SDKs | default |
The loom login session in ~/.loom/credentials a client uses when the constructor names none. |
LOOM_LOG_LEVEL |
Python and TypeScript SDKs | unset | The SDK logger's level (debug, info, warning/warn, error, off). |
LOOM_MENTOR_BRIEF |
Python and TypeScript SDKs | off | on fetches mentor.brief in the background on the first call. |
LOOM_AUTO_RUN |
Python SDK | off | Bind an ambient run to each Agent's lifetime. |
See Python SDK and TypeScript SDK.
Coding-agent plugins and hook scripts
| Variable | Read by | Default | Meaning |
|---|---|---|---|
LOOM_ORG, LOOM_NAMESPACE, LOOM_AGENT |
the plugins' lib/loom-client.mjs, integrations/cursor/, integrations/generic/, dev/loom_init.py |
~/.loom/config.json, then the token's claims, then default / coding / the client's name |
The identity the hooks and scripts write captured rows under. |
LOOM_HOOK_TIMEOUT_MS |
the plugins' lib/loom-client.mjs |
5 × the measured /v1/health round trip, between 3000 and 8000 |
The timeout that aborts each hook request; loom doctor --client reports it. |
LOOM_HOOK_EXIT_MS |
the plugins' lib/loom-client.mjs |
LOOM_HOOK_TIMEOUT_MS |
How long a hook process waits after it sends before it exits. |
LOOM_SHUNT_READ_CAP |
the plugins' hooks/loom-code-shunt.mjs |
0 (off) |
Lines above which a ranged read of an indexed, unmodified file is sent to the code tools instead. |
See Claude Code plugin.
Operator scripts
| Variable | Read by | Default | Meaning |
|---|---|---|---|
LOOM_REPO |
redeploy.sh |
the script's directory | The deploy checkout. |
LOOM_REDEPLOY_READY_TIMEOUT_S |
redeploy.sh |
180 |
How long to wait for the idle colour's /v1/health to report ready before aborting the swap. |
LOOM_PUBLIC_HEALTH_URL |
redeploy.sh |
unset | When set, the health URL clients use is probed last. |
LOOM_PREFLIGHT_STRICT |
redeploy.sh |
1 |
0 turns ledger-only migration rows and checksum drift into a report instead of a stop. |
LOOM_PREFLIGHT_HEALTH_URL |
dev/redeploy_preflight.sh |
http://localhost:7777/v1/health |
The health URL the preflight reads. |
LOOM_PREFLIGHT_PORT |
dev/redeploy_preflight.sh |
7777 |
The port the preflight checks. |
LOOM_PREFLIGHT_MIGRATE |
dev/redeploy_preflight.sh |
$PYTHON -m server.core.schema.migrate --dry-run |
The migration dry-run command the preflight runs. |
HDX_BASE, HDX_COOKIE or HDX_EMAIL + HDX_PASSWORD, HDX_DB, HDX_PREFIX, HDX_CONNECTION_ID, DRY_RUN |
deploy/clickstack_sources.sh |
HDX_DB=default, HDX_PREFIX=loom, DRY_RUN=0 |
The HyperDX instance, credentials and naming for registering Loom's ClickStack sources. |
LOOM_ADMIN_TOKEN |
dev/onboard_tenant.py |
unset | The admin token that onboards a tenant. |
LOOM_OUTPUT_DIR |
dev/loom_init.py, dev/onboard_tenant.py |
. |
Where the onboarding scripts write their output files. |
LOOM_REBUILD_DIR |
scripts/ops/table_rebuild.py, scripts/ops/vector_codec_rebuild.py |
. |
Where the rebuild scripts look for the ABORT_REBUILD file that stops a run, and where vector_codec_rebuild.py records the UUIDs of the twins it creates (<table>_rebuild.uuid), which decide whether a twin is a leftover; run every line of one rebuild from the same directory. |
LANGFUSE_HOST, LANGFUSE_ORG_API_KEY |
dev/loom_init.py |
unset | Langfuse project provisioning during dev/loom_init.py. |
The redeploy procedure and its preflight are in Deployment and Upgrades; the compiler-tier workers in Code index operations; ClickStack in ClickStack.
Related
- Configuration reference: every
LOOM_*settings field. - Deployment: required environment, providers and the production checklist.