.env.example

Discord

DISCORD_TOKEN= CLIENT_ID= GUILD_ID=

LLM providers (set one or more)

OPENAI_API_KEY= GOOGLE_API_KEY= ANTHROPIC_API_KEY= CLAUDE_OAUTH_REFRESH_TOKEN= OPENAI_OAUTH_REFRESH_TOKEN= XAI_API_KEY= ELEVENLABS_API_KEY= XAI_BASE_URL=https://api.x.ai/v1

Local Ollama (optional, used as embedding fallback when OpenAI is unavailable)

OLLAMA_BASE_URL=http://127.0.0.1:11434

Web Search providers (optional, needed for live web search)

BRAVE_SEARCH_API_KEY= SERPAPI_API_KEY=

GIPHY GIF Search (optional, needed for model-directed GIF replies)

GIPHY_API_KEY= GIPHY_RATING=pg-13

Music Search/Playback Providers

YOUTUBE_API_KEY= SOUNDCLOUD_CLIENT_ID=

Dashboard

DASHBOARD_PORT=8787

Bind address for dashboard/API server (default loopback-only)

DASHBOARD_HOST=127.0.0.1

Required for private dashboard/admin APIs when PUBLIC_HTTPS_ENABLED=true

DASHBOARD_TOKEN=

Separate token for public allowlisted API routes (e.g. stream ingest over tunnel)

PUBLIC_API_TOKEN=

Optional: auto-create a public HTTPS URL that forwards to localhost dashboard

PUBLIC_HTTPS_ENABLED=false PUBLIC_HTTPS_PROVIDER=cloudflared

Optional override target. Default is http://127.0.0.1:${DASHBOARD_PORT}

PUBLIC_HTTPS_TARGET_URL=

Optional cloudflared binary/path override

PUBLIC_HTTPS_CLOUDFLARED_BIN=cloudflared

Optional screen-share link TTL minutes (2..30)

PUBLIC_SHARE_SESSION_TTL_MINUTES=12

Optional native-only mode for screen watch. Set false to disable the share-link fallback entirely.

STREAM_LINK_FALLBACK=true

Optional defaults

DEFAULT_PROVIDER=openai DEFAULT_MODEL_OPENAI=gpt-5.4-mini DEFAULT_MODEL_ANTHROPIC=claude-haiku-4-5 DEFAULT_MODEL_XAI=grok-3-mini-latest DEFAULT_MODEL_CLAUDE_OAUTH=claude-sonnet-4-6 DEFAULT_MODEL_OPENAI_OAUTH=gpt-5.4 DEFAULT_MODEL_CODEX_CLI=gpt-5.4

Claude Code (local) — uses your Claude Code subscription, no API key needed

DEFAULT_MODEL_CLAUDE_CODE=sonnet DEFAULT_MEMORY_EMBEDDING_MODEL=text-embedding-3-small

Voice golden live smoke (optional)

RUN_LIVE_VOICE_GOLDEN=0 LIVE_VOICE_GOLDEN_BRAIN_ONLY=0 LIVE_VOICE_GOLDEN_MODES=voice_agent,openai_realtime,gemini_realtime,elevenlabs_realtime LIVE_VOICE_GOLDEN_NO_JUDGE=1 LIVE_VOICE_GOLDEN_MAX_CASES=3

Instance identity (distinguishes multiple bot instances in Loki/Grafana)

Set a unique value per instance, e.g. "clanky", "clanky-2", "prodbot"

CLANKER_INSTANCE_ID=default

Structured runtime logs for debugging/Loki ingestion

RUNTIME_STRUCTURED_LOGS_ENABLED=true RUNTIME_STRUCTURED_LOGS_STDOUT=true RUNTIME_STRUCTURED_LOGS_FILE_PATH=data/logs/runtime-actions.ndjson

E2E Testing (bot-to-bot Discord integration tests)

All E2E_ vars can be omitted if system bot is already configured via top-level vars

E2E_SYSTEM_BOT_TOKEN=your_system_bot_token_here (falls back to DISCORD_TOKEN)

E2E_SYSTEM_BOT_USER_ID=123456789012345678 (falls back to CLIENT_ID)

E2E_DRIVER_BOT_TOKEN=your_driver_bot_token_here (required - separate test bot)

E2E_DRIVER_BOT_2_TOKEN=your_second_driver_bot_token_here (required for dialogue tests)

E2E_TEST_GUILD_ID=123456789012345678

E2E_TEST_VOICE_CHANNEL_ID=123456789012345678

E2E_TEST_TEXT_CHANNEL_ID=123456789012345678 (optional)