-
Notifications
You must be signed in to change notification settings - Fork 4.4k
04 Configuration
Relevant source files
The following files were used as context for generating this wiki page:
This page provides an overview of ZeroClaw's configuration system, including how configuration is loaded, the priority hierarchy of configuration sources, and how config integrates with major subsystems. For detailed reference of all configuration options, see Configuration File Reference. For environment variable overrides, see Environment Variables. For encrypted secret storage, see Secret Management. For workspace directory structure and management, see Workspace Management.
ZeroClaw's configuration system follows a three-tier priority model: environment variables override config.toml settings, which override built-in defaults. Configuration is centralized in a single Config struct that orchestrates initialization of all subsystems including providers, channels, tools, memory backends, and security policies.
The configuration system supports:
-
File-based configuration via
~/.zeroclaw/config.toml - Environment variable overrides for API keys and runtime settings
- Encrypted secret storage using ChaCha20-Poly1305
- Multi-workspace support with active workspace markers
- Interactive onboarding wizard for first-time setup
- Quick non-interactive setup for automation
ZeroClaw resolves configuration from three sources in descending priority order:
graph TD
EnvVars["Environment Variables<br/>(Highest Priority)"]
ConfigFile["config.toml<br/>(Medium Priority)"]
Defaults["Built-in Defaults<br/>(Lowest Priority)"]
EnvVars -->|overrides| ConfigFile
ConfigFile -->|overrides| Defaults
Defaults -->|used when not set| FinalConfig["Final Config"]
ConfigFile -->|used when not set| FinalConfig
EnvVars -->|used when set| FinalConfig
Sources: src/config/schema.rs:48-144, src/channels/mod.rs:34-35
| Config Key | config.toml | Environment Variable | Final Value |
|---|---|---|---|
api_key |
"sk-from-file" |
OPENROUTER_API_KEY="sk-from-env" |
"sk-from-env" |
default_model |
"claude-sonnet-4-5" |
(not set) | "claude-sonnet-4-5" |
default_temperature |
(not set) | (not set) |
0.7 (default) |
The Config::load_or_init() method implements this priority cascade. See Configuration Loading Process below for details.
Sources: src/config/schema.rs:1620-1750, src/onboard/wizard.rs:61-196
The primary configuration file is ~/.zeroclaw/config.toml. The file is organized into logical sections corresponding to subsystems:
graph LR
ConfigToml["config.toml"]
ConfigToml --> Provider["[provider]<br/>default_provider, api_key"]
ConfigToml --> Agent["[agent]<br/>max_tool_iterations, compact_context"]
ConfigToml --> Channels["[channels_config]<br/>telegram, discord, slack, etc."]
ConfigToml --> Memory["[memory]<br/>backend, auto_save, embedding_*"]
ConfigToml --> Security["[autonomy]<br/>level, workspace_only"]
ConfigToml --> Runtime["[runtime]<br/>adapter, docker_config"]
ConfigToml --> Tools["[composio], [browser], [http_request]"]
ConfigToml --> Gateway["[gateway]<br/>port, require_pairing"]
ConfigToml --> Scheduler["[scheduler], [cron], [heartbeat]"]
ConfigToml --> Secrets["[secrets]<br/>encrypt"]
Sources: src/config/schema.rs:48-144
The Config struct is defined in src/config/schema.rs:48-144 with the following major sections:
pub struct Config {
// Core provider settings
pub api_key: Option<String>,
pub default_provider: Option<String>,
pub default_model: Option<String>,
pub default_temperature: f64,
// Subsystem configurations
pub agent: AgentConfig,
pub autonomy: AutonomyConfig,
pub channels_config: ChannelsConfig,
pub memory: MemoryConfig,
pub runtime: RuntimeConfig,
pub gateway: GatewayConfig,
pub composio: ComposioConfig,
pub browser: BrowserConfig,
pub hardware: HardwareConfig,
pub proxy: ProxyConfig,
// Advanced features
pub model_routes: Vec<ModelRouteConfig>,
pub agents: HashMap<String, DelegateAgentConfig>,
pub secrets: SecretsConfig,
// ... and more
}Each section is a dedicated struct with its own defaults. For example, MemoryConfig (src/config/schema.rs:2244-2329) contains settings for the memory backend, embedding models, vector search weights, and cache configuration.
Sources: src/config/schema.rs:48-144, src/config/schema.rs:2244-2329
sequenceDiagram
participant Main as "main.rs"
participant ConfigLoader as "Config::load_or_init()"
participant FileSystem as "Filesystem"
participant EnvVars as "Environment"
participant SecretStore as "SecretStore"
participant Subsystems as "Subsystems"
Main->>ConfigLoader: load_or_init()
ConfigLoader->>FileSystem: Check ~/.zeroclaw/config.toml
alt config.toml exists
FileSystem-->>ConfigLoader: Return file contents
ConfigLoader->>ConfigLoader: Parse TOML to Config struct
alt secrets.encrypt = true
ConfigLoader->>SecretStore: decrypt_secrets()
SecretStore-->>ConfigLoader: Decrypted values
end
ConfigLoader->>EnvVars: Read OPENROUTER_API_KEY, etc.
EnvVars-->>ConfigLoader: Environment overrides
ConfigLoader->>ConfigLoader: Apply env overrides
else config.toml missing
ConfigLoader->>ConfigLoader: Create default Config
ConfigLoader->>FileSystem: Write config.toml
end
ConfigLoader-->>Main: Return Config
Main->>Subsystems: Initialize with Config
Sources: src/config/schema.rs:1620-1750, src/channels/mod.rs:846-1027
The configuration loading sequence involves several steps:
-
Workspace Resolution: Determine active workspace directory
- Check
ZEROCLAW_WORKSPACEenvironment variable - Look for
active_workspace.tomlmarker - Default to
~/.zeroclaw/workspace
- Check
-
Config File Parsing: Read
config.tomlfrom workspace parent directory- If missing, create with defaults
- Parse TOML to
Configstruct
-
Secret Decryption: If
secrets.encrypt = true, decrypt encrypted fields- Load encryption key from
~/.zeroclaw/secret.key - Decrypt
api_key,composio.api_key, channel tokens, etc.
- Load encryption key from
-
Environment Variable Application: Override config values with env vars
-
OPENROUTER_API_KEY→config.api_key -
ANTHROPIC_API_KEY→ provider-specific override -
ZEROCLAW_*prefixed variables
-
-
Validation: Validate configuration consistency
- Check required fields for enabled features
- Validate proxy URLs, rate limits, etc.
Sources: src/config/schema.rs:1620-1750, src/config/schema.rs:1938-2027
The workspace directory is the primary working directory for ZeroClaw. Default location: ~/.zeroclaw/workspace.
~/.zeroclaw/
├── config.toml # Main configuration file
├── secret.key # Encryption key (when secrets.encrypt=true)
├── active_workspace.toml # Optional: marks active workspace
└── workspace/ # Active workspace directory
├── AGENTS.md # Agent identity (OpenClaw format)
├── SOUL.md # Personality definition
├── TOOLS.md # Tool usage guidelines
├── IDENTITY.md # User preferences
├── USER.md # User information
├── MEMORY.md # Curated long-term memory
├── state/ # Runtime state
│ ├── jobs.db # Cron job database
│ ├── memory.db # SQLite memory backend
│ └── models_cache.json
├── skills/ # Skill definitions
└── memory/ # Daily memory files (optional)
The workspace directory serves multiple purposes:
- Identity files: OpenClaw or AIEOS format identity definitions loaded into system prompt
- State storage: Persistent databases for memory, cron jobs, health checks
-
Tool scoping: When
workspace_only = true, file tools are restricted to workspace subtree
Sources: src/channels/mod.rs:846-1027, src/onboard/wizard.rs:769-824
For multi-workspace setups and workspace switching, see Workspace Management.
Configuration flows from the Config struct to all major subsystems during initialization.
graph TD
Config["Config Struct"]
Config --> Provider["Provider<br/>(default_provider, api_key, reliability)"]
Config --> Memory["Memory Backend<br/>(memory.backend, memory.auto_save)"]
Config --> Security["SecurityPolicy<br/>(autonomy.level, autonomy.workspace_only)"]
Config --> Tools["Tool Registry<br/>(composio, browser, http_request)"]
Config --> Channels["Channel Implementations<br/>(channels_config.telegram, discord, etc.)"]
Config --> Runtime["RuntimeAdapter<br/>(runtime.adapter, docker_config)"]
Config --> Gateway["HTTP Gateway<br/>(gateway.port, gateway.require_pairing)"]
Config --> Scheduler["Scheduler<br/>(scheduler.*, cron.*)"]
Provider --> Agent["Agent Core"]
Memory --> Agent
Security --> Agent
Tools --> Agent
Channels --> Agent
Gateway --> Agent
Sources: src/channels/mod.rs:101-123, src/tools/mod.rs:89-238
The provider subsystem reads configuration from multiple sources:
// From config.toml
let provider_name = config.default_provider.as_deref().unwrap_or("openrouter");
let model = config.default_model.as_deref().unwrap_or("anthropic/claude-sonnet-4.6");
let api_key = config.api_key.as_deref();
// With reliability settings
let reliability = &config.reliability; // ReliabilityConfig with retries, backoff
// Create resilient provider
let provider = providers::create_resilient_provider(
provider_name,
api_key,
reliability,
)?;Sources: src/channels/mod.rs:266-308, src/config/schema.rs:2034-2093
Channels read their specific configuration sections:
// Telegram channel config from [channels_config.telegram]
if let Some(telegram_cfg) = &config.channels_config.telegram {
let channel = TelegramChannel::new(
telegram_cfg.bot_token.clone(),
telegram_cfg.allowed_users.clone(),
telegram_cfg.stream_mode,
telegram_cfg.draft_update_interval_ms,
telegram_cfg.mention_only,
)?;
channels.push(Arc::new(channel));
}Sources: src/config/schema.rs:2405-2462, src/channels/mod.rs:1047-1133
Tools receive relevant config sections during registry construction:
// Composio tool (optional, requires enabled flag and API key)
if config.composio.enabled {
if let Some(key) = config.composio.api_key.as_deref() {
tools.push(Box::new(ComposioTool::new(
key,
Some(&config.composio.entity_id),
security.clone(),
)));
}
}
// Browser tool (requires enabled flag)
if config.browser.enabled {
tools.push(Box::new(BrowserTool::new(
security.clone(),
config.browser.allowed_domains.clone(),
// ... more browser config fields
)));
}Sources: src/tools/mod.rs:160-218, src/tools/composio.rs:23-40
The AutonomyConfig section controls security enforcement:
pub struct AutonomyConfig {
pub level: AutonomyLevel, // ReadOnly | Supervised | Full
pub workspace_only: bool, // Restrict file ops to workspace
pub forbidden_paths: Vec<String>, // Additional blocked paths
pub allowed_commands: Vec<String>, // Shell command allowlist
pub max_actions_per_hour: u32, // Rate limiting
// ...
}The SecurityPolicy is constructed from AutonomyConfig and passed to all tools:
let security = Arc::new(SecurityPolicy::from_config(&config.autonomy, &workspace_dir));
let tools = all_tools(&security, /* ... */);Sources: src/config/schema.rs:2094-2193, src/tools/mod.rs:72-86
The following diagram maps configuration concepts to actual code entities:
graph TB
subgraph "Configuration Files"
ConfigToml["~/.zeroclaw/config.toml"]
EnvFile["~/.zeroclaw/workspace/.env"]
SecretKey["~/.zeroclaw/secret.key"]
end
subgraph "Config Schema (src/config/schema.rs)"
ConfigStruct["Config struct<br/>line 48-144"]
AgentConfig["AgentConfig struct<br/>line 243-280"]
AutonomyConfig["AutonomyConfig struct<br/>line 2094-2193"]
ChannelsConfig["ChannelsConfig struct<br/>line 2405-2613"]
MemoryConfig["MemoryConfig struct<br/>line 2244-2329"]
ComposioConfig["ComposioConfig struct<br/>line 599-625"]
BrowserConfig["BrowserConfig struct<br/>line 691-740"]
end
subgraph "Config Loading (src/config/schema.rs)"
LoadOrInit["Config::load_or_init()<br/>line 1620-1750"]
ApplyEnv["apply_env_overrides()<br/>line 1796-1936"]
SecretStoreDecrypt["SecretStore::decrypt()<br/>line 3446-3509"]
end
subgraph "Subsystem Initialization"
CreateProvider["create_resilient_provider()<br/>src/providers/mod.rs"]
CreateMemory["create_memory()<br/>src/memory/mod.rs"]
AllTools["all_tools()<br/>src/tools/mod.rs:89-238"]
BuildChannels["build system prompt, channels<br/>src/channels/mod.rs:1047-1133"]
end
ConfigToml --> LoadOrInit
EnvFile --> ApplyEnv
SecretKey --> SecretStoreDecrypt
LoadOrInit --> ConfigStruct
ApplyEnv --> ConfigStruct
SecretStoreDecrypt --> ConfigStruct
ConfigStruct --> AgentConfig
ConfigStruct --> AutonomyConfig
ConfigStruct --> ChannelsConfig
ConfigStruct --> MemoryConfig
ConfigStruct --> ComposioConfig
ConfigStruct --> BrowserConfig
ConfigStruct --> CreateProvider
MemoryConfig --> CreateMemory
ConfigStruct --> AllTools
ConfigStruct --> BuildChannels
Sources: src/config/schema.rs:48-144, src/config/schema.rs:1620-1750, src/channels/mod.rs:1047-1133, src/tools/mod.rs:89-238
ZeroClaw supports environment variable overrides for most configuration values. The override system follows a naming convention:
| Config Section | Environment Variable Pattern | Example |
|---|---|---|
| Provider API keys | {PROVIDER}_API_KEY |
OPENROUTER_API_KEY |
| Generic API key | ZEROCLAW_API_KEY |
ZEROCLAW_API_KEY |
| Model selection | ZEROCLAW_MODEL |
ZEROCLAW_MODEL=gpt-4o |
| Workspace path | ZEROCLAW_WORKSPACE |
ZEROCLAW_WORKSPACE=/custom/path |
Provider credential resolution follows this priority:
- Explicit API key in config (
config.api_key) - Provider-specific env var (e.g.,
ANTHROPIC_API_KEY) - Generic env var (
ZEROCLAW_API_KEYorOPENROUTER_API_KEY) - OAuth flow (for supported providers)
Sources: src/config/schema.rs:1796-1936, src/channels/mod.rs:34-35
For complete environment variable reference, see Environment Variables.
ZeroClaw provides two initialization modes:
The interactive wizard (zeroclaw onboard --interactive) guides users through 9 configuration steps:
graph LR
Start["zeroclaw onboard --interactive"] --> Step1["1. Workspace Setup"]
Step1 --> Step2["2. AI Provider & API Key"]
Step2 --> Step3["3. Channels"]
Step3 --> Step4["4. Tunnel"]
Step4 --> Step5["5. Tool Mode & Security"]
Step5 --> Step6["6. Hardware"]
Step6 --> Step7["7. Memory Configuration"]
Step7 --> Step8["8. Project Context"]
Step8 --> Step9["9. Workspace Files"]
Step9 --> Save["Save config.toml"]
Sources: src/onboard/wizard.rs:61-196
For automation or CI/CD, use quick setup:
zeroclaw onboard --api-key "sk-..." --provider openrouter --memory sqliteThis generates a sensible default config instantly without prompts.
Sources: src/onboard/wizard.rs:301-463
The Config struct implements validation for configuration consistency:
impl Config {
pub fn validate(&self) -> Result<()> {
// Proxy configuration validation
self.proxy.validate()?;
// Gateway: disallow public bind without tunnel
if !self.gateway.host.starts_with("127.")
&& !self.gateway.allow_public_bind
&& !self.tunnel.enabled() {
bail!("Gateway bound to public IP without tunnel");
}
// Memory backend: check embedding provider when using vector search
if self.memory.backend == "sqlite"
&& self.memory.embedding_provider == "none" {
warn!("Vector search disabled without embedding provider");
}
// ... more validation rules
Ok(())
}
}Validation occurs automatically during Config::load_or_init().
Sources: src/config/schema.rs:1752-1794, src/config/schema.rs:886-921
-
Configuration File Reference: Complete reference for all
config.tomlsections and fields - Environment Variables: Full list of supported environment variable overrides
- Secret Management: Details on ChaCha20-Poly1305 encryption, key management, and secret migration
- Workspace Management: Multi-workspace support, active workspace markers, and directory structure
Sources: src/config/schema.rs:48-144, src/config/mod.rs:1-17, src/channels/mod.rs:34-52, src/onboard/wizard.rs:61-463