Configuration
ClawDesk uses a single TOML configuration file (clawdesk.toml) as its primary source of truth. This guide covers the full config schema, environment variable overrides, validation, and hot-reload behavior.
Configuration File Location
ClawDesk searches for clawdesk.toml in the following order:
- Path specified by
--configCLI flag - Path specified by
CLAWDESK_CONFIGenvironment variable ./clawdesk.toml(current working directory)~/.config/clawdesk/clawdesk.toml/etc/clawdesk/clawdesk.toml
# Explicit path
clawdesk-cli gateway --config /path/to/clawdesk.toml
# Via environment variable
export CLAWDESK_CONFIG=~/my-project/clawdesk.toml
clawdesk-cli gateway
Run clawdesk-cli config show to see which config file is currently active and its resolved values.
Full Configuration Structure
Below is the complete configuration schema with all sections and their defaults.
[gateway] — Server Settings
[gateway]
bind = "127.0.0.1" # Listen address
port = 18789 # Listen port
log_level = "info" # trace, debug, info, warn, error
log_format = "pretty" # pretty, json, compact
workers = 0 # Tokio worker threads (0 = auto/num_cpus)
request_timeout_secs = 30 # HTTP request timeout
max_body_size = "10mb" # Maximum request body size
cors_origins = ["*"] # Allowed CORS origins
tls_cert = "" # Path to TLS certificate (optional)
tls_key = "" # Path to TLS private key (optional)
[agents.*] — Agent Definitions
Each agent is a named table under [agents]:
[agents.default]
name = "default"
provider = "anthropic" # Provider key to use
model = "" # Override provider's default_model
system_prompt = "You are a helpful AI assistant."
temperature = 0.7
max_tokens = 4096
top_p = 1.0
stop_sequences = []
tools_enabled = true # Allow tool/function calling
memory_enabled = true # Persist conversation history
memory_window = 50 # Number of past messages to include
[agents.coder]
name = "coder"
provider = "anthropic"
model = "claude-sonnet-4-20250514"
system_prompt = """
You are an expert software engineer. Write clean, idiomatic code.
Always explain your reasoning before writing code.
"""
temperature = 0.3
max_tokens = 8192
tools_enabled = true
If model is left empty, the agent uses the provider's default_model. You can define as many agents as you need — each channel can be routed to a different agent.
[channels.*] — Channel Connections
Channels connect external messaging platforms to ClawDesk agents:
[channels.telegram]
type = "telegram"
enabled = true
token = "${TELEGRAM_BOT_TOKEN}"
agent = "default" # Route to this agent
webhook_path = "/webhook/telegram"
allowed_users = [] # Empty = allow all
rate_limit = 30 # Max messages per minute per user
[channels.discord]
type = "discord"
enabled = true
token = "${DISCORD_BOT_TOKEN}"
guild_id = "${DISCORD_GUILD_ID}"
agent = "default"
command_prefix = "!"
allowed_channels = [] # Empty = allow all channels
[channels.slack]
type = "slack"
enabled = true
bot_token = "${SLACK_BOT_TOKEN}"
app_token = "${SLACK_APP_TOKEN}"
signing_secret = "${SLACK_SIGNING_SECRET}"
agent = "default"
[channels.webchat]
type = "webchat"
enabled = true
agent = "default"
path = "/chat"
anonymous_allowed = true
[channels.whatsapp]
type = "whatsapp"
enabled = false
token = "${WHATSAPP_TOKEN}"
phone_number_id = "${WHATSAPP_PHONE_ID}"
verify_token = "${WHATSAPP_VERIFY_TOKEN}"
agent = "default"
[channels.matrix]
type = "matrix"
enabled = false
homeserver = "https://matrix.org"
user_id = "@clawdesk:matrix.org"
access_token = "${MATRIX_ACCESS_TOKEN}"
agent = "default"
Supported channel types:
| Type | Platform | Auth Method |
|---|---|---|
telegram | Telegram | Bot token |
discord | Discord | Bot token + Guild ID |
slack | Slack | Bot token + App token |
webchat | Built-in Web UI | Optional auth |
whatsapp | WhatsApp Business | Cloud API token |
signal | Signal | Signal CLI |
imessage | iMessage | AppleScript (macOS only) |
matrix | Matrix/Element | Access token |
line | LINE | Channel access token |
google_chat | Google Chat | Service account |
ms_teams | Microsoft Teams | App registration |
nostr | Nostr | nsec key |
[providers.*] — AI Provider Config
[providers.anthropic]
type = "anthropic"
api_key = "${ANTHROPIC_API_KEY}"
default_model = "claude-sonnet-4-20250514"
max_retries = 3
timeout_secs = 60
base_url = "" # Custom API endpoint (optional)
enabled = true
[providers.openai]
type = "openai"
api_key = "${OPENAI_API_KEY}"
default_model = "gpt-4o"
organization = "" # OpenAI org ID (optional)
max_retries = 3
timeout_secs = 60
enabled = true
[providers.ollama]
type = "ollama"
base_url = "http://localhost:11434"
default_model = "llama3.1"
enabled = true
[providers.google]
type = "google"
api_key = "${GOOGLE_API_KEY}"
default_model = "gemini-2.0-flash"
enabled = true
[providers.bedrock]
type = "bedrock"
region = "us-east-1"
access_key_id = "${AWS_ACCESS_KEY_ID}"
secret_access_key = "${AWS_SECRET_ACCESS_KEY}"
default_model = "anthropic.claude-sonnet-4-20250514-v1:0"
enabled = false
[session] — Session Management
[session]
timeout_minutes = 30 # Session expiry after inactivity
max_history = 100 # Max messages per session
storage_backend = "sochdb" # sochdb | memory
cleanup_interval_secs = 300 # Expired session cleanup interval
[storage] — SochDB Configuration
[storage]
engine = "sochdb"
path = "./data" # Data directory
max_connections = 16 # Connection pool size
wal_enabled = true # Write-ahead logging
compaction_interval_secs = 3600 # Auto-compaction interval
backup_enabled = false
backup_path = "./backups"
backup_interval_secs = 86400 # Daily backups
[security] — Access Control
[security]
auth_enabled = false # Require authentication for API
api_keys = [] # Allowed API keys
jwt_secret = "" # JWT signing secret
rate_limit_enabled = true
rate_limit_requests = 60 # Requests per window
rate_limit_window_secs = 60 # Window duration
ip_allowlist = [] # Empty = allow all
ip_blocklist = []
When deploying ClawDesk to a public server, always enable authentication and restrict CORS origins. An unauthenticated gateway exposed to the internet allows anyone to consume your AI provider quota.
[plugins] — Plugin Configuration
[plugins]
enabled = true
directory = "./plugins" # Plugin search directory
auto_load = true # Load all plugins on startup
[plugins.web_search]
enabled = true
api_key = "${SEARCH_API_KEY}"
engine = "duckduckgo"
[plugins.code_execution]
enabled = false
sandbox = "docker" # docker | wasm
timeout_secs = 30
Environment Variables
ClawDesk supports environment variable substitution in TOML values using ${VAR_NAME} syntax. Additionally, several built-in environment variables control runtime behavior:
| Variable | Description | Default |
|---|---|---|
CLAWDESK_CONFIG | Path to config file | ./clawdesk.toml |
CLAWDESK_LOG | Log level override | Value from config |
CLAWDESK_LOG_FORMAT | Log format override | Value from config |
CLAWDESK_BIND | Bind address override | Value from config |
CLAWDESK_PORT | Port override | Value from config |
ANTHROPIC_API_KEY | Anthropic API key | — |
OPENAI_API_KEY | OpenAI API key | — |
GOOGLE_API_KEY | Google AI API key | — |
AWS_ACCESS_KEY_ID | AWS access key (Bedrock) | — |
AWS_SECRET_ACCESS_KEY | AWS secret key (Bedrock) | — |
TELEGRAM_BOT_TOKEN | Telegram bot token | — |
DISCORD_BOT_TOKEN | Discord bot token | — |
DISCORD_GUILD_ID | Discord guild/server ID | — |
SLACK_BOT_TOKEN | Slack bot OAuth token | — |
SLACK_APP_TOKEN | Slack app-level token | — |
SLACK_SIGNING_SECRET | Slack signing secret | — |
Using a .env File
ClawDesk automatically loads a .env file from the project root:
ANTHROPIC_API_KEY=sk-ant-api03-...
TELEGRAM_BOT_TOKEN=7123456789:AAF...
DISCORD_BOT_TOKEN=MTIx...
DISCORD_GUILD_ID=1234567890
CLAWDESK_LOG=debug
Add .env to your .gitignore to prevent accidental credential exposure.
Config Validation at Startup
ClawDesk validates the entire configuration at startup before the gateway begins accepting requests. Validation checks include:
- Schema validation — All fields match expected types
- Provider reachability — Enabled providers are contacted with a health check
- Channel credentials — Tokens are verified with their respective APIs
- Port availability — The configured gateway port is free
- Storage access — The data directory is writable
Run validation manually:
clawdesk-cli config validate
🔍 Validating clawdesk.toml...
✅ Schema valid
✅ Provider: anthropic connected (claude-sonnet-4-20250514)
✅ Provider: ollama connected (llama3.1)
✅ Channel: telegram token valid
✅ Channel: discord token valid, guild accessible
✅ Storage: sochdb writable at ./data
✅ Gateway: port 18789 available
Configuration is valid.
If validation fails, ClawDesk prints actionable error messages and exits with a non-zero status:
❌ Validating clawdesk.toml...
❌ Provider: anthropic 401 Unauthorized — check ANTHROPIC_API_KEY
⚠️ Channel: discord guild_id not set — will be ignored
✅ Provider: ollama connected
1 error, 1 warning. Fix errors before starting the gateway.
Hot-Reload Support
ClawDesk watches clawdesk.toml for changes and applies updates without restarting the gateway. The following sections support hot-reload:
| Section | Hot-Reload | Notes |
|---|---|---|
[gateway] | ❌ | Requires restart (bind address/port) |
[agents.*] | ✅ | System prompts, models, parameters |
[channels.*] | ✅ | New channels added, existing updated |
[providers.*] | ✅ | API keys, models, timeouts |
[session] | ✅ | Timeout and history limits |
[security] | ✅ | Rate limits, allowlists |
[plugins] | ✅ | Plugin enable/disable |
[storage] | ❌ | Requires restart |
When a hot-reload occurs, the gateway logs it:
INFO clawdesk_gateway > Config file changed, reloading...
INFO clawdesk_gateway > Agent "default" updated: model changed to claude-sonnet-4-20250514
INFO clawdesk_gateway > Channel "slack" added and connected
INFO clawdesk_gateway > Reload complete (2 changes applied)
Use clawdesk-cli config watch to monitor config changes in real time from a separate terminal.
Example Configurations
Minimal Local Setup (Ollama Only)
[gateway]
bind = "127.0.0.1"
port = 18789
log_level = "info"
[providers.ollama]
type = "ollama"
base_url = "http://localhost:11434"
default_model = "llama3.1"
enabled = true
[agents.default]
name = "default"
provider = "ollama"
system_prompt = "You are a helpful assistant."
[storage]
engine = "sochdb"
path = "./data"
Multi-Provider with Fallback
[gateway]
bind = "127.0.0.1"
port = 18789
log_level = "info"
# Primary provider
[providers.anthropic]
type = "anthropic"
api_key = "${ANTHROPIC_API_KEY}"
default_model = "claude-sonnet-4-20250514"
enabled = true
# Fallback provider
[providers.ollama]
type = "ollama"
base_url = "http://localhost:11434"
default_model = "llama3.1"
enabled = true
[agents.default]
name = "default"
provider = "anthropic"
system_prompt = "You are a helpful assistant powered by ClawDesk."
temperature = 0.7
max_tokens = 4096
[agents.coder]
name = "coder"
provider = "anthropic"
model = "claude-sonnet-4-20250514"
system_prompt = "You are a senior software engineer. Write production-quality code."
temperature = 0.2
max_tokens = 8192
[storage]
engine = "sochdb"
path = "./data"
Production Deployment with Channels
[gateway]
bind = "0.0.0.0"
port = 18789
log_level = "warn"
log_format = "json"
workers = 8
tls_cert = "/etc/clawdesk/tls/cert.pem"
tls_key = "/etc/clawdesk/tls/key.pem"
cors_origins = ["https://app.example.com"]
[providers.anthropic]
type = "anthropic"
api_key = "${ANTHROPIC_API_KEY}"
default_model = "claude-sonnet-4-20250514"
max_retries = 5
timeout_secs = 120
enabled = true
[agents.support]
name = "support"
provider = "anthropic"
system_prompt = """
You are a customer support agent for Acme Corp.
Be polite, concise, and helpful. Escalate billing
issues to human agents.
"""
temperature = 0.5
max_tokens = 2048
memory_enabled = true
memory_window = 20
[channels.telegram]
type = "telegram"
enabled = true
token = "${TELEGRAM_BOT_TOKEN}"
agent = "support"
rate_limit = 20
[channels.discord]
type = "discord"
enabled = true
token = "${DISCORD_BOT_TOKEN}"
guild_id = "${DISCORD_GUILD_ID}"
agent = "support"
command_prefix = "!"
[channels.slack]
type = "slack"
enabled = true
bot_token = "${SLACK_BOT_TOKEN}"
app_token = "${SLACK_APP_TOKEN}"
signing_secret = "${SLACK_SIGNING_SECRET}"
agent = "support"
[channels.webchat]
type = "webchat"
enabled = true
agent = "support"
path = "/chat"
[session]
timeout_minutes = 60
max_history = 200
storage_backend = "sochdb"
[storage]
engine = "sochdb"
path = "/var/lib/clawdesk/data"
wal_enabled = true
backup_enabled = true
backup_path = "/var/lib/clawdesk/backups"
backup_interval_secs = 43200
[security]
auth_enabled = true
api_keys = ["${CLAWDESK_API_KEY}"]
rate_limit_enabled = true
rate_limit_requests = 100
rate_limit_window_secs = 60
ip_blocklist = []
[plugins]
enabled = true
directory = "/opt/clawdesk/plugins"
Next Steps
- First Channel → — Walk through connecting Telegram, Discord, or Slack step by step.
- Architecture Overview — Full documentation for ClawDesk's architecture.
- Security Model — Hardening ClawDesk for production.