docs/src/configuration.md
Rama main · réplica de lectura del repositorio original.
# Configuration
Moltis uses a **layered config model** with two files:
| File | Owner | Purpose |
|------|-------|---------|
| `defaults.toml` | **Moltis** | Shipped defaults, regenerated on every startup |
| `moltis.toml` | **You** | Your 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.
```admonish tip title="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
| Platform | Default Path |
|----------|--------------|
| macOS/Linux | `~/.config/moltis/moltis.toml` |
| Custom | Set 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.
## Agent-Readable Docs
Moltis packages the documentation as local markdown files when the install
format supports external share files, such as `.deb`, `.rpm`, Homebrew, and
similar system packages. Agents are pointed at those local files through the
system prompt so they can read setup, configuration, channel, and
troubleshooting docs without needing web access.
Resolution order is `MOLTIS_DOCS_DIR`, the packaged share docs directory
(`<share>/docs`), the source checkout docs in development, then an embedded
fallback copied to `~/.moltis/docs/moltis/`. Moltis also writes a generated
`config-template.md` under `~/.moltis/docs/moltis/` for the current server port
and points agents at it separately.
## Basic Settings
```toml
[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.
```toml
[providers]
offered = ["anthropic", "openai", "gemini"]
[providers.anthropic]
enabled = true
[providers.openai]
enabled = true
models = ["gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"]
stream_transport = "sse" # "sse", "websocket", or "auto"
[providers.gemini]
enabled = true
models = ["gemini-2.5-flash", "gemini-2.5-pro"]
[providers.local-llm]
enabled = true
models = ["qwen2.5-coder-7b-q4_k_m"]
[chat]
priority_models = ["gpt-5.6-sol"]
```
See [Providers](providers.md) 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:
```toml
[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:
```toml
[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.
```admonish info
When you modify the packages list and restart, Moltis automatically rebuilds the sandbox image with a new tag.
```
## Web Search
Configure the built-in `web_search` tool:
```toml
[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:
```toml
[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.
## Default Reasoning
Set a default reasoning/thinking effort for model-less and new main sessions:
```toml
[chat]
reasoning_default = "high"
```
Accepted values are `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`.
`extra-high` is also accepted and is saved as the canonical `xhigh` value.
`max` is a distinct level above Extra High, not an alias for `xhigh`.
Omit `chat.reasoning_default` to keep Off (the existing behavior); `off` is
not a config value. An explicit session choice, either Off or a reasoning
level, always takes precedence over this default. Support for reasoning and
individual levels depends on the selected model and provider.
## 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.
```toml
[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:
```toml
[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](memory-surfaces.md) 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.
```toml
[auth]
disabled = false # Set true to disable auth entirely
```
```admonish 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:
```toml
[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](hooks.md) for the full hook system documentation.
## MCP Servers
Connect to Model Context Protocol servers:
```toml
[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 **Settings** → **Environment Variables**.
## Telegram Integration
```toml
[channels.telegram.my-bot]
token = "123456:ABC..."
dm_policy = "allowlist"
allowlist = ["123456789"] # Telegram user IDs or usernames (strings)
```
See [Telegram](telegram.md) for full configuration reference and setup instructions.
## Discord Integration
```toml
[channels]
offered = ["telegram", "discord"]
[channels.discord.my-bot]
token = "MTIzNDU2Nzg5.example.bot-token"
dm_policy = "allowlist"
mention_mode = "mention"
allowlist = ["your_username"]
```
See [Discord](discord.md) for full configuration reference and setup instructions.
## Slack Integration
```toml
[channels]
offered = ["slack"]
[channels.slack.my-bot]
bot_token = "xoxb-..."
app_token = "xapp-..."
# Optional. Defaults to Slack; set only for Slack-compatible proxies/gateways.
api_base_url = "https://slack.com/api"
dm_policy = "allowlist"
allowlist = ["U123456789"]
```
See [Slack](slack.md) for full configuration reference and setup instructions.
## TLS / HTTPS
```toml
[tls]
enabled = true
cert_path = "~/.config/moltis/cert.pem"
key_path = "~/.config/moltis/key.pem"
# If custom paths are not set and auto_generate is true, Moltis generates a
# local CA and server certificate for localhost/private-network names. Public
# VPS IP access should set public_ip; public domains should use a reverse proxy
# or custom CA-issued certificates.
# public_ip = "203.0.113.10"
# Port for the plain-HTTP redirect / CA-download server.
# Defaults to the server port + 1 when not set.
# http_redirect_port = 13132
# Serve plain HTTP when bound to a loopback address (127.0.0.1, ::1,
# localhost). New installs write `true`; configs without the key keep HTTPS.
loopback_http = true
```
Override via environment variable: `MOLTIS_TLS__HTTP_REDIRECT_PORT=8080`.
### Loopback over plain HTTP
With `loopback_http = true`, a gateway bound to loopback serves
`http://localhost:<port>`. Browsers treat that origin as a secure context:
passkeys, service workers and `Secure` cookies all work, and there is no
certificate to trust. Any non-loopback bind, such as `0.0.0.0` or a LAN IP,
still uses HTTPS. Set `loopback_http = false` to keep HTTPS on localhost, for
example if you already rely on `https://localhost` bookmarks or passkeys.
### Trusting the local CA
When TLS is active with auto-generated certificates and Moltis runs from a
terminal on your desktop, it asks once whether to trust its local CA:
- **macOS:** the login keychain, which shows a password dialog.
- **Linux:** the system store via `sudo update-ca-certificates`.
- **Windows:** the user root store.
- **Firefox and Chromium:** their NSS databases, when NSS `certutil` is installed.
Moltis remembers your answer for that CA in `certs/ca-trust.txt`. Run
`moltis trust-ca` at any time to install the CA manually.
The CA carries X.509 name constraints that limit it to `localhost`,
`*.localhost`, `.local`, loopback, private (RFC 1918), CGNAT and link-local
addresses, plus any extra names the server certificate needs, such as
`public_ip` or the machine's hostname. A leaked CA key therefore cannot be used
to impersonate public websites. The CA is valid for 10 years and is kept when
the server certificate renews. A new CA is generated only when the certificate
needs a name outside its scope; you then need to trust it again. CA and server
private keys are stored with owner-only permissions.
## Opening the Browser on Start
```toml
[server]
open_browser = "first-run" # "first-run" | "always" | "never"
```
- `first-run` (default) opens the web UI until onboarding is finished.
- `always` opens it on every start.
- `never` never opens a browser.
A browser is opened only when Moltis runs in an interactive terminal on a
desktop session: never over SSH, inside a container, in CI, or under a service
manager. On Linux, a `DISPLAY` or `WAYLAND_DISPLAY` is also required. The
`--open-browser` and `--no-open-browser` flags override this setting for a
single run. The `BROWSER` environment variable selects which browser to use.
## Tailscale Integration
Expose Moltis over your Tailscale network:
```toml
[tailscale]
mode = "serve" # "off", "serve", or "funnel"
reset_on_exit = true
```
## Observability
```toml
[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.
```toml
[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.
```admonish info title="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:
| Variable | Description |
|----------|-------------|
| `MOLTIS_CONFIG_DIR` | Configuration directory |
| `MOLTIS_DATA_DIR` | Data directory |
| `MOLTIS_SERVER__PORT` | Server port override |
| `MOLTIS_SERVER__BIND` | Server bind address override |
| `MOLTIS_TOOLS__AGENT_TIMEOUT_SECS` | Agent run timeout override |
| `MOLTIS_TOOLS__AGENT_MAX_ITERATIONS` | Agent loop iteration cap override |
`MOLTIS_FILES_DIR` is different from these startup overrides: Moltis supplies
it to local command agents and `exec` as the resolved
[Managed Files](managed-files.md) path. Use it instead of assuming
`<data_dir>/files`.
## CLI Flags
```bash
moltis --config-dir /path/to/config --data-dir /path/to/data
```
## Complete Example
```toml
[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
```