DOCS · REFERENCE
Configuration
Every environment variable specd reads, what it defaults to, and which ones fail closed.
On this page
Configuration lives in a repo-root .env. The API, the migration runner and Next.js each load it themselves — nothing needs sourcing into your shell.
Core
| Variable | Notes |
|---|
DATABASE_URL | Postgres with the vector extension. docker-compose maps host 5433 to avoid clashing with a local Postgres on 5432. |
PORT | API port. Default 4000. |
API_PUBLIC_URL | How the outside world reaches the API — used for webhook URLs and the App registration flow. |
WEB_ORIGIN | Origin of the web app, for CORS and links. |
JWT_SECRET | Session signing. Change it in any non-local environment. |
VAULT_MASTER_KEY | 32-byte master key for the credential vault (envelope encryption). Generate with openssl rand -base64 32. |
AI
| Variable | Notes |
|---|
ANTHROPIC_API_KEY | Optional. Without it the platform still runs; agent runs fail with a clear, honest error. |
SPECD_DEFAULT_MODEL | Platform default. Allowlist: claude-opus-5 · claude-sonnet-5 · claude-haiku-4-5. |
SPECD_AI_MODE | Set to subscription_runner to drive the locally signed-in Claude Code CLI instead of an API key. |
SPECD_USD_TO_EUR | EUR per USD, used to meter run cost from the model's USD rates. |
Knowledge index
| Variable | Notes |
|---|
SPECD_EMBEDDING_PROVIDER | hash (default — deterministic, offline, lexical), voyage, or openai for any OpenAI-compatible /v1/embeddings endpoint. |
VOYAGE_API_KEY | Required by voyage. The API refuses to start without it rather than falling back to hash behind your back. |
SPECD_EMBEDDING_BASE_URL | For openai — e.g. http://localhost:11434/v1 for Ollama. |
SPECD_EMBEDDING_MODEL | Must produce 1024-dimension vectors. mxbai-embed-large fits; nomic-embed-text is 768 and is refused. |
SPECD_EMBEDDING_API_KEY | For endpoints that need one. |
VCS
| Variable | Notes |
|---|
SPECD_LOCAL_REPO_ROOT | Root the local-git adapter may touch. Repos registered via specd connect must live under it. |
GITHUB_APP_ID · GITHUB_APP_SLUG · GITHUB_APP_PRIVATE_KEY | From the App GitHub generated. Real newlines or \n escapes both work. |
GITHUB_WEBHOOK_SECRET | Required for webhooks. Empty rejects every delivery — it never means "skip the signature check". |
GITLAB_WEBHOOK_SECRET | Same rule, same reason. |
GITHUB_API_BASE · GITHUB_BASE · GITHUB_CLONE_BASE | GitHub Enterprise Server only. |
SPECD_BUILD_ROOT | Scratch root for hosted build clones. Each run gets its own directory and deletes it afterwards. Defaults to the system temp dir. |
Workers and retention
| Variable | Default | Notes |
|---|
SPECD_INDEX_WORKER_ENABLED | true | The in-process index worker. |
SPECD_INDEX_POLL_MS | 60000 | A backstop for a dropped LISTEN connection — not how work normally starts. |
SPECD_INDEX_LEASE_SECONDS | 900 | How long a claimed index run is held. |
SPECD_WEBHOOK_RETENTION_DAYS | 30 | Delivery rows are the audit trail for "why did specd do that last week". |
SPECD_WEBHOOK_PRUNE_INTERVAL_MS | 86400000 | Pruned daily and at startup. |
SPECD_RUNNER_LEASE_SECONDS | 180 | Lease for spec/onboard jobs. |
SPECD_RUNNER_LEASE_BUILD_SECONDS | 900 | Builds legitimately take longer to look alive. |
SPECD_RUNNER_MAX_RECLAIMS | 3 | Then failed as repeatedly abandoned, rather than bouncing forever. |
SPECD_RUNNER_POLL_MS | 5000 | Runner daemon poll interval. |