# ───────────────────────────────────────────────────────────── # CompanyBrain — environment configuration # Copy to `.env` and fill in. Sensible defaults work out of the box. # ───────────────────────────────────────────────────────────── # ── Core ──────────────────────────────────────────────────── NODE_ENV=development # Postgres connection string (must have the `vector` extension available). # The bundled docker-compose provisions this automatically. DATABASE_URL=postgres://companybrain:companybrain@localhost:5432/companybrain # Auth mode: # single (default) — no sign-in. Every request maps to one default workspace. # The frictionless self-host experience. Optionally gate it # with ACCESS_TOKEN below so an exposed instance is not open. # multi — full auth: register/login, sessions, API keys, many workspaces. AUTH_MODE=single # Optional shared bearer token that guards single-user mode when set (leave blank for local). ACCESS_TOKEN= # Secret used to sign auth JWTs (only used in multi mode). CHANGE in production (openssl rand -hex 32). JWT_SECRET=dev-only-change-me-0000000000000000000000000000000000000000000000000000 # Optional: encrypt connector credentials at rest with AES-256-GCM. When set, # stored connection tokens are encrypted with a key derived from this value; # leave empty to store them as-is. Keep it stable and backed up (rotating it # makes existing encrypted credentials unreadable). openssl rand -hex 32. CREDENTIALS_KEY= # ── API server ────────────────────────────────────────────── API_HOST=0.0.0.0 API_PORT=3333 # Public URL the API is reachable at (used by SDKs, extension, MCP). COMPANYBRAIN_API_URL=http://localhost:3333 # CORS allow-list (comma separated). Use * for local dev only. CORS_ORIGINS=http://localhost:3000 # Per-principal cap on LLM generations per minute, shared across chat and # playbook synthesis (the endpoints that hit the model every request). Bounds # provider cost if a key leaks or an agent loop runs away. 60/min is well above # interactive use; set to 0 to disable for high-volume automation. LLM_RATE_LIMIT_PER_MIN=60 # Run pending DB migrations automatically on API boot. Set false to run them # yourself (e.g. `pnpm db:migrate`) before the server starts. AUTO_MIGRATE=true # Include the raw error message in 500 responses. Off in production by default # so internal details aren't disclosed to clients (errors are always logged # server-side). Set true to debug a production instance. EXPOSE_ERROR_DETAILS=false # Allow outbound webhooks to target internal/private/loopback addresses. Off by # default so a user-registered webhook can't be pointed at the cloud metadata # endpoint or host-internal services (SSRF). Set true only for local integrations. WEBHOOK_ALLOW_INTERNAL=false # Allow connectors to crawl internal/private/loopback URLs. Connectors store the # fetched content for users to read, so an internal target is a read-SSRF risk. # Unset defaults to allow in single-user mode (your own box, internal wikis are # fine) and block in multi-tenant mode (AUTH_MODE=multi). Set true/false to force. # CONNECTOR_ALLOW_INTERNAL= # ── Web dashboard ─────────────────────────────────────────── WEB_PORT=3000 NEXT_PUBLIC_API_URL=http://localhost:3333 # ── Embeddings ────────────────────────────────────────────── # Provider: `local` (zero-config, deterministic, no keys) | `openai` | `ollama` | `google` EMBEDDING_PROVIDER=local # For OpenAI, text-embedding-3-large gives the best retrieval quality; it is # requested at 1536 dims (Matryoshka) so it fits the vector column with no change. EMBEDDING_MODEL=text-embedding-3-small EMBEDDING_DIMENSIONS=1536 # ── Retrieval tuning (optional) ───────────────────────────── # Hybrid fusion weights: raise the vector arm to favor semantic matches. RRF_VECTOR_WEIGHT=2 RRF_KEYWORD_WEIGHT=1 # HyDE (hypothetical-document embeddings) samples to average when a search asks # for hyde. 1 keeps latency low; raise it to trade latency for recall. HYDE_SAMPLES=1 # ── LLM (for RAG chat, summaries, auto-tagging) ───────────── # Provider: `anthropic` | `openai` | `ollama` | `none` LLM_PROVIDER=anthropic LLM_MODEL=claude-sonnet-5 # Enrich memories on ingest (LLM summary + auto-tags + extracted facts). # Runs only when an LLM provider is configured. Set to false to disable. ENRICH_ON_INGEST=true # Temporal reasoning: on ingest, ask the LLM whether a new memory supersedes an # older one (a moved date, a rotated owner). Superseded memories drop out of # recall by default. Opt-in; needs an LLM provider. Off by default. TEMPORAL_RESOLUTION=false TEMPORAL_CANDIDATES=5 # ── Media ingestion ───────────────────────────────────────── # Image OCR needs a vision LLM (anthropic or openai). Audio transcription needs # openai (Whisper). Video needs the ffmpeg binary on the host plus a vision # and/or audio provider. ffmpeg is auto-detected on PATH; override if needed. FFMPEG_PATH=ffmpeg FFPROBE_PATH=ffprobe # ── Provider API keys (only needed if you pick that provider) ─ OPENAI_API_KEY= ANTHROPIC_API_KEY= GOOGLE_API_KEY= # Where the Ollama server lives. Leave unset for the defaults: localhost when # the API runs on your machine, host.docker.internal when it runs in Docker # Compose (so it reaches Ollama on the host). Set it to point somewhere else. # OLLAMA_BASE_URL=http://localhost:11434 # ── Integrations / connectors (optional) ──────────────────── # Slack SLACK_CLIENT_ID= SLACK_CLIENT_SECRET= SLACK_SIGNING_SECRET= # Google (Docs / Drive / Gmail) GOOGLE_CLIENT_ID= GOOGLE_CLIENT_SECRET= # Notion NOTION_CLIENT_ID= NOTION_CLIENT_SECRET= # GitHub GITHUB_APP_ID= GITHUB_APP_PRIVATE_KEY= # ── Object storage (for uploaded files, optional) ─────────── # Provider: `local` | `s3` STORAGE_PROVIDER=local STORAGE_LOCAL_PATH=./.docker-data/uploads S3_ENDPOINT= S3_REGION=us-east-1 S3_BUCKET=companybrain S3_ACCESS_KEY_ID= S3_SECRET_ACCESS_KEY= # ── Background jobs / queue ───────────────────────────────── # Provider: `memory` (in-process, default) | `redis` QUEUE_PROVIDER=memory REDIS_URL=redis://localhost:6379 # Connector auto-sync scheduler. Runs periodic syncs for connections that set a # syncIntervalMinutes. Set to `true` on all but one replica if you run several. DISABLE_SCHEDULER=false # ── Telemetry (fully optional, off by default) ────────────── TELEMETRY_ENABLED=false