Configuration¶
All settings come from environment variables (loaded from .env by Bun; a
shell variable overrides the file). See .env.example for the annotated list.
Required¶
| Variable | Purpose |
|---|---|
DATABASE_URL |
Postgres connection string (matches docker-compose.yml) |
ENCRYPTION_KEY |
32+ random characters; derives the AES-256-GCM key that seals OAuth tokens. Rotating it invalidates every stored token. |
Models (bring your own key)¶
Spaces ships without model access: you bring the keys of the providers you pay for and usage is billed to those accounts.
| Provider | Get a key | Notes |
|---|---|---|
| Anthropic | console.anthropic.com → API keys | Claude models directly (sk-ant-…) |
| OpenAI | platform.openai.com → API keys | GPT models directly; also serves knowledge-base embeddings (sk-…) |
| OpenRouter | openrouter.ai → Keys | One key for every vendor; OpenRouter routes each request itself (sk-or-…) |
LLM provider keys are entered under
Organization → Models, stored encrypted with ENCRYPTION_KEY and verified
when saved; they are not environment variables. No model is configured by
name either. Spaces routes automatically for the provider in use: it scores that provider's chat models by price, generation and size
class and fills three tiers — small (review, chat, fast mode), medium
(planning and implementation) and large (quality mode, retry escalation).
The organization policy under Organization → Models tunes it: preference
(cost / balanced / quality), provider order, whether premium ("pro") models
may be used, and optional pins per tier. With OpenRouter first in the order
every tier is openrouter/openrouter/auto and OpenRouter routes each request
itself. Templates that still pin a model from a provider without a key fall
back to the same-size tier.
| Variable | Default | Purpose |
|---|---|---|
EMBEDDING_MODEL |
openai/text-embedding-3-small |
Embedding model for the organization knowledge base; served by OPENAI_API_KEY, or through OpenRouter (OPENROUTER_API_KEY) for openai/* and openrouter/<vendor>/<model> ids. Without a usable key, knowledge search is full-text only. |
EMBEDDING_DIMENSIONS |
1536 |
Size of the vector column; must match the model's output |
Optional¶
| Variable | Default | Purpose |
|---|---|---|
PORT |
3000 |
Web UI + API port |
PUBLIC_URL |
unset | Public origin behind a TLS-terminating proxy, for OAuth callbacks, GitHub App manifests and invite links; the forwarded headers are honoured when unset |
WORKER_ID |
random UUID | Worker identity (per process) |
WORKER_MAX_CONCURRENT_JOBS |
4 |
Jobs one worker runs at once across projects |
SUPERVISOR_MAX_WORKERS |
4 |
Cap on per-project workers (each ~300–500 MB) |
WORKER_IDLE_EXIT_SECONDS |
300 |
Idle time before a per-project worker exits |
AIDLC_WORKSPACE_ROOT |
~/.aidlc/workspaces |
Where GitHub repos are cloned (<owner>/<name>) |
SPACES_BROWSER_PATH |
Playwright's bundled Chromium, else a system Chromium/Chrome | Override the Chromium binary for the agents' built-in browser tools |
PLAYWRIGHT_BROWSERS_PATH |
Playwright default (~/.cache/ms-playwright) |
Where playwright install chromium puts browsers; the Docker image uses /ms-playwright |
AIDLC_GOVERNANCE_WORKSPACE |
1 |
0 keeps specs inside the application repo instead of a governing workspace |
AIDLC_GOVERNANCE_ROOT |
<workspace root>/_governance |
Location of governing workspaces |
AIDLC_WORKTREE_ROOT |
<repo>/.aidlc-worktrees |
Where workstream worktrees are created |
AGENT_DATABASE_URL |
the application's database server | Server on which each checkout's test database (agent_<checkout>) is created |
AGENT_COMMAND_TIMEOUT_SECONDS |
1200 |
Longest any shell command an agent runs may take (minimum 60) |
RAILWAY_DEPLOYMENT_DRAINING_SECONDS |
Railway default | How long a deploy lets a running stage finish before the old container stops (set it to about 900) |
The package-manager caches agents use (bun, npm, yarn, pnpm, pip, Go) live in
<workspace root>/../cache, on the same volume as the workspaces, unless a
project sets its own.
Running the test suite¶
bun test runs a preload (tests/setup/db-guard.ts) that keeps the suite off
databases that are not test databases:
| Variable | Purpose |
|---|---|
TEST_DATABASE_URL |
Used as the suite's database when set |
DATABASE_URL |
Used only when it is local, or its database is named for tests (test, agent, ci) |
ALLOW_TEST_DATABASE |
1 accepts any DATABASE_URL (only for a disposable database) |
Anything else (a deployed application's database, such as Railway's railway)
makes the database suites skip with a message instead of writing to it.
Authentication and teams¶
| Variable | Default | Purpose |
|---|---|---|
AUTH_DISABLED |
unset | 1 turns sign-in off (single-user local use); every route is open |
OPEN_REGISTRATION |
unset | 1 lets anyone register; otherwise only the first user, invitees and people let in from the waitlist can, and the landing page offers the waitlist |
DEFAULT_TEAM_NAME |
Default team |
Name of the team created for the first user |
DEFAULT_ORG_NAME |
Organization |
Name of the organization created for the first user |
GITHUB_SIGNIN_CLIENT_ID |
unset | Client id of the GitHub OAuth app used for "Continue with GitHub" |
GITHUB_SIGNIN_CLIENT_SECRET |
unset | Its client secret; both are needed or the button is not offered |
Sessions are HttpOnly cookies (30 days; Secure when served over HTTPS).
Signing in identifies a person to the whole deployment, so it uses its own
GitHub OAuth app from the two variables above, never an organization's
integration credentials. Register the app on GitHub with the callback
<your origin>/api/oauth/github/callback.
Integrations (OAuth)¶
Not configured through the environment. A team owner or admin sets each
provider app up under Organization → Integrations; credentials are
stored encrypted with ENCRYPTION_KEY. GitHub is created for you as a GitHub
App (manifest flow) and Slack from a prefilled manifest; Atlassian and Linear
are registered by hand with callback
http://<host>:<port>/api/oauth/<provider>/callback and these scopes (the
card shows them ready to copy). The GitHub scopes below only apply when a
classic OAuth App is pasted in; a GitHub App carries its permissions itself.
| Provider | Scopes |
|---|---|
| GitHub | repo, read:org, read:user |
| Atlassian (Jira + Confluence) | read:jira-user, read:jira-work, write:jira-work, read:confluence-content.all, read:confluence-content.summary, read:confluence-space.summary, search:confluence, write:confluence-content, offline_access — enable the same scopes on the app's Permissions page, and reconnect after adding any |
| Linear | read, write |
| Slack | channels:read, chat:write, users:read |
Per-project settings (UI)¶
- Orchestrator (overview): autonomous mode (auto-approve gates), max concurrent runs, speed mode (fast / balanced / quality).
- Knowledge scope (Context tab): which integrations and repositories the project's agents may query, with Jira project keys, Linear teams/projects, Confluence spaces and GitHub repos.
- Repositories (overview): add, edit, make primary, relearn, retry clone.
Files agents write¶
| File | Written by | Purpose |
|---|---|---|
.aidlc/dev-setup.md |
dev-environment setup | Install/build/test/lint commands, test baseline, blockers (local-only) |
specs/<feature>/code-review.md |
review |
Review status and findings |
specs/<feature>/delivery-status.md |
before deliver/review |
PR, CI, merge, deploy state from GitHub |
specs/<feature>/delivery-report.md |
deliver |
Delivery status, UAT results, pending approvals |