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​