Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Configuration

Moltis uses a layered config model with two files:

FileOwnerPurpose
defaults.tomlMoltisShipped defaults, regenerated on every startup
moltis.tomlYouYour overrides only

On first run, both files are created in ~/.config/moltis/. Your moltis.toml starts nearly empty — only the installation-specific port is set. All other settings inherit from defaults.toml automatically.

Merge Order

Settings are resolved in this order (later wins):

  1. Built-in defaults — compiled into Moltis (MoltisConfig::default())
  2. defaults.toml — Moltis-managed, refreshed on every startup
  3. moltis.toml — your overrides (additive deep merge)
  4. MOLTIS_* environment variables — highest precedence

This means you only need to put values in moltis.toml that you intentionally want to differ from the shipped defaults. When Moltis upgrades and improves a default, your installation picks it up automatically — unless you’ve overridden that specific setting.

Don’t copy defaults into moltis.toml

Copying a built-in default into moltis.toml “freezes” it — future built-in improvements for that setting won’t apply. The Settings UI shows Built-in, Overridden, and Custom badges so you can see which values are yours and which are inherited.

Configuration File Location

PlatformDefault Path
macOS/Linux~/.config/moltis/moltis.toml
CustomSet via --config-dir or MOLTIS_CONFIG_DIR

The defaults.toml file lives in the same directory. Do not edit it — your changes will be overwritten on the next startup.

Checking Config

moltis config check validates your override file (moltis.toml) against the known config schema. It also checks that Moltis-managed defaults.toml exists and can be parsed, but it does not treat defaults.toml as user-authored input.

New config fields should be added to the Rust config schema and its Default implementation. Moltis regenerates defaults.toml from those built-in defaults on startup, while moltis.toml should contain only values you intentionally override.

Basic Settings

[server]
port = 13131                    # HTTP/WebSocket port
bind = "0.0.0.0"               # Listen address

[identity]
name = "Moltis"                 # Agent display name

[tools]
agent_timeout_secs = 600        # Agent run timeout (seconds, 0 = no timeout)
agent_max_iterations = 25       # Max tool call iterations per run

LLM Providers

Configure providers through the web UI or directly in moltis.toml. API keys can be set via environment variables (e.g. ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY) or in the config file.

[providers]
offered = ["anthropic", "openai", "gemini"]

[providers.anthropic]
enabled = true

[providers.openai]
enabled = true
models = ["gpt-5.3", "gpt-5.2"]
stream_transport = "sse"        # "sse", "websocket", or "auto"

[providers.gemini]
enabled = true
models = ["gemini-2.5-flash-preview-05-20", "gemini-2.0-flash"]

[providers.local-llm]
enabled = true
models = ["qwen2.5-coder-7b-q4_k_m"]

[chat]
priority_models = ["gpt-5.2"]

See Providers for the full list of supported providers and configuration options.

Remote Execution

Command execution can stay local, route to a paired node, or use SSH:

[tools.exec]
host = "local"                 # "local", "node", or "ssh"
# node = "mac-mini"            # default paired node when host = "node"
# ssh_target = "deploy@box"    # default SSH target when host = "ssh"

When host = "ssh", Moltis can work in two modes:

  • System OpenSSH: reuse your existing host aliases, agent forwarding policy, and ~/.ssh/config.
  • Managed targets: create or import a deploy key in Settings → SSH, then bind that key to a named target. Moltis stores the private key in its credential store and encrypts it with the vault whenever the vault is unsealed. Imported keys may be passphrase-protected, Moltis strips the passphrase during import so runtime execution can stay non-interactive.

For stricter SSH verification, managed targets also accept a pasted known_hosts line from ssh-keyscan -H host. The SSH settings page can scan that for you, and saved targets can refresh or clear their stored pin later. When present, Moltis uses that pin instead of your global OpenSSH known-host policy for that target.

Managed targets appear in the Nodes page and chat node picker, so users can see where exec will run without digging through config. If multiple managed targets exist, the default one is used when tools.exec.host = "ssh" and no session-specific route is selected. moltis doctor also reports remote-exec inventory, active backend mode, and obvious SSH setup problems from the CLI.

Settings -> Tools shows the effective tool inventory for the active session and model, including tool-calling support, MCP server state, skills/plugins, and available execution routes. It is session-aware by design, switching the model or disabling MCP for a session changes what appears there.

Sandbox Configuration

Commands run inside isolated containers for security:

[tools.exec.sandbox]
mode = "all"                    # "off", "non-main", or "all"
scope = "session"               # "command", "session", or "global"
workspace_mount = "ro"          # "ro", "rw", or "none"
# host_data_dir = "/host/path/data"  # Optional override if auto-detection cannot resolve the host path
home_persistence = "shared"     # "off", "session", or "shared" (default: "shared")
# shared_home_dir = "/path/to/shared-home"  # Optional path for shared mode
backend = "auto"                # "auto", "docker", or "apple-container"
no_network = true

# Packages installed in the sandbox image
packages = [
    "curl",
    "git",
    "jq",
    "tmux",
    "python3",
    "python3-pip",
    "nodejs",
    "npm",
    "golang-go",
]

If Moltis runs inside Docker and also mounts the host container socket (/var/run/docker.sock), Moltis now auto-detects the host path backing /home/moltis/.moltis from the parent container’s mount table. If that inspection cannot resolve the correct path, set host_data_dir explicitly.

Info

When you modify the packages list and restart, Moltis automatically rebuilds the sandbox image with a new tag.

Configure the built-in web_search tool:

[tools.web.search]
enabled = true
provider = "brave"               # "brave" or "perplexity"
max_results = 5                  # 1-10
timeout_seconds = 30
cache_ttl_minutes = 15
duckduckgo_fallback = false      # Default: do not use DuckDuckGo fallback
# api_key = "..."                # Brave key, or use BRAVE_API_KEY

[tools.web.search.perplexity]
# api_key = "..."                # Or use PERPLEXITY_API_KEY / OPENROUTER_API_KEY
# base_url = "..."               # Optional override
# model = "perplexity/sonar-pro" # Optional override

If no search API key is configured:

  • with duckduckgo_fallback = false (default), Moltis returns a clear hint to set BRAVE_API_KEY or PERPLEXITY_API_KEY
  • with duckduckgo_fallback = true, Moltis attempts DuckDuckGo HTML search, which may hit CAPTCHA/rate limits

Skills

Configure skill discovery and agent-managed personal skills:

[skills]
enabled = true
auto_load = ["commit"]
enable_agent_sidecar_files = false  # Opt-in: allow agents to write sidecar text files in personal skills
enable_self_improvement = true     # System prompt guidance for autonomous skill creation/update

enable_agent_sidecar_files is disabled by default. When enabled, Moltis registers the write_skill_files tool so agents can write supplementary files such as script.sh, Dockerfile, templates, or _meta.json inside <data_dir>/skills/<name>/. Writes stay confined to that personal skill directory, reject path traversal and symlink escapes, and are recorded in ~/.moltis/logs/security-audit.jsonl.

enable_self_improvement (default: true) injects system prompt guidance that encourages the agent to proactively create and update skills after complex tasks (5+ tool calls), tricky error fixes, or non-obvious workflows. The patch_skill tool allows surgical find/replace updates without rewriting the entire skill body.

Chat Message Queue

When a new message arrives while an agent run is already active, Moltis can either replay queued messages one-by-one or merge them into a single follow-up message.

[chat]
message_queue_mode = "followup"  # Default: one-by-one replay
prompt_memory_mode = "live-reload"

# Options:
#   "followup" - Queue each message and run them sequentially
#   "collect"  - Merge queued text and run once after the active run
#   "live-reload" - Re-read MEMORY.md before each turn
#   "frozen-at-session-start" - Keep the first MEMORY.md snapshot for the session

Memory System

Long-term memory uses embeddings for semantic search:

[memory]
style = "hybrid"              # Or "prompt-only", "search-only", "off"
agent_write_mode = "hybrid"   # Or "prompt-only", "search-only", "off"
user_profile_write_mode = "explicit-and-auto" # Or "explicit-only", "off"
backend = "builtin"             # Or "qmd"
provider = "openai"             # Or "local", "ollama", "custom"
model = "text-embedding-3-small"
citations = "auto"              # "on", "off", or "auto"
llm_reranking = false
search_merge_strategy = "rrf"   # Or "linear"
session_export = "on-new-or-reset" # Or "off"

See Memory Surfaces for the boundary between session_state, prompt memory, searchable memory, and sandbox persistence. memory.style chooses the high-level behavior, while chat.prompt_memory_mode only affects prompt-visible MEMORY.md. memory.agent_write_mode controls where agent-authored writes are allowed to land. memory.user_profile_write_mode controls whether Moltis writes the managed USER.md surface, and whether browser/channel timezone or location signals may update it silently. memory.session_export controls whether session rollover exports are written at all.

Authentication

Authentication is only required when accessing Moltis from a non-localhost address. When running on localhost or 127.0.0.1, no authentication is needed by default.

When you access Moltis from a network address (e.g., http://192.168.1.100:13131), a one-time setup code is printed to the terminal. Use it to set up a password or passkey.

[auth]
disabled = false                # Set true to disable auth entirely

Warning

Only set disabled = true if Moltis is running on a trusted private network. Never expose an unauthenticated instance to the internet.

Hooks

Configure lifecycle hooks:

[hooks]
[[hooks.hooks]]
name = "my-hook"
command = "./hooks/my-hook.sh"
events = ["BeforeToolCall", "AfterToolCall"]
timeout = 5                     # Timeout in seconds

[hooks.hooks.env]
MY_VAR = "value"               # Environment variables for the hook

See Hooks for the full hook system documentation.

MCP Servers

Connect to Model Context Protocol servers:

[mcp]
request_timeout_secs = 30
                                    # Default timeout for MCP requests (seconds)

[mcp.servers.filesystem]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed"]
request_timeout_secs = 90        # Optional override for this server

[mcp.servers.github]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-github"]
env = { GITHUB_TOKEN = "ghp_..." }

[mcp.servers.remote_api]
transport = "sse"
url = "https://mcp.example.com/mcp?api_key=$REMOTE_MCP_KEY"
headers = { Authorization = "Bearer ${REMOTE_MCP_TOKEN}" }

[mcp.servers.remote_http]
transport = "streamable-http"
url = "https://mcp.example.com/mcp"
headers = { Authorization = "Bearer ${API_KEY}" }

Remote MCP URLs and headers support $NAME or ${NAME} placeholders. For live remote servers, values resolve from Moltis-managed env overrides, either [env] in config or SettingsEnvironment Variables.

Telegram Integration

[channels.telegram.my-bot]
token = "123456:ABC..."
dm_policy = "allowlist"
allowlist = ["123456789"]       # Telegram user IDs or usernames (strings)

See Telegram for full configuration reference and setup instructions.

Discord Integration

[channels]
offered = ["telegram", "discord"]

[channels.discord.my-bot]
token = "MTIzNDU2Nzg5.example.bot-token"
dm_policy = "allowlist"
mention_mode = "mention"
allowlist = ["your_username"]

See Discord for full configuration reference and setup instructions.

Slack Integration

[channels]
offered = ["slack"]

[channels.slack.my-bot]
bot_token = "xoxb-..."
app_token = "xapp-..."
dm_policy = "allowlist"
allowlist = ["U123456789"]

See Slack for full configuration reference and setup instructions.

TLS / HTTPS

[tls]
enabled = true
cert_path = "~/.config/moltis/cert.pem"
key_path = "~/.config/moltis/key.pem"
# If paths don't exist, a self-signed certificate is generated

# Port for the plain-HTTP redirect / CA-download server.
# Defaults to the server port + 1 when not set.
# http_redirect_port = 13132

Override via environment variable: MOLTIS_TLS__HTTP_REDIRECT_PORT=8080.

Tailscale Integration

Expose Moltis over your Tailscale network:

[tailscale]
mode = "serve"                  # "off", "serve", or "funnel"
reset_on_exit = true

Observability

[metrics]
enabled = true
prometheus_endpoint = true

Process Environment Variables ([env])

The [env] section injects variables into the Moltis process at startup. This is useful in Docker deployments where passing individual -e flags is inconvenient, or when you want API keys stored in the config file rather than the host environment.

[env]
BRAVE_API_KEY = "your-brave-key"
OPENROUTER_API_KEY = "sk-or-..."
ELEVENLABS_API_KEY = "..."

Precedence: existing process environment variables are never overwritten. If BRAVE_API_KEY is already set via docker -e or the host shell, the [env] value is skipped. This means docker -e always wins.

Settings UI vs [env]

Environment variables configured through the Settings UI (Settings > Environment) are also injected into the Moltis process at startup. Precedence: host/docker -e > config [env] > Settings UI.

Environment Variables

All settings can be overridden via environment variables:

VariableDescription
MOLTIS_CONFIG_DIRConfiguration directory
MOLTIS_DATA_DIRData directory
MOLTIS_SERVER__PORTServer port override
MOLTIS_SERVER__BINDServer bind address override
MOLTIS_TOOLS__AGENT_TIMEOUT_SECSAgent run timeout override
MOLTIS_TOOLS__AGENT_MAX_ITERATIONSAgent loop iteration cap override

CLI Flags

moltis --config-dir /path/to/config --data-dir /path/to/data

Complete Example

[server]
port = 13131
bind = "0.0.0.0"

[identity]
name = "Atlas"

[tools]
agent_timeout_secs = 600
agent_max_iterations = 25

[providers]
offered = ["anthropic", "openai", "gemini"]

[tools.exec.sandbox]
mode = "all"
scope = "session"
workspace_mount = "ro"
home_persistence = "session"
# shared_home_dir = "/path/to/shared-home"
backend = "auto"
no_network = true
packages = ["curl", "git", "jq", "python3", "nodejs", "golang-go"]

[memory]
backend = "builtin"
provider = "openai"
model = "text-embedding-3-small"

[auth]
disabled = false

[hooks]
[[hooks.hooks]]
name = "audit-log"
command = "./hooks/audit.sh"
events = ["BeforeToolCall"]
timeout = 5