Configuration#
claude-review is configured with a single TOML file, passed via the --config flag (default: config.toml). Secrets can be overridden with environment variables.
Complete Annotated Example#
# -----------------------------------------------------------------------
# Server
# -----------------------------------------------------------------------
[server]
listen = "0.0.0.0:3000" # Bind address (default: "0.0.0.0:3000")
webhook_path = "/webhook" # Webhook route (default: "/webhook")
# -----------------------------------------------------------------------
# GitHub App
# -----------------------------------------------------------------------
[github]
app_id = 123456 # GitHub App ID (required)
private_key_path = "key.pem" # Path to PEM private key (required unless GITHUB_APP_PRIVATE_KEY is set)
# api_base_url = "https://api.github.com" # Override for GHES
# webhook_secret = "..." # Prefer GITHUB_WEBHOOK_SECRET env var
# -----------------------------------------------------------------------
# LLM
# -----------------------------------------------------------------------
[llm]
provider = "claude" # "claude", "anthropic", or "openai"
model = "claude-sonnet-4-6"
# api_key = "..." # Prefer env var (ANTHROPIC_API_KEY, OPENAI_API_KEY, or LLM_API_KEY)
# base_url = "https://api.anthropic.com" # Override for proxies / self-hosted
max_tokens = 4096 # Max output tokens (default: 4096)
# temperature = 0.2 # Sampling temperature (optional; ignored when extended thinking is on)
[llm.anthropic] # Anthropic-specific options (ignored for openai provider)
api_version = "2023-06-01" # Anthropic API version header (default: "2023-06-01")
# betas = ["prompt-caching-2024-07-31"] # Beta feature flags
prompt_caching = false # Enable prompt caching (default: false)
extended_thinking = false # Enable extended thinking (default: false)
# thinking_budget = 10000 # Token budget for thinking (default: 10000 when thinking is enabled)
# custom_headers = { "x-custom" = "value" } # Extra headers sent with every request
# -----------------------------------------------------------------------
# Proxy (optional)
# -----------------------------------------------------------------------
# [proxy]
# http = "http://proxy:8080"
# https = "http://proxy:8080"
# socks5 = "socks5://proxy:1080"
# no_proxy = ["localhost", "127.0.0.1", "*.internal"]
# -----------------------------------------------------------------------
# Mention Trigger (@bot review)
# -----------------------------------------------------------------------
[mention_trigger]
enabled = false # Set to true to enable @mention triggers (default: false)
bot_name = "claude-review" # Bot username to listen for (default: "claude-review")
ignore_bots = true # Ignore comments from bot accounts (default: true)
# -----------------------------------------------------------------------
# Rate Limiting
# -----------------------------------------------------------------------
[rate_limit]
requests_per_hour = 60 # Token refill rate per repo (default: 60)
burst = 5 # Max burst capacity (default: 5)
bypass_users = ["ci-bot"] # Users exempt from rate limits
# -----------------------------------------------------------------------
# Whitelists (all empty = allow everything)
# -----------------------------------------------------------------------
[whitelist]
organizations = [] # Allowed GitHub orgs (empty = all)
users = [] # Allowed users (empty = all)
repositories = [] # Allowed repos as "owner/repo" (empty = all)
# -----------------------------------------------------------------------
# Sandbox
# -----------------------------------------------------------------------
[sandbox]
enabled = true # Enable OS-level sandbox (default: true)
allowed_read_paths = [] # Extra paths mounted read-only in sandbox
allowed_write_paths = [] # Extra paths mounted read-write in sandbox
network_policy = "none" # "none", "limited", or "full" (default: "none")
timeout_seconds = 300 # Process timeout in seconds (default: 300)
# -----------------------------------------------------------------------
# MCP Servers (optional)
# -----------------------------------------------------------------------
# [[mcp.servers]]
# name = "filesystem"
# type = "stdio"
# command = "npx"
# args = ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
# enabled = true
# [mcp.servers.env]
# NODE_ENV = "production"
# -----------------------------------------------------------------------
# Anti-injection
# -----------------------------------------------------------------------
[anti_injection]
max_title_length = 500 # Truncate PR titles beyond this length (default: 500)
max_description_length = 10000 # Truncate PR descriptions (default: 10000)
max_diff_length = 500000 # Truncate diffs (default: 500000)
max_comment_length = 5000 # Truncate individual comments (default: 5000)
suspicious_patterns = [] # Additional regex patterns to flag as suspicious
# -----------------------------------------------------------------------
# Rules (optional, repeatable)
# -----------------------------------------------------------------------
# [[rules]]
# name = "skip-generated"
# condition = 'file.path matches ".*\\.gen\\..*"'
# priority = 10
# [[rules.actions]]
# type = "skip_file"
Section Reference#
[server]#
| listen | string | "0.0.0.0:3000" | Socket address to bind |
| webhook_path | string | "/webhook" | HTTP path for GitHub webhook delivery |
[github]#
| app_id | integer | – | – | GitHub App ID (required) |
| private_key_path | path | – | GITHUB_APP_PRIVATE_KEY (base64) | Path to the PEM private key file |
| api_base_url | string | "https://api.github.com" | – | API base URL (set for GitHub Enterprise Server) |
| webhook_secret | string | – | GITHUB_WEBHOOK_SECRET | HMAC-SHA256 webhook secret |
[llm]#
| provider | string | – | – | "claude", "anthropic", or "openai" (required) |
| model | string | – | – | Model identifier (required) |
| api_key | string | – | ANTHROPIC_API_KEY, OPENAI_API_KEY, LLM_API_KEY | API key |
| base_url | string | provider default | – | API base URL |
| max_tokens | integer | 4096 | – | Maximum output tokens |
| temperature | float | – | – | Sampling temperature (omit for provider default) |
[llm.anthropic]#
| api_version | string | "2023-06-01" | anthropic-version header value |
| betas | string[] | [] | Beta feature flags for anthropic-beta header |
| prompt_caching | bool | false | Enable prompt caching |
| extended_thinking | bool | false | Enable extended thinking |
| thinking_budget | integer | 10000 | Token budget for thinking (only when extended thinking is enabled) |
| custom_headers | map | {} | Extra HTTP headers on every request |
[proxy]#
| http | string | – | HTTP proxy URL |
| https | string | – | HTTPS proxy URL |
| socks5 | string | – | SOCKS5 proxy URL |
| no_proxy | string[] | [] | Hostnames/patterns excluded from proxying (sets NO_PROXY) |
[mention_trigger]#
When enabled, users can comment @<bot_name> review on a pull request to trigger a review on demand. The same rate limits, whitelist rules, and deduplication apply. Requires subscribing to the Issue comment webhook event (requires Issues permission) in your GitHub App settings.
| enabled | bool | false | Enable @mention triggered reviews (opt-in) |
| bot_name | string | "claude-review" | Bot username to listen for (case-insensitive) |
| ignore_bots | bool | true | Ignore comments from bot accounts (usernames containing [bot]) to prevent loops |
[rate_limit]#
| requests_per_hour | integer | 60 | Sustained request rate per repository |
| burst | integer | 5 | Maximum burst size (token bucket capacity) |
| bypass_users | string[] | [] | GitHub usernames exempt from rate limits |
[whitelist]#
All three lists default to empty, which means everything is allowed. When any list is non-empty, only matching entries are permitted. The lists are evaluated with case-insensitive comparison.
| organizations | string[] | [] | Allowed GitHub organization logins |
| users | string[] | [] | Allowed GitHub user logins |
| repositories | string[] | [] | Allowed repositories as "owner/repo" |
[sandbox]#
| enabled | bool | true | Enable OS-level sandboxing |
| allowed_read_paths | path[] | [] | Additional paths mounted read-only |
| allowed_write_paths | path[] | [] | Additional paths mounted read-write |
| network_policy | string | "none" | "none", "limited", or "full" |
| timeout_seconds | integer | 300 | Maximum execution time for sandboxed processes |
[mcp]#
The mcp.servers key is an array of tables. Each entry defines one MCP server connection.
| name | string | – | Unique server name (used to prefix tool names) |
| type | string | – | Transport: "stdio", "http", "sse", or "websocket" / "ws" |
| enabled | bool | true | Enable/disable this server |
Transport-specific fields are documented in MCP Integration.
[anti_injection]#
| max_title_length | integer | 500 | Truncation limit for PR title |
| max_description_length | integer | 10000 | Truncation limit for PR body |
| max_diff_length | integer | 500000 | Truncation limit for the diff |
| max_comment_length | integer | 5000 | Truncation limit for individual comments |
| suspicious_patterns | string[] | [] | Additional regex patterns appended to the built-in injection detectors |
[[rules]]#
Rules are defined as an array of tables. See Rule Engine for the full expression language.
| name | string | – | Human-readable rule name (required) |
| condition | string | – | Expression evaluated per file or per PR (required) |
| priority | integer | 0 | Higher-priority rules are evaluated first |
| actions | array | – | List of actions to execute when the condition is true |
Environment Variable Precedence#
Environment variables override config file values. The resolution order for API keys is:
LLM_API_KEY (highest priority, any provider)
ANTHROPIC_API_KEY (for claude and anthropic providers)
OPENAI_API_KEY (for openai provider)
api_key in [llm] config (lowest priority)