Skip to content

Environment variables

Every setting trimus-server, trimus-worker, and trimus-cli read from the environment — with defaults, meanings, and the component that reads each one. This is the operator's #1 reference; treat it as authoritative.

Where each var is read

Most server config is parsed once by internal/config/config.go at startup (the ~45 vars in the Server config tables below). A second set of vars is read directly by the workers, adapters, crypto vault, health probes, and the CLI — those are noted with their reading component. A handful (embeddings, context-compression enabled + threshold, GEPA evaluator) are also editable at runtime from /admin/operations without a restart.


Master table

Every environment variable Trimus reads, alphabetically. Detail sections follow.

Core server (internal/config/config.go)

Variable Default Read by Meaning
DATABASE_URL required server, worker‑none, CLI Postgres connection string. Server refuses to start if unset.
TRIMUS_HOST "" (all interfaces) server Bind address.
PORT 3100 server HTTP listen port.
LOG_LEVEL info server, worker debug / info / warn / error.
WORKER_POOL_SIZE 5 server In‑process heartbeat worker goroutines.
RATE_LIMIT_RPM 300 server Requests/min per limiter key.
TRIMUS_MAX_REMOTE_WORKERS 10000 server Cap on total remote_workers rows; a fresh registration past it → 503. 0 disables the cap. Idempotent re-registration is exempt (#153).
TRIMUS_REQUIRE_WORKER_APPROVAL false server When true, a worker registered via the public POST /api/workers/register endpoint sits pending with an inert key and no operating prompt until an instance-admin approves it on /admin/workers; its register/heartbeat return 403 until then. Workers created from the /admin/workers Register worker form are approved immediately — the admin's action is the admission decision (#335). false keeps today's auto-onboard. Existing workers backfill to approved (#210 / #148).
TRIMUS_MAX_SSE_CONNS_PER_USER 20 server Cap on concurrent live-event (SSE) subscriptions per actor (API-key id, else user id); over it → 429. Instance admins exempt. 0 disables (#183).
TRIMUS_METRICS_TOKEN "" (unauthenticated) server When set, /metrics requires Authorization: Bearer <token>. Unset keeps the usual unauthenticated Prometheus-scrape behaviour (#147).
TRIMUS_TRUSTED_PROXIES "" (none trusted) server CIDR allowlist; X-Forwarded-For is honoured only from these. Invalid CIDR = boot error (SEC‑014).
SECRET_KEY "" server App secret used on the login submit path.
TRIMUS_PUBLIC_URL http://localhost:<PORT> server URL agents/integrations use to reach the API. Trailing slash trimmed.
TRIMUS_STORAGE_DIR ./storage server Disk root for attachments + assets + logos.
TRIMUS_HOME $HOME/.trimus server, worker Disk root for company/agent/project working dirs.
TRIMUS_ADMIN_EMAIL "" server Seed admin email (first boot only). Also folded into the instance-admin allowlist below.
TRIMUS_ADMIN_PASSWORD "" server Seed admin password (first boot only).
TRIMUS_INSTANCE_ADMINS "" server Comma-separated emails who are instance admins (see all companies). Env-authoritative (#142): the DB users.instance_role column does not grant instance-admin. TRIMUS_ADMIN_EMAIL is included automatically. Changing this requires a restart.
TRIMUS_SESSION_SECRET Removed (#155): no-op. Sessions are opaque random tokens persisted in user_sessions and validated against the DB, so they survive restarts regardless of any secret. Setting this now does nothing; the old "sessions die on restart" warning was incorrect and is gone.
TRIMUS_ENCRYPTION_KEY nil (warns SEC‑010) server, CLI base64 32‑byte AES‑256 KEK. Unset ⇒ encrypted writes refused.
TRIMUS_SECURE_COOKIES false server Secure flag on session/auth cookies. Set true behind HTTPS. When secure, the session cookie also uses the hardened __Host- prefix (#154); reads tolerate the legacy name so no forced re-login.
TRIMUS_CSRF_TRUSTED_ORIGINS "" server Comma‑sep cross‑origin POST allowlist.
TRIMUS_MAX_UPLOAD_SIZE 25000000 (25 MB) server Global multipart upload cap, bytes.
TRIMUS_RUN_EVENTS_RETENTION_DAYS 30 server Retain run‑event rows for succeeded runs (failed kept indefinitely).
TRIMUS_ANTHROPIC_API_VERSION 2023-06-01 server anthropic-version request header.
TRIMUS_MODE local server Deployment posture. local = permissive defaults (current behavior). hosted = enforce production invariants at startup (see Deployment mode & TLS). Unknown value = boot error.
TRIMUS_LICENSE "" server Inline Ed25519-signed license token (#136). Empty ⇒ a built-in 30-day trial, then read-only. Verified offline at boot; a bad/expired/missing license degrades the instance to read-only (data still viewable) but never blocks boot. See Licensing.
TRIMUS_LICENSE_FILE "" server Path to a file containing the license token, used when TRIMUS_LICENSE is unset. A configured-but-unreadable path is a boot error.
TRIMUS_ROLE all server Process role (#134). all = one process serves HTTP and runs every background singleton — identical to the binary/single-process deploy (the default). web = HTTP/API/UI only, no singletons (scale N replicas). scheduler = the singletons only (heartbeat dispatch, backup crons, GEPA, retention, …), no HTTP — run exactly one replica (no leader election yet). Unknown value = boot error. See Kubernetes.
TRIMUS_TLS_CERT "" server PEM cert path for built-in TLS. Must be set together with TRIMUS_TLS_KEY (one without the other = boot error). Unset ⇒ plain HTTP (terminate TLS at a proxy).
TRIMUS_TLS_KEY "" server PEM private-key path for built-in TLS.
TRIMUS_SELFTEST_PUBLIC_URL false server When true, background‑probe <TRIMUS_PUBLIC_URL>/healthz after startup and WARN if unreachable. Non‑blocking, opt‑in.

Default LLM fallback (config.go)

Variable Default Meaning
TRIMUS_DEFAULT_LLM_PROVIDER openai Fallback provider for agents with no adapter_config/provider binding.
TRIMUS_DEFAULT_LLM_MODEL gpt-4o Fallback model id.
TRIMUS_DEFAULT_LLM_API_KEY "" Fallback LLM API key.
TRIMUS_DEFAULT_LLM_BASE_URL https://api.openai.com/v1 Fallback upstream base URL.

OAuth (config.go)

Variable Default Meaning
TRIMUS_OAUTH_GOOGLE_CLIENT_ID "" Google OAuth client id.
TRIMUS_OAUTH_GOOGLE_CLIENT_SECRET "" Google OAuth client secret.
TRIMUS_OAUTH_GITHUB_CLIENT_ID "" GitHub OAuth client id.
TRIMUS_OAUTH_GITHUB_CLIENT_SECRET "" GitHub OAuth client secret.
TRIMUS_OAUTH_REDIRECT_BASE_URL "" (→ TRIMUS_PUBLIC_URL) OAuth redirect base (also the OIDC redirect base).
TRIMUS_OIDC_ISSUER "" Generic OIDC issuer URL (e.g. https://login.example.com). Discovery hits <issuer>/.well-known/openid-configuration at startup. When set with the client id+secret, a "Sign in with …" SSO button appears on the login page.
TRIMUS_OIDC_CLIENT_ID "" OIDC client id.
TRIMUS_OIDC_CLIENT_SECRET "" OIDC client secret. Encryption key required (OIDC tokens are stored encrypted, like other OAuth tokens).
TRIMUS_OIDC_DISPLAY_NAME "SSO" Label for the OIDC login button (e.g. Okta, Company SSO).

Channels (config.go) — see slack.md

Variable Default Meaning
TRIMUS_TELEGRAM_BOT_TOKEN "" Enables Telegram (with company id).
TRIMUS_TELEGRAM_COMPANY_ID "" Company Telegram binds to.
TRIMUS_TELEGRAM_DEFAULT_AGENT_ID "" Default agent for Telegram DMs.
TRIMUS_SLACK_BOT_TOKEN "" Slack bot user token (xoxb-).
TRIMUS_SLACK_APP_TOKEN "" Slack app‑level token (xapp-, Socket Mode).
TRIMUS_SLACK_COMPANY_ID "" Company Slack binds to.
TRIMUS_SLACK_DEFAULT_AGENT_ID "" Default agent for Slack DMs.
TRIMUS_SLACK_USER_ALLOWLIST "" Required when Slack is otherwise configured. CSV user IDs or *. Unset ⇒ boot error.
TRIMUS_SLACK_ENFORCE_ALLOWLIST_ON_MENTIONS false true also enforces TRIMUS_SLACK_USER_ALLOWLIST on channel @-mentions (default: mentions are gated only by the bot's channel membership).

Concierge chat context (config.go)

Variable Default Meaning
CONCIERGE_CONTEXT_NOTES_LIMIT 15 Recent user notes per chat digest (storage clamps >200).
CONCIERGE_CONTEXT_ISSUES_LIMIT 15 Issues per chat digest.

Attachments (config.go) — see attachments.md

Variable Default Meaning
TRIMUS_ATTACHMENT_MAX_UPLOAD_BYTES 50000000 (50 MB) Per‑attachment cap (413 over).
TRIMUS_ATTACHMENT_MAX_FILES_PER_REQUEST 20 Files per multipart create‑issue.
TRIMUS_ATTACHMENT_EXTRACT_TIMEOUT_SEC 5 Per‑attachment text‑extraction timeout.
TRIMUS_ATTACHMENT_EXTRACTED_TEXT_MAX_BYTES 200000 extracted_text column cap per row.
TRIMUS_ATTACHMENT_CONTEXT_CHAR_LIMIT 50000 Char cap on the rendered ## Attachments block.

Self‑evolution (config.go)

Variable Default Meaning
TRIMUS_EVOLUTION_SETTLER_CHAT_QUIET_SEC 900 Quiet window before scoring a chat trace.
TRIMUS_EVOLUTION_SETTLER_HEARTBEAT_QUIET_SEC 3600 Quiet window before scoring a heartbeat trace.
TRIMUS_EVOLUTION_TRACE_RETENTION_DAYS 90 Evolution‑trace retention.

Observability & tracing (read directly)

Variable Default Read by Meaning
OTEL_EXPORTER_OTLP_ENDPOINT "" server (main.go) Enables OTLP/HTTP trace export. Standard OTel vars (OTEL_SERVICE_NAME, …) honoured.

Stale‑run watcher (read in main.go)

Variable Default Meaning
TRIMUS_STALE_RUN_THRESHOLD_SEC 600 Seconds with no activity → mark stale.
TRIMUS_STALE_RUN_GRACE_SEC 300 Additional seconds → grace prompt.
TRIMUS_STALE_RUN_CANCEL_SEC 300 Additional seconds → auto‑cancel.

Model lifecycle (read in main.go) — see #99

Variable Default Meaning
TRIMUS_MODEL_LIFECYCLE_ENABLED false Set true to start the model‑lifecycle worker. It periodically queries each provider's live model catalog and flags agents whose configured model has been retired (after two consecutive misses, so a transient provider‑API blip never false‑positives). Affected agents surface on each company's Model Lifecycle page (/companies/{id}/models) with a one‑click bulk migration. Off by default because it makes scheduled outbound provider‑API calls.
TRIMUS_MODEL_CHECK_INTERVAL_SEC 21600 (6h) Interval between model‑catalog checks when the worker is enabled.

Egress / DNS (read in main.go) — see adapter-isolation.md

Variable Default Meaning
TRIMUS_EGRESS_DNS_ADDR "" (off) When set (e.g. :5353), starts the deny‑by‑default egress DNS resolver. Also propagated to remote workers (#79): if it resolves to an ip:53 address, the docker exec path passes --dns <ip>.
TRIMUS_WORKER_EGRESS_PROXY "" (off) HTTPS/HTTP proxy URL propagated to remote workers (#79). Remote agents run with HTTPS_PROXY/HTTP_PROXY set to this (and NO_PROXY exempting loopback) so their outbound traffic routes through your egress proxy, which enforces the per‑company allowlist and logs connections. Best‑effort routing for cooperative agents — not a hard sandbox (a --dangerously-skip-permissions agent can unset it; for hard containment run workers in a network‑restricted environment).
TRIMUS_EGRESS_DNS_DEFAULT bridge gateway Override the DNS server address published into sandbox containers.

Outbound HTTP proxy (read in internal/httpclient)

Corporate environments (financial services, healthcare, government) commonly require all outbound traffic to traverse a proxy. Every outbound *http.Client in Trimus is now constructed through internal/httpclient, which honours the standard proxy env vars and the Trimus‑specific overrides below. The SSRF‑guarded clients (plugin http_fetch, A2A, webhooks) trust the configured proxy host even when it lives on a private IP, while still blocking direct dials to private/reserved IPs.

Variable Default Read by Meaning
HTTP_PROXY / HTTPS_PROXY / NO_PROXY "" server, worker, CLI Standard Go proxy env. Honoured by all outbound clients. Lowercase variants also read.
TRIMUS_HTTP_PROXY "" (→ HTTP_PROXY) server, worker, CLI Trimus‑specific HTTP proxy override. Wins over HTTP_PROXY so Trimus can use a different proxy than the host OS.
TRIMUS_HTTPS_PROXY "" (→ HTTPS_PROXY) server, worker, CLI Trimus‑specific HTTPS proxy override.
TRIMUS_NO_PROXY "" (→ NO_PROXY) server, worker, CLI Trimus‑specific bypass list. Include the Trimus server host here when workers are co‑located so worker→server traffic stays direct.
TRIMUS_PROXY_AUTH_USER "" server, worker, CLI Username injected into the effective proxy URL when it carries no credentials.
TRIMUS_PROXY_AUTH_PASS "" server, worker, CLI Password paired with TRIMUS_PROXY_AUTH_USER.

Notes:

  • A bare &http.Client{} already honours HTTP_PROXY via Go's DefaultTransport; the TRIMUS_* overrides only take effect because clients route through internal/httpclient.
  • The worker passes its environment (including proxy vars) to the Claude CLI subprocess via cmd.Env = os.Environ(), so the agent's own outbound calls inherit the proxy.
  • AWS Bedrock uses the AWS SDK, which reads HTTPS_PROXY itself — leave it to the SDK rather than double‑configuring.
  • Per‑provider proxy routing (a proxy_url column on company_providers) is a future enhancement and intentionally out of scope here.

Sandbox / adapter hardening (read in adapters)

Variable Default Read by Meaning
TRIMUS_PLUGIN_SANDBOX "" (sandbox on) internal/plugins/sandbox.go disabled bypasses the plugin Docker sandbox (dev only).
TRIMUS_PLUGIN_SANDBOX_SECURITY_OPTS "" plugins Comma‑sep extra --security-opt flags for plugin containers.
TRIMUS_PLUGIN_PIDS_LIMIT 100 plugins --pids-limit for plugin containers.
TRIMUS_DOCKER_PIDS_LIMIT 100 adapters/docker.go --pids-limit default for the docker adapter (per‑agent config wins).
TRIMUS_DOCKER_SECURITY_OPTS "" adapters/docker.go Comma‑sep extra --security-opt for docker/sandbox adapters (seccomp/AppArmor).
TRIMUS_SANDBOX_PIDS_LIMIT 100 adapters/sandbox_wrap.go --pids-limit for claude_sandbox/codex_sandbox.
TRIMUS_MOUNT_ALLOWLIST_ROOT "" (blocklist only) adapters/sandbox_wrap.go Comma‑sep host path prefixes; when set, an agent sandbox bind mount (adapter_config.extra_mounts) must sit under one of them. A blocklist of host‑sensitive paths (Docker/containerd sockets, /, /etc, /root, /proc, /sys, /dev, …) is always enforced regardless of this var (#158).
TRIMUS_FORBID_DANGEROUS_CLAUDE_PERMISSIONS "" (allowed) adapters/safety.go Truthy ⇒ drop the Claude CLI --dangerously-skip-permissions flag (SEC‑015).
TRIMUS_CLAUDE_BINARY_ALLOWLIST "" (any) adapters/safety.go Comma‑sep basenames/abs‑paths the claude binary must match.
TRIMUS_PLUGIN_BINARY_ALLOWLIST "" (any) internal/plugins/sandbox.go Comma-separated basenames/abs-paths the plugin host binary must match before it runs (empty = allow all). Mirrors TRIMUS_CLAUDE_BINARY_ALLOWLIST for plugins (#184).
TRIMUS_CLAUDE_EXTRA_PATH "" adapters/claude_local.go (BuildClaudeEnv) + cmd/worker Colon‑sep directories prepended to the PATH of the spawned claude CLI (and the Bash tool it runs skills with). Use this when the server/worker runs under a minimal‑environment supervisor (#117/#119): launchd/systemd give the service a bare PATH (/usr/bin:/bin:/usr/sbin:/sbin), so skill‑invoked tools in ~/.local/bin, ~/.cargo/bin, /opt/homebrew/bin, etc. (and an apiKeyHelper like forge) aren't found. Leading ~/ and $HOME expand against the service's HOME; dirs already on PATH are skipped. Example: TRIMUS_CLAUDE_EXTRA_PATH=~/.local/bin:/opt/homebrew/bin:~/.cargo/bin.
TRIMUS_HOMES_ROOT "" (any abs path) internal/home Comma‑sep allowed ancestors for a company home_dir.

Subagents (read in engine/handler)

Variable Default Read by Meaning
TRIMUS_MAX_SUBAGENT_RUNS_PER_MINUTE 50 engine/subagent_limits.go Cross‑tenant trailing‑60s subagent run budget. Env-only (not overridable from /admin/operations; takes effect on restart).
TRIMUS_AWAIT_SUBAGENTS_TIMEOUT 60 handler/chat_actions.go Seconds /await-subagents blocks before timing out. Env-only (not overridable from /admin/operations; takes effect on restart).
TRIMUS_MAX_SUBAGENT_DEPTH 3 db/query/agents.go Max depth of the subagent spawn chain (spawn refused past it). Env-only.
TRIMUS_MAX_SUBAGENTS_PER_PARENT 5 db/query/agents.go Max direct children per parent agent. Env-only.
TRIMUS_SUBAGENT_COST_WARN_USD 1.0 handler/ui_subagents.go Per‑run cost yellow‑band on the /admin/subagents dashboard.
TRIMUS_SUBAGENT_COST_CRITICAL_USD 5.0 handler/ui_subagents.go Per‑run cost red‑band on /admin/subagents.

Pricing & cost (read in engine/workers)

Variable Default Read by Meaning
TRIMUS_PRICING_FILE "" (embedded table) engine/pricing.go Path to a JSON model‑pricing override file.
TRIMUS_COST_BUDGET_ALERTER "" (on) worker disable turns off the monthly‑budget DM alerter.
TRIMUS_COST_BUDGET_ALERTER_INTERVAL_HOURS 1 worker Alerter tick cadence (1–24).
TRIMUS_OPS_SPEND_WARN_USD 10.0 handler/ui_operations_spend.go 24 h spend tile yellow‑band threshold on /admin/operations.
TRIMUS_OPS_SPEND_CRITICAL_USD 100.0 handler/ui_operations_spend.go 24 h spend tile red‑band threshold.

Feature toggles (read in workers/engine)

Variable Default Read by Meaning
TRIMUS_EMBEDDING_ENABLED false worker, engine true enables note + company-knowledge embedding and semantic retrieval. Runtime‑editable.
TRIMUS_KNOWLEDGE_GIT_SYNC_ENABLED false worker true enables the scheduled git-sync worker that imports company-knowledge docs from each company's configured repository. Manual "Sync now" works regardless. Runtime‑editable.
TRIMUS_SLACK_INGEST_ENABLED false worker true enables the Slack knowledge-sync worker that ingests admin-selected Slack channels into each company's Knowledge Base (~90-day re-scan) (#266). Runtime-editable. See slack.md.
TRIMUS_COMPILED_KNOWLEDGE_ENABLED false worker, engine true enables Compiled Knowledge (#220): the compile worker distils each company/project/agent's knowledge into typed, cross-linked wiki articles, and the engine injects a compact index of them into every heartbeat prompt. Needs a company LLM provider. Runtime‑editable. See concepts/compiled-knowledge.md.
TRIMUS_CONTEXT_COMPRESSION_ENABLED false worker true enables the context‑compression worker.
TRIMUS_CONTEXT_COMPRESSION_THRESHOLD_TOKENS 50000 worker Token budget above which an agent is a compression candidate. Runtime‑editable.
TRIMUS_GEPA_EVAL_ENABLED false worker true enables the GEPA prompt‑evolution evaluator.
TRIMUS_GEPA_EVAL_LLM_ENABLED false worker true lets GEPA call an LLM to draft prompt revisions (else heuristic).
TRIMUS_EVOLUTION_ENABLED false worker true enables the self-evolution optimizer worker (drafts prompt revisions from scored traces; winning candidates land in each agent's proposals queue for approval). Runtime-editable.
TRIMUS_LOCAL_ADAPTERS "" server (main.go) Reserved — logged only; enforcement deferred. See local-adapter-deprecation.md.

Heartbeat‑run retention (read in worker)

Variable Default Meaning
TRIMUS_HEARTBEAT_RUN_RETENTION "" (on) disable skips the terminal‑run retention worker.
TRIMUS_HEARTBEAT_RUN_RETENTION_DAYS 90 Retain terminal heartbeat_runs rows this long (clamped 1–3650).
TRIMUS_HEARTBEAT_RUN_RETENTION_INTERVAL_HOURS 24 Sweep cadence (clamped 1–168).

Readiness probe thresholds (read in handler/health.go) — see monitoring.md

Variable Default Meaning
TRIMUS_READYZ_WORKER_ERROR_RATE_PCT 50.0 Worker error‑rate above which /readyz flips not‑ready.
TRIMUS_READYZ_POOL_UTILIZATION_PCT 90.0 DB pool utilisation escalation threshold.
TRIMUS_READYZ_CHANNEL_STALENESS_SEC 60 Channel staleness before channel:<name> is not‑ready.
TRIMUS_READYZ_DISK_PCT 90.0 Root‑fs usage escalation threshold.
TRIMUS_READYZ_CHECK_P99_MS 1000 Per‑check p99 latency escalation (clamped 1–60000).
TRIMUS_READYZ_BACKUP_MAX_AGE_HOURS 36 Backup‑freshness staleness threshold on /readyz.

Backups (read in CLI + workers) — see backup-and-restore.md

Variable Default Meaning
TRIMUS_BACKUP_DIR /var/backups/trimus Local backup directory.
TRIMUS_BACKUP_RETENTION_DAYS 30 Local prune horizon; 0 disables pruning.
TRIMUS_BACKUP_CRON "" (on) disable turns off the daily backup cron.
TRIMUS_BACKUP_CRON_INTERVAL_HOURS 24 Backup cron cadence.
TRIMUS_BACKUP_VERIFY_INTERVAL_HOURS 24 Verify‑cron cadence.
TRIMUS_BACKUP_RECONCILE "" (on) disable turns off on‑disk↔audit reconciliation.
TRIMUS_BACKUP_RECONCILE_INTERVAL_HOURS 6 Reconcile cadence.
TRIMUS_BACKUP_HEALTH_CHECK "" (on) disable turns off the composite backup‑health worker.
TRIMUS_BACKUP_HEALTH_INTERVAL_HOURS 1 Health‑check cadence.
TRIMUS_BACKUP_NO_VERIFY "" Truthy skips the inline verify after a CLI backup.
TRIMUS_BACKUP_S3_BUCKET "" (S3 off) Enables S3 upload when set.
TRIMUS_BACKUP_S3_PREFIX trimus-backups/ S3 key prefix.
TRIMUS_BACKUP_S3_REGION us-east-1 S3 region.
TRIMUS_BACKUP_S3_ENDPOINT "" Custom S3 endpoint (MinIO, R2, …).
TRIMUS_BACKUP_S3_PATH_STYLE "" true forces path‑style addressing.

Login lockout (read in db/query/login_attempts.go)

Variable Default Meaning
TRIMUS_LOGIN_LOCKOUT_THRESHOLD (see security.md) Consecutive failures before lockout.
TRIMUS_LOGIN_LOCKOUT_WINDOW 15m Sliding failure window.
TRIMUS_LOGIN_LOCKOUT_DURATION 30m Lockout duration once tripped.

Remote worker (cmd/worker) — see remote-workers.md

Variable Default Meaning
TRIMUS_SERVER_URL required URL of the trimus-server the worker claims tasks from.
TRIMUS_WORKER_KEY required Worker bearer key from /api/workers/register.
TRIMUS_WORKER_NAME hostname Worker display name.
TRIMUS_WORKER_TAGS "" CSV capability tags sent at first registration. Server-authoritative thereafter — retag on /admin/workers; changing this var later has no effect (#336).
TRIMUS_WORKER_CONCURRENCY 2 Parallel task slots.
TRIMUS_WORKER_POLL_SEC 5 Claim‑loop poll interval.
TRIMUS_WORKER_LLM_ALLOWED_HOSTS "" CSV of extra hostnames the worker may send its own environment LLM API key to when dialing that base_url (api.openai.com and api.anthropic.com are always allowed; #170).

CLI & chat REPL (cmd/trimus-cli)

Variable Default Meaning
TRIMUS_QUIET "" 1 suppresses non‑essential CLI output.
TRIMUS_API_KEY "" Bearer key for trimus-cli chat.
TRIMUS_BASE_URL "" API base for trimus-cli chat.
TRIMUS_CHAT_HISTORY / TRIMUS_NO_HISTORY REPL history file / disable.
NO_COLOR / TRIMUS_CHAT_NO_COLOR Disable ANSI colour in the REPL.

Provider CLI credentials inside local adapters

The claude_local / codex_local adapters inherit the host environment, so the upstream CLIs may also consult their own vars (ANTHROPIC_API_KEY, ANTHROPIC_BASE_URL, OPENAI_API_KEY, OPENAI_BASE_URL, CODEX_HOME, AWS_REGION/AWS_DEFAULT_REGION). These are the CLIs' own contracts, not Trimus config — set them on the service only when you mean to.


The vars you must get right

DATABASE_URL (required)

Postgres connection string. Server refuses to start if unset.

postgres://<user>:<password>@<host>:<port>/<db>?sslmode=disable

Use sslmode=require (or verify-full with a CA bundle) in production. Postgres 16+ with the pgvector extension is expected (semantic note search uses it). See database.md.

TRIMUS_ENCRYPTION_KEY (load‑bearing)

Base64‑encoded 32‑byte AES‑256 Key Encryption Key (KEK). Generate:

openssl rand -base64 32

Unset ⇒ encrypted writes are REFUSED (not plaintext)

Without this key the KEK/DEK vault is not initialised. The server still boots and read‑only paths work, but every encrypted‑write endpoint returns 503 — company secrets, provider API keys, OAuth tokens, and signed‑trigger secrets cannot be created or rotated (finding SEC‑010). The warning is surfaced on stderr, a structured WARN log, and a UI banner on the secrets form. There is no "store in plaintext" mode.

Validated at startup: must be valid base64 decoding to exactly 32 bytes, or the server exits with a clear error. See secrets-and-encryption.md and key-rotation.md.

TRIMUS_SESSION_SECRET

Signs user session cookies. Unset ⇒ a random key is generated at startup and every restart invalidates all sessions (logged WARN). Set it long, random, and durable:

TRIMUS_SESSION_SECRET="$(openssl rand -base64 64)"

TRIMUS_PUBLIC_URL

The URL agents and integrations use to reach the API (skill callbacks, OAuth redirects, webhook payload links). Default http://localhost:<PORT>; trailing slash is trimmed. Set this whenever Trimus sits behind a reverse proxy or has a public hostname.

TRIMUS_TRUSTED_PROXIES (SEC‑014)

CIDR allowlist. X-Forwarded-For is honoured only when the direct caller IP falls inside one of these ranges — otherwise the spoofable header is ignored and the rate limiter keys on the socket peer. Empty (the default) is the secure posture for a fresh install not yet behind a proxy. An invalid CIDR is a boot error (fail loud, never silently re‑open the bypass).

TRIMUS_TRUSTED_PROXIES=10.0.0.0/8,172.16.0.0/12

Server / runtime

PORT (default 3100), TRIMUS_HOST (default all interfaces), LOG_LEVEL (info).

WORKER_POOL_SIZE (default 5) — concurrent heartbeat‑running goroutines inside trimus-server. Raise if agents queue; lower under memory pressure.

RATE_LIMIT_RPM (default 300) — per‑limiter requests/minute, applied to public, SSE, and API groups. See security.md.

TRIMUS_MAX_UPLOAD_SIZE (default 25_000_000, 25 MB) — global multipart cap. The 1 MB JSON body cap on most API/UI routes and the per‑attachment cap (TRIMUS_ATTACHMENT_MAX_UPLOAD_BYTES) are separate.

TRIMUS_RUN_EVENTS_RETENTION_DAYS (default 30) — retain streaming‑event rows for succeeded runs. Failed‑run events are kept indefinitely. Invalid values revert to default with a WARN.

Storage

TRIMUS_HOME (default $HOME/.trimus) — company/agent/project working dirs. Move to /var/lib/trimus on multi‑user hosts. TRIMUS_STORAGE_DIR (default ./storage) — uploaded attachments, assets, and per‑company logos; use an absolute path in production. See storage.md.

Default LLM fallback

Used only by agents with no provider binding and no adapter_config provider — mostly the seed/test path. In production, configure providers explicitly (see providers.md). TRIMUS_DEFAULT_LLM_PROVIDER (openai), TRIMUS_DEFAULT_LLM_MODEL (gpt-4o), TRIMUS_DEFAULT_LLM_API_KEY (none), TRIMUS_DEFAULT_LLM_BASE_URL (https://api.openai.com/v1). TRIMUS_ANTHROPIC_API_VERSION (2023-06-01) sets the anthropic-version header on every Anthropic call.

Auth / security

TRIMUS_ADMIN_EMAIL / TRIMUS_ADMIN_PASSWORD seed a single admin at first boot only (ignored once any user exists). TRIMUS_SECURE_COOKIEStrue behind HTTPS. TRIMUS_CSRF_TRUSTED_ORIGINS is the cross‑origin POST allowlist. SECRET_KEY is the login‑submit secret. OAuth: setting both client‑id and client‑secret for a provider enables its login button; redirect base defaults to TRIMUS_PUBLIC_URL. Full setup in security.md.

Login lockout (SEC‑013)

Per‑(email, IP) sliding‑window lockout, read directly by db/query/login_attempts.go: TRIMUS_LOGIN_LOCKOUT_THRESHOLD (consecutive failures), TRIMUS_LOGIN_LOCKOUT_WINDOW (default 15 min), TRIMUS_LOGIN_LOCKOUT_DURATION (default 30 min). Recover a locked account with trimus-cli unlock-user <email>. Client IP is keyed via the TRIMUS_TRUSTED_PROXIES logic above.

Channel adapters

Off by default; each starts at boot once its var set is configured.

TelegramTRIMUS_TELEGRAM_BOT_TOKEN + TRIMUS_TELEGRAM_COMPANY_ID (optionally …_DEFAULT_AGENT_ID). No allowlist — anyone who finds the bot can DM it. One bot → one company → one default agent.

Slack — see slack.md. Requires TRIMUS_SLACK_BOT_TOKEN + TRIMUS_SLACK_APP_TOKEN + TRIMUS_SLACK_COMPANY_ID and TRIMUS_SLACK_USER_ALLOWLIST.

Slack will not start without an allowlist

TRIMUS_SLACK_USER_ALLOWLIST (CSV of U… user IDs, or * for the whole workspace) is required when Slack is otherwise configured. The dispatcher refuses to construct without it, so you cannot accidentally deploy a no‑policy bot into a workspace containing contractors.

Concierge chat context

CONCIERGE_CONTEXT_NOTES_LIMIT / CONCIERGE_CONTEXT_ISSUES_LIMIT (both default 15) size the per‑message digest the Concierge prepends to each chat turn. Larger = more context, more tokens. Values ≤ 0 revert to default; the notes query hard‑caps at 200 internally.

Subagent guardrails

TRIMUS_MAX_SUBAGENT_RUNS_PER_MINUTE (default 50) — cross‑tenant trailing‑60‑second budget for subagent heartbeat runs; a typo (≤ 0 / non‑numeric) reverts to default rather than disabling the guard. TRIMUS_AWAIT_SUBAGENTS_TIMEOUT (default 60 s) — how long /await-subagents blocks. Both are re‑read per call from the process environment — the Operations page marks them env-only (no instance_flags override is consulted), so a new value takes effect only on restart with a new env.

Issue attachments

See attachments.md for the full pipeline. Caps: TRIMUS_ATTACHMENT_MAX_UPLOAD_BYTES (50 MB), TRIMUS_ATTACHMENT_MAX_FILES_PER_REQUEST (20), TRIMUS_ATTACHMENT_EXTRACT_TIMEOUT_SEC (5), TRIMUS_ATTACHMENT_EXTRACTED_TEXT_MAX_BYTES (200 KB), TRIMUS_ATTACHMENT_CONTEXT_CHAR_LIMIT (50 KB ≈ 12k tokens).

Adapter & sandbox hardening

See adapter-isolation.md. The docker, claude_sandbox, and codex_sandbox adapters honour TRIMUS_DOCKER_PIDS_LIMIT / TRIMUS_SANDBOX_PIDS_LIMIT (100), TRIMUS_DOCKER_SECURITY_OPTS (comma‑sep --security-opt). Plugin containers honour TRIMUS_PLUGIN_PIDS_LIMIT (100), TRIMUS_PLUGIN_SANDBOX_SECURITY_OPTS, and TRIMUS_PLUGIN_SANDBOX=disabled (dev opt‑out). The Claude CLI guardrails TRIMUS_FORBID_DANGEROUS_CLAUDE_PERMISSIONS and TRIMUS_CLAUDE_BINARY_ALLOWLIST default permissive and can be tightened per instance.

Egress DNS

When TRIMUS_EGRESS_DNS_ADDR is set, the deny‑by‑default DNS resolver starts: sandboxed containers resolve only allow‑listed hostnames, everything else gets NXDOMAIN. TRIMUS_EGRESS_DNS_DEFAULT overrides the resolver address published into containers (default: the bridge gateway). See adapter-isolation.md.

Observability

OTEL_EXPORTER_OTLP_ENDPOINT enables OTLP/HTTP trace export; the standard OTel env vars are honoured. See monitoring.md.

Stale‑run watcher

Two‑stage stale → grace → cancel pipeline (defaults total 20 min):

Variable Default Meaning
TRIMUS_STALE_RUN_THRESHOLD_SEC 600 No activity → stale.
TRIMUS_STALE_RUN_GRACE_SEC 300 → grace prompt.
TRIMUS_STALE_RUN_CANCEL_SEC 300 → auto‑cancel (error=auto_cancel_stale).

Per‑agent / per‑company column overrides (migration 088) take precedence: agent → company → env default; NULL inherits upward. The poll cadence (30 s) is code‑tunable only. Activity kinds emitted: run.stale_detected, run.grace_prompt_sent, run.auto_cancelled.

Reading them all at once

trimus-server logs the resolved configuration at INFO on startup with secret values redacted (internal/middleware/redact.go). When debugging "is this var being picked up?", grep the startup log. Live‑editable flags and their effective values are also shown at /admin/operations.

A minimum production environment

DATABASE_URL='postgres://trimus:STRONGPW@db.internal:5432/trimus?sslmode=require'
TRIMUS_ENCRYPTION_KEY='<base64 32-byte>'
TRIMUS_SESSION_SECRET='<long random string>'
TRIMUS_PUBLIC_URL='https://trimus.example.com'
TRIMUS_HOME=/var/lib/trimus/home
TRIMUS_STORAGE_DIR=/var/lib/trimus/storage
TRIMUS_SECURE_COOKIES=true
TRIMUS_CSRF_TRUSTED_ORIGINS=https://trimus.example.com
TRIMUS_TRUSTED_PROXIES=10.0.0.0/8
LOG_LEVEL=info

That plus a reachable Postgres is enough for a real deployment. Layer OAuth, OTel, backups, and channels on as separate concerns.

Where to next