All .env variables: DATABASE_URL, ANTHROPIC_API_KEY, OPENAI_API_KEY, PORT, HEARTBEAT_INTERVAL. Config validation layer, per-environment overrides, and secrets-safe git practices.
Every environment variable Paperclip uses, how the config validation layer works, and best practices for managing secrets safely.
Copy the template to get started:
cp .env.example .env
Never commit .env to git — it's in .gitignore by default. Only commit .env.example with placeholder values.
ANTHROPIC_API_KEY=sk-ant-api03-...
Required if you use the Claude Code adapter (the default). Get your key at console.anthropic.com → API Keys.
OPENAI_API_KEY=sk-proj-...
Only needed if you configure agents with adapter_type: 'openai'.
DATABASE_URL=
Leave blank to use the embedded PGlite dev database (recommended for local development).
Set to a PostgreSQL connection string for staging/production:
DATABASE_URL=postgresql://user:password@localhost:5432/paperclip
Paperclip detects which to use based on whether this value is set.
PORT=3100
NODE_ENV=development
| Variable | Default | Notes |
|---|---|---|
PORT |
3100 |
API server port |
NODE_ENV |
development |
Set to production to disable dev-only endpoints like /api/dev/reset |
HEARTBEAT_INTERVAL_MS=60000
How often (in milliseconds) the scheduler polls for agents whose next_run_at has passed. Default is 60 seconds. Lower this in development to speed up testing:
HEARTBEAT_INTERVAL_MS=5000 # poll every 5 seconds in dev
Warning: Setting this below 5000ms can cause thundering-herd behavior — multiple runs starting before the previous ones complete.
VITE_API_URL=http://localhost:3100
The URL the React frontend uses to call the API. In production, set this to your public API domain:
VITE_API_URL=https://api.yourdomain.com
Vite only exposes variables prefixed with
VITE_to the browser bundle. All other.envvariables stay server-side only.
WEBHOOK_NOTIFICATION_URL=https://hooks.slack.com/services/...
If set, Paperclip POSTs a JSON payload here when an approval gate is created, an agent is auto-paused for budget, or a run fails. Works with Slack incoming webhooks, Discord webhooks, or any HTTP endpoint.
Paperclip validates required environment variables at startup in apps/server/src/config.ts:
const config = {
anthropicApiKey: process.env.ANTHROPIC_API_KEY,
port: parseInt(process.env.PORT ?? '3100'),
nodeEnv: process.env.NODE_ENV ?? 'development',
// ...
};
// Throws at startup if required keys are missing
if (!config.anthropicApiKey) {
throw new Error('ANTHROPIC_API_KEY is required. Set it in your .env file.');
}
This means missing config fails fast at startup rather than silently at runtime during the first heartbeat.
# .env.example — commit this file, never .env
ANTHROPIC_API_KEY= # Required: sk-ant-...
OPENAI_API_KEY= # Optional: sk-...
DATABASE_URL= # Leave blank for PGlite dev mode
PORT=3100
NODE_ENV=development
HEARTBEAT_INTERVAL_MS=60000
VITE_API_URL=http://localhost:3100
WEBHOOK_NOTIFICATION_URL= # Optional: Slack/Discord webhook
Keep all variable names present in .env.example with empty values and a comment — this serves as documentation for anyone setting up the project.
VITE_?ANTHROPIC_API_KEY is missing at startup?