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.exampleis tracked.
Required
Section titled “Required”| 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).
Networking
Section titled “Networking”| 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/. |
Database pool & lifecycle
Section titled “Database pool & lifecycle”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. |
Workspace & background workers
Section titled “Workspace & background workers”| 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.) |
Chat & agent runtimes
Section titled “Chat & agent runtimes”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 installedcodex/claudebinary using your owncodex login/claude login, and reach the knowledge mesh over the host’s own MCP surface. Each needs its binary onPATHand an operator login; they are never auto-selected.
OpenClaw gateway
Section titled “OpenClaw gateway”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. |
Host-native & vendor-CLI tuning
Section titled “Host-native & vendor-CLI tuning”| 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. |
LLM bootstrap
Section titled “LLM bootstrap”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. |
Worker throughput
Section titled “Worker throughput”| 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. |
Harvester & connectors
Section titled “Harvester & connectors”| 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. |
OAuth callback overrides
Section titled “OAuth callback overrides”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.
Linear connector
Section titled “Linear connector”| 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). |
Channel webhook secrets
Section titled “Channel webhook secrets”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>.
Removed env vars
Section titled “Removed env vars”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 encryptedoauth_appstable via Admin SPA → OAuth Apps.GITHUB_TOKEN— populated by GitHub device-flow OAuth into theintegrationstable.GOOGLE_CALENDAR_TOKEN— populated by Google OAuth into theintegrationstable.
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.