Configuration
This content is for v0.2.0. Switch to the latest version for up-to-date documentation.
Configuration is read from environment variables (see .env.example). The AI
variables are the ones you will change per provider:
| Variable | Purpose | Default |
|---|---|---|
AI_API_KEY | API key for the AI provider | (required) |
AI_BASE_URL | OpenAI-compatible base URL | https://api.deepseek.com/v1 |
AI_MODEL | Chat model name | deepseek-chat |
AI_PROVIDER | Provider label for telemetry (gen_ai.provider.name); derived from AI_BASE_URL when unset | (derived) |
AI_TIMEOUT | Per-request timeout | 300s |
GITHUB_APP_ID | GitHub App ID | (required) |
GITHUB_PRIVATE_KEY | GitHub App private key (PEM) | (required) |
GITHUB_WEBHOOK_SECRET | Webhook HMAC secret | (required) |
GITHUB_BOT_LOGINS | Comma-separated bot account login(s) the bot skips to avoid replying to itself; override when deployed under a different App slug (<app-slug>[bot]) | thrillhousebot[bot],thrillhouse-bot[bot] |
WEBHOOK_DEDUP_TTL | Webhook deduplication time-to-live for GitHub redeliveries | 24h |
THRILLHOUSEBOT_REVIEW_MANUAL_TRIGGER_ALLOWED_LOGINS | Comma-separated allowlist of logins permitted to trigger manual /review without repo access | (empty) |
MANUAL_TRIGGER_AUTH_TIMEOUT | Upper bound on the manual-trigger write-access check on the webhook ACK thread; fails closed (denies) if GitHub is slower | 5s |
WEBHOOK_SKIP_DRAFTS | Skip auto-review while a PR is a draft (reviewed once marked ready / on later pushes) | false |
WEBHOOK_REQUIRED_LABELS | Comma-separated labels; only auto-review PRs carrying at least one (case-insensitive) | (empty — no gate) |
WEBHOOK_EXCLUDED_LABELS | Comma-separated labels; skip auto-review of PRs carrying any (wins over required) | (empty) |
WEBHOOK_BASE_BRANCHES | Comma-separated globs; only auto-review PRs whose base branch matches one (e.g. main,release/*). Globs are gitignore-style: * does not cross /, so use ** to span slashes (** alone matches every branch) | (empty — all branches) |
WEBHOOK_IGNORED_BASE_BRANCHES | Comma-separated globs; skip auto-review of PRs whose base branch matches one (wins over allowlist; same */** rule — match nested branches with **, e.g. dependabot/**) | (empty) |
REVIEW_CONVERSATIONAL_REPLIES_ENABLED | Answer @thrillhousebot mentions in PR threads (including finding replies) with an AI reply | true |
REVIEW_LABELS_ENABLED | Opt in to context-aware PR labels (see PR labels) | false |
REVIEW_LABELS_APPLY | When labels are enabled, add them to the PR instead of only suggesting them in a comment | false |
REVIEW_LABELS_ALLOW_CREATE | Allow the bot to create suggested labels that don’t exist yet | false |
REVIEW_LABELS_MAX | Maximum labels applied or suggested per PR | 3 |
GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET | OAuth credentials for dashboard login | (required for dashboard) |
DASHBOARD_URL | Public dashboard URL (OAuth callback base) | http://localhost:8080 |
DATASOURCE_DB_KIND | h2 or postgresql | h2 (dev), postgresql (%prod) |
HTTP_CONNECT_TIMEOUT | Outbound HTTP connect timeout (GitHub API, OAuth) | 10s |
HTTP_REQUEST_TIMEOUT | Outbound HTTP request timeout (GitHub API, OAuth) | 10s |
WEBSOCKET_KEEPALIVE_MS | Dashboard WebSocket keepalive interval in ms; 0 or negative disables it (and stale replay-buffer eviction) | 25000 |
The app validates configuration at startup and fails fast if a required value
(GITHUB_APP_ID, GITHUB_PRIVATE_KEY, GITHUB_WEBHOOK_SECRET, AI_API_KEY) is missing or — for
the private key — not a valid PEM RSA key, naming every offending variable in one message instead of
surfacing later on the first webhook or review. Dashboard OAuth (GITHUB_CLIENT_ID /
GITHUB_CLIENT_SECRET) is optional: leave both unset and the dashboard login is simply disabled.
Cost tracking uses per-model pricing keyed by the model name, for example:
thrillhousebot.ai.pricing.deepseek-chat.input-per-1k=0.00014thrillhousebot.ai.pricing.deepseek-chat.output-per-1k=0.00028If you switch to a different AI_MODEL, add a matching
thrillhousebot.ai.pricing.<model>.* pair so the dashboard can compute cost.
PR labels
Section titled “PR labels”ThrillhouseBot can suggest context-aware labels (area, change type, risk) drawn
from the diff. The feature is off by default; turn it on with
REVIEW_LABELS_ENABLED=true.
When enabled, the model is shown the repository’s existing labels and picks the
few that best describe the PR — it only ever chooses from labels that already
exist, so it respects whatever label scheme the repo already uses. What happens
next depends on REVIEW_LABELS_APPLY:
false(default): the suggestions are posted as a one-line comment on the first review, leaving the decision to a maintainer.true: the labels are added to the PR automatically.
Set REVIEW_LABELS_ALLOW_CREATE=true to let the bot create a suggested label
that doesn’t exist yet (off by default, so it never invents labels), and
REVIEW_LABELS_MAX to cap how many labels it applies or suggests (default 3).
Labelling is best-effort — a failure here never blocks or fails the review.