Every variable in .env.example, grouped as the file groups them, with the comment that describes it and its placeholder value.
This page is generated from reference/environment-variables.mdx — do not edit it by hand.
Generated from .env.example at the repository root by apps/web/scripts/docs/generate.ts — do not edit by hand.
Use this page to find what each environment variable configures when you run Spectrace yourself.
.env.example is the source of truth for configuration; this page lists its 48 variables in the same 16 sections. The Required? column is filled only where the source comment says so explicitly — a blank cell means the file does not state it, not that the variable is optional. Values are the placeholders from the file, shown so you can recognise the expected shape.
Chat provider is selectable; embeddings are always OpenAI (pgvector is fixed at 1536 dims), so OPENAI_API_KEY is required regardless of AI_PROVIDER.
sk-...
AI_PROVIDER
AI_PROVIDER selects the chat provider: openai (default) | anthropic | google
openai
ANTHROPIC_API_KEY
Required only for the matching AI_PROVIDER:
sk-ant-...
GOOGLE_GENERATIVE_AI_API_KEY
Required only for the matching AI_PROVIDER:
...
AI_CHAT_MODEL
Model overrides — apply to every provider, OpenAI included. Unset → OpenAI keeps each agent's registry model; other providers use per-provider defaults. Commented out in .env.example.
Register a SEPARATE app per environment: an app has exactly one webhook URL, so a shared app sends production events wherever it was last pointed. Setup guide: https://spectrace.io/docs/integrations/github-app
Variable
Required?
Description
Example / default
GITHUB_APP_ID
The numeric App ID from the app's settings page — NOT GITHUB_CLIENT_ID.
123456
GITHUB_APP_PRIVATE_KEY
The downloaded .pem. Real newlines, \n escapes, or base64 of the whole file all work; a key that cannot be parsed is reported by the diagnostic below rather than failing later as an opaque 401.
The App's own webhook secret. Distinct from GITHUB_WEBHOOK_SECRET below: that one is for the legacy per-repo webhooks the OAuth connect flow installs, and the two coexist while the App migration is in progress.
browser signed in as the platform owner (the user whose email matches STEALTH_OWNER_EMAIL). Reveals no secrets, 404s for everyone else, and is subject to the stealth/beta access gate like any other page. Commented out in .env.example.
Shared secret for the LEGACY per-repo webhook signature verification (issues + PR webhooks). Auto-registered on repos by the GitHub connect flow. The PR webhook route rejects unsigned deliveries with 401 when this is unset; the issues route returns 503 in production and skips verification outside it.
Integration token encryption (AES-256-GCM, applied to OAuth tokens at rest). Linear and Slack fall back to GITHUB_TOKEN_ENCRYPTION_KEY when their own key is unset; Jira does not — set JIRA_TOKEN_ENCRYPTION_KEY for the Jira integration. Rotating a key makes existing stored tokens undecryptable — reconnect the integration after any rotation.
generate-a-long-random-string
JIRA_TOKEN_ENCRYPTION_KEY
(empty)
LINEAR_TOKEN_ENCRYPTION_KEY
(empty)
SLACK_TOKEN_ENCRYPTION_KEY
(empty)
VSCODE_AUTH_CODE_ENCRYPTION_KEY
Optional
Optional. Encrypts the short-lived session stored against a VS Code sign-in code. Left unset it is derived from SUPABASE_SERVICE_ROLE_KEY, so there is nothing to configure — set it only to rotate independently of Supabase.
Launch stage — ONE var drives both the middleware access gate and the stealth/beta tag on the logo. Values: stealth | beta. Unset = public (no gate, no badge). NEXT_PUBLIC_* is inlined at build time, so changing it requires a redeploy.
beta
BETA_ACCESS_CODE
Master access code the gate accepts while stealth/beta is on (either name). Commented out in .env.example.