Skip to main content

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:

  1. Path specified by --config CLI flag
  2. Path specified by CLAWDESK_CONFIG environment variable
  3. ./clawdesk.toml (current working directory)
  4. ~/.config/clawdesk/clawdesk.toml
  5. /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
tip

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
info

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:

TypePlatformAuth Method
telegramTelegramBot token
discordDiscordBot token + Guild ID
slackSlackBot token + App token
webchatBuilt-in Web UIOptional auth
whatsappWhatsApp BusinessCloud API token
signalSignalSignal CLI
imessageiMessageAppleScript (macOS only)
matrixMatrix/ElementAccess token
lineLINEChannel access token
google_chatGoogle ChatService account
ms_teamsMicrosoft TeamsApp registration
nostrNostrnsec 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 = []
danger

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:

VariableDescriptionDefault
CLAWDESK_CONFIGPath to config file./clawdesk.toml
CLAWDESK_LOGLog level overrideValue from config
CLAWDESK_LOG_FORMATLog format overrideValue from config
CLAWDESK_BINDBind address overrideValue from config
CLAWDESK_PORTPort overrideValue from config
ANTHROPIC_API_KEYAnthropic API key
OPENAI_API_KEYOpenAI API key
GOOGLE_API_KEYGoogle AI API key
AWS_ACCESS_KEY_IDAWS access key (Bedrock)
AWS_SECRET_ACCESS_KEYAWS secret key (Bedrock)
TELEGRAM_BOT_TOKENTelegram bot token
DISCORD_BOT_TOKENDiscord bot token
DISCORD_GUILD_IDDiscord guild/server ID
SLACK_BOT_TOKENSlack bot OAuth token
SLACK_APP_TOKENSlack app-level token
SLACK_SIGNING_SECRETSlack signing secret

Using a .env File

ClawDesk automatically loads a .env file from the project root:

.env
ANTHROPIC_API_KEY=sk-ant-api03-...
TELEGRAM_BOT_TOKEN=7123456789:AAF...
DISCORD_BOT_TOKEN=MTIx...
DISCORD_GUILD_ID=1234567890
CLAWDESK_LOG=debug
warning

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:

SectionHot-ReloadNotes
[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)
tip

Use clawdesk-cli config watch to monitor config changes in real time from a separate terminal.


Example Configurations

Minimal Local Setup (Ollama Only)

clawdesk.toml
[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

clawdesk.toml
[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

clawdesk.toml
[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