Skip to content

Environment variables

The host reads its configuration from .env.<env> (loaded via scripts/load-env.sh) — it does not pick up environment variables outside that flow. Start from the tracked .env.example, copy it to .env.dev / .env.staging / .env.production, and fill in the blanks.

Two rules worth internalizing up front:

  • OAuth credentials never live in env. Third-party OAuth application keys (GitHub, Google, Strava, Tidal, …) are stored encrypted in the database and configured through the Admin SPA → OAuth Apps. See Removed env vars below.
  • Never commit a populated .env. All .env.<env> files are gitignored; only .env.example is tracked.
Var Purpose Notes
DATABASE_URL Postgres connection string The database name MUST end in _dev / _staging / _prod so the reset guardrail can classify it.
HOST_MASTER_KEY 32-byte hex key for AES-256-GCM credential encryption at rest Generate with node -e "console.log(require('crypto').randomBytes(32).toString('hex'))". Different per environment. The host refuses to boot without it.

That’s the minimum to boot. Chat works out of the box once a model provider is configured (see Chat & agent runtimes and LLM bootstrap).

Var Default Purpose
HOST :: Bind address. The dual-stack default serves IPv4, IPv6, and Tailscale. An IPv4-only bind (0.0.0.0) silently breaks localhost access on macOS.
PORT 3000 HTTP port. The embedded Admin SPA is served at http://localhost:<PORT>/admin/.

Safety nets for the shared Postgres pool and for graceful shutdown. The defaults are sane — only tune these if you’re chasing a specific pool or restart issue.

Var Default Purpose
PG_IDLE_IN_TXN_TIMEOUT_MS 300000 Reap any pooled session left idle-in-transaction longer than this (ms), so a worker that opens a transaction and hangs can’t hold row/FK locks indefinitely. 0 disables.
PG_MAX_LIFETIME_S 1800 Rotate pooled sockets after this many seconds so severed/zombie sockets can’t accumulate. 0 disables.
PG_CONNECT_TIMEOUT_S 30 Fail a connection attempt that can’t complete within this many seconds. 0 disables.
SHUTDOWN_DEADLINE_MS 30000 Hard deadline (ms) on graceful SIGINT/SIGTERM shutdown — if cleanup hasn’t finished within it, force-exit so the supervisor restarts a healthy process instead of hanging. 0 disables.
Var Default Purpose
DEFAULT_WORKSPACE_ID (unset) When set to a workspace UUID, enables the cron schedulers (GitHub sync, calendar sync, memory distillation, etc.) and anchors webhook routes that need to resolve a workspace. Background workers stay dormant without it.
HOST_FILE_WATCHER 0 Set to 1 for headless deployments without the desktop client to enable the local file watcher for markdown / calendar files. (On normal installs the Tauri client owns file watching.)

Carabase chat is multi-engine. The active engine is chosen per workspace (auto resolves to OpenClaw when a gateway is configured, otherwise the host-native floor):

  • openclaw — the premium default, backed by the OpenClaw gateway. Model selection happens inside OpenClaw, not in env.
  • host_native — the OSS chat floor. Runs a grounded, retrieval-tool ReAct loop directly against the workspace’s configured model provider, no gateway required.
  • codex_cli / claude_code — read-only vendor-CLI bridges. They drive a locally installed codex / claude binary using your own codex login / claude login, and reach the knowledge mesh over the host’s own MCP surface. Each needs its binary on PATH and an operator login; they are never auto-selected.

Only needed when the OpenClaw runtime is in use.

Var Default Purpose
OPENCLAW_GATEWAY_PASSWORD (unset) Bearer token for the OpenClaw gateway. Must match ~/.openclaw/config.toml. Required only if you run the OpenClaw runtime — see OpenClaw setup.
OPENCLAW_GATEWAY_URL http://localhost:18789 Gateway address. Override only for a non-default port.
OPENCLAW_WORKSPACE_DIR ~/.openclaw/workspace Where the dream-cycle reads DREAMS.md from.
OPENCLAW_CONFIG_PATH openclaw.config.json Carabase’s own MCP-server config for OpenClaw to consume.
MCP_SERVERS_PATH mcp-servers.json Path to the external-MCP server config.
Var Default Purpose
CHAT_HOST_NATIVE_DEADLINE_MS 120000 Wall-clock ceiling (ms) on a single host-native chat turn — bounds a stuck turn without slowing a fast one. Raise it for slow local models.
CODEX_CLI_DEADLINE_MS 300000 Run deadline (ms) for the Codex CLI bridge; the source of truth its MCP startup/tool timeouts derive from.
CARABASE_CLI_MCP_TIMEOUT_MS 30000 Startup window (ms) for a vendor-CLI bridge’s MCP connection to the host.
CARABASE_CLI_MCP_CONNECT_RETRIES 2 Retries (→ attempts = retries + 1, clamped 0–5) if the bridge’s MCP tools don’t connect on the first try, before failing the turn visibly.

These keys let background workers (harvest, embeddings, memory distillation) reach a model provider, and seed the host-native chat floor before model routing is configured in the Admin SPA. Configure providers properly via the first-run wizard and the Admin SPA’s AI Engine page; these env values are a fallback.

Var Default Purpose
OPENAI_API_KEY (unset) OpenAI key for utility model tiers + embeddings.
OPENROUTER_API_KEY (unset) OpenRouter key — an alternative to OpenAI.
OLLAMA_URL http://localhost:11434 Local Ollama server — a fully local alternative to a hosted provider.
EMBEDDING_MODEL text-embedding-3-small Override the default embedding model.
LLM_MODEL gpt-4o-mini Override the default utility/bootstrap model.
EMBEDDING_DIMENSIONS 4096 Vector dimension. Changing it requires regenerating the schema migration.
Var Default Purpose
EXTRACT_DOCUMENT_TEXT_CONCURRENCY 4 (clamped [1,16]) How many document/image extraction jobs run in parallel. Each job is an extraction/vision-OCR call plus an embedding write. Crank it temporarily to drain a large extraction backlog (e.g. a Drive/Gmail backfill), then restore it — this queue has no daily token cap, so a higher rate spends cost faster. Also divides EXTRACT_MEMORY_BUDGET_MB into per-file parse caps.
EXTRACT_MEMORY_BUDGET_MB 2048 Aggregate heap budget for concurrent document extraction. The per-file parse cap is derived as (budget / concurrency) / per-format peak-memory multiplier; a file over its cap records a clear extraction error instead of exhausting the host’s memory.
CARABASE_BOOT_SWEEP_DELAY_MS 30000 Delay (plus jitter) before boot-time orphan-recovery sweeps re-enqueue crashed jobs after a restart. 0 sweeps immediately.
HARVEST_CONCURRENCY 3 Max parallel harvest jobs.
Var Default Purpose
HARVESTER_DEVICE_AUTH_REQUIRED off Strict mode for edge harvester push auth — when on, every harvester sync push must carry a bearer token matching a paired device.
HARVEST_LLM_PROVIDER / HARVEST_LLM_MODEL (provider default) Provider/model for harvest entity extraction.
WHISPER_PROVIDER / WHISPER_MODEL auto Voice-transcription provider/model (auto-detected if blank).
DISTILL_LLM_PROVIDER / DISTILL_LLM_MODEL inherit harvest Memory-distillation overrides.
BRIDGE_LLM_PROVIDER / BRIDGE_LLM_MODEL inherit harvest Memory-graph bridge overrides (translating facts into knowledge-graph edges).
GITHUB_REPOS (unset) Comma-separated owner/repo list for GitHub sync. Sync rules supersede this.
GOOGLE_CALENDAR_ID primary Calendar to sync.
VISUAL_INVESTIGATION_ENABLED 0 Adds the host-only visual-investigation chat tool (text-only answers over photo density) to the host-native retrieval palette.

Connector OAuth credentials live in the encrypted oauth_apps table (Admin SPA → OAuth Apps). You only need these env vars to override a callback URL when the host is reachable on a non-default origin (e.g. behind a reverse proxy or on a Tailnet hostname). Each defaults to http://localhost:<PORT>/api/v1/auth/<provider>/callback.

STRAVA_REDIRECT_URI, TIDAL_REDIRECT_URI, BEEPER_REDIRECT_URI, SPOTIFY_REDIRECT_URI, WHOOP_REDIRECT_URI, REDDIT_REDIRECT_URI, GOOGLE_REDIRECT_URI.

Var Purpose
LINEAR_REDIRECT_URI Public OAuth callback URL — set to a reachable host (Tailscale Funnel / reverse proxy) so Linear’s redirect can reach you.
LINEAR_WEBHOOK_URL Public webhook URL. Derived from LINEAR_REDIRECT_URI’s origin when unset — usually you only need to set the redirect URI.
LINEAR_REQUEST_ADMIN_SCOPE Set to 1 to additionally request Linear’s admin scope and auto-register the org webhook on connect. Off by default (cron-pull freshness still works without admin).

Webhook signing secrets (Slack, Telegram, WhatsApp, Matrix, Linear, generic) are not env vars. Store them encrypted via POST /api/v1/integrations with skill_name webhook:<channel>.

These were once honored as fallbacks but were removed for the OSS launch. Configure them in their proper home instead:

  • GITHUB_OAUTH_CLIENT_ID, GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET — store in the encrypted oauth_apps table via Admin SPA → OAuth Apps.
  • GITHUB_TOKEN — populated by GitHub device-flow OAuth into the integrations table.
  • GOOGLE_CALENDAR_TOKEN — populated by Google OAuth into the integrations table.

If any of these are still set in a leftover .env.<env>, the host returns 503 Not Configured on the affected auth route, with a message pointing you at the right config surface.