Environment variables
1. How they are read
The whole environment surface, in one place, so memhtml manifest can describe it and a reader
does not have to grep for process.env.
Every variable is read through effect/Config rather than process.env directly: a missing
required value becomes a typed failure with the variable’s name in it, and a default is
declared next to the name it defaults for.
2. The variables
The middle column is the value the binary falls back to when the variable is unset. A row with no default changes behavior by its absence, and its description says how.
| Variable | When unset | Description |
|---|---|---|
MEMHTML_ROOT |
~/memhtml |
The memory repo’s root: a git repository holding the corpus and .memhtml/. |
MEMHTML_REFUSE_ENV_ROOT |
no default | Set to any value but 0, false, no, or off (absent or blank is off; case-insensitive) makes memhtml take its repo from --repo alone: MEMHTML_ROOT and the ~/memhtml default stop being doors, and a call that opens a repo without --repo is refused with ERR_REPO_REQUIRED at exit 2 before memhtml opens anything. For CI, for a test suite calling the CLI in-process, and for an agent runtime that exports MEMHTML_ROOT to every subprocess it starts. Commands that never open a repo (manifest, help, agents-doc, eval discriminate) are unaffected. It governs the roots memhtml resolves from its own environment: a caller that hands the in-process run() a layer it built states that layer’s root itself. Read by memhtml only: memhtml-mcp takes its root from MEMHTML_ROOT, which memhtml serve mcp --repo sets for the child explicitly. |
MEMHTML_TRACE_ROOT |
~/.claude |
Where memhtml trace index reads Claude Code transcripts from. Read-only; never written. |
MEMHTML_AWS_REGION |
us-east-1 |
The Bedrock region for embeddings and the sleep cycle’s model-calling phases. |
AWS_BEARER_TOKEN_BEDROCK |
no default | Bedrock bearer token, read by the AWS SDK itself. Absent means the default credential chain; retrieval then degrades to the lexical floor rather than failing. |
MEMHTML_LLM_BASE_URL |
no default | An OpenAI- and Anthropic-compatible LLM proxy’s origin, e.g. http://127.0.0.1:4000 for an agentgateway listener. Set, every model call leaves through it instead of going to Bedrock directly: the Anthropic sleep models and the consolidator agent on /v1/messages, the OpenAI sleep model and the entity extractor on /v1/chat/completions, embeddings on /v1/embeddings. Absent means Bedrock directly, under MEMHTML_AWS_REGION and the Bedrock credential. A set-but-malformed value fails at startup naming this variable rather than falling back to the direct path. |
MEMHTML_LLM_API_KEY |
no default | A bearer token for the LLM proxy, sent as Authorization: Bearer <key>. Read only when MEMHTML_LLM_BASE_URL is set; absent means the proxy takes no credential. |
MEMHTML_LLM_MODEL_PREFIX |
bedrock/ |
The prefix in front of every Bedrock model id a proxied request carries, so global.anthropic.claude-opus-5 is asked for as bedrock/global.anthropic.claude-opus-5: the LiteLLM convention, which a LiteLLM proxy routes with one bedrock/* entry and which keeps the id after the slash exactly what Bedrock wants. Set it to none for a proxy that takes bare Bedrock ids. Read only when MEMHTML_LLM_BASE_URL is set. |
MEMHTML_LLM_MODEL_MAP |
no default | from=to pairs, comma-separated, naming single models to the proxy by exact id when the prefix rule does not fit: cohere.embed-v4:0=cohere-embed-v4. A mapped id is sent verbatim, without the prefix; every other id follows MEMHTML_LLM_MODEL_PREFIX. Read only when MEMHTML_LLM_BASE_URL is set. |
MEMHTML_OPENAI_PROMPT_CACHE |
off |
How the OpenAI sleep model’s chat-completions requests ask Bedrock to treat prompt caching. off sends prompt_cache_options: {mode: "explicit"} with no breakpoints, which Bedrock documents as no prompt caching and no cache-write charge; implicit sends no caching field and leaves the endpoint’s default in place. Off by default because Bedrock’s implicit mode for GPT-5.6 writes the whole prompt to the cache at 1.25x the input rate on every call that clears the 1,024-token minimum, and the sleep prompts share no prefix long enough to ever be read back. Set implicit for an OpenAI-compatible endpoint that rejects the Bedrock-only field. Read on the direct path and the proxy path alike. Any other value fails at startup naming this variable. |
MEMHTML_EMBED |
on |
off disables the embedder entirely. An explicit opt-out, distinct from a missing credential: a missing credential degrades one search at call time, off degrades every search, and an operator reading this manifest needs those to be different states. |
MEMHTML_VECTOR_COVERAGE_FLOOR |
0.95 |
The share of indexed chunks that must carry a vector in the configured space, 0 to 1, before the vector arm is trusted. Below it search and recall drop the vector arm and report degraded: true with vectorCoverage, doctor reports vectorCoverageLow and healthy: false, and a sleep run warns. A sparse plane ranks the few embedded files above every exact match, so it is treated as absent rather than run. Sleep also refuses below a fixed hard floor of 0.5, which this variable does not move: a value under 0.5 keeps search and doctor accepting a plane sleep still refuses. Remedy: memhtml index embed, or memhtml index rebuild --embed. |
MEMHTML_LLM |
on |
off makes every model-calling sleep phase report no model bound and stay ok, so a credential-free run is honest rather than red. entity-resolution still runs its deterministic normalization and character-overlap passes; the others do nothing. |
MEMHTML_EXTRACT_ENTITIES |
on |
off removes the one global.openai.gpt-5.6-terra call per write batch that extracts memhtml-entity metas the ops did not declare; MEMHTML_LLM=off removes it too. On by default, like MEMHTML_EMBED. It changes what a write STORES: extracted entities land in the files as if authored, and the write itself never waits on or fails with the model. A failed extraction is a logged warning and an unextracted batch. |
OTEL_EXPORTER_OTLP_ENDPOINT |
no default | An OTLP collector’s base URL, e.g. http://localhost:4318. Set, the ~30 Effect.withSpan annotations already in the code (retrieval, embeddings, model calls, indexing, the sleep cycle, store writes, db.*, git.*) export as traces to <endpoint>/v1/traces, batched, flushed on exit. Unset, nothing is loaded and behavior is byte-identical. Export can never fail a command: a down collector is one stderr warning and a command that proceeds untraced. |
OTEL_SERVICE_NAME |
no default | Overrides the service.name resource attribute on exported traces. Absent, each process names itself: memhtml-cli or memhtml-mcp. Read only when OTEL_EXPORTER_OTLP_ENDPOINT is set. |
MEMHTML_MCP_BIN |
no default | An explicit path to the memhtml-mcp entry point, read only by the memhtml serve mcp supervisor. Absent means the sibling-path default. The two apps ship as one build, so apps/cli/dist/serve.js finds apps/mcp/dist/bin.js two directories over. An operator sets it for a split deployment that does not keep the apps side by side; it locates the server rather than configuring the store, so it changes no retrieval behavior. |
3. Provenance
A loader generates this page from apps/cli/src/config.ts while the site builds, so no file in the repository holds it: CONFIG_VARS is what memhtml manifest publishes, so a variable this page omits is one the binary does not read. Change the registry and this page changes with it.