Skip to Content
ReferenceEnvironment variables
Reference · Configuration

NovusLens reads its configuration from the environment, and the customer profile refuses guesses.

NovusLens takes its settings from environment variablesEnvironment variableA named setting made available to a running program. The customer launcher reads these settings from the installation environment file.. In an installation, ./lens setup writes the settings to .novuslens.env, and Docker ComposeDocker ComposeThe Docker tool that starts and connects the services listed in one configuration file. passes a fixed set of variables to each service. Setup settings describes every line of that file. A variable in the operator’s shell does not reach the services. A variable Compose does not pass keeps its default.

The profile decides how strict the platform is. In the dev profile, development conveniences are on and public development values are used with a warning. In the customer profile, the same variables are required, and a missing or public value stops the service from starting. Every installation runs the customer profile.

A default in the tables is the value the code uses when the variable is unset. Where the default depends on the profile, both are shown. “None; required” means the service refuses to start without the variable. The In an installation column gives what Compose passes: a fixed value, a line of .novuslens.env, or “not passed” when the default applies.

Profile and security

VariableDefaultIn an installationWhere readMeaning
CONWAY_PROFILEdevcustomer, fixedpackages/common_py/src/common_py/profile.py, apps/ui/lib/profile.tscustomer turns every development convenience into a refusal. The services and the UI treat any other value as dev.
CONWAY_SESSION_SECRETdev: a public development value built into the code, with a warning. customer: none; must be set, at least 24 characters, and not the public valuefrom .novuslens.envapps/ui/lib/session.ts, packages/common_py/src/common_py/profile.pySigns the login session cookieCookieA small value a browser keeps and sends back to a website. NovusLens uses a signed cookie to remember the signed-in account.. Changing it signs everyone out. In the customer profileDeployment profileA setting that selects customer or development behaviour. Customer mode refuses development credentials and uses the signed-in session as the identity. the UI refuses to sign a session without a strong value.
CONWAY_IDENTITY_SALTdev: a public development saltSaltExtra data mixed into a value before its fingerprint is calculated. It makes matching or guessing the original value harder. built into the code, with a warning. customer: nonefrom .novuslens.envapps/connectors/src/conway_connectors/personnel.py, packages/common_py/src/common_py/profile.pySalts the sealed personnel hashesHashA fixed-length fingerprint calculated from content. Comparing fingerprints helps detect changes and match records.. Choose it once and keep it.
CONWAY_SERVICE_TOKENempty; dev runs without onefrom .novuslens.envapps/reasoning/src/conway_reasoning/serve.py, apps/ui/lib/profile.ts, apps/connectors/src/conway_connectors/agent_producer.py, packages/common_py/src/common_py/profile.pyThe shared service tokenService tokenA secret value sent with requests between NovusLens services. The receiving service refuses requests with a missing or wrong value. for requests from the web application to the reasoning service, sent in the X-Conway-Service-Token header. In the customer profile the reasoning service refuses every request without it, except /health and /ready. The web application adds it after identifying the signed-in viewer. The agent producer reads it to call the service.
MYCELIUM_GATEWAY_TOKENemptyfrom .novuslens.envpackages/common_py/src/common_py/profile.py, compose.ymlThe bearer tokenBearer tokenA secret value sent with a request to prove that the caller holds it. Anyone who obtains it can use it, so it must be protected. for the meshMeshA set of connected Mycelium services that exchange updates and keep the NovusLens log. gatewayGatewayA service that accepts requests and passes them into another system. The Mycelium gateway gives NovusLens access to the mesh.. Compose gives the same value to the mesh nodes and the services, and refuses to start without it. The sidecarSidecarA separate supporting process that runs beside the application. Here it runs Mycelium and exposes the gateway that NovusLens calls. and the MyceliumMyceliumThe application infrastructure underneath NovusLens. Its connected services exchange updates and keep the ordered structural log. SDKSDKSoftware development kit: a package of code that helps another program use a service. NovusLens uses mycelium-py to talk to Mycelium., which live outside this repository, read it; this page relies on the comment in profile.py for that behaviour.
NOVUSLENS_MCP_EXPOSEunset: on in dev, off in customerfrom .novuslens.env, 0 by defaultapps/reasoning/src/conway_reasoning/serve.pySet to 1 to register the analysis tools on the mesh gateway in the customer profile. In an installation they then reach MCPMCPModel Context Protocol: a standard way for an AI application to discover and call named tools supplied by another program. clients on its Docker network only.
NOVUSLENS_TLS_PROXYunset (no proxyProxyA service that receives a request and forwards it to another service. The NovusLens web proxy adds the signed-in identity and service token. declared)from .novuslens.env, 0 by defaultapps/ui/lib/cookiePolicy.ts, apps/ui/app/login/page.tsx, compose.ymlSet to 1 to declare a TLS-terminating proxyTLS-terminating proxyA service that receives an encrypted HTTPS connection and forwards the request to the application. The customer supplies and configures it. or single sign-onSSOSingle sign-on: signing in through an organisation's existing identity service instead of a separate product account. gateway in front of the UI. Sign-in is then refused when a request reaches the declared proxy over plain HTTPHTTPHypertext Transfer Protocol: the rules a browser or program uses to send a request to a web service and receive its response.. A proxy that sends X-Forwarded-Proto: https makes the session cookie encrypted-only. Setup saves it when you answer proxy; see Network access.
NOVUSLENS_ALLOW_LOOPBACK_WEBHOOKunsetnot passedapps/reasoning/src/conway_reasoning/notify.pySet to 1 to allow a webhook endpointEndpointA particular address on a service that accepts a defined kind of request. on the loopbackLoopbackA network address that refers to the same host, such as 127.0.0.1. Other hosts cannot reach a service through that address. address. An installation refuses loopback endpoints: inside it, a loopback address is the service’s own containerContainerA running program with its own packaged software and isolated environment, managed by Docker on the host.. Cloud metadata hosts and link-local addresses are refused whatever this is set to.
NOVUSLENS_WEBHOOK_ALLOWLISTempty: no allow-listAllow-listA list of permitted actions, resources or destinations. It excludes everything else only when its issuer says the list is complete.from .novuslens.env, empty by defaultapps/reasoning/src/conway_reasoning/notify.pyA comma-separated list of host suffixes. When set, a webhook host must equal one of them or end with one of them.

Database

VariableDefaultIn an installationWhere readMeaning
DATABASE_URLdev: a local PostgreSQLPostgresThe database software that stores the tables read by the NovusLens screens, along with document bodies, access records and protected personnel records. at 127.0.0.1, port 5433, with the development credential built into the code. customer: none; a missing value stops the commandbuilt from POSTGRES_PASSWORD in .novuslens.env, for the installation’s own databaseapps/graph/src/conway_graph/db.py, apps/ui/lib/twin.ts, apps/ui/lib/guide.ts, compose.ymlThe PostgreSQL connection string. It holds the read modelRead modelThe database tables used by the map, Ask and Find. NovusLens rebuilds these tables from its history of recorded changes., the evidence bodies, the sealed identities and the audit trail. Connections give up after five seconds.

Mesh

VariableDefaultIn an installationWhere readMeaning
NOVUSLENS_MESH_HTTP_ADDR127.0.0.1mesh-0, fixedapps/mesh/src/conway_mesh/build.py, apps/connectors/src/conway_connectors/__main__.py, apps/graph/src/conway_graph/keyperson.py, apps/reasoning/src/conway_reasoning/serve.pyThe address clients use to reach the mesh HTTP gateway.
NOVUSLENS_MESH_HTTP_BASE84008400, fixedapps/mesh/src/conway_mesh/build.py, apps/connectors/src/conway_connectors/__main__.py, apps/reasoning/src/conway_reasoning/serve.pyThe first HTTP port. In development, mesh node i listens on this value plus i. In an installation each node has its own container and listens on 8400.
MYCELIUM_DIR/Volumes/Scratch/Myceliumnot passedapps/mesh/src/conway_mesh/twin.pyThe location of the substrateSubstrateThe shared Mycelium software beneath NovusLens. It stores records and lets NovusLens components exchange them. checkout. It is used only when CONWAY_SDK_FROM_CHECKOUT=1, which is a development path.
CONWAY_SDK_FROM_CHECKOUTunsetnot passedapps/mesh/src/conway_mesh/twin.pySet to 1 to import the Mycelium SDK from the checkout instead of the pinnedPinA recorded choice of one exact dependency version. It prevents an update from changing that dependency without a deliberate decision. wheelWheelA packaged Python library ready to install. A vendored wheel is stored in this repository so its exact bytes can be checked.. This is a development override, and the service refuses it in the customer profile.

Compose also sets the substrate’s own variables for each mesh node: MYCELIUM_DATA_DIR, MYCELIUM_PORT, MYCELIUM_HTTP_PORT, MYCELIUM_HTTP_ADDR, MYCELIUM_PEERS, MYCELIUM_ROLE and MYCELIUM_HOSTNAME. Operators do not set these. They are read by the substrate, outside this repository. NOVUSLENS_MESH_NETWORK in .novuslens.env chooses the private address range the nodes use.

Reasoning

VariableDefaultIn an installationWhere readMeaning
NOVUSLENS_PROJECTION_INTERVAL30from .novuslens.envcompose.yml, default in apps/reasoning/src/conway_reasoning/project.pySeconds between read-model projectionProjectionThe regular pass that brings the read model up to date with the canonical log. It runs every 30 seconds by default. passes. Compose passes it to the projection worker as --interval. Setup and the projection command refuse values under five seconds.
CONWAY_LLM_ENDPOINThttp://localhost:11434/v1/chat/completionsfrom .novuslens.envapps/mesh/src/conway_mesh/build_agent.py, packages/common_py/src/common_py/llm_http.pyThe OpenAI-compatible chat endpoint for every model call: the interview reader, Compass, Strategy and the meaning sweep all send their requests through it. Setup asks for the model server and writes its address here.
CONWAY_BUILD_MODELCONWAY_LLM_MODEL if set, otherwise gpt-oss:20bfrom .novuslens.env; gpt-oss:20b when emptyapps/mesh/src/conway_mesh/build_agent.pyThe model the interview reader uses. ./lens monitor shows it as missing when the model server does not have it.
CONWAY_LLM_MODELgpt-oss:20bnot passedapps/mesh/src/conway_mesh/build_agent.pyThe older name for the build model. It is used only when CONWAY_BUILD_MODEL is empty.
CONWAY_COMPASS_MODELqwen3:30bfrom .novuslens.env; qwen3:30b when emptyapps/reasoning/src/conway_reasoning/compass.py, apps/reasoning/src/conway_reasoning/strategy.py, apps/meaning/src/conway_meaning/deep_sweep.pyThe model for Compass answers. It is also the fallback for the Strategy and sweep models.
CONWAY_STRATEGY_MODELCONWAY_COMPASS_MODEL if set, otherwise qwen3:30bthe Compass modelapps/reasoning/src/conway_reasoning/strategy.pyThe model for Strategy.
CONWAY_SWEEP_MODELCONWAY_COMPASS_MODEL if set, otherwise qwen3:30bthe Compass modelapps/meaning/src/conway_meaning/deep_sweep.pyThe model for the meaning-contradiction sweep.
CONWAY_LLM_API_KEYunsetfrom .novuslens.envpackages/common_py/src/common_py/llm_http.pyThe bearer key used only when CONWAY_LLM_ENDPOINT is exactly https://openrouter.ai/api/v1/chat/completions. The request helper never sends it to local test stubs or any other endpoint. Setup saves it when you choose openrouter, from your answer or from OPENROUTER_API_KEY, and refuses that choice without it. In CIContinuous integrationAutomated checks run when code changes, usually including building the code and running tests., the gate workflow maps the Actions secret OPENROUTER_API_KEY to this variable.
CONWAY_LLM_FREE_ONLYunsetnot passedpackages/common_py/src/common_py/llm_http.pySet to 1 to restrict remote calls to OpenRouter and openrouter/free, or the exact confirmed xing4-phala-zero profile with all four provider price caps zero. Arbitrary named free suffixes and paid models refuse. Local endpoints are exempt. Default CI uses the router for all four model roles.
CONWAY_LLM_CI_PROFILEunset (off)not passedpackages/common_py/src/common_py/llm_http.pygpt-oss-20b-darkbloom-fp8-capped permits only GPT OSS 20B via Darkbloom fp8 at prompt/completion caps 0.018/0.09 USD per million tokens, request/image zero; it conflicts with free-only mode and requires separate paid permission. xing4-phala-zero permits only Xing4 29B via Phala with all four caps zero, including under free-only mode. Both require manual dev, account-plugin confirmation, parameter support and no provider fallback. Stricter caller limits/privacy remain; caps are not a total budget.
CONWAY_LLM_ACCOUNT_PLUGINS_OFFunset (refuse named profiles)not passedpackages/common_py/src/common_py/llm_http.pyBoth named profiles require exact 1: an operator declaration that account default plugins are off and not forced on. This is not automatic verification or paid permission. The workflow boolean defaults false and sets it only after manual dev admission. Reconfirm after account-policy changes.
CONWAY_STRUCTURED_ANSWERSunset (off)not passedapps/reasoning/src/conway_reasoning/compass.pySet to 1 to add a structured final-answer instruction to Compass. The code describes this as an opt-in path that is measured before it becomes the default.
CONWAY_AGENT_EVIDENCE_CONFIGunsetnot passedapps/reasoning/src/conway_reasoning/serve.py, apps/reasoning/src/conway_reasoning/agent_evidence.pyDevelopment only: the path to the enrolmentEnrolmentThe operator's recorded permission for a source to send specified record types about named agents, using an identified signing key. file and a switch for the service delivery worker. Installations use activated database policy and the projection worker.

User interface

VariableDefaultIn an installationWhere readMeaning
NOVUSLENS_UI_PORT3111from .novuslens.envcompose.ymlThe host port of the web application. Compose publishes it on NOVUSLENS_UI_BIND.
NOVUSLENS_UI_BIND127.0.0.1from .novuslens.env, 127.0.0.1 by defaultcompose.yml, deploy/installer/src/novuslens_installer/configuration.pyThe host address Compose publishes the web port on. Any other address needs NOVUSLENS_TLS_PROXY=1.
CONWAY_REASONING_URLhttp://127.0.0.1:8500http://reasoning:8500, fixedapps/ui/lib/profile.ts, scripts/answer_eval.pyThe address the UI uses to reach the reasoning service.

The UI also reads CONWAY_PROFILE, CONWAY_SESSION_SECRET, CONWAY_SERVICE_TOKEN, DATABASE_URL and NOVUSLENS_TLS_PROXY. Those are described in the tables above.

These developer scripts read their own variables. They are not used by an installation.

VariableDefaultWhere readMeaning
E2E_BASE_URLhttp://127.0.0.1:3111apps/ui/playwright.config.ts, apps/ui/scripts/shoot-panel.mjs, apps/ui/scripts/check-overlaps.mjsDeveloper scripts only: the address the browser checks run against.
NOVUSLENS_GATE_UI_PORT3111opsDeveloper gates only: the UI port, from 1 to 65535. Choose a free port when a separate demo is running. ops e2e passes this address to its browser tests.
NOVUSLENS_URLhttp://127.0.0.1:3111apps/ui/scripts/capture-screens.mjsDeveloper script only: the address that screenshot capture uses.
NOVUSLENS_CAPTURE_REPORT/tmp/novuslens-capture-report.jsonapps/ui/scripts/capture-screens.mjsDeveloper script only: the JSONJSONJavaScript Object Notation: a text format for data, using named fields, lists and values. Configuration files and service messages use it. report of captured views, failures and refreshed copies. Set a different path to retain each capture attempt.
NOVUSLENS_CAPTURE_PASSPHRASEa development passphrase built into the scriptapps/ui/scripts/capture-screens.mjsDeveloper script only: the passphrase used for screenshot capture.

Connectors

VariableDefaultIn an installationWhere readMeaning
CONWAY_OBSERVATION_TTL_DAYS30from .novuslens.env, 30 by defaultapps/connectors/src/conway_connectors/corrector.pyThe number of days a measured observation counts as the current picture. An older measurement stays in the record as historical and is left out of the current view. It is not erased.

The connectorsConnectorSoftware that reads records from a source system, such as an incident tool. A customer-written file connects those records to teams or services in NovusLens. also read CONWAY_IDENTITY_SALT and CONWAY_SERVICE_TOKEN, described in the profile table, and the mesh address and port variables, described in the mesh table.

Logging

Every Python command and service, and the user interface server, reads these as it starts.

VariableDefaultWhere readMeaning
CONWAY_LOG_LEVELINFOpackages/common_py/src/common_py/logging_config.py, apps/ui/lib/log.tsThe lowest level written: DEBUG, INFO, WARNING, ERROR or CRITICAL, in any case. Any other value, or an empty one, stops the command or the user interface server as it starts and names the value.
CONWAY_LOG_JSON0packages/common_py/src/common_py/logging_config.py, apps/ui/lib/log.ts1 writes one JSON object per log line, for a log collector. 0 writes plain lines. Any other value stops the command or the user interface server as it starts.
NO_COLORunsetpackages/common_py/src/common_py/logging_config.py, apps/ui/lib/log.tsAny value, including empty, turns off colour in log lines written to a terminal. Lines written to a file or a pipe never carry colour.

Settings only setup and Compose read

The other lines of .novuslens.env choose the images, the installation’s name and directory, the demo and the first operator account. No NovusLens service reads them. Setup settings describes each one.

Named manual inference and account declaration

The default CI route remains openrouter/free. The xing4-phala-zero manual profile pins the named Xing model to Phala. It requires parameter support, disables provider fallback and caps prompt, completion, request and image provider prices at zero. It extends CONWAY_LLM_FREE_ONLY=1 only for that exact reviewed profile; arbitrary free suffixes and paid alternatives are refused.

Both named profiles require account-plugins-off: true on an explicit manual version=dev dispatch. This operator declaration means the CI key’s account plugins are off and cannot be forced on by account policy. It is not an automatic account check and must be reassessed if account settings change. Missing or false confirmation refuses before an ops command; the shared HTTP guard also requires CONWAY_LLM_ACCOUNT_PLUGINS_OFF=1. OpenRouter documents account plugin defaults and forced overrides . Provider price caps do not cap account add-on fees or total spend. Paid-profile permission remains a separate decision.

The inference-compatibility component accepts only the confirmed named-zero profile. It makes one real public BuildAgent.chat request with the existing static group schema, low effort and 8,192-token limit. It makes no inferenceInferenceThe work a language model does to produce an answer from its instructions and input. preflight call, formatting nudge or retry. Its shape result is protocol evidence, not model semantic qualification or an application-gate pass. The ordinary live routing matrix and all twelve application gates remain required.

Last updated