chmonitor

Environment Variables

Full reference for every chmonitor environment variable, grouped by category with build-time vs runtime notes.

This is the complete list of every supported environment variable, grouped by category. Start with the two rules that govern how variables are named and when they take effect, then jump to the category you need.

One canonical name per setting

A setting the browser needs (auth provider, cloud mode, feature flags) is inlined into the client bundle at build time as a VITE_* var. You do not set it twice. Set the canonical CHM_* name once and vite.config.ts derives the matching client VITE_*:

Set this (canonical)Derives this (client, build-time)
CHM_AUTH_PROVIDERVITE_AUTH_PROVIDER
CHM_CLERK_PUBLISHABLE_KEYVITE_CLERK_PUBLISHABLE_KEY
CHM_CLOUD_MODEVITE_CLOUD_MODE
CHM_FEATURE_CONVERSATION_DBVITE_FEATURE_CONVERSATION_DB
CHM_FEATURE_USER_CONNECTIONS_DBVITE_FEATURE_USER_CONNECTIONS_DB
CHM_EDITIONVITE_EDITION

Precedence per var: explicit VITE_* → canonical CHM_* → legacy NEXT_PUBLIC_* → built-in default. The explicit VITE_* (and legacy NEXT_PUBLIC_*) forms still work as overrides.

A dual-surface setting must still be present at both build time (so vite inlines its VITE_*) and runtime (so the server reads it) — but it is the same single name in both places.

Cloud mode is a build-time contract. CHM_CLOUD_MODE / CHM_DEPLOYMENT_MODE=cloud must be set before the build so VITE_CLOUD_MODE is inlined into the client bundle. Setting it only at runtime on a prebuilt OSS image (e.g. the published Docker image) splits the product: the server enforces cloud behaviour (demo-host guard) while the client still renders OSS UI. /api/healthz detects and warns on this mismatch and reports a cloudMode object. The reverse — a cloud build with the runtime var unset — is safe (fail-closed: both halves degrade to OSS).

Client variable prefix by app

Browser-exposed variables are build-time inlined. The prefix depends on which app you run:

AppClient prefixExample
apps/dashboard (TanStack Start, current)VITE_*VITE_AUTH_PROVIDER
Legacy Next.js (v0.2 and earlier)NEXT_PUBLIC_*NEXT_PUBLIC_AUTH_PROVIDER

Tables below show the explicit VITE_* form for clarity, but you usually only set the canonical CHM_* name (above) and let the VITE_* derive. If you are migrating from v0.2, substitute NEXT_PUBLIC_ wherever you see VITE_. Server-side variables (CLICKHOUSE_*, CHM_*, LLM_*, CLERK_SECRET_KEY, etc.) are the same.

Authoritative example: apps/dashboard/.env.example.

Build-time vs runtime

There are two categories of environment variables:

CategoryWhen resolvedHow to setExample
Build-timeWhen pnpm run build runsCI environment / shell before the buildVITE_FEATURE_CONVERSATION_DB, VITE_AUTH_PROVIDER, VITE_CLERK_PUBLISHABLE_KEY
RuntimeWhen the server process starts per requestwrangler.toml [vars], wrangler secret put, Docker -e, k8s ConfigMap/SecretCLICKHOUSE_HOST, CONVERSATION_STORE_BACKEND

VITE_* variables are build-time only

Setting a VITE_* var in wrangler.toml [vars] or as a Docker -e flag has no effect on the running app — the bundle already has the value from when it was built. Always rebuild and redeploy when changing these variables.

All other vars (unless noted) are runtime — read from process.env when the Worker or Node process handles a request.

ClickHouse connection

Required. Set at least CLICKHOUSE_HOST.

VariableRequiredDefaultPurpose
CLICKHOUSE_HOSTYesComma-separated ClickHouse host URLs, e.g. http://ch-1:8123,http://ch-2:8123.
CLICKHOUSE_USERNodefaultComma-separated usernames, one per host.
CLICKHOUSE_PASSWORDNo""Comma-separated passwords, one per host.
CLICKHOUSE_NAMENoComma-separated display labels shown in the host selector.

CLICKHOUSE_HOST defines the host count. CLICKHOUSE_USER and CLICKHOUSE_PASSWORD may be either a single value (applied to all hosts) or one value per host position. CLICKHOUSE_NAME is optional. Position N maps to host index N.

See Multiple hosts and Custom name.

Query execution

VariableDefaultPurpose
CLICKHOUSE_MAX_EXECUTION_TIME60Query timeout in seconds.
CLICKHOUSE_TZserver defaultTime zone for date/time display.
CLICKHOUSE_DATABASEsystemDatabase used for app-owned tables (self-tracking events, dashboards).
EVENTS_TABLE_NAMEsystem.monitoring_eventsFull table name override for self-tracking events.

Connection pool

VariableDefaultPurpose
CLICKHOUSE_POOL_SIZE10Max concurrent ClickHouse clients per host.
CLICKHOUSE_POOL_TIMEOUT300000Idle client timeout in milliseconds (5 min).
CLICKHOUSE_POOL_CLEANUP_INTERVAL60000Stale-client cleanup interval in milliseconds (1 min).

Health alerting

The cron sweep (GET /api/cron/health-sweep, Cloudflare Cron Trigger every 5 minutes) runs health checks over all hosts and can post webhook alerts without a browser tab open.

VariableDefaultPurpose
CRON_SECRETRequired shared secret guarding the cron endpoints /api/cron/health-sweep and /api/cron/retention-prune. Send as Authorization: Bearer <secret> (or ?secret=<secret>). When unset/empty the endpoints fail closed and return HTTP 503 (they do not run) — retention-prune is destructive, so it must not be reachable unauthenticated.
HEALTH_ALERT_ENABLEDfalseSet true to POST webhook alerts. Checks run regardless; alerts only fire when true.
HEALTH_ALERT_WEBHOOK_URLSlack- or Discord-compatible webhook URL. Required for alerts to be dispatched.
HEALTH_ALERT_MIN_SEVERITYwarningMinimum severity to alert: warning (warning + critical) or critical (critical only).
# Alert Slack on warning-or-worse
CRON_SECRET=a-long-random-string
HEALTH_ALERT_ENABLED=true
HEALTH_ALERT_WEBHOOK_URL=https://hooks.slack.com/services/T000/B000/XXXX
HEALTH_ALERT_MIN_SEVERITY=warning

Weekly health report

A second cron job (GET /api/cron/weekly-report) builds a proactive weekly HTML report per opted-in host — a 7-day narrative from the AI insights engine, adaptive statistical baselines, and the disk-capacity forecaster. Opt-in, never opt-out: reports are generated only for hosts listed in CHM_WEEKLY_REPORT_HOSTS.

VariableDefaultPurpose
CHM_WEEKLY_REPORT_HOSTSunset (no reports)Comma-separated host indices to opt in, e.g. 0,2. Uses the same CRON_SECRET guard as health-sweep.
# Opt host 0 and host 2 into the Monday 08:00 UTC weekly report
CRON_SECRET=a-long-random-string
CHM_WEEKLY_REPORT_HOSTS=0,2

Persisted regardless of delivery outcome; best-effort delivered to HEALTH_ALERT_WEBHOOK_URL (above) when configured. See Health — Weekly health report for the report contents and how to view a persisted report.

Prometheus metrics exporter

GET /api/v1/metrics serves system.metrics + system.asynchronous_metrics for every configured host (labeled host="<id>"), plus a chmonitor_alerts_firing gauge from the in-memory alert-dedup state, as Prometheus text exposition format. Cached ~30s; concurrent scrapes share one query batch.

VariableDefaultPurpose
CHM_FEATURE_PROMETHEUS_ENABLEDmode (self-hosted→true, cloud→false)Canonical, server-only (no client bundle exposure needed). Set explicitly to override either default. Never gated on Clerk/billing — disabled returns 404 rather than 403 so cloud never advertises the surface.
# Scrape this instance from Prometheus
CHM_FEATURE_PROMETHEUS_ENABLED=true
# prometheus.yml
scrape_configs:
  - job_name: chmonitor
    scrape_interval: 30s
    metrics_path: /api/v1/metrics
    static_configs:
      - targets: ['dash.example.com']

OTel trace export

Exports chmonitor's OWN query traces — a dashboard-request span per request, with a nested clickhouse-query span per ClickHouse call carrying query_id/read_bytes/host attributes when available — to an external OTLP collector for correlation with the rest of your tracing stack. This is DISTINCT from the built-in OTel span viewer, which reads spans already stored in system.opentelemetry_span_log.

VariableDefaultPurpose
CHM_OTEL_EXPORTER_URLunset (disabled)Collector's OTLP/HTTP traces endpoint. Must be an absolute http(s) URL, including the /v1/traces path. Unset or invalid → trace export stays off: zero spans, zero network calls, zero added latency (fail-open). Server-only, never gated on Clerk/billing.
# Export to a local Jaeger instance (OTLP/HTTP receiver)
CHM_OTEL_EXPORTER_URL=http://jaeger:4318/v1/traces

Runs on Cloudflare Workers: the exporter uses OTLP/HTTP (not gRPC, which Workers cannot run), and the batch export is flushed inline before each response returns rather than deferred with waitUntil (Workers request middleware doesn't expose it here) — so export only adds latency when explicitly enabled.

Feature permissions

All features are public and enabled by default. Override only what needs different behavior.

VariableDefaultPurpose
CHM_CONFIG_FILEPath to TOML or YAML config file for feature overrides.
CHM_DISABLED_FEATURESComma-separated feature ids to disable entirely.
CHM_AUTH_REQUIRED_FEATURESComma-separated feature ids that require authentication.
CHM_FEATURE_{ID}_ACCESSpublicPer-feature access: public, guest (alias for public), or authenticated.
CHM_FEATURE_{ID}_ENABLEDtruePer-feature enabled flag: true or false.

Replace {ID} with an uppercase feature id: OVERVIEW, AGENT, INSIGHTS, HEALTH, QUERIES, TABLES, METRICS, DASHBOARD, SECURITY, LOGS, SETTINGS, BILLING, CLUSTER, OPERATIONS, ACTIONS, MCP, DOCS, ABOUT, PEERDB.

CHM_FEATURE_AGENT_ACCESS=authenticated
CHM_FEATURE_METRICS_ENABLED=false
CHM_DISABLED_FEATURES=settings,insights

See Feature permissions for config-file examples and precedence details.

Rate limiting

Per-IP (and, for the agent, per-signed-in-identity) request throttling on the SQL-executing API surfaces. All three share one implementation (lib/api/rate-limiter.ts, checkRateLimitDurable): an in-memory token bucket everywhere, upgraded to a fleet-wide Cloudflare Rate Limiting binding on Workers deploys (CHM_RATE_LIMIT_API / CHM_RATE_LIMIT_AGENT / CHM_RATE_LIMIT_MCP in wrangler.toml) so the limit holds across isolates, not just per-isolate. Requests over the limit get 429 with a Retry-After header. None of these need to be set for the defaults to apply.

VariableDefaultPurpose
RATE_LIMIT_API_PER_MIN100GET data routes (e.g. /api/v1/charts/$name), per IP.
RATE_LIMIT_AGENT_PER_MIN10POST /api/v1/agent, per IP then tightened per signed-in identity.
RATE_LIMIT_MCP_PER_MIN30/api/mcp (POST/GET/DELETE), per IP. Same class of capability as the agent route — arbitrary read-only SQL via the query tool — over the MCP transport.

Authentication

The active server-side auth provider is set by CHM_AUTH_PROVIDER. See Authentication for the full model.

VariableDefaultPurpose
CHM_AUTH_PROVIDERnoneServer auth provider: none, clerk, proxy, or trusted. Canonical — the client VITE_AUTH_PROVIDER is derived from it at build time.
VITE_AUTH_PROVIDER(from CHM_AUTH_PROVIDER)Client-side build-time value. Auto-derived from CHM_AUTH_PROVIDER; only set explicitly to override.
CHM_API_KEY_SECRETShared secret for chm_ API keys. When set, API-key auth is always on alongside the active provider. Issue keys at /api/v1/auth/api-key.

Keep secrets server-side

CLERK_SECRET_KEY, CHM_API_KEY_SECRET, and every trust-gate secret below are runtime secrets. Never prefix them with VITE_ or NEXT_PUBLIC_, and never expose them to the browser.

Clerk (CHM_AUTH_PROVIDER=clerk)

VariableDefaultPurpose
CHM_CLERK_PUBLISHABLE_KEYClerk publishable key (pk_..., public). Canonical — the client VITE_CLERK_PUBLISHABLE_KEY is derived from it at build time.
VITE_CLERK_PUBLISHABLE_KEY(from CHM_CLERK_PUBLISHABLE_KEY)Client-side build-time value. Auto-derived; only set explicitly to override. Must be present before pnpm run build.
CLERK_SECRET_KEYClerk secret key (sk_...). Runtime only, secret. Never expose to the browser.
CHM_CLERK_PUBLIC_READfalseWhen true, anonymous visitors can view read-only monitoring content; writes (AI agent, control actions, arbitrary SQL) still require sign-in. Runtime only. See Clerk → public read-only mode.

Reverse proxy (CHM_AUTH_PROVIDER=proxy)

Trust a reverse proxy that already authenticated the user. Either mechanism below can authenticate a request.

Cloudflare Access JWT:

VariableDefaultPurpose
CHM_CF_ACCESS_TEAM_DOMAINCloudflare Access team URL (https://<team>.cloudflareaccess.com). Enables Cf-Access-Jwt-Assertion JWT verification.
CHM_CF_ACCESS_AUDAccess application AUD tag the JWT must carry.

Trusted header (bare subject):

VariableDefaultPurpose
CHM_PROXY_AUTH_SECRETShared secret. When set, the identity header is honored only if this secret is also present (constant-time compare). Without it, the trusted-header mechanism is disabled.
CHM_PROXY_SHARED_SECRET_HEADERX-Chm-Proxy-SecretHeader the proxy sends containing the shared secret.
CHM_PROXY_AUTH_HEADERX-Forwarded-UserHeader the proxy sends containing the authenticated user identity.

Trusted-header gate

When CHM_PROXY_AUTH_SECRET is set, the identity header (X-Forwarded-User by default) is honored only when the request also carries a matching shared-secret header (constant-time compared). Without CHM_PROXY_AUTH_SECRET, the entire trusted-header mechanism is disabled and identity headers are ignored.

Trusted reverse proxy (CHM_AUTH_PROVIDER=trusted)

Use when an upstream proxy (oauth2-proxy, Authelia, Traefik ForwardAuth, nginx auth-url) forwards the user's full identity as HTTP headers. Extracts a complete principal — name, email, avatar, groups, custom claims.

Trust gate — configure exactly one:

VariableDefaultPurpose
CHM_TRUSTED_AUTH_SECRETShared secret (runtime secret). The proxy must send it in CHM_TRUSTED_SHARED_SECRET_HEADER. Constant-time compared. Recommended.
CHM_TRUSTED_ALLOW_INSECUREfalseWhen true, trusts headers with no secret check. Only safe when the service is unreachable except via the proxy (e.g. k8s ClusterIP).
CHM_TRUSTED_SHARED_SECRET_HEADERX-Chm-Proxy-SecretHeader name carrying the shared secret.

Identity headers — all optional; defaults match common proxy conventions:

VariableDefaultPopulates
CHM_TRUSTED_USER_HEADERX-Forwarded-UserSubject / user id. Falls back to the email header.
CHM_TRUSTED_EMAIL_HEADERX-Forwarded-EmailEmail address.
CHM_TRUSTED_NAME_HEADERX-Forwarded-Preferred-UsernameDisplay name.
CHM_TRUSTED_AVATAR_HEADERX-Forwarded-AvatarAvatar URL.
CHM_TRUSTED_GROUPS_HEADERX-Forwarded-GroupsComma- or space-separated groups.
CHM_TRUSTED_ROLE_HEADERX-Forwarded-RoleSingle role; merged into the groups list.
CHM_TRUSTED_CUSTOM_HEADERSExtra claims. Comma-separated field:Header-Name pairs, e.g. team:X-Forwarded-Team.

Access control:

VariableDefaultPurpose
CHM_TRUSTED_ALLOWED_GROUPSComma-separated group names. When set, users whose forwarded groups do not intersect are denied 403. Case-insensitive.

See Trusted proxy for setup examples (oauth2-proxy + Dex + Traefik, nginx).

AI agent / LLM provider

The agent uses an OpenAI-compatible API. Set LLM_API_KEY to enable it. Keep all LLM keys server-side — never prefix them with VITE_.

VariableDefaultPurpose
LLM_API_KEYProvider API key (fallback when no provider-specific key is set).
LLM_API_BASEhttps://openrouter.ai/api/v1OpenAI-compatible API base URL.
LLM_MODELopenrouter:openrouter/freeModel identifier in provider:modelId form.
LLM_EXTRA_MODELSAdditional model picker entries. Format: provider:modelId[|contextLength][|description], comma-separated. Providers: openrouter, nvidia, anyrouter.

Provider-specific keys

Provider-specific keys take priority over the generic LLM_API_KEY / LLM_API_BASE.

VariablePurpose
OPENROUTER_API_KEYOpenRouter API key.
OPENROUTER_API_BASEOpenRouter base URL.
OPENROUTER_REFERERHTTP referer sent to OpenRouter (for rankings).
OPENROUTER_APP_NAMEApp name sent to OpenRouter (for rankings).
OPENROUTER_MODELS_APIOpenRouter models list endpoint (default https://openrouter.ai/api/v1/models).
NVIDIA_API_KEYNVIDIA NIM API key.
NVIDIA_API_BASENVIDIA NIM base URL.
ANYROUTER_API_KEYAnyRouter API key.
ANYROUTER_API_BASEAnyRouter base URL.

Agent behavior

VariableDefaultPurpose
AGENT_API_TOKENShared Bearer token for the agent API (POST /api/v1/agent). Accepted when CHM_FEATURE_AGENT_ACCESS=authenticated.
AGENT_ENABLE_CONTROL_TOOLSfalseEnable kill-query, optimize, and other write actions. Keep false unless users are trusted.

See AI agent — configuration for full details.

Conversation store

Agent conversations default to browser localStorage. Enable server-side persistence with two steps:

Enable the feature (build-time)

Set CHM_FEATURE_CONVERSATION_DB=true (the client VITE_FEATURE_CONVERSATION_DB is derived from it at build time — must be present before pnpm run build). Also requires Clerk auth (CHM_AUTH_PROVIDER=clerk).

Choose a backend (runtime)

Configure a backend at runtime via CONVERSATION_STORE_BACKEND.

VariableDefaultPurpose
CHM_FEATURE_CONVERSATION_DBfalseCanonical. Set true to enable server-side conversation persistence. Requires Clerk. Drives the build-time VITE_FEATURE_CONVERSATION_DB.
VITE_FEATURE_CONVERSATION_DB(from CHM_FEATURE_CONVERSATION_DB)Client-side build-time value. Auto-derived; only set explicitly to override. Must be present before pnpm run build.
CONVERSATION_STORE_BACKEND(auto)Runtime. Backend: agentstate, d1, postgres, or memory. When unset, the server auto-selects the first available backend (AgentState if key present → D1 binding → Postgres via DATABASE_URL → Memory).

AgentState backend:

VariableDefaultPurpose
AGENTSTATE_API_KEYAgentState API key. Required when CONVERSATION_STORE_BACKEND=agentstate.
AGENTSTATE_BASE_URLhttps://agentstate.app/apiAgentState API base URL.
AGENTSTATE_AI_ENRICHfalseSet true to enable AI enrichment of stored conversations.

Cloudflare D1 backend:

VariableDefaultPurpose
CHM_CLOUD_D1_DATABASE_IDCloudflare D1 database UUID for the CHM_CLOUD_D1 binding.
AGENT_CHM_CLOUD_D1_DATABASE_IDAlias for CHM_CLOUD_D1_DATABASE_ID.

PostgreSQL backend:

VariablePurpose
DATABASE_URLPostgreSQL connection string.
POSTGRES_URLAlternative PostgreSQL connection string.
POSTGRES_PRISMA_URLPrisma-specific PostgreSQL connection string.

See Conversation history — backends for setup and fallback behavior.

User connections (server storage)

Let signed-in users save personal ClickHouse hosts to the server. All four of these must be present together, or the server returns "User connections database storage is not enabled".

VariableDefaultPurpose
CHM_FEATURE_USER_CONNECTIONS_DBfalseCanonical. Set true to enable. Drives the build-time VITE_FEATURE_USER_CONNECTIONS_DB.
VITE_FEATURE_USER_CONNECTIONS_DB(from CHM_FEATURE_USER_CONNECTIONS_DB)Client-side build-time value. Auto-derived; only set explicitly to override.
CHM_AUTH_PROVIDERnoneMust be clerk — connections are keyed by the Clerk userId.
CHM_USER_CONNECTIONS_ENCRYPTION_KEY32-byte base64 key (secret) encrypting saved credentials at rest (AES-256-GCM).

Plus a database backend: the CHM_CLOUD_D1 binding on Cloudflare, or DATABASE_URL / POSTGRES_URL on Docker / Kubernetes.

See User connections for the full setup.

AI insights store

The AI Insights panel on /overview persists its findings through a pluggable store. It is additive opt-in and defaults to ClickHouse; the D1, Postgres, and AgentState backends reuse the conversation-store env above.

VariableDefaultPurpose
INSIGHTS_STORE_BACKENDautoBackend: auto, clickhouse, d1, postgres, agentstate, or memory. auto and clickhouse both use the ClickHouse monitoring_findings table. auto never silently follows other env; a selected backend missing its prerequisite falls back to ClickHouse.
INSIGHTS_D1Optional dedicated D1 binding for the d1 backend. Falls back to CHM_CLOUD_D1 when unset.

postgres reuses DATABASE_URL; agentstate reuses AGENTSTATE_API_KEY (+ optional AGENTSTATE_BASE_URL).

See AI agent — AI Insights persistence for setup and fallback behavior. GET /api/v1/insights/backend reports the active backend.

PeerDB monitoring

Optional. Set PEERDB_API_URL to enable the PeerDB section (Mirrors and Peers) in the sidebar.

VariableDefaultPurpose
PEERDB_API_URLPeerDB REST API base URL. For the PeerDB UI (NextAuth), include /api suffix — e.g. https://peerdb.example.com/api. For the raw flow-api, use the bare origin — e.g. http://localhost:8113.
PEERDB_PASSWORDPeerDB password. Sent as HTTP Basic with an empty username. Server-side only.
PEERDB_CACHE_TTL_MS10000Server-side response cache TTL in milliseconds. Set 0 to disable.
PEERDB_CACHE_MAX_ENTRIES500Max cached PeerDB responses before oldest are evicted.
PEERDB_FETCH_TIMEOUT_MS10000Upstream PeerDB request timeout in milliseconds.

chmonitor proxies only a read-only allowlist of PeerDB endpoints; mutating operations (create/drop/pause, alert config) are rejected with 403.

# PeerDB UI behind NextAuth
PEERDB_API_URL=https://peerdb.example.com/api
PEERDB_PASSWORD=your-peerdb-ui-password

# Raw flow-api (no auth)
PEERDB_API_URL=http://localhost:8113

Analytics & branding

All client-side, all build-time. VITE_* for TanStack app; NEXT_PUBLIC_* for legacy Next.js.

VariableDefaultPurpose
VITE_TITLE_SHORTClickHouseBrowser tab title (short form).
VITE_LOGOCustom logo URL shown in the header.
VITE_AUTOCOMPLETE_LIMITMax results in autocomplete dropdowns.
VITE_MEASUREMENT_IDGoogle Analytics measurement ID (G-...).
VITE_SELINE_ENABLEDfalseEnable Seline analytics.
VITE_VERCEL_ANALYTICSfalseEnable Vercel Analytics.
VITE_ANALYTICS_KEY (derived from CHM_ANALYTICS_KEY)PostHog project key for opt-in Product Analytics (SaaS funnel tracking). Empty = disabled.
VITE_ANALYTICS_HOST (derived from CHM_ANALYTICS_HOST)https://us.i.posthog.comPostHog ingest host — point at a self-hosted PostHog instance.

Runtime & build

VariableDefaultPurpose
NODE_ENVdevelopmentRuntime environment: development, production, test.
ENABLE_CLOUDFLAREfalseEnable Cloudflare-specific build configuration.
CLOUDFLARE_WORKERSSet to 1 when running on Cloudflare Workers.
CF_PAGESSet automatically by Cloudflare Pages at runtime.
MINIFLARESet to 1 when running locally with Miniflare.
DOCS_CONTENT_ROOTOverride docs content source directory.

Build-time only

Injected at build time for the About page.

VariablePurpose
VITE_GIT_SHACurrent commit SHA.
VITE_GIT_REFCurrent git branch or tag.
VITE_BUILD_TIMESTAMPISO build timestamp.
VITE_CISet to true in CI environments.

Query config source

VariableDefaultPurpose
CHM_CONFIG_SOURCEtsQuery-config resolution path: ts (hand-written TypeScript configs, current default everywhere) or declarative (opt-in data-only catalog, validated against the same schema and kept at parity — see Catalog contributing). Any value other than the literal string declarative resolves to ts. A malformed declarative entry logs an error and falls back to the ts config rather than crashing.
CHM_CONFIG_DIRECTORY/etc/chmonitor/queries.dSelf-hosted only. Directory scanned once at startup for *.yaml local query-config overrides — no PR or fork needed. Each file must satisfy the same declarative schema as the catalog; an invalid file (bad YAML, schema violation, or duplicate name) is skipped with a warning log, never crashes boot. Checked first, ahead of CHM_CONFIG_SOURCE — a local file overrides a same-named built-in ts or declarative config regardless of that setting. Requires a real filesystem (Docker/K8s; not available on the Cloudflare Worker deploy). Mount example in the repo's docker-compose.yml.
CHM_PACK_REGISTRY_URLComma-separated community query-pack URLs (HTTP(S) or file://), consulted when CHM_CONFIG_SOURCE=declarative. Each pack is a single YAML manifest ({ name, version, queries: [...] }) fetched once at startup (no hot-reload). HTTP(S) fetches are SSRF-guarded; file:// reads a local, operator-chosen path. Precedence (highest to lowest): the self-hosted local queries.d override > packs > the built-in declarative catalog > ts configs. Within packs, the last URL wins on a name collision (logged). An unreachable or malformed pack — or a single bad query inside an otherwise-valid pack — is skipped with a warning; the built-in catalog always still serves.

Legacy / migration

VariableNotes
NEXT_PUBLIC_AUTH_PROVIDERRenamed to VITE_AUTH_PROVIDER in v0.3. Old name still works as a fallback.
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEYRenamed to VITE_CLERK_PUBLISHABLE_KEY in v0.3.
NEXT_PUBLIC_FEATURE_CONVERSATION_DBDeprecated alias for VITE_FEATURE_CONVERSATION_DB=true.
NEXT_PUBLIC_AUTOCOMPLETE_LIMITRenamed to VITE_AUTOCOMPLETE_LIMIT in v0.3.
NEXT_PUBLIC_RUNNING_QUERIES_REFRESH_MSRenamed to VITE_RUNNING_QUERIES_REFRESH_MS in v0.3.
CLICKHOUSE_EXCLUDE_USER_DEFAULTComma-separated usernames excluded from history-queries by default.

See Migrate to v0.3 for the full rename list.

On this page