Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/adolfousier_opencrabs.json
T
OpenCode 68a9071cf1 feat: reconcile local master with origin (exa/hot-platform hunters, leaks ledger, latest results)
Local branch had diverged from origin/master (sibling commits on the same base). Rewrote local history linearly on top of origin/master, folding in all local content: exa/hot-platform discovery hunters, leaks ledger, nightly sweep orchestrator, updated .gitignore and skill docs, plus the latest hunt output and vault state. Remote-only files (vault keys, channel scripts) were restored rather than dropped, so the resulting tree is a full union of both sides.
2026-08-07 12:53:47 +08:00

1 line
842 KiB
JSON

{"repo": "adolfousier/opencrabs", "files": {"config.toml.example": {"970277a7052287663a41d7c90bcdbc38542a2d50": {"t": 1785746799.281197, "n": 30543, "h": "ea825ec03e330254", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Xiaomi MiMo\n# ========================================\n# OpenAI-compatible, keyed. Get an API key (sk-...) at platform.xiaomimimo.com\n# and put it in keys.toml ([providers.xiaomi] api_key). With no key this section\n# is skipped and onboarding prompts you for one.\n#\n# base_url is optional — it defaults to the official endpoint below. Models are\n# fetched live from /v1/models (chat models only), so the /models picker shows\n# what's actually available; the list here is just an offline fallback. Thinking\n# is ON by default (the model streams its reasoning); set enable_thinking = false\n# to turn it off. Prompt caching is automatic server-side — nothing to configure.\n[providers.xiaomi]\nenabled = true\n# base_url = \"https://api.xiaomimimo.com/v1\" # optional — this is the default\ndefault_model = \"mimo-v2.5-pro\"\nmodels = [\"mimo-v2.5-pro\", \"mimo-v2-pro\", \"mimo-v2.5\", \"mimo-v2-omni\", \"mimo-v2-flash\"]\ncontext_window = 1000000 # compaction budget (auto-compacts at 65%/90%); default 200000; works on any provider\nvision_model = \"mimo-v2.5-pro\" # MiMo v2.5 is multimodal — analyze_image uses it natively (falls back to Gemini if image.vision is set)\n# enable_thinking = false # uncomment to disable the model's reasoning output\n# force_default = true # ENFORCE this provider's default pair on EVERY session.\n# By default a new default applies to NEW sessions only — existing/live\n# sessions keep their own provider+model. Set force_default = true on the\n# provider you want as the global default, and on config reload its\n# default_model pair is pushed to every non-archived session (only when this\n# section is the active default provider). Off/absent = new-sessions-only.\n\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M3\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# Command Code CLI — local `command-code` subprocess (also on PATH as `cmd`).\n# Uses your Command Code account (~/.commandcode/auth.json from `command-code\n# login`). No proxy, no API key.\n# Install: npm install -g command-code (then run `command-code login`)\n# Models per `command-code --list-models` — full ids or the short name after\n# the last `/` both work. Leave `models` unset to use the built-in list.\n[providers.command_code_cli]\nenabled = false\ndefault_model = \"deepseek/deepseek-v4-flash\"\nmodels = [\n \"claude-sonnet-5\",\n \"claude-opus-4-8\",\n \"gpt-5.5\",\n \"google/gemini-3.5-flash\",\n \"deepseek/deepseek-v4-flash\",\n \"moonshotai/Kimi-K2.7-Code\",\n \"zai-org/GLM-5.2\",\n \"Qwen/Qwen3.7-Max\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M3\"\nmodels = [\"MiniMax-M3\", \"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n[providers.moonshot]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default, api.moonshot.ai) or \"coding\" (api.kimi.com, Kimi token subscription)\ndefault_model = \"k3\"\nmodels = [\"k3\", \"kimi-for-coding\", \"kimi-for-coding-highspeed\"]\n# API key goes in keys.toml: [providers.moonshot] api_key = \"...\"\n# API plan key from platform.moonshot.ai; Coding plan key from kimi.com\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# Vision provider priority — overrides the default REGISTRATIONS scan\n# order for the analyze_image tool. Each entry is a provider name\n# (e.g. \"minimax\", \"anthropic\"). Resolution order:\n# 1. This list (first enabled match with vision_model wins)\n# 2. All enabled providers in REGISTRATIONS priority order\n# 3. Custom providers\n# 4. Gemini [image.vision] fallback\n# Empty or absent = scan all providers as before.\n# vision = [\"minimax\", \"anthropic\"]\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M3\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for the main chat session.\n# When set, new sessions inherit these values instead of the most recent session's provider/model.\n# Existing sessions pick up the new defaults on next resume (via sync_provider_for_session).\n# Useful for enforcing a specific model across all sessions without manual /models switching.\n# Priority: agent defaults > most recent session > config active provider.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# default_provider = \"xiaomi\"\n# default_model = \"mimo-v2.5-pro\"\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Lazy tool-schema loading (default: true — RECOMMENDED). Each request ships\n# only the CORE tool schemas (~4k tokens) plus `tool_search`. The agent calls\n# `tool_search(\"what I need\")` to discover and activate the extended tools\n# (browser, channels, sub-agents, media, system) on demand — they then ride on\n# subsequent requests for the session. We recommend leaving this on: load only\n# the core set and let the agent pull the rest as needed.\n#\n# Setting `lazy_tools = false` reverts to sending the FULL tool-schema set —\n# ALL ~95 tools (~20k tokens) — in EVERY single request, whether the turn uses\n# them or not. That overhead is counted by the provider on every call (real\n# cost, not just display). Only set false if a model in your setup struggles\n# to reach for `tool_search`.\n# lazy_tools = false\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n# Redact sensitive data from tool outputs and display (default: true).\n# When true, API keys, tokens, passwords, and IP addresses are redacted\n# from tool call displays and outputs. Set to false during sysadmin/devops\n# work where seeing IPs, tokens, and passwords is necessary.\n# redact_sensitive_data = false\n\n# Enable debug file logging from config, on top of the `--debug` CLI flag.\n# Lets you (or the agent, on request) turn detailed logs in ~/.opencrabs/logs/\n# on or off by flipping this to true/false. The change hot-reloads with no\n# restart. Effective state is `--debug OR debug_logs`, so the flag always wins.\ndebug_logs = false\n\n# Thinking-loop timeout in seconds (#890). If the model streams for this long\n# without emitting a single tool call, the stream is killed and retried with\n# multi-language phantom enforcement injected into the prompt. Catches the\n# failure mode where a reasoning model loops internally (thinking tokens\n# flowing, 0 tool calls) for an hour or more. Default 600 = 10 min.\n# Set to 0 to disable. Hot-reloads with no restart.\nthinking_loop_timeout_secs = 600\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Browser automation (feature: browser)\n# ========================================\n# By default each profile launches its own headless Chromium (~250-300MB each).\n# To share ONE Chromium across multiple profiles (big memory win on small VDS),\n# start a standalone instance with remote debugging:\n#\n# chromium --remote-debugging-port=9222 --headless --no-sandbox\n#\n# then point every profile's config at it. Prefer the http:// form — OpenCrabs\n# queries /json/version to find the real devtools websocket URL. (A bare\n# ws://host:port is also accepted and normalized to http:// automatically.)\n# [browser]\n# cdp_endpoint = \"http://localhost:9222\"\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n# \"auto\" — reply to all while there is at most one active sender, then switch\n# to mention-only once a second unique sender appears in the chat\n\n[channels.whatsapp]\nenabled = false\n# You pair the bot to a WhatsApp account by scanning its QR — it then runs AS\n# that account. It can be your own number (talk to it in \"Message Yourself\") or\n# any other number you own, including a WhatsApp Business account, to serve that\n# account's incoming DMs.\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\nallowed_phones = [\"+15551234567\"]\n# bot_owner = [\"+15551234567\"] # Operator phone(s) for owner-only commands. The operator can DM the\n # bot and is always allowed regardless of response_policy. Auto-seeded\n # from the first allowed_phones entry on first run; set explicitly to\n # pin a different operator than the paired account.\n# response_policy = \"auto\" # Who the bot answers. The paired account's own self-chat and bot_owner\n # are ALWAYS allowed. Options:\n # \"auto\" — legacy: open when allowed_phones is empty, else\n # owner/operator + allowed_phones (default)\n # \"owner_only\" — only the paired self-chat and bot_owner operators\n # \"allowlist\" — owner/operator + the contacts in allowed_phones\n # \"open\" — every incoming DM (business serving any customer)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789012345] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789] # Owner ID(s): owner-only commands (e.g. /cd) and gated actions.\n # Auto-seeded from the first allowed_users entry on first run; set it\n # explicitly to pin the owner instead of relying on list order.\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\" | \"auto\"\n# silence_group_start = true # Silently ignore /start from non-allowed users in groups (default: true)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n# rich_messages = true # Native rich messages — flow logs, collapsible tool calls,\n # status bubble with task preview. Default: true since v0.3.64.\n # Toggle available in the onboard dialog (/onboard:provider →\n # Telegram channel step). Set to false if your audience uses\n # Telegram Web or older clients (no HTML fallback).\n\n# Per-group access control (per-chat ACL). Tiers:\n# - allowed_users (above) = admins: may DM the bot and act in any chat.\n# - bot_owner = owner: always allowed everywhere.\n# - groups.<chat_id>.allowed_users = users allowed in THAT group ONLY. They are\n# refused in DMs unless they are also an admin/owner — this blocks the \"DM the\n# bot privately to escape group oversight\" bypass.\n# DMs are gated to admins + owner. If neither allowed_users nor bot_owner is set\n# the bot is unconfigured and stays open (no hard lockout); set either to lock down.\n# Each group may also override respond_to just for that group.\n# [channels.telegram.groups.-1001234567890]\n# allowed_users = [222333444, 555666777] # allowed in this group only, never via DM\n# respond_to = \"mention\" # per-group override of the global respond_to\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# bot_owner = [\"U12345678\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# bot_owner = [\"member_id\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "197f11516ae0be6b158319a532b98003bdd1bcee": {"t": 1785767743.2048774, "n": 30543, "h": "ea825ec03e330254", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Xiaomi MiMo\n# ========================================\n# OpenAI-compatible, keyed. Get an API key (sk-...) at platform.xiaomimimo.com\n# and put it in keys.toml ([providers.xiaomi] api_key). With no key this section\n# is skipped and onboarding prompts you for one.\n#\n# base_url is optional — it defaults to the official endpoint below. Models are\n# fetched live from /v1/models (chat models only), so the /models picker shows\n# what's actually available; the list here is just an offline fallback. Thinking\n# is ON by default (the model streams its reasoning); set enable_thinking = false\n# to turn it off. Prompt caching is automatic server-side — nothing to configure.\n[providers.xiaomi]\nenabled = true\n# base_url = \"https://api.xiaomimimo.com/v1\" # optional — this is the default\ndefault_model = \"mimo-v2.5-pro\"\nmodels = [\"mimo-v2.5-pro\", \"mimo-v2-pro\", \"mimo-v2.5\", \"mimo-v2-omni\", \"mimo-v2-flash\"]\ncontext_window = 1000000 # compaction budget (auto-compacts at 65%/90%); default 200000; works on any provider\nvision_model = \"mimo-v2.5-pro\" # MiMo v2.5 is multimodal — analyze_image uses it natively (falls back to Gemini if image.vision is set)\n# enable_thinking = false # uncomment to disable the model's reasoning output\n# force_default = true # ENFORCE this provider's default pair on EVERY session.\n# By default a new default applies to NEW sessions only — existing/live\n# sessions keep their own provider+model. Set force_default = true on the\n# provider you want as the global default, and on config reload its\n# default_model pair is pushed to every non-archived session (only when this\n# section is the active default provider). Off/absent = new-sessions-only.\n\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M3\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# Command Code CLI — local `command-code` subprocess (also on PATH as `cmd`).\n# Uses your Command Code account (~/.commandcode/auth.json from `command-code\n# login`). No proxy, no API key.\n# Install: npm install -g command-code (then run `command-code login`)\n# Models per `command-code --list-models` — full ids or the short name after\n# the last `/` both work. Leave `models` unset to use the built-in list.\n[providers.command_code_cli]\nenabled = false\ndefault_model = \"deepseek/deepseek-v4-flash\"\nmodels = [\n \"claude-sonnet-5\",\n \"claude-opus-4-8\",\n \"gpt-5.5\",\n \"google/gemini-3.5-flash\",\n \"deepseek/deepseek-v4-flash\",\n \"moonshotai/Kimi-K2.7-Code\",\n \"zai-org/GLM-5.2\",\n \"Qwen/Qwen3.7-Max\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M3\"\nmodels = [\"MiniMax-M3\", \"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n[providers.moonshot]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default, api.moonshot.ai) or \"coding\" (api.kimi.com, Kimi token subscription)\ndefault_model = \"k3\"\nmodels = [\"k3\", \"kimi-for-coding\", \"kimi-for-coding-highspeed\"]\n# API key goes in keys.toml: [providers.moonshot] api_key = \"...\"\n# API plan key from platform.moonshot.ai; Coding plan key from kimi.com\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# Vision provider priority — overrides the default REGISTRATIONS scan\n# order for the analyze_image tool. Each entry is a provider name\n# (e.g. \"minimax\", \"anthropic\"). Resolution order:\n# 1. This list (first enabled match with vision_model wins)\n# 2. All enabled providers in REGISTRATIONS priority order\n# 3. Custom providers\n# 4. Gemini [image.vision] fallback\n# Empty or absent = scan all providers as before.\n# vision = [\"minimax\", \"anthropic\"]\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M3\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for the main chat session.\n# When set, new sessions inherit these values instead of the most recent session's provider/model.\n# Existing sessions pick up the new defaults on next resume (via sync_provider_for_session).\n# Useful for enforcing a specific model across all sessions without manual /models switching.\n# Priority: agent defaults > most recent session > config active provider.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# default_provider = \"xiaomi\"\n# default_model = \"mimo-v2.5-pro\"\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Lazy tool-schema loading (default: true — RECOMMENDED). Each request ships\n# only the CORE tool schemas (~4k tokens) plus `tool_search`. The agent calls\n# `tool_search(\"what I need\")` to discover and activate the extended tools\n# (browser, channels, sub-agents, media, system) on demand — they then ride on\n# subsequent requests for the session. We recommend leaving this on: load only\n# the core set and let the agent pull the rest as needed.\n#\n# Setting `lazy_tools = false` reverts to sending the FULL tool-schema set —\n# ALL ~95 tools (~20k tokens) — in EVERY single request, whether the turn uses\n# them or not. That overhead is counted by the provider on every call (real\n# cost, not just display). Only set false if a model in your setup struggles\n# to reach for `tool_search`.\n# lazy_tools = false\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n# Redact sensitive data from tool outputs and display (default: true).\n# When true, API keys, tokens, passwords, and IP addresses are redacted\n# from tool call displays and outputs. Set to false during sysadmin/devops\n# work where seeing IPs, tokens, and passwords is necessary.\n# redact_sensitive_data = false\n\n# Enable debug file logging from config, on top of the `--debug` CLI flag.\n# Lets you (or the agent, on request) turn detailed logs in ~/.opencrabs/logs/\n# on or off by flipping this to true/false. The change hot-reloads with no\n# restart. Effective state is `--debug OR debug_logs`, so the flag always wins.\ndebug_logs = false\n\n# Thinking-loop timeout in seconds (#890). If the model streams for this long\n# without emitting a single tool call, the stream is killed and retried with\n# multi-language phantom enforcement injected into the prompt. Catches the\n# failure mode where a reasoning model loops internally (thinking tokens\n# flowing, 0 tool calls) for an hour or more. Default 600 = 10 min.\n# Set to 0 to disable. Hot-reloads with no restart.\nthinking_loop_timeout_secs = 600\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Browser automation (feature: browser)\n# ========================================\n# By default each profile launches its own headless Chromium (~250-300MB each).\n# To share ONE Chromium across multiple profiles (big memory win on small VDS),\n# start a standalone instance with remote debugging:\n#\n# chromium --remote-debugging-port=9222 --headless --no-sandbox\n#\n# then point every profile's config at it. Prefer the http:// form — OpenCrabs\n# queries /json/version to find the real devtools websocket URL. (A bare\n# ws://host:port is also accepted and normalized to http:// automatically.)\n# [browser]\n# cdp_endpoint = \"http://localhost:9222\"\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n# \"auto\" — reply to all while there is at most one active sender, then switch\n# to mention-only once a second unique sender appears in the chat\n\n[channels.whatsapp]\nenabled = false\n# You pair the bot to a WhatsApp account by scanning its QR — it then runs AS\n# that account. It can be your own number (talk to it in \"Message Yourself\") or\n# any other number you own, including a WhatsApp Business account, to serve that\n# account's incoming DMs.\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\nallowed_phones = [\"+15551234567\"]\n# bot_owner = [\"+15551234567\"] # Operator phone(s) for owner-only commands. The operator can DM the\n # bot and is always allowed regardless of response_policy. Auto-seeded\n # from the first allowed_phones entry on first run; set explicitly to\n # pin a different operator than the paired account.\n# response_policy = \"auto\" # Who the bot answers. The paired account's own self-chat and bot_owner\n # are ALWAYS allowed. Options:\n # \"auto\" — legacy: open when allowed_phones is empty, else\n # owner/operator + allowed_phones (default)\n # \"owner_only\" — only the paired self-chat and bot_owner operators\n # \"allowlist\" — owner/operator + the contacts in allowed_phones\n # \"open\" — every incoming DM (business serving any customer)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789012345] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789] # Owner ID(s): owner-only commands (e.g. /cd) and gated actions.\n # Auto-seeded from the first allowed_users entry on first run; set it\n # explicitly to pin the owner instead of relying on list order.\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\" | \"auto\"\n# silence_group_start = true # Silently ignore /start from non-allowed users in groups (default: true)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n# rich_messages = true # Native rich messages — flow logs, collapsible tool calls,\n # status bubble with task preview. Default: true since v0.3.64.\n # Toggle available in the onboard dialog (/onboard:provider →\n # Telegram channel step). Set to false if your audience uses\n # Telegram Web or older clients (no HTML fallback).\n\n# Per-group access control (per-chat ACL). Tiers:\n# - allowed_users (above) = admins: may DM the bot and act in any chat.\n# - bot_owner = owner: always allowed everywhere.\n# - groups.<chat_id>.allowed_users = users allowed in THAT group ONLY. They are\n# refused in DMs unless they are also an admin/owner — this blocks the \"DM the\n# bot privately to escape group oversight\" bypass.\n# DMs are gated to admins + owner. If neither allowed_users nor bot_owner is set\n# the bot is unconfigured and stays open (no hard lockout); set either to lock down.\n# Each group may also override respond_to just for that group.\n# [channels.telegram.groups.-1001234567890]\n# allowed_users = [222333444, 555666777] # allowed in this group only, never via DM\n# respond_to = \"mention\" # per-group override of the global respond_to\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# bot_owner = [\"U12345678\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# bot_owner = [\"member_id\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "ed61adf4176ffc57f0a94fe43eea14f5be162f06": {"t": 1785767744.5054626, "n": 30086, "h": "df8d8002ebf0a279", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Xiaomi MiMo\n# ========================================\n# OpenAI-compatible, keyed. Get an API key (sk-...) at platform.xiaomimimo.com\n# and put it in keys.toml ([providers.xiaomi] api_key). With no key this section\n# is skipped and onboarding prompts you for one.\n#\n# base_url is optional — it defaults to the official endpoint below. Models are\n# fetched live from /v1/models (chat models only), so the /models picker shows\n# what's actually available; the list here is just an offline fallback. Thinking\n# is ON by default (the model streams its reasoning); set enable_thinking = false\n# to turn it off. Prompt caching is automatic server-side — nothing to configure.\n[providers.xiaomi]\nenabled = true\n# base_url = \"https://api.xiaomimimo.com/v1\" # optional — this is the default\ndefault_model = \"mimo-v2.5-pro\"\nmodels = [\"mimo-v2.5-pro\", \"mimo-v2-pro\", \"mimo-v2.5\", \"mimo-v2-omni\", \"mimo-v2-flash\"]\ncontext_window = 1000000 # compaction budget (auto-compacts at 65%/90%); default 200000; works on any provider\nvision_model = \"mimo-v2.5-pro\" # MiMo v2.5 is multimodal — analyze_image uses it natively (falls back to Gemini if image.vision is set)\n# enable_thinking = false # uncomment to disable the model's reasoning output\n# force_default = true # ENFORCE this provider's default pair on EVERY session.\n# By default a new default applies to NEW sessions only — existing/live\n# sessions keep their own provider+model. Set force_default = true on the\n# provider you want as the global default, and on config reload its\n# default_model pair is pushed to every non-archived session (only when this\n# section is the active default provider). Off/absent = new-sessions-only.\n\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M3\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# Command Code CLI — local `command-code` subprocess (also on PATH as `cmd`).\n# Uses your Command Code account (~/.commandcode/auth.json from `command-code\n# login`). No proxy, no API key.\n# Install: npm install -g command-code (then run `command-code login`)\n# Models per `command-code --list-models` — full ids or the short name after\n# the last `/` both work. Leave `models` unset to use the built-in list.\n[providers.command_code_cli]\nenabled = false\ndefault_model = \"deepseek/deepseek-v4-flash\"\nmodels = [\n \"claude-sonnet-5\",\n \"claude-opus-4-8\",\n \"gpt-5.5\",\n \"google/gemini-3.5-flash\",\n \"deepseek/deepseek-v4-flash\",\n \"moonshotai/Kimi-K2.7-Code\",\n \"zai-org/GLM-5.2\",\n \"Qwen/Qwen3.7-Max\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M3\"\nmodels = [\"MiniMax-M3\", \"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n[providers.moonshot]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default, api.moonshot.ai) or \"coding\" (api.kimi.com, Kimi token subscription)\ndefault_model = \"k3\"\nmodels = [\"k3\", \"kimi-for-coding\", \"kimi-for-coding-highspeed\"]\n# API key goes in keys.toml: [providers.moonshot] api_key = \"...\"\n# API plan key from platform.moonshot.ai; Coding plan key from kimi.com\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# Vision provider priority — overrides the default REGISTRATIONS scan\n# order for the analyze_image tool. Each entry is a provider name\n# (e.g. \"minimax\", \"anthropic\"). Resolution order:\n# 1. This list (first enabled match with vision_model wins)\n# 2. All enabled providers in REGISTRATIONS priority order\n# 3. Custom providers\n# 4. Gemini [image.vision] fallback\n# Empty or absent = scan all providers as before.\n# vision = [\"minimax\", \"anthropic\"]\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M3\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for the main chat session.\n# When set, new sessions inherit these values instead of the most recent session's provider/model.\n# Existing sessions pick up the new defaults on next resume (via sync_provider_for_session).\n# Useful for enforcing a specific model across all sessions without manual /models switching.\n# Priority: agent defaults > most recent session > config active provider.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# default_provider = \"xiaomi\"\n# default_model = \"mimo-v2.5-pro\"\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Lazy tool-schema loading (default: true — RECOMMENDED). Each request ships\n# only the CORE tool schemas (~4k tokens) plus `tool_search`. The agent calls\n# `tool_search(\"what I need\")` to discover and activate the extended tools\n# (browser, channels, sub-agents, media, system) on demand — they then ride on\n# subsequent requests for the session. We recommend leaving this on: load only\n# the core set and let the agent pull the rest as needed.\n#\n# Setting `lazy_tools = false` reverts to sending the FULL tool-schema set —\n# ALL ~95 tools (~20k tokens) — in EVERY single request, whether the turn uses\n# them or not. That overhead is counted by the provider on every call (real\n# cost, not just display). Only set false if a model in your setup struggles\n# to reach for `tool_search`.\n# lazy_tools = false\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n# Redact sensitive data from tool outputs and display (default: true).\n# When true, API keys, tokens, passwords, and IP addresses are redacted\n# from tool call displays and outputs. Set to false during sysadmin/devops\n# work where seeing IPs, tokens, and passwords is necessary.\n# redact_sensitive_data = false\n\n# Enable debug file logging from config, on top of the `--debug` CLI flag.\n# Lets you (or the agent, on request) turn detailed logs in ~/.opencrabs/logs/\n# on or off by flipping this to true/false. The change hot-reloads with no\n# restart. Effective state is `--debug OR debug_logs`, so the flag always wins.\ndebug_logs = false\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Browser automation (feature: browser)\n# ========================================\n# By default each profile launches its own headless Chromium (~250-300MB each).\n# To share ONE Chromium across multiple profiles (big memory win on small VDS),\n# start a standalone instance with remote debugging:\n#\n# chromium --remote-debugging-port=9222 --headless --no-sandbox\n#\n# then point every profile's config at it. Prefer the http:// form — OpenCrabs\n# queries /json/version to find the real devtools websocket URL. (A bare\n# ws://host:port is also accepted and normalized to http:// automatically.)\n# [browser]\n# cdp_endpoint = \"http://localhost:9222\"\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n# \"auto\" — reply to all while there is at most one active sender, then switch\n# to mention-only once a second unique sender appears in the chat\n\n[channels.whatsapp]\nenabled = false\n# You pair the bot to a WhatsApp account by scanning its QR — it then runs AS\n# that account. It can be your own number (talk to it in \"Message Yourself\") or\n# any other number you own, including a WhatsApp Business account, to serve that\n# account's incoming DMs.\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\nallowed_phones = [\"+15551234567\"]\n# bot_owner = [\"+15551234567\"] # Operator phone(s) for owner-only commands. The operator can DM the\n # bot and is always allowed regardless of response_policy. Auto-seeded\n # from the first allowed_phones entry on first run; set explicitly to\n # pin a different operator than the paired account.\n# response_policy = \"auto\" # Who the bot answers. The paired account's own self-chat and bot_owner\n # are ALWAYS allowed. Options:\n # \"auto\" — legacy: open when allowed_phones is empty, else\n # owner/operator + allowed_phones (default)\n # \"owner_only\" — only the paired self-chat and bot_owner operators\n # \"allowlist\" — owner/operator + the contacts in allowed_phones\n # \"open\" — every incoming DM (business serving any customer)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789012345] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789] # Owner ID(s): owner-only commands (e.g. /cd) and gated actions.\n # Auto-seeded from the first allowed_users entry on first run; set it\n # explicitly to pin the owner instead of relying on list order.\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\" | \"auto\"\n# silence_group_start = true # Silently ignore /start from non-allowed users in groups (default: true)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n# rich_messages = true # Native rich messages — flow logs, collapsible tool calls,\n # status bubble with task preview. Default: true since v0.3.64.\n # Toggle available in the onboard dialog (/onboard:provider →\n # Telegram channel step). Set to false if your audience uses\n # Telegram Web or older clients (no HTML fallback).\n\n# Per-group access control (per-chat ACL). Tiers:\n# - allowed_users (above) = admins: may DM the bot and act in any chat.\n# - bot_owner = owner: always allowed everywhere.\n# - groups.<chat_id>.allowed_users = users allowed in THAT group ONLY. They are\n# refused in DMs unless they are also an admin/owner — this blocks the \"DM the\n# bot privately to escape group oversight\" bypass.\n# DMs are gated to admins + owner. If neither allowed_users nor bot_owner is set\n# the bot is unconfigured and stays open (no hard lockout); set either to lock down.\n# Each group may also override respond_to just for that group.\n# [channels.telegram.groups.-1001234567890]\n# allowed_users = [222333444, 555666777] # allowed in this group only, never via DM\n# respond_to = \"mention\" # per-group override of the global respond_to\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# bot_owner = [\"U12345678\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# bot_owner = [\"member_id\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "d862bb8c1cb83379f48d6290f5d843b3a09392ba": {"t": 1785767745.984496, "n": 29629, "h": "3dc671c92565791b", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Xiaomi MiMo\n# ========================================\n# OpenAI-compatible, keyed. Get an API key (sk-...) at platform.xiaomimimo.com\n# and put it in keys.toml ([providers.xiaomi] api_key). With no key this section\n# is skipped and onboarding prompts you for one.\n#\n# base_url is optional — it defaults to the official endpoint below. Models are\n# fetched live from /v1/models (chat models only), so the /models picker shows\n# what's actually available; the list here is just an offline fallback. Thinking\n# is ON by default (the model streams its reasoning); set enable_thinking = false\n# to turn it off. Prompt caching is automatic server-side — nothing to configure.\n[providers.xiaomi]\nenabled = true\n# base_url = \"https://api.xiaomimimo.com/v1\" # optional — this is the default\ndefault_model = \"mimo-v2.5-pro\"\nmodels = [\"mimo-v2.5-pro\", \"mimo-v2-pro\", \"mimo-v2.5\", \"mimo-v2-omni\", \"mimo-v2-flash\"]\ncontext_window = 1000000 # compaction budget (auto-compacts at 65%/90%); default 200000; works on any provider\nvision_model = \"mimo-v2.5-pro\" # MiMo v2.5 is multimodal — analyze_image uses it natively (falls back to Gemini if image.vision is set)\n# enable_thinking = false # uncomment to disable the model's reasoning output\n\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M3\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# Command Code CLI — local `command-code` subprocess (also on PATH as `cmd`).\n# Uses your Command Code account (~/.commandcode/auth.json from `command-code\n# login`). No proxy, no API key.\n# Install: npm install -g command-code (then run `command-code login`)\n# Models per `command-code --list-models` — full ids or the short name after\n# the last `/` both work. Leave `models` unset to use the built-in list.\n[providers.command_code_cli]\nenabled = false\ndefault_model = \"deepseek/deepseek-v4-flash\"\nmodels = [\n \"claude-sonnet-5\",\n \"claude-opus-4-8\",\n \"gpt-5.5\",\n \"google/gemini-3.5-flash\",\n \"deepseek/deepseek-v4-flash\",\n \"moonshotai/Kimi-K2.7-Code\",\n \"zai-org/GLM-5.2\",\n \"Qwen/Qwen3.7-Max\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M3\"\nmodels = [\"MiniMax-M3\", \"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n[providers.moonshot]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default, api.moonshot.ai) or \"coding\" (api.kimi.com, Kimi token subscription)\ndefault_model = \"k3\"\nmodels = [\"k3\", \"kimi-for-coding\", \"kimi-for-coding-highspeed\"]\n# API key goes in keys.toml: [providers.moonshot] api_key = \"...\"\n# API plan key from platform.moonshot.ai; Coding plan key from kimi.com\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# Vision provider priority — overrides the default REGISTRATIONS scan\n# order for the analyze_image tool. Each entry is a provider name\n# (e.g. \"minimax\", \"anthropic\"). Resolution order:\n# 1. This list (first enabled match with vision_model wins)\n# 2. All enabled providers in REGISTRATIONS priority order\n# 3. Custom providers\n# 4. Gemini [image.vision] fallback\n# Empty or absent = scan all providers as before.\n# vision = [\"minimax\", \"anthropic\"]\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M3\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for the main chat session.\n# When set, new sessions inherit these values instead of the most recent session's provider/model.\n# Existing sessions pick up the new defaults on next resume (via sync_provider_for_session).\n# Useful for enforcing a specific model across all sessions without manual /models switching.\n# Priority: agent defaults > most recent session > config active provider.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# default_provider = \"xiaomi\"\n# default_model = \"mimo-v2.5-pro\"\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Lazy tool-schema loading (default: true — RECOMMENDED). Each request ships\n# only the CORE tool schemas (~4k tokens) plus `tool_search`. The agent calls\n# `tool_search(\"what I need\")` to discover and activate the extended tools\n# (browser, channels, sub-agents, media, system) on demand — they then ride on\n# subsequent requests for the session. We recommend leaving this on: load only\n# the core set and let the agent pull the rest as needed.\n#\n# Setting `lazy_tools = false` reverts to sending the FULL tool-schema set —\n# ALL ~95 tools (~20k tokens) — in EVERY single request, whether the turn uses\n# them or not. That overhead is counted by the provider on every call (real\n# cost, not just display). Only set false if a model in your setup struggles\n# to reach for `tool_search`.\n# lazy_tools = false\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n# Redact sensitive data from tool outputs and display (default: true).\n# When true, API keys, tokens, passwords, and IP addresses are redacted\n# from tool call displays and outputs. Set to false during sysadmin/devops\n# work where seeing IPs, tokens, and passwords is necessary.\n# redact_sensitive_data = false\n\n# Enable debug file logging from config, on top of the `--debug` CLI flag.\n# Lets you (or the agent, on request) turn detailed logs in ~/.opencrabs/logs/\n# on or off by flipping this to true/false. The change hot-reloads with no\n# restart. Effective state is `--debug OR debug_logs`, so the flag always wins.\ndebug_logs = false\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Browser automation (feature: browser)\n# ========================================\n# By default each profile launches its own headless Chromium (~250-300MB each).\n# To share ONE Chromium across multiple profiles (big memory win on small VDS),\n# start a standalone instance with remote debugging:\n#\n# chromium --remote-debugging-port=9222 --headless --no-sandbox\n#\n# then point every profile's config at it. Prefer the http:// form — OpenCrabs\n# queries /json/version to find the real devtools websocket URL. (A bare\n# ws://host:port is also accepted and normalized to http:// automatically.)\n# [browser]\n# cdp_endpoint = \"http://localhost:9222\"\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n# \"auto\" — reply to all while there is at most one active sender, then switch\n# to mention-only once a second unique sender appears in the chat\n\n[channels.whatsapp]\nenabled = false\n# You pair the bot to a WhatsApp account by scanning its QR — it then runs AS\n# that account. It can be your own number (talk to it in \"Message Yourself\") or\n# any other number you own, including a WhatsApp Business account, to serve that\n# account's incoming DMs.\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\nallowed_phones = [\"+15551234567\"]\n# bot_owner = [\"+15551234567\"] # Operator phone(s) for owner-only commands. The operator can DM the\n # bot and is always allowed regardless of response_policy. Auto-seeded\n # from the first allowed_phones entry on first run; set explicitly to\n # pin a different operator than the paired account.\n# response_policy = \"auto\" # Who the bot answers. The paired account's own self-chat and bot_owner\n # are ALWAYS allowed. Options:\n # \"auto\" — legacy: open when allowed_phones is empty, else\n # owner/operator + allowed_phones (default)\n # \"owner_only\" — only the paired self-chat and bot_owner operators\n # \"allowlist\" — owner/operator + the contacts in allowed_phones\n # \"open\" — every incoming DM (business serving any customer)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789012345] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789] # Owner ID(s): owner-only commands (e.g. /cd) and gated actions.\n # Auto-seeded from the first allowed_users entry on first run; set it\n # explicitly to pin the owner instead of relying on list order.\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\" | \"auto\"\n# silence_group_start = true # Silently ignore /start from non-allowed users in groups (default: true)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n# rich_messages = true # Native rich messages — flow logs, collapsible tool calls,\n # status bubble with task preview. Default: true since v0.3.64.\n # Toggle available in the onboard dialog (/onboard:provider →\n # Telegram channel step). Set to false if your audience uses\n # Telegram Web or older clients (no HTML fallback).\n\n# Per-group access control (per-chat ACL). Tiers:\n# - allowed_users (above) = admins: may DM the bot and act in any chat.\n# - bot_owner = owner: always allowed everywhere.\n# - groups.<chat_id>.allowed_users = users allowed in THAT group ONLY. They are\n# refused in DMs unless they are also an admin/owner — this blocks the \"DM the\n# bot privately to escape group oversight\" bypass.\n# DMs are gated to admins + owner. If neither allowed_users nor bot_owner is set\n# the bot is unconfigured and stays open (no hard lockout); set either to lock down.\n# Each group may also override respond_to just for that group.\n# [channels.telegram.groups.-1001234567890]\n# allowed_users = [222333444, 555666777] # allowed in this group only, never via DM\n# respond_to = \"mention\" # per-group override of the global respond_to\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# bot_owner = [\"U12345678\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# bot_owner = [\"member_id\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "1617a5aa95bde5b12101182f26ce732e0aba5179": {"t": 1785767747.3536606, "n": 29300, "h": "db7ca19912f604ac", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Xiaomi MiMo\n# ========================================\n# OpenAI-compatible, keyed. Get an API key (sk-...) at platform.xiaomimimo.com\n# and put it in keys.toml ([providers.xiaomi] api_key). With no key this section\n# is skipped and onboarding prompts you for one.\n#\n# base_url is optional — it defaults to the official endpoint below. Models are\n# fetched live from /v1/models (chat models only), so the /models picker shows\n# what's actually available; the list here is just an offline fallback. Thinking\n# is ON by default (the model streams its reasoning); set enable_thinking = false\n# to turn it off. Prompt caching is automatic server-side — nothing to configure.\n[providers.xiaomi]\nenabled = true\n# base_url = \"https://api.xiaomimimo.com/v1\" # optional — this is the default\ndefault_model = \"mimo-v2.5-pro\"\nmodels = [\"mimo-v2.5-pro\", \"mimo-v2-pro\", \"mimo-v2.5\", \"mimo-v2-omni\", \"mimo-v2-flash\"]\ncontext_window = 1000000 # compaction budget (auto-compacts at 65%/90%); default 200000; works on any provider\nvision_model = \"mimo-v2.5-pro\" # MiMo v2.5 is multimodal — analyze_image uses it natively (falls back to Gemini if image.vision is set)\n# enable_thinking = false # uncomment to disable the model's reasoning output\n\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M3\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# Command Code CLI — local `command-code` subprocess (also on PATH as `cmd`).\n# Uses your Command Code account (~/.commandcode/auth.json from `command-code\n# login`). No proxy, no API key.\n# Install: npm install -g command-code (then run `command-code login`)\n# Models per `command-code --list-models` — full ids or the short name after\n# the last `/` both work. Leave `models` unset to use the built-in list.\n[providers.command_code_cli]\nenabled = false\ndefault_model = \"deepseek/deepseek-v4-flash\"\nmodels = [\n \"claude-sonnet-5\",\n \"claude-opus-4-8\",\n \"gpt-5.5\",\n \"google/gemini-3.5-flash\",\n \"deepseek/deepseek-v4-flash\",\n \"moonshotai/Kimi-K2.7-Code\",\n \"zai-org/GLM-5.2\",\n \"Qwen/Qwen3.7-Max\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M3\"\nmodels = [\"MiniMax-M3\", \"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n[providers.moonshot]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default, api.moonshot.ai) or \"coding\" (api.kimi.com, Kimi token subscription)\ndefault_model = \"k3\"\nmodels = [\"k3\", \"kimi-for-coding\", \"kimi-for-coding-highspeed\"]\n# API key goes in keys.toml: [providers.moonshot] api_key = \"...\"\n# API plan key from platform.moonshot.ai; Coding plan key from kimi.com\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# Vision provider priority — overrides the default REGISTRATIONS scan\n# order for the analyze_image tool. Each entry is a provider name\n# (e.g. \"minimax\", \"anthropic\"). Resolution order:\n# 1. This list (first enabled match with vision_model wins)\n# 2. All enabled providers in REGISTRATIONS priority order\n# 3. Custom providers\n# 4. Gemini [image.vision] fallback\n# Empty or absent = scan all providers as before.\n# vision = [\"minimax\", \"anthropic\"]\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M3\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for the main chat session.\n# When set, new sessions inherit these values instead of the most recent session's provider/model.\n# Existing sessions pick up the new defaults on next resume (via sync_provider_for_session).\n# Useful for enforcing a specific model across all sessions without manual /models switching.\n# Priority: agent defaults > most recent session > config active provider.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# default_provider = \"xiaomi\"\n# default_model = \"mimo-v2.5-pro\"\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Lazy tool-schema loading (default: true — RECOMMENDED). Each request ships\n# only the CORE tool schemas (~4k tokens) plus `tool_search`. The agent calls\n# `tool_search(\"what I need\")` to discover and activate the extended tools\n# (browser, channels, sub-agents, media, system) on demand — they then ride on\n# subsequent requests for the session. We recommend leaving this on: load only\n# the core set and let the agent pull the rest as needed.\n#\n# Setting `lazy_tools = false` reverts to sending the FULL tool-schema set —\n# ALL ~95 tools (~20k tokens) — in EVERY single request, whether the turn uses\n# them or not. That overhead is counted by the provider on every call (real\n# cost, not just display). Only set false if a model in your setup struggles\n# to reach for `tool_search`.\n# lazy_tools = false\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n# Redact sensitive data from tool outputs and display (default: true).\n# When true, API keys, tokens, passwords, and IP addresses are redacted\n# from tool call displays and outputs. Set to false during sysadmin/devops\n# work where seeing IPs, tokens, and passwords is necessary.\n# redact_sensitive_data = false\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Browser automation (feature: browser)\n# ========================================\n# By default each profile launches its own headless Chromium (~250-300MB each).\n# To share ONE Chromium across multiple profiles (big memory win on small VDS),\n# start a standalone instance with remote debugging:\n#\n# chromium --remote-debugging-port=9222 --headless --no-sandbox\n#\n# then point every profile's config at it. Prefer the http:// form — OpenCrabs\n# queries /json/version to find the real devtools websocket URL. (A bare\n# ws://host:port is also accepted and normalized to http:// automatically.)\n# [browser]\n# cdp_endpoint = \"http://localhost:9222\"\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n# \"auto\" — reply to all while there is at most one active sender, then switch\n# to mention-only once a second unique sender appears in the chat\n\n[channels.whatsapp]\nenabled = false\n# You pair the bot to a WhatsApp account by scanning its QR — it then runs AS\n# that account. It can be your own number (talk to it in \"Message Yourself\") or\n# any other number you own, including a WhatsApp Business account, to serve that\n# account's incoming DMs.\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\nallowed_phones = [\"+15551234567\"]\n# bot_owner = [\"+15551234567\"] # Operator phone(s) for owner-only commands. The operator can DM the\n # bot and is always allowed regardless of response_policy. Auto-seeded\n # from the first allowed_phones entry on first run; set explicitly to\n # pin a different operator than the paired account.\n# response_policy = \"auto\" # Who the bot answers. The paired account's own self-chat and bot_owner\n # are ALWAYS allowed. Options:\n # \"auto\" — legacy: open when allowed_phones is empty, else\n # owner/operator + allowed_phones (default)\n # \"owner_only\" — only the paired self-chat and bot_owner operators\n # \"allowlist\" — owner/operator + the contacts in allowed_phones\n # \"open\" — every incoming DM (business serving any customer)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789012345] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789] # Owner ID(s): owner-only commands (e.g. /cd) and gated actions.\n # Auto-seeded from the first allowed_users entry on first run; set it\n # explicitly to pin the owner instead of relying on list order.\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\" | \"auto\"\n# silence_group_start = true # Silently ignore /start from non-allowed users in groups (default: true)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n# rich_messages = true # Native rich messages — flow logs, collapsible tool calls,\n # status bubble with task preview. Default: true since v0.3.64.\n # Toggle available in the onboard dialog (/onboard:provider →\n # Telegram channel step). Set to false if your audience uses\n # Telegram Web or older clients (no HTML fallback).\n\n# Per-group access control (per-chat ACL). Tiers:\n# - allowed_users (above) = admins: may DM the bot and act in any chat.\n# - bot_owner = owner: always allowed everywhere.\n# - groups.<chat_id>.allowed_users = users allowed in THAT group ONLY. They are\n# refused in DMs unless they are also an admin/owner — this blocks the \"DM the\n# bot privately to escape group oversight\" bypass.\n# DMs are gated to admins + owner. If neither allowed_users nor bot_owner is set\n# the bot is unconfigured and stays open (no hard lockout); set either to lock down.\n# Each group may also override respond_to just for that group.\n# [channels.telegram.groups.-1001234567890]\n# allowed_users = [222333444, 555666777] # allowed in this group only, never via DM\n# respond_to = \"mention\" # per-group override of the global respond_to\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# bot_owner = [\"U12345678\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# bot_owner = [\"member_id\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "e4d540effbc67451d50ab3d64fa63916d3ffbbc7": {"t": 1785767748.7680044, "n": 29292, "h": "529f2f4dc485d0e7", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Xiaomi MiMo\n# ========================================\n# OpenAI-compatible, keyed. Get an API key (sk-...) at platform.xiaomimimo.com\n# and put it in keys.toml ([providers.xiaomi] api_key). With no key this section\n# is skipped and onboarding prompts you for one.\n#\n# base_url is optional — it defaults to the official endpoint below. Models are\n# fetched live from /v1/models (chat models only), so the /models picker shows\n# what's actually available; the list here is just an offline fallback. Thinking\n# is ON by default (the model streams its reasoning); set enable_thinking = false\n# to turn it off. Prompt caching is automatic server-side — nothing to configure.\n[providers.xiaomi]\nenabled = true\n# base_url = \"https://api.xiaomimimo.com/v1\" # optional — this is the default\ndefault_model = \"mimo-v2.5-pro\"\nmodels = [\"mimo-v2.5-pro\", \"mimo-v2-pro\", \"mimo-v2.5\", \"mimo-v2-omni\", \"mimo-v2-flash\"]\ncontext_window = 1000000 # compaction budget (auto-compacts at 65%/90%); default 200000; works on any provider\nvision_model = \"mimo-v2.5-pro\" # MiMo v2.5 is multimodal — analyze_image uses it natively (falls back to Gemini if image.vision is set)\n# enable_thinking = false # uncomment to disable the model's reasoning output\n\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M2.7\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# Command Code CLI — local `command-code` subprocess (also on PATH as `cmd`).\n# Uses your Command Code account (~/.commandcode/auth.json from `command-code\n# login`). No proxy, no API key.\n# Install: npm install -g command-code (then run `command-code login`)\n# Models per `command-code --list-models` — full ids or the short name after\n# the last `/` both work. Leave `models` unset to use the built-in list.\n[providers.command_code_cli]\nenabled = false\ndefault_model = \"deepseek/deepseek-v4-flash\"\nmodels = [\n \"claude-sonnet-5\",\n \"claude-opus-4-8\",\n \"gpt-5.5\",\n \"google/gemini-3.5-flash\",\n \"deepseek/deepseek-v4-flash\",\n \"moonshotai/Kimi-K2.7-Code\",\n \"zai-org/GLM-5.2\",\n \"Qwen/Qwen3.7-Max\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M2.7\"\nmodels = [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n[providers.moonshot]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default, api.moonshot.ai) or \"coding\" (api.kimi.com, Kimi token subscription)\ndefault_model = \"k3\"\nmodels = [\"k3\", \"kimi-for-coding\", \"kimi-for-coding-highspeed\"]\n# API key goes in keys.toml: [providers.moonshot] api_key = \"...\"\n# API plan key from platform.moonshot.ai; Coding plan key from kimi.com\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# Vision provider priority — overrides the default REGISTRATIONS scan\n# order for the analyze_image tool. Each entry is a provider name\n# (e.g. \"minimax\", \"anthropic\"). Resolution order:\n# 1. This list (first enabled match with vision_model wins)\n# 2. All enabled providers in REGISTRATIONS priority order\n# 3. Custom providers\n# 4. Gemini [image.vision] fallback\n# Empty or absent = scan all providers as before.\n# vision = [\"minimax\", \"anthropic\"]\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M2.7\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for the main chat session.\n# When set, new sessions inherit these values instead of the most recent session's provider/model.\n# Existing sessions pick up the new defaults on next resume (via sync_provider_for_session).\n# Useful for enforcing a specific model across all sessions without manual /models switching.\n# Priority: agent defaults > most recent session > config active provider.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# default_provider = \"xiaomi\"\n# default_model = \"mimo-v2.5-pro\"\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Lazy tool-schema loading (default: true — RECOMMENDED). Each request ships\n# only the CORE tool schemas (~4k tokens) plus `tool_search`. The agent calls\n# `tool_search(\"what I need\")` to discover and activate the extended tools\n# (browser, channels, sub-agents, media, system) on demand — they then ride on\n# subsequent requests for the session. We recommend leaving this on: load only\n# the core set and let the agent pull the rest as needed.\n#\n# Setting `lazy_tools = false` reverts to sending the FULL tool-schema set —\n# ALL ~95 tools (~20k tokens) — in EVERY single request, whether the turn uses\n# them or not. That overhead is counted by the provider on every call (real\n# cost, not just display). Only set false if a model in your setup struggles\n# to reach for `tool_search`.\n# lazy_tools = false\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n# Redact sensitive data from tool outputs and display (default: true).\n# When true, API keys, tokens, passwords, and IP addresses are redacted\n# from tool call displays and outputs. Set to false during sysadmin/devops\n# work where seeing IPs, tokens, and passwords is necessary.\n# redact_sensitive_data = false\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Browser automation (feature: browser)\n# ========================================\n# By default each profile launches its own headless Chromium (~250-300MB each).\n# To share ONE Chromium across multiple profiles (big memory win on small VDS),\n# start a standalone instance with remote debugging:\n#\n# chromium --remote-debugging-port=9222 --headless --no-sandbox\n#\n# then point every profile's config at it. Prefer the http:// form — OpenCrabs\n# queries /json/version to find the real devtools websocket URL. (A bare\n# ws://host:port is also accepted and normalized to http:// automatically.)\n# [browser]\n# cdp_endpoint = \"http://localhost:9222\"\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n# \"auto\" — reply to all while there is at most one active sender, then switch\n# to mention-only once a second unique sender appears in the chat\n\n[channels.whatsapp]\nenabled = false\n# You pair the bot to a WhatsApp account by scanning its QR — it then runs AS\n# that account. It can be your own number (talk to it in \"Message Yourself\") or\n# any other number you own, including a WhatsApp Business account, to serve that\n# account's incoming DMs.\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\nallowed_phones = [\"+15551234567\"]\n# bot_owner = [\"+15551234567\"] # Operator phone(s) for owner-only commands. The operator can DM the\n # bot and is always allowed regardless of response_policy. Auto-seeded\n # from the first allowed_phones entry on first run; set explicitly to\n # pin a different operator than the paired account.\n# response_policy = \"auto\" # Who the bot answers. The paired account's own self-chat and bot_owner\n # are ALWAYS allowed. Options:\n # \"auto\" — legacy: open when allowed_phones is empty, else\n # owner/operator + allowed_phones (default)\n # \"owner_only\" — only the paired self-chat and bot_owner operators\n # \"allowlist\" — owner/operator + the contacts in allowed_phones\n # \"open\" — every incoming DM (business serving any customer)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789012345] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789] # Owner ID(s): owner-only commands (e.g. /cd) and gated actions.\n # Auto-seeded from the first allowed_users entry on first run; set it\n # explicitly to pin the owner instead of relying on list order.\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\" | \"auto\"\n# silence_group_start = true # Silently ignore /start from non-allowed users in groups (default: true)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n# rich_messages = true # Native rich messages — flow logs, collapsible tool calls,\n # status bubble with task preview. Default: true since v0.3.64.\n # Toggle available in the onboard dialog (/onboard:provider →\n # Telegram channel step). Set to false if your audience uses\n # Telegram Web or older clients (no HTML fallback).\n\n# Per-group access control (per-chat ACL). Tiers:\n# - allowed_users (above) = admins: may DM the bot and act in any chat.\n# - bot_owner = owner: always allowed everywhere.\n# - groups.<chat_id>.allowed_users = users allowed in THAT group ONLY. They are\n# refused in DMs unless they are also an admin/owner — this blocks the \"DM the\n# bot privately to escape group oversight\" bypass.\n# DMs are gated to admins + owner. If neither allowed_users nor bot_owner is set\n# the bot is unconfigured and stays open (no hard lockout); set either to lock down.\n# Each group may also override respond_to just for that group.\n# [channels.telegram.groups.-1001234567890]\n# allowed_users = [222333444, 555666777] # allowed in this group only, never via DM\n# respond_to = \"mention\" # per-group override of the global respond_to\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# bot_owner = [\"U12345678\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# bot_owner = [\"member_id\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "745ad200db3fd91f925ad0e31190c4e6634bd49b": {"t": 1785767750.0837982, "n": 28916, "h": "8f05b91bcd12be67", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Xiaomi MiMo\n# ========================================\n# OpenAI-compatible, keyed. Get an API key (sk-...) at platform.xiaomimimo.com\n# and put it in keys.toml ([providers.xiaomi] api_key). With no key this section\n# is skipped and onboarding prompts you for one.\n#\n# base_url is optional — it defaults to the official endpoint below. Models are\n# fetched live from /v1/models (chat models only), so the /models picker shows\n# what's actually available; the list here is just an offline fallback. Thinking\n# is ON by default (the model streams its reasoning); set enable_thinking = false\n# to turn it off. Prompt caching is automatic server-side — nothing to configure.\n[providers.xiaomi]\nenabled = true\n# base_url = \"https://api.xiaomimimo.com/v1\" # optional — this is the default\ndefault_model = \"mimo-v2.5-pro\"\nmodels = [\"mimo-v2.5-pro\", \"mimo-v2-pro\", \"mimo-v2.5\", \"mimo-v2-omni\", \"mimo-v2-flash\"]\ncontext_window = 1000000 # compaction budget (auto-compacts at 65%/90%); default 200000; works on any provider\nvision_model = \"mimo-v2.5-pro\" # MiMo v2.5 is multimodal — analyze_image uses it natively (falls back to Gemini if image.vision is set)\n# enable_thinking = false # uncomment to disable the model's reasoning output\n\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M2.7\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# Command Code CLI — local `command-code` subprocess (also on PATH as `cmd`).\n# Uses your Command Code account (~/.commandcode/auth.json from `command-code\n# login`). No proxy, no API key.\n# Install: npm install -g command-code (then run `command-code login`)\n# Models per `command-code --list-models` — full ids or the short name after\n# the last `/` both work. Leave `models` unset to use the built-in list.\n[providers.command_code_cli]\nenabled = false\ndefault_model = \"deepseek/deepseek-v4-flash\"\nmodels = [\n \"claude-sonnet-5\",\n \"claude-opus-4-8\",\n \"gpt-5.5\",\n \"google/gemini-3.5-flash\",\n \"deepseek/deepseek-v4-flash\",\n \"moonshotai/Kimi-K2.7-Code\",\n \"zai-org/GLM-5.2\",\n \"Qwen/Qwen3.7-Max\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M2.7\"\nmodels = [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# Vision provider priority — overrides the default REGISTRATIONS scan\n# order for the analyze_image tool. Each entry is a provider name\n# (e.g. \"minimax\", \"anthropic\"). Resolution order:\n# 1. This list (first enabled match with vision_model wins)\n# 2. All enabled providers in REGISTRATIONS priority order\n# 3. Custom providers\n# 4. Gemini [image.vision] fallback\n# Empty or absent = scan all providers as before.\n# vision = [\"minimax\", \"anthropic\"]\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M2.7\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for the main chat session.\n# When set, new sessions inherit these values instead of the most recent session's provider/model.\n# Existing sessions pick up the new defaults on next resume (via sync_provider_for_session).\n# Useful for enforcing a specific model across all sessions without manual /models switching.\n# Priority: agent defaults > most recent session > config active provider.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# default_provider = \"xiaomi\"\n# default_model = \"mimo-v2.5-pro\"\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Lazy tool-schema loading (default: true — RECOMMENDED). Each request ships\n# only the CORE tool schemas (~4k tokens) plus `tool_search`. The agent calls\n# `tool_search(\"what I need\")` to discover and activate the extended tools\n# (browser, channels, sub-agents, media, system) on demand — they then ride on\n# subsequent requests for the session. We recommend leaving this on: load only\n# the core set and let the agent pull the rest as needed.\n#\n# Setting `lazy_tools = false` reverts to sending the FULL tool-schema set —\n# ALL ~95 tools (~20k tokens) — in EVERY single request, whether the turn uses\n# them or not. That overhead is counted by the provider on every call (real\n# cost, not just display). Only set false if a model in your setup struggles\n# to reach for `tool_search`.\n# lazy_tools = false\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n# Redact sensitive data from tool outputs and display (default: true).\n# When true, API keys, tokens, passwords, and IP addresses are redacted\n# from tool call displays and outputs. Set to false during sysadmin/devops\n# work where seeing IPs, tokens, and passwords is necessary.\n# redact_sensitive_data = false\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Browser automation (feature: browser)\n# ========================================\n# By default each profile launches its own headless Chromium (~250-300MB each).\n# To share ONE Chromium across multiple profiles (big memory win on small VDS),\n# start a standalone instance with remote debugging:\n#\n# chromium --remote-debugging-port=9222 --headless --no-sandbox\n#\n# then point every profile's config at it. Prefer the http:// form — OpenCrabs\n# queries /json/version to find the real devtools websocket URL. (A bare\n# ws://host:port is also accepted and normalized to http:// automatically.)\n# [browser]\n# cdp_endpoint = \"http://localhost:9222\"\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n# \"auto\" — reply to all while there is at most one active sender, then switch\n# to mention-only once a second unique sender appears in the chat\n\n[channels.whatsapp]\nenabled = false\n# You pair the bot to a WhatsApp account by scanning its QR — it then runs AS\n# that account. It can be your own number (talk to it in \"Message Yourself\") or\n# any other number you own, including a WhatsApp Business account, to serve that\n# account's incoming DMs.\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\nallowed_phones = [\"+15551234567\"]\n# bot_owner = [\"+15551234567\"] # Operator phone(s) for owner-only commands. The operator can DM the\n # bot and is always allowed regardless of response_policy. Auto-seeded\n # from the first allowed_phones entry on first run; set explicitly to\n # pin a different operator than the paired account.\n# response_policy = \"auto\" # Who the bot answers. The paired account's own self-chat and bot_owner\n # are ALWAYS allowed. Options:\n # \"auto\" — legacy: open when allowed_phones is empty, else\n # owner/operator + allowed_phones (default)\n # \"owner_only\" — only the paired self-chat and bot_owner operators\n # \"allowlist\" — owner/operator + the contacts in allowed_phones\n # \"open\" — every incoming DM (business serving any customer)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789012345] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789] # Owner ID(s): owner-only commands (e.g. /cd) and gated actions.\n # Auto-seeded from the first allowed_users entry on first run; set it\n # explicitly to pin the owner instead of relying on list order.\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\" | \"auto\"\n# silence_group_start = true # Silently ignore /start from non-allowed users in groups (default: true)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n# rich_messages = true # Native rich messages — flow logs, collapsible tool calls,\n # status bubble with task preview. Default: true since v0.3.64.\n # Toggle available in the onboard dialog (/onboard:provider →\n # Telegram channel step). Set to false if your audience uses\n # Telegram Web or older clients (no HTML fallback).\n\n# Per-group access control (per-chat ACL). Tiers:\n# - allowed_users (above) = admins: may DM the bot and act in any chat.\n# - bot_owner = owner: always allowed everywhere.\n# - groups.<chat_id>.allowed_users = users allowed in THAT group ONLY. They are\n# refused in DMs unless they are also an admin/owner — this blocks the \"DM the\n# bot privately to escape group oversight\" bypass.\n# DMs are gated to admins + owner. If neither allowed_users nor bot_owner is set\n# the bot is unconfigured and stays open (no hard lockout); set either to lock down.\n# Each group may also override respond_to just for that group.\n# [channels.telegram.groups.-1001234567890]\n# allowed_users = [222333444, 555666777] # allowed in this group only, never via DM\n# respond_to = \"mention\" # per-group override of the global respond_to\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# bot_owner = [\"U12345678\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# bot_owner = [\"member_id\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "15a57720ac60935032649a3b94eebc915417f648": {"t": 1785767751.6971264, "n": 28749, "h": "907768eba5a4d039", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Xiaomi MiMo\n# ========================================\n# OpenAI-compatible, keyed. Get an API key (sk-...) at platform.xiaomimimo.com\n# and put it in keys.toml ([providers.xiaomi] api_key). With no key this section\n# is skipped and onboarding prompts you for one.\n#\n# base_url is optional — it defaults to the official endpoint below. Models are\n# fetched live from /v1/models (chat models only), so the /models picker shows\n# what's actually available; the list here is just an offline fallback. Thinking\n# is ON by default (the model streams its reasoning); set enable_thinking = false\n# to turn it off. Prompt caching is automatic server-side — nothing to configure.\n[providers.xiaomi]\nenabled = true\n# base_url = \"https://api.xiaomimimo.com/v1\" # optional — this is the default\ndefault_model = \"mimo-v2.5-pro\"\nmodels = [\"mimo-v2.5-pro\", \"mimo-v2-pro\", \"mimo-v2.5\", \"mimo-v2-omni\", \"mimo-v2-flash\"]\ncontext_window = 1000000 # compaction budget (auto-compacts at 65%/90%); default 200000; works on any provider\nvision_model = \"mimo-v2.5-pro\" # MiMo v2.5 is multimodal — analyze_image uses it natively (falls back to Gemini if image.vision is set)\n# enable_thinking = false # uncomment to disable the model's reasoning output\n\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M2.7\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# Command Code CLI — local `cmd` subprocess. Uses your Command Code account\n# (~/.commandcode/auth.json from `cmd login`). No proxy, no API key.\n# Install: npm install -g command-code (then run `cmd login`)\n# Models per `cmd --list-models`. taste-1 is the flagship meta model.\n[providers.command_code_cli]\nenabled = false\ndefault_model = \"taste-1\"\nmodels = [\n \"taste-1\",\n \"deepseek/deepseek-v4-flash\",\n \"moonshotai/Kimi-K2.7-Code\",\n \"zai-org/GLM-5.2\",\n \"xiaomi/mimo-v2.5\",\n \"MiniMaxAI/MiniMax-M2.7\",\n \"Qwen/Qwen3.6-Max-Preview\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M2.7\"\nmodels = [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# Vision provider priority — overrides the default REGISTRATIONS scan\n# order for the analyze_image tool. Each entry is a provider name\n# (e.g. \"minimax\", \"anthropic\"). Resolution order:\n# 1. This list (first enabled match with vision_model wins)\n# 2. All enabled providers in REGISTRATIONS priority order\n# 3. Custom providers\n# 4. Gemini [image.vision] fallback\n# Empty or absent = scan all providers as before.\n# vision = [\"minimax\", \"anthropic\"]\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M2.7\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for the main chat session.\n# When set, new sessions inherit these values instead of the most recent session's provider/model.\n# Existing sessions pick up the new defaults on next resume (via sync_provider_for_session).\n# Useful for enforcing a specific model across all sessions without manual /models switching.\n# Priority: agent defaults > most recent session > config active provider.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# default_provider = \"xiaomi\"\n# default_model = \"mimo-v2.5-pro\"\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Lazy tool-schema loading (default: true — RECOMMENDED). Each request ships\n# only the CORE tool schemas (~4k tokens) plus `tool_search`. The agent calls\n# `tool_search(\"what I need\")` to discover and activate the extended tools\n# (browser, channels, sub-agents, media, system) on demand — they then ride on\n# subsequent requests for the session. We recommend leaving this on: load only\n# the core set and let the agent pull the rest as needed.\n#\n# Setting `lazy_tools = false` reverts to sending the FULL tool-schema set —\n# ALL ~95 tools (~20k tokens) — in EVERY single request, whether the turn uses\n# them or not. That overhead is counted by the provider on every call (real\n# cost, not just display). Only set false if a model in your setup struggles\n# to reach for `tool_search`.\n# lazy_tools = false\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n# Redact sensitive data from tool outputs and display (default: true).\n# When true, API keys, tokens, passwords, and IP addresses are redacted\n# from tool call displays and outputs. Set to false during sysadmin/devops\n# work where seeing IPs, tokens, and passwords is necessary.\n# redact_sensitive_data = false\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Browser automation (feature: browser)\n# ========================================\n# By default each profile launches its own headless Chromium (~250-300MB each).\n# To share ONE Chromium across multiple profiles (big memory win on small VDS),\n# start a standalone instance with remote debugging:\n#\n# chromium --remote-debugging-port=9222 --headless --no-sandbox\n#\n# then point every profile's config at it. Prefer the http:// form — OpenCrabs\n# queries /json/version to find the real devtools websocket URL. (A bare\n# ws://host:port is also accepted and normalized to http:// automatically.)\n# [browser]\n# cdp_endpoint = \"http://localhost:9222\"\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n# \"auto\" — reply to all while there is at most one active sender, then switch\n# to mention-only once a second unique sender appears in the chat\n\n[channels.whatsapp]\nenabled = false\n# You pair the bot to a WhatsApp account by scanning its QR — it then runs AS\n# that account. It can be your own number (talk to it in \"Message Yourself\") or\n# any other number you own, including a WhatsApp Business account, to serve that\n# account's incoming DMs.\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\nallowed_phones = [\"+15551234567\"]\n# bot_owner = [\"+15551234567\"] # Operator phone(s) for owner-only commands. The operator can DM the\n # bot and is always allowed regardless of response_policy. Auto-seeded\n # from the first allowed_phones entry on first run; set explicitly to\n # pin a different operator than the paired account.\n# response_policy = \"auto\" # Who the bot answers. The paired account's own self-chat and bot_owner\n # are ALWAYS allowed. Options:\n # \"auto\" — legacy: open when allowed_phones is empty, else\n # owner/operator + allowed_phones (default)\n # \"owner_only\" — only the paired self-chat and bot_owner operators\n # \"allowlist\" — owner/operator + the contacts in allowed_phones\n # \"open\" — every incoming DM (business serving any customer)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789012345] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789] # Owner ID(s): owner-only commands (e.g. /cd) and gated actions.\n # Auto-seeded from the first allowed_users entry on first run; set it\n # explicitly to pin the owner instead of relying on list order.\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\" | \"auto\"\n# silence_group_start = true # Silently ignore /start from non-allowed users in groups (default: true)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n# rich_messages = true # Native rich messages — flow logs, collapsible tool calls,\n # status bubble with task preview. Default: true since v0.3.64.\n # Toggle available in the onboard dialog (/onboard:provider →\n # Telegram channel step). Set to false if your audience uses\n # Telegram Web or older clients (no HTML fallback).\n\n# Per-group access control (per-chat ACL). Tiers:\n# - allowed_users (above) = admins: may DM the bot and act in any chat.\n# - bot_owner = owner: always allowed everywhere.\n# - groups.<chat_id>.allowed_users = users allowed in THAT group ONLY. They are\n# refused in DMs unless they are also an admin/owner — this blocks the \"DM the\n# bot privately to escape group oversight\" bypass.\n# DMs are gated to admins + owner. If neither allowed_users nor bot_owner is set\n# the bot is unconfigured and stays open (no hard lockout); set either to lock down.\n# Each group may also override respond_to just for that group.\n# [channels.telegram.groups.-1001234567890]\n# allowed_users = [222333444, 555666777] # allowed in this group only, never via DM\n# respond_to = \"mention\" # per-group override of the global respond_to\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# bot_owner = [\"U12345678\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# bot_owner = [\"member_id\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "caf9a36d695516d06917c31949183396e006c0d5": {"t": 1785767753.3953898, "n": 28194, "h": "b9bd01c0ebdfa6f1", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Xiaomi MiMo\n# ========================================\n# OpenAI-compatible, keyed. Get an API key (sk-...) at platform.xiaomimimo.com\n# and put it in keys.toml ([providers.xiaomi] api_key). With no key this section\n# is skipped and onboarding prompts you for one.\n#\n# base_url is optional — it defaults to the official endpoint below. Models are\n# fetched live from /v1/models (chat models only), so the /models picker shows\n# what's actually available; the list here is just an offline fallback. Thinking\n# is ON by default (the model streams its reasoning); set enable_thinking = false\n# to turn it off. Prompt caching is automatic server-side — nothing to configure.\n[providers.xiaomi]\nenabled = true\n# base_url = \"https://api.xiaomimimo.com/v1\" # optional — this is the default\ndefault_model = \"mimo-v2.5-pro\"\nmodels = [\"mimo-v2.5-pro\", \"mimo-v2-pro\", \"mimo-v2.5\", \"mimo-v2-omni\", \"mimo-v2-flash\"]\ncontext_window = 1000000 # compaction budget (auto-compacts at 65%/90%); default 200000; works on any provider\nvision_model = \"mimo-v2.5-pro\" # MiMo v2.5 is multimodal — analyze_image uses it natively (falls back to Gemini if image.vision is set)\n# enable_thinking = false # uncomment to disable the model's reasoning output\n\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M2.7\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M2.7\"\nmodels = [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# Vision provider priority — overrides the default REGISTRATIONS scan\n# order for the analyze_image tool. Each entry is a provider name\n# (e.g. \"minimax\", \"anthropic\"). Resolution order:\n# 1. This list (first enabled match with vision_model wins)\n# 2. All enabled providers in REGISTRATIONS priority order\n# 3. Custom providers\n# 4. Gemini [image.vision] fallback\n# Empty or absent = scan all providers as before.\n# vision = [\"minimax\", \"anthropic\"]\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M2.7\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for the main chat session.\n# When set, new sessions inherit these values instead of the most recent session's provider/model.\n# Existing sessions pick up the new defaults on next resume (via sync_provider_for_session).\n# Useful for enforcing a specific model across all sessions without manual /models switching.\n# Priority: agent defaults > most recent session > config active provider.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# default_provider = \"xiaomi\"\n# default_model = \"mimo-v2.5-pro\"\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Lazy tool-schema loading (default: true — RECOMMENDED). Each request ships\n# only the CORE tool schemas (~4k tokens) plus `tool_search`. The agent calls\n# `tool_search(\"what I need\")` to discover and activate the extended tools\n# (browser, channels, sub-agents, media, system) on demand — they then ride on\n# subsequent requests for the session. We recommend leaving this on: load only\n# the core set and let the agent pull the rest as needed.\n#\n# Setting `lazy_tools = false` reverts to sending the FULL tool-schema set —\n# ALL ~95 tools (~20k tokens) — in EVERY single request, whether the turn uses\n# them or not. That overhead is counted by the provider on every call (real\n# cost, not just display). Only set false if a model in your setup struggles\n# to reach for `tool_search`.\n# lazy_tools = false\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n# Redact sensitive data from tool outputs and display (default: true).\n# When true, API keys, tokens, passwords, and IP addresses are redacted\n# from tool call displays and outputs. Set to false during sysadmin/devops\n# work where seeing IPs, tokens, and passwords is necessary.\n# redact_sensitive_data = false\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Browser automation (feature: browser)\n# ========================================\n# By default each profile launches its own headless Chromium (~250-300MB each).\n# To share ONE Chromium across multiple profiles (big memory win on small VDS),\n# start a standalone instance with remote debugging:\n#\n# chromium --remote-debugging-port=9222 --headless --no-sandbox\n#\n# then point every profile's config at it. Prefer the http:// form — OpenCrabs\n# queries /json/version to find the real devtools websocket URL. (A bare\n# ws://host:port is also accepted and normalized to http:// automatically.)\n# [browser]\n# cdp_endpoint = \"http://localhost:9222\"\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n# \"auto\" — reply to all while there is at most one active sender, then switch\n# to mention-only once a second unique sender appears in the chat\n\n[channels.whatsapp]\nenabled = false\n# You pair the bot to a WhatsApp account by scanning its QR — it then runs AS\n# that account. It can be your own number (talk to it in \"Message Yourself\") or\n# any other number you own, including a WhatsApp Business account, to serve that\n# account's incoming DMs.\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\nallowed_phones = [\"+15551234567\"]\n# bot_owner = [\"+15551234567\"] # Operator phone(s) for owner-only commands. The operator can DM the\n # bot and is always allowed regardless of response_policy. Auto-seeded\n # from the first allowed_phones entry on first run; set explicitly to\n # pin a different operator than the paired account.\n# response_policy = \"auto\" # Who the bot answers. The paired account's own self-chat and bot_owner\n # are ALWAYS allowed. Options:\n # \"auto\" — legacy: open when allowed_phones is empty, else\n # owner/operator + allowed_phones (default)\n # \"owner_only\" — only the paired self-chat and bot_owner operators\n # \"allowlist\" — owner/operator + the contacts in allowed_phones\n # \"open\" — every incoming DM (business serving any customer)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789012345] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789] # Owner ID(s): owner-only commands (e.g. /cd) and gated actions.\n # Auto-seeded from the first allowed_users entry on first run; set it\n # explicitly to pin the owner instead of relying on list order.\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\" | \"auto\"\n# silence_group_start = true # Silently ignore /start from non-allowed users in groups (default: true)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n# rich_messages = true # Native rich messages — flow logs, collapsible tool calls,\n # status bubble with task preview. Default: true since v0.3.64.\n # Toggle available in the onboard dialog (/onboard:provider →\n # Telegram channel step). Set to false if your audience uses\n # Telegram Web or older clients (no HTML fallback).\n\n# Per-group access control (per-chat ACL). Tiers:\n# - allowed_users (above) = admins: may DM the bot and act in any chat.\n# - bot_owner = owner: always allowed everywhere.\n# - groups.<chat_id>.allowed_users = users allowed in THAT group ONLY. They are\n# refused in DMs unless they are also an admin/owner — this blocks the \"DM the\n# bot privately to escape group oversight\" bypass.\n# DMs are gated to admins + owner. If neither allowed_users nor bot_owner is set\n# the bot is unconfigured and stays open (no hard lockout); set either to lock down.\n# Each group may also override respond_to just for that group.\n# [channels.telegram.groups.-1001234567890]\n# allowed_users = [222333444, 555666777] # allowed in this group only, never via DM\n# respond_to = \"mention\" # per-group override of the global respond_to\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# bot_owner = [\"U12345678\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# bot_owner = [\"member_id\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "af362f409b4dafab2bf9a9231b8a124f47ec3377": {"t": 1785767754.7872856, "n": 28024, "h": "ecd68da84e1ef9bc", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Xiaomi MiMo\n# ========================================\n# OpenAI-compatible, keyed. Get an API key (sk-...) at platform.xiaomimimo.com\n# and put it in keys.toml ([providers.xiaomi] api_key). With no key this section\n# is skipped and onboarding prompts you for one.\n#\n# base_url is optional — it defaults to the official endpoint below. Models are\n# fetched live from /v1/models (chat models only), so the /models picker shows\n# what's actually available; the list here is just an offline fallback. Thinking\n# is ON by default (the model streams its reasoning); set enable_thinking = false\n# to turn it off. Prompt caching is automatic server-side — nothing to configure.\n[providers.xiaomi]\nenabled = true\n# base_url = \"https://api.xiaomimimo.com/v1\" # optional — this is the default\ndefault_model = \"mimo-v2.5-pro\"\nmodels = [\"mimo-v2.5-pro\", \"mimo-v2-pro\", \"mimo-v2.5\", \"mimo-v2-omni\", \"mimo-v2-flash\"]\ncontext_window = 1000000 # compaction budget (auto-compacts at 65%/90%); default 200000; works on any provider\nvision_model = \"mimo-v2.5-pro\" # MiMo v2.5 is multimodal — analyze_image uses it natively (falls back to Gemini if image.vision is set)\n# enable_thinking = false # uncomment to disable the model's reasoning output\n\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M2.7\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M2.7\"\nmodels = [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# Vision provider priority — overrides the default REGISTRATIONS scan\n# order for the analyze_image tool. Each entry is a provider name\n# (e.g. \"minimax\", \"anthropic\"). Resolution order:\n# 1. This list (first enabled match with vision_model wins)\n# 2. All enabled providers in REGISTRATIONS priority order\n# 3. Custom providers\n# 4. Gemini [image.vision] fallback\n# Empty or absent = scan all providers as before.\n# vision = [\"minimax\", \"anthropic\"]\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M2.7\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for the main chat session.\n# When set, new sessions inherit these values instead of the most recent session's provider/model.\n# Existing sessions pick up the new defaults on next resume (via sync_provider_for_session).\n# Useful for enforcing a specific model across all sessions without manual /models switching.\n# Priority: agent defaults > most recent session > config active provider.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# default_provider = \"xiaomi\"\n# default_model = \"mimo-v2.5-pro\"\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Lazy tool-schema loading (default: true — RECOMMENDED). Each request ships\n# only the CORE tool schemas (~4k tokens) plus `tool_search`. The agent calls\n# `tool_search(\"what I need\")` to discover and activate the extended tools\n# (browser, channels, sub-agents, media, system) on demand — they then ride on\n# subsequent requests for the session. We recommend leaving this on: load only\n# the core set and let the agent pull the rest as needed.\n#\n# Setting `lazy_tools = false` reverts to sending the FULL tool-schema set —\n# ALL ~95 tools (~20k tokens) — in EVERY single request, whether the turn uses\n# them or not. That overhead is counted by the provider on every call (real\n# cost, not just display). Only set false if a model in your setup struggles\n# to reach for `tool_search`.\n# lazy_tools = false\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n# Redact sensitive data from tool outputs and display (default: true).\n# When true, API keys, tokens, passwords, and IP addresses are redacted\n# from tool call displays and outputs. Set to false during sysadmin/devops\n# work where seeing IPs, tokens, and passwords is necessary.\n# redact_sensitive_data = false\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Browser automation (feature: browser)\n# ========================================\n# By default each profile launches its own headless Chromium (~250-300MB each).\n# To share ONE Chromium across multiple profiles (big memory win on small VDS),\n# start a standalone instance with remote debugging:\n#\n# chromium --remote-debugging-port=9222 --headless --no-sandbox\n#\n# then point every profile's config at it. Prefer the http:// form — OpenCrabs\n# queries /json/version to find the real devtools websocket URL. (A bare\n# ws://host:port is also accepted and normalized to http:// automatically.)\n# [browser]\n# cdp_endpoint = \"http://localhost:9222\"\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n# \"auto\" — reply to all while there is at most one active sender, then switch\n# to mention-only once a second unique sender appears in the chat\n\n[channels.whatsapp]\nenabled = false\n# You pair the bot to a WhatsApp account by scanning its QR — it then runs AS\n# that account. It can be your own number (talk to it in \"Message Yourself\") or\n# any other number you own, including a WhatsApp Business account, to serve that\n# account's incoming DMs.\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\nallowed_phones = [\"+15551234567\"]\n# bot_owner = [\"+15551234567\"] # Operator phone(s) for owner-only commands. The operator can DM the\n # bot and is always allowed regardless of response_policy. Auto-seeded\n # from the first allowed_phones entry on first run; set explicitly to\n # pin a different operator than the paired account.\n# response_policy = \"auto\" # Who the bot answers. The paired account's own self-chat and bot_owner\n # are ALWAYS allowed. Options:\n # \"auto\" — legacy: open when allowed_phones is empty, else\n # owner/operator + allowed_phones (default)\n # \"owner_only\" — only the paired self-chat and bot_owner operators\n # \"allowlist\" — owner/operator + the contacts in allowed_phones\n # \"open\" — every incoming DM (business serving any customer)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789012345] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789] # Owner ID(s): owner-only commands (e.g. /cd) and gated actions.\n # Auto-seeded from the first allowed_users entry on first run; set it\n # explicitly to pin the owner instead of relying on list order.\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\" | \"auto\"\n# silence_group_start = true # Silently ignore /start from non-allowed users in groups (default: true)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n# rich_messages = true # Native rich messages (tables/headings/lists/math). Default false:\n # rich is unreadable on Telegram Web and older clients (no fallback),\n # so enable only when your audience is on current mobile/desktop apps.\n\n# Per-group access control (per-chat ACL). Tiers:\n# - allowed_users (above) = admins: may DM the bot and act in any chat.\n# - bot_owner = owner: always allowed everywhere.\n# - groups.<chat_id>.allowed_users = users allowed in THAT group ONLY. They are\n# refused in DMs unless they are also an admin/owner — this blocks the \"DM the\n# bot privately to escape group oversight\" bypass.\n# DMs are gated to admins + owner. If neither allowed_users nor bot_owner is set\n# the bot is unconfigured and stays open (no hard lockout); set either to lock down.\n# Each group may also override respond_to just for that group.\n# [channels.telegram.groups.-1001234567890]\n# allowed_users = [222333444, 555666777] # allowed in this group only, never via DM\n# respond_to = \"mention\" # per-group override of the global respond_to\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# bot_owner = [\"U12345678\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# bot_owner = [\"member_id\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "c6be08ae75c0149bc376166e0602100770065b68": {"t": 1785767756.6466086, "n": 27806, "h": "eeafdf5026ae1045", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Xiaomi MiMo\n# ========================================\n# OpenAI-compatible, keyed. Get an API key (sk-...) at platform.xiaomimimo.com\n# and put it in keys.toml ([providers.xiaomi] api_key). With no key this section\n# is skipped and onboarding prompts you for one.\n#\n# base_url is optional — it defaults to the official endpoint below. Models are\n# fetched live from /v1/models (chat models only), so the /models picker shows\n# what's actually available; the list here is just an offline fallback. Thinking\n# is ON by default (the model streams its reasoning); set enable_thinking = false\n# to turn it off. Prompt caching is automatic server-side — nothing to configure.\n[providers.xiaomi]\nenabled = true\n# base_url = \"https://api.xiaomimimo.com/v1\" # optional — this is the default\ndefault_model = \"mimo-v2.5-pro\"\nmodels = [\"mimo-v2.5-pro\", \"mimo-v2-pro\", \"mimo-v2.5\", \"mimo-v2-omni\", \"mimo-v2-flash\"]\ncontext_window = 1000000 # compaction budget (auto-compacts at 65%/90%); default 200000; works on any provider\nvision_model = \"mimo-v2.5-pro\" # MiMo v2.5 is multimodal — analyze_image uses it natively (falls back to Gemini if image.vision is set)\n# enable_thinking = false # uncomment to disable the model's reasoning output\n\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M2.7\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M2.7\"\nmodels = [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# Vision provider priority — overrides the default REGISTRATIONS scan\n# order for the analyze_image tool. Each entry is a provider name\n# (e.g. \"minimax\", \"anthropic\"). Resolution order:\n# 1. This list (first enabled match with vision_model wins)\n# 2. All enabled providers in REGISTRATIONS priority order\n# 3. Custom providers\n# 4. Gemini [image.vision] fallback\n# Empty or absent = scan all providers as before.\n# vision = [\"minimax\", \"anthropic\"]\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M2.7\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for spawned sub-agents (e.g., research tasks, parallel tool calls).\n# Priority: subagent_provider > session's active provider.\n# Useful for routing sub-agents to a cheaper/faster model while keeping the main session on a premium one.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Lazy tool-schema loading (default: true — RECOMMENDED). Each request ships\n# only the CORE tool schemas (~4k tokens) plus `tool_search`. The agent calls\n# `tool_search(\"what I need\")` to discover and activate the extended tools\n# (browser, channels, sub-agents, media, system) on demand — they then ride on\n# subsequent requests for the session. We recommend leaving this on: load only\n# the core set and let the agent pull the rest as needed.\n#\n# Setting `lazy_tools = false` reverts to sending the FULL tool-schema set —\n# ALL ~95 tools (~20k tokens) — in EVERY single request, whether the turn uses\n# them or not. That overhead is counted by the provider on every call (real\n# cost, not just display). Only set false if a model in your setup struggles\n# to reach for `tool_search`.\n# lazy_tools = false\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n# Redact sensitive data from tool outputs and display (default: true).\n# When true, API keys, tokens, passwords, and IP addresses are redacted\n# from tool call displays and outputs. Set to false during sysadmin/devops\n# work where seeing IPs, tokens, and passwords is necessary.\n# redact_sensitive_data = false\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Browser automation (feature: browser)\n# ========================================\n# By default each profile launches its own headless Chromium (~250-300MB each).\n# To share ONE Chromium across multiple profiles (big memory win on small VDS),\n# start a standalone instance with remote debugging:\n#\n# chromium --remote-debugging-port=9222 --headless --no-sandbox\n#\n# then point every profile's config at it. Prefer the http:// form — OpenCrabs\n# queries /json/version to find the real devtools websocket URL. (A bare\n# ws://host:port is also accepted and normalized to http:// automatically.)\n# [browser]\n# cdp_endpoint = \"http://localhost:9222\"\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n# \"auto\" — reply to all while there is at most one active sender, then switch\n# to mention-only once a second unique sender appears in the chat\n\n[channels.whatsapp]\nenabled = false\n# You pair the bot to a WhatsApp account by scanning its QR — it then runs AS\n# that account. It can be your own number (talk to it in \"Message Yourself\") or\n# any other number you own, including a WhatsApp Business account, to serve that\n# account's incoming DMs.\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\nallowed_phones = [\"+15551234567\"]\n# bot_owner = [\"+15551234567\"] # Operator phone(s) for owner-only commands. The operator can DM the\n # bot and is always allowed regardless of response_policy. Auto-seeded\n # from the first allowed_phones entry on first run; set explicitly to\n # pin a different operator than the paired account.\n# response_policy = \"auto\" # Who the bot answers. The paired account's own self-chat and bot_owner\n # are ALWAYS allowed. Options:\n # \"auto\" — legacy: open when allowed_phones is empty, else\n # owner/operator + allowed_phones (default)\n # \"owner_only\" — only the paired self-chat and bot_owner operators\n # \"allowlist\" — owner/operator + the contacts in allowed_phones\n # \"open\" — every incoming DM (business serving any customer)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789012345] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789] # Owner ID(s): owner-only commands (e.g. /cd) and gated actions.\n # Auto-seeded from the first allowed_users entry on first run; set it\n # explicitly to pin the owner instead of relying on list order.\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\" | \"auto\"\n# silence_group_start = true # Silently ignore /start from non-allowed users in groups (default: true)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n# rich_messages = true # Native rich messages (tables/headings/lists/math). Default false:\n # rich is unreadable on Telegram Web and older clients (no fallback),\n # so enable only when your audience is on current mobile/desktop apps.\n\n# Per-group access control (per-chat ACL). Tiers:\n# - allowed_users (above) = admins: may DM the bot and act in any chat.\n# - bot_owner = owner: always allowed everywhere.\n# - groups.<chat_id>.allowed_users = users allowed in THAT group ONLY. They are\n# refused in DMs unless they are also an admin/owner — this blocks the \"DM the\n# bot privately to escape group oversight\" bypass.\n# DMs are gated to admins + owner. If neither allowed_users nor bot_owner is set\n# the bot is unconfigured and stays open (no hard lockout); set either to lock down.\n# Each group may also override respond_to just for that group.\n# [channels.telegram.groups.-1001234567890]\n# allowed_users = [222333444, 555666777] # allowed in this group only, never via DM\n# respond_to = \"mention\" # per-group override of the global respond_to\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# bot_owner = [\"U12345678\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# bot_owner = [\"member_id\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "18b411b1e6308563200a609e2ee95a56c1ce228c": {"t": 1785767758.160978, "n": 27345, "h": "8dc8592ca0ab972e", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Xiaomi MiMo\n# ========================================\n# OpenAI-compatible, keyed. Get an API key (sk-...) at platform.xiaomimimo.com\n# and put it in keys.toml ([providers.xiaomi] api_key). With no key this section\n# is skipped and onboarding prompts you for one.\n#\n# base_url is optional — it defaults to the official endpoint below. Models are\n# fetched live from /v1/models (chat models only), so the /models picker shows\n# what's actually available; the list here is just an offline fallback. Thinking\n# is ON by default (the model streams its reasoning); set enable_thinking = false\n# to turn it off. Prompt caching is automatic server-side — nothing to configure.\n[providers.xiaomi]\nenabled = true\n# base_url = \"https://api.xiaomimimo.com/v1\" # optional — this is the default\ndefault_model = \"mimo-v2.5-pro\"\nmodels = [\"mimo-v2.5-pro\", \"mimo-v2-pro\", \"mimo-v2.5\", \"mimo-v2-omni\", \"mimo-v2-flash\"]\ncontext_window = 1000000 # compaction budget (auto-compacts at 65%/90%); default 200000; works on any provider\nvision_model = \"mimo-v2.5-pro\" # MiMo v2.5 is multimodal — analyze_image uses it natively (falls back to Gemini if image.vision is set)\n# enable_thinking = false # uncomment to disable the model's reasoning output\n\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M2.7\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M2.7\"\nmodels = [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M2.7\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for spawned sub-agents (e.g., research tasks, parallel tool calls).\n# Priority: subagent_provider > session's active provider.\n# Useful for routing sub-agents to a cheaper/faster model while keeping the main session on a premium one.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Lazy tool-schema loading (default: true — RECOMMENDED). Each request ships\n# only the CORE tool schemas (~4k tokens) plus `tool_search`. The agent calls\n# `tool_search(\"what I need\")` to discover and activate the extended tools\n# (browser, channels, sub-agents, media, system) on demand — they then ride on\n# subsequent requests for the session. We recommend leaving this on: load only\n# the core set and let the agent pull the rest as needed.\n#\n# Setting `lazy_tools = false` reverts to sending the FULL tool-schema set —\n# ALL ~95 tools (~20k tokens) — in EVERY single request, whether the turn uses\n# them or not. That overhead is counted by the provider on every call (real\n# cost, not just display). Only set false if a model in your setup struggles\n# to reach for `tool_search`.\n# lazy_tools = false\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n# Redact sensitive data from tool outputs and display (default: true).\n# When true, API keys, tokens, passwords, and IP addresses are redacted\n# from tool call displays and outputs. Set to false during sysadmin/devops\n# work where seeing IPs, tokens, and passwords is necessary.\n# redact_sensitive_data = false\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Browser automation (feature: browser)\n# ========================================\n# By default each profile launches its own headless Chromium (~250-300MB each).\n# To share ONE Chromium across multiple profiles (big memory win on small VDS),\n# start a standalone instance with remote debugging:\n#\n# chromium --remote-debugging-port=9222 --headless --no-sandbox\n#\n# then point every profile's config at it. Prefer the http:// form — OpenCrabs\n# queries /json/version to find the real devtools websocket URL. (A bare\n# ws://host:port is also accepted and normalized to http:// automatically.)\n# [browser]\n# cdp_endpoint = \"http://localhost:9222\"\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n# \"auto\" — reply to all while there is at most one active sender, then switch\n# to mention-only once a second unique sender appears in the chat\n\n[channels.whatsapp]\nenabled = false\n# You pair the bot to a WhatsApp account by scanning its QR — it then runs AS\n# that account. It can be your own number (talk to it in \"Message Yourself\") or\n# any other number you own, including a WhatsApp Business account, to serve that\n# account's incoming DMs.\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\nallowed_phones = [\"+15551234567\"]\n# bot_owner = [\"+15551234567\"] # Operator phone(s) for owner-only commands. The operator can DM the\n # bot and is always allowed regardless of response_policy. Auto-seeded\n # from the first allowed_phones entry on first run; set explicitly to\n # pin a different operator than the paired account.\n# response_policy = \"auto\" # Who the bot answers. The paired account's own self-chat and bot_owner\n # are ALWAYS allowed. Options:\n # \"auto\" — legacy: open when allowed_phones is empty, else\n # owner/operator + allowed_phones (default)\n # \"owner_only\" — only the paired self-chat and bot_owner operators\n # \"allowlist\" — owner/operator + the contacts in allowed_phones\n # \"open\" — every incoming DM (business serving any customer)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789012345] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789] # Owner ID(s): owner-only commands (e.g. /cd) and gated actions.\n # Auto-seeded from the first allowed_users entry on first run; set it\n # explicitly to pin the owner instead of relying on list order.\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\" | \"auto\"\n# silence_group_start = true # Silently ignore /start from non-allowed users in groups (default: true)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n# rich_messages = true # Native rich messages (tables/headings/lists/math). Default false:\n # rich is unreadable on Telegram Web and older clients (no fallback),\n # so enable only when your audience is on current mobile/desktop apps.\n\n# Per-group access control (per-chat ACL). Tiers:\n# - allowed_users (above) = admins: may DM the bot and act in any chat.\n# - bot_owner = owner: always allowed everywhere.\n# - groups.<chat_id>.allowed_users = users allowed in THAT group ONLY. They are\n# refused in DMs unless they are also an admin/owner — this blocks the \"DM the\n# bot privately to escape group oversight\" bypass.\n# DMs are gated to admins + owner. If neither allowed_users nor bot_owner is set\n# the bot is unconfigured and stays open (no hard lockout); set either to lock down.\n# Each group may also override respond_to just for that group.\n# [channels.telegram.groups.-1001234567890]\n# allowed_users = [222333444, 555666777] # allowed in this group only, never via DM\n# respond_to = \"mention\" # per-group override of the global respond_to\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# bot_owner = [\"U12345678\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# bot_owner = [\"member_id\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "3c4e1d35978af631982da7df3bed6ac36fc1e4a9": {"t": 1785767759.6372132, "n": 26256, "h": "6462575b82140877", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Xiaomi MiMo\n# ========================================\n# OpenAI-compatible, keyed. Get an API key (sk-...) at platform.xiaomimimo.com\n# and put it in keys.toml ([providers.xiaomi] api_key). With no key this section\n# is skipped and onboarding prompts you for one.\n#\n# base_url is optional — it defaults to the official endpoint below. Models are\n# fetched live from /v1/models (chat models only), so the /models picker shows\n# what's actually available; the list here is just an offline fallback. Thinking\n# is ON by default (the model streams its reasoning); set enable_thinking = false\n# to turn it off. Prompt caching is automatic server-side — nothing to configure.\n[providers.xiaomi]\nenabled = true\n# base_url = \"https://api.xiaomimimo.com/v1\" # optional — this is the default\ndefault_model = \"mimo-v2.5-pro\"\nmodels = [\"mimo-v2.5-pro\", \"mimo-v2-pro\", \"mimo-v2.5\", \"mimo-v2-omni\", \"mimo-v2-flash\"]\ncontext_window = 1000000 # compaction budget (auto-compacts at 65%/90%); default 200000; works on any provider\nvision_model = \"mimo-v2.5-pro\" # MiMo v2.5 is multimodal — analyze_image uses it natively (falls back to Gemini if image.vision is set)\n# enable_thinking = false # uncomment to disable the model's reasoning output\n\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M2.7\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M2.7\"\nmodels = [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M2.7\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for spawned sub-agents (e.g., research tasks, parallel tool calls).\n# Priority: subagent_provider > session's active provider.\n# Useful for routing sub-agents to a cheaper/faster model while keeping the main session on a premium one.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Lazy tool-schema loading (default: true — RECOMMENDED). Each request ships\n# only the CORE tool schemas (~4k tokens) plus `tool_search`. The agent calls\n# `tool_search(\"what I need\")` to discover and activate the extended tools\n# (browser, channels, sub-agents, media, system) on demand — they then ride on\n# subsequent requests for the session. We recommend leaving this on: load only\n# the core set and let the agent pull the rest as needed.\n#\n# Setting `lazy_tools = false` reverts to sending the FULL tool-schema set —\n# ALL ~95 tools (~20k tokens) — in EVERY single request, whether the turn uses\n# them or not. That overhead is counted by the provider on every call (real\n# cost, not just display). Only set false if a model in your setup struggles\n# to reach for `tool_search`.\n# lazy_tools = false\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n# Redact sensitive data from tool outputs and display (default: true).\n# When true, API keys, tokens, passwords, and IP addresses are redacted\n# from tool call displays and outputs. Set to false during sysadmin/devops\n# work where seeing IPs, tokens, and passwords is necessary.\n# redact_sensitive_data = false\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Browser automation (feature: browser)\n# ========================================\n# By default each profile launches its own headless Chromium (~250-300MB each).\n# To share ONE Chromium across multiple profiles (big memory win on small VDS),\n# start a standalone instance with remote debugging:\n#\n# chromium --remote-debugging-port=9222 --headless --no-sandbox\n#\n# then point every profile's config at it. Prefer the http:// form — OpenCrabs\n# queries /json/version to find the real devtools websocket URL. (A bare\n# ws://host:port is also accepted and normalized to http:// automatically.)\n# [browser]\n# cdp_endpoint = \"http://localhost:9222\"\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n# \"auto\" — reply to all while there is at most one active sender, then switch\n# to mention-only once a second unique sender appears in the chat\n\n[channels.whatsapp]\nenabled = false\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\n# Access control is purely phone-based — add numbers here to restrict who can message the bot.\nallowed_phones = [\"+15551234567\"]\n# bot_owner = [\"+15551234567\"] # Owner phone(s) for owner-only commands. Auto-seeded from the first\n # allowed_phones entry on first run; set explicitly to pin the owner.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789012345] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789] # Owner ID(s): owner-only commands (e.g. /cd) and gated actions.\n # Auto-seeded from the first allowed_users entry on first run; set it\n # explicitly to pin the owner instead of relying on list order.\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\" | \"auto\"\n# silence_group_start = true # Silently ignore /start from non-allowed users in groups (default: true)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n# rich_messages = true # Native rich messages (tables/headings/lists/math). Default false:\n # rich is unreadable on Telegram Web and older clients (no fallback),\n # so enable only when your audience is on current mobile/desktop apps.\n\n# Per-group access control (per-chat ACL). Tiers:\n# - allowed_users (above) = admins: may DM the bot and act in any chat.\n# - bot_owner = owner: always allowed everywhere.\n# - groups.<chat_id>.allowed_users = users allowed in THAT group ONLY. They are\n# refused in DMs unless they are also an admin/owner — this blocks the \"DM the\n# bot privately to escape group oversight\" bypass.\n# DMs are gated to admins + owner. If neither allowed_users nor bot_owner is set\n# the bot is unconfigured and stays open (no hard lockout); set either to lock down.\n# Each group may also override respond_to just for that group.\n# [channels.telegram.groups.-1001234567890]\n# allowed_users = [222333444, 555666777] # allowed in this group only, never via DM\n# respond_to = \"mention\" # per-group override of the global respond_to\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# bot_owner = [\"U12345678\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# bot_owner = [\"member_id\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "30fcc0702082a5d67abb78fab75ec79e1454fa5e": {"t": 1785767761.3073142, "n": 25227, "h": "0fc1f363ff054c63", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Xiaomi MiMo\n# ========================================\n# OpenAI-compatible, keyed. Get an API key (sk-...) at platform.xiaomimimo.com\n# and put it in keys.toml ([providers.xiaomi] api_key). With no key this section\n# is skipped and onboarding prompts you for one.\n#\n# base_url is optional — it defaults to the official endpoint below. Models are\n# fetched live from /v1/models (chat models only), so the /models picker shows\n# what's actually available; the list here is just an offline fallback. Thinking\n# is ON by default (the model streams its reasoning); set enable_thinking = false\n# to turn it off. Prompt caching is automatic server-side — nothing to configure.\n[providers.xiaomi]\nenabled = true\n# base_url = \"https://api.xiaomimimo.com/v1\" # optional — this is the default\ndefault_model = \"mimo-v2.5-pro\"\nmodels = [\"mimo-v2.5-pro\", \"mimo-v2-pro\", \"mimo-v2.5\", \"mimo-v2-omni\", \"mimo-v2-flash\"]\ncontext_window = 1000000 # compaction budget (auto-compacts at 65%/90%); default 200000; works on any provider\nvision_model = \"mimo-v2.5-pro\" # MiMo v2.5 is multimodal — analyze_image uses it natively (falls back to Gemini if image.vision is set)\n# enable_thinking = false # uncomment to disable the model's reasoning output\n\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M2.7\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M2.7\"\nmodels = [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M2.7\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for spawned sub-agents (e.g., research tasks, parallel tool calls).\n# Priority: subagent_provider > session's active provider.\n# Useful for routing sub-agents to a cheaper/faster model while keeping the main session on a premium one.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Lazy tool-schema loading (default: true — RECOMMENDED). Each request ships\n# only the CORE tool schemas (~4k tokens) plus `tool_search`. The agent calls\n# `tool_search(\"what I need\")` to discover and activate the extended tools\n# (browser, channels, sub-agents, media, system) on demand — they then ride on\n# subsequent requests for the session. We recommend leaving this on: load only\n# the core set and let the agent pull the rest as needed.\n#\n# Setting `lazy_tools = false` reverts to sending the FULL tool-schema set —\n# ALL ~95 tools (~20k tokens) — in EVERY single request, whether the turn uses\n# them or not. That overhead is counted by the provider on every call (real\n# cost, not just display). Only set false if a model in your setup struggles\n# to reach for `tool_search`.\n# lazy_tools = false\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n# Redact sensitive data from tool outputs and display (default: true).\n# When true, API keys, tokens, passwords, and IP addresses are redacted\n# from tool call displays and outputs. Set to false during sysadmin/devops\n# work where seeing IPs, tokens, and passwords is necessary.\n# redact_sensitive_data = false\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Browser automation (feature: browser)\n# ========================================\n# By default each profile launches its own headless Chromium (~250-300MB each).\n# To share ONE Chromium across multiple profiles (big memory win on small VDS),\n# start a standalone instance with remote debugging:\n#\n# chromium --remote-debugging-port=9222 --headless --no-sandbox\n#\n# then point every profile's config at it. Prefer the http:// form — OpenCrabs\n# queries /json/version to find the real devtools websocket URL. (A bare\n# ws://host:port is also accepted and normalized to http:// automatically.)\n# [browser]\n# cdp_endpoint = \"http://localhost:9222\"\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n\n[channels.whatsapp]\nenabled = false\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\n# Access control is purely phone-based — add numbers here to restrict who can message the bot.\nallowed_phones = [\"+15551234567\"]\n# bot_owner = [\"+15551234567\"] # Owner phone(s) for owner-only commands. Auto-seeded from the first\n # allowed_phones entry on first run; set explicitly to pin the owner.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789012345] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789] # Owner ID(s): owner-only commands (e.g. /cd) and gated actions.\n # Auto-seeded from the first allowed_users entry on first run; set it\n # explicitly to pin the owner instead of relying on list order.\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# silence_group_start = true # Silently ignore /start from non-allowed users in groups (default: true)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n# rich_messages = true # Native rich messages (tables/headings/lists/math). Default false:\n # rich is unreadable on Telegram Web and older clients (no fallback),\n # so enable only when your audience is on current mobile/desktop apps.\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# bot_owner = [\"U12345678\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# bot_owner = [\"member_id\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "422a725ce73aaaaf53ec37f237ddb7ff6abd6385": {"t": 1785767762.91445, "n": 24044, "h": "2bd4f14f295b7f7b", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Xiaomi MiMo\n# ========================================\n# OpenAI-compatible, keyed. Get an API key (sk-...) at platform.xiaomimimo.com\n# and put it in keys.toml ([providers.xiaomi] api_key). With no key this section\n# is skipped and onboarding prompts you for one.\n#\n# base_url is optional — it defaults to the official endpoint below. Models are\n# fetched live from /v1/models (chat models only), so the /models picker shows\n# what's actually available; the list here is just an offline fallback. Thinking\n# is ON by default (the model streams its reasoning); set enable_thinking = false\n# to turn it off. Prompt caching is automatic server-side — nothing to configure.\n[providers.xiaomi]\nenabled = true\n# base_url = \"https://api.xiaomimimo.com/v1\" # optional — this is the default\ndefault_model = \"mimo-v2.5-pro\"\nmodels = [\"mimo-v2.5-pro\", \"mimo-v2-pro\", \"mimo-v2.5\", \"mimo-v2-omni\", \"mimo-v2-flash\"]\ncontext_window = 1000000 # compaction budget (auto-compacts at 65%/90%); default 200000; works on any provider\nvision_model = \"mimo-v2.5-pro\" # MiMo v2.5 is multimodal — analyze_image uses it natively (falls back to Gemini if image.vision is set)\n# enable_thinking = false # uncomment to disable the model's reasoning output\n\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M2.7\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M2.7\"\nmodels = [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M2.7\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for spawned sub-agents (e.g., research tasks, parallel tool calls).\n# Priority: subagent_provider > session's active provider.\n# Useful for routing sub-agents to a cheaper/faster model while keeping the main session on a premium one.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Lazy tool-schema loading (default: true — RECOMMENDED). Each request ships\n# only the CORE tool schemas (~4k tokens) plus `tool_search`. The agent calls\n# `tool_search(\"what I need\")` to discover and activate the extended tools\n# (browser, channels, sub-agents, media, system) on demand — they then ride on\n# subsequent requests for the session. We recommend leaving this on: load only\n# the core set and let the agent pull the rest as needed.\n#\n# Setting `lazy_tools = false` reverts to sending the FULL tool-schema set —\n# ALL ~95 tools (~20k tokens) — in EVERY single request, whether the turn uses\n# them or not. That overhead is counted by the provider on every call (real\n# cost, not just display). Only set false if a model in your setup struggles\n# to reach for `tool_search`.\n# lazy_tools = false\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n# Redact sensitive data from tool outputs and display (default: true).\n# When true, API keys, tokens, passwords, and IP addresses are redacted\n# from tool call displays and outputs. Set to false during sysadmin/devops\n# work where seeing IPs, tokens, and passwords is necessary.\n# redact_sensitive_data = false\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Browser automation (feature: browser)\n# ========================================\n# By default each profile launches its own headless Chromium (~250-300MB each).\n# To share ONE Chromium across multiple profiles (big memory win on small VDS),\n# start a standalone instance with remote debugging:\n#\n# chromium --remote-debugging-port=9222 --headless --no-sandbox\n#\n# then point every profile's config at it. Prefer the http:// form — OpenCrabs\n# queries /json/version to find the real devtools websocket URL. (A bare\n# ws://host:port is also accepted and normalized to http:// automatically.)\n# [browser]\n# cdp_endpoint = \"http://localhost:9222\"\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n\n[channels.whatsapp]\nenabled = false\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\n# Access control is purely phone-based — add numbers here to restrict who can message the bot.\nallowed_phones = [\"+15551234567\"]\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# silence_group_start = true # Silently ignore /start from non-allowed users in groups (default: true)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n# rich_messages = true # Native rich messages (tables/headings/lists/math). Default false:\n # rich is unreadable on Telegram Web and older clients (no fallback),\n # so enable only when your audience is on current mobile/desktop apps.\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "fc93dc26ffe25d825a1095d05149bf52e152fcde": {"t": 1785767764.335309, "n": 24183, "h": "2ed2b145c2c186f7", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Xiaomi MiMo ⭐ DEFAULT (opencrabs x Xiaomi collab)\n# ========================================\n# FREE + KEYLESS during the launch window (until 2026-06-25): leave api_key\n# unset. Requests go through our proxy, which supplies the key server-side, so\n# no key ever lives on your machine. This is the default provider for fresh\n# installs — new users land almost straight in chat.\n#\n# After the cutoff, set your own key in keys.toml ([providers.xiaomi] api_key).\n#\n# Models are fetched live from the proxy's /v1/models (chat models only), so the\n# /models picker always shows what's actually available. The list below is just\n# an offline fallback. Thinking is ON by default (the model streams its\n# reasoning); set enable_thinking = false to turn it off. Prompt caching is\n# automatic server-side — nothing to configure.\n[providers.xiaomi]\nenabled = true\nbase_url = \"https://xiaomi-collab.opencrabs.com/v1/chat/completions\"\ndefault_model = \"mimo-v2.5-pro\"\nmodels = [\"mimo-v2.5-pro\", \"mimo-v2-pro\", \"mimo-v2.5\", \"mimo-v2-omni\", \"mimo-v2-flash\"]\ncontext_window = 1000000 # compaction budget (auto-compacts at 65%/90%); default 200000; works on any provider\nvision_model = \"mimo-v2.5-pro\" # MiMo v2.5 is multimodal — analyze_image uses it natively (falls back to Gemini if image.vision is set)\n# enable_thinking = false # uncomment to disable the model's reasoning output\n\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M2.7\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M2.7\"\nmodels = [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M2.7\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for spawned sub-agents (e.g., research tasks, parallel tool calls).\n# Priority: subagent_provider > session's active provider.\n# Useful for routing sub-agents to a cheaper/faster model while keeping the main session on a premium one.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Lazy tool-schema loading (default: true — RECOMMENDED). Each request ships\n# only the CORE tool schemas (~4k tokens) plus `tool_search`. The agent calls\n# `tool_search(\"what I need\")` to discover and activate the extended tools\n# (browser, channels, sub-agents, media, system) on demand — they then ride on\n# subsequent requests for the session. We recommend leaving this on: load only\n# the core set and let the agent pull the rest as needed.\n#\n# Setting `lazy_tools = false` reverts to sending the FULL tool-schema set —\n# ALL ~95 tools (~20k tokens) — in EVERY single request, whether the turn uses\n# them or not. That overhead is counted by the provider on every call (real\n# cost, not just display). Only set false if a model in your setup struggles\n# to reach for `tool_search`.\n# lazy_tools = false\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n# Redact sensitive data from tool outputs and display (default: true).\n# When true, API keys, tokens, passwords, and IP addresses are redacted\n# from tool call displays and outputs. Set to false during sysadmin/devops\n# work where seeing IPs, tokens, and passwords is necessary.\n# redact_sensitive_data = false\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Browser automation (feature: browser)\n# ========================================\n# By default each profile launches its own headless Chromium (~250-300MB each).\n# To share ONE Chromium across multiple profiles (big memory win on small VDS),\n# start a standalone instance with remote debugging:\n#\n# chromium --remote-debugging-port=9222 --headless --no-sandbox\n#\n# then point every profile's config at it. Prefer the http:// form — OpenCrabs\n# queries /json/version to find the real devtools websocket URL. (A bare\n# ws://host:port is also accepted and normalized to http:// automatically.)\n# [browser]\n# cdp_endpoint = \"http://localhost:9222\"\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n\n[channels.whatsapp]\nenabled = false\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\n# Access control is purely phone-based — add numbers here to restrict who can message the bot.\nallowed_phones = [\"+15551234567\"]\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# silence_group_start = true # Silently ignore /start from non-allowed users in groups (default: true)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n# rich_messages = true # Native rich messages (tables/headings/lists/math). Default false:\n # rich is unreadable on Telegram Web and older clients (no fallback),\n # so enable only when your audience is on current mobile/desktop apps.\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "2dd79d3e7bc54b186065e26ed5cfbd7f539e45fd": {"t": 1785767765.8246925, "n": 24069, "h": "9ba8f58940160e6d", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Xiaomi MiMo ⭐ DEFAULT (opencrabs x Xiaomi collab)\n# ========================================\n# FREE + KEYLESS during the launch window (until 2026-06-25): leave api_key\n# unset. Requests go through our proxy, which supplies the key server-side, so\n# no key ever lives on your machine. This is the default provider for fresh\n# installs — new users land almost straight in chat.\n#\n# After the cutoff, set your own key in keys.toml ([providers.xiaomi] api_key).\n#\n# Models are fetched live from the proxy's /v1/models (chat models only), so the\n# /models picker always shows what's actually available. The list below is just\n# an offline fallback. Thinking is ON by default (the model streams its\n# reasoning); set enable_thinking = false to turn it off. Prompt caching is\n# automatic server-side — nothing to configure.\n[providers.xiaomi]\nenabled = true\nbase_url = \"https://xiaomi-collab.opencrabs.com/v1/chat/completions\"\ndefault_model = \"mimo-v2.5-pro\"\nmodels = [\"mimo-v2.5-pro\", \"mimo-v2-pro\", \"mimo-v2.5\", \"mimo-v2-omni\", \"mimo-v2-flash\"]\ncontext_window = 1000000 # compaction budget (auto-compacts at 65%/90%); default 200000; works on any provider\nvision_model = \"mimo-v2.5-pro\" # MiMo v2.5 is multimodal — analyze_image uses it natively (falls back to Gemini if image.vision is set)\n# enable_thinking = false # uncomment to disable the model's reasoning output\n\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M2.7\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M2.7\"\nmodels = [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M2.7\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for spawned sub-agents (e.g., research tasks, parallel tool calls).\n# Priority: subagent_provider > session's active provider.\n# Useful for routing sub-agents to a cheaper/faster model while keeping the main session on a premium one.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Lazy tool-schema loading (default: true — RECOMMENDED). Each request ships\n# only the CORE tool schemas (~4k tokens) plus `tool_search`. The agent calls\n# `tool_search(\"what I need\")` to discover and activate the extended tools\n# (browser, channels, sub-agents, media, system) on demand — they then ride on\n# subsequent requests for the session. We recommend leaving this on: load only\n# the core set and let the agent pull the rest as needed.\n#\n# Setting `lazy_tools = false` reverts to sending the FULL tool-schema set —\n# ALL ~95 tools (~20k tokens) — in EVERY single request, whether the turn uses\n# them or not. That overhead is counted by the provider on every call (real\n# cost, not just display). Only set false if a model in your setup struggles\n# to reach for `tool_search`.\n# lazy_tools = false\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n# Redact sensitive data from tool outputs and display (default: true).\n# When true, API keys, tokens, passwords, and IP addresses are redacted\n# from tool call displays and outputs. Set to false during sysadmin/devops\n# work where seeing IPs, tokens, and passwords is necessary.\n# redact_sensitive_data = false\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Browser automation (feature: browser)\n# ========================================\n# By default each profile launches its own headless Chromium (~250-300MB each).\n# To share ONE Chromium across multiple profiles (big memory win on small VDS),\n# start a standalone instance with remote debugging:\n#\n# chromium --remote-debugging-port=9222 --headless --no-sandbox\n#\n# then point every profile's config at it. Prefer the http:// form — OpenCrabs\n# queries /json/version to find the real devtools websocket URL. (A bare\n# ws://host:port is also accepted and normalized to http:// automatically.)\n# [browser]\n# cdp_endpoint = \"http://localhost:9222\"\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n\n[channels.whatsapp]\nenabled = false\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\n# Access control is purely phone-based — add numbers here to restrict who can message the bot.\nallowed_phones = [\"+15551234567\"]\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n# rich_messages = true # Native rich messages (tables/headings/lists/math). Default false:\n # rich is unreadable on Telegram Web and older clients (no fallback),\n # so enable only when your audience is on current mobile/desktop apps.\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "8d551dcfccb0b8afd653db7755ba8c5490d0e858": {"t": 1785767767.5386527, "n": 23740, "h": "2b992242b4ce3db8", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Xiaomi MiMo ⭐ DEFAULT (opencrabs x Xiaomi collab)\n# ========================================\n# FREE + KEYLESS during the launch window (until 2026-06-25): leave api_key\n# unset. Requests go through our proxy, which supplies the key server-side, so\n# no key ever lives on your machine. This is the default provider for fresh\n# installs — new users land almost straight in chat.\n#\n# After the cutoff, set your own key in keys.toml ([providers.xiaomi] api_key).\n#\n# Models are fetched live from the proxy's /v1/models (chat models only), so the\n# /models picker always shows what's actually available. The list below is just\n# an offline fallback. Thinking is ON by default (the model streams its\n# reasoning); set enable_thinking = false to turn it off. Prompt caching is\n# automatic server-side — nothing to configure.\n[providers.xiaomi]\nenabled = true\nbase_url = \"https://xiaomi-collab.opencrabs.com/v1/chat/completions\"\ndefault_model = \"mimo-v2.5-pro\"\nmodels = [\"mimo-v2.5-pro\", \"mimo-v2-pro\", \"mimo-v2.5\", \"mimo-v2-omni\", \"mimo-v2-flash\"]\ncontext_window = 1000000 # compaction budget (auto-compacts at 65%/90%); default 200000; works on any provider\nvision_model = \"mimo-v2.5-pro\" # MiMo v2.5 is multimodal — analyze_image uses it natively (falls back to Gemini if image.vision is set)\n# enable_thinking = false # uncomment to disable the model's reasoning output\n\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M2.7\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M2.7\"\nmodels = [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M2.7\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for spawned sub-agents (e.g., research tasks, parallel tool calls).\n# Priority: subagent_provider > session's active provider.\n# Useful for routing sub-agents to a cheaper/faster model while keeping the main session on a premium one.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Lazy tool-schema loading (default: true — RECOMMENDED). Each request ships\n# only the CORE tool schemas (~4k tokens) plus `tool_search`. The agent calls\n# `tool_search(\"what I need\")` to discover and activate the extended tools\n# (browser, channels, sub-agents, media, system) on demand — they then ride on\n# subsequent requests for the session. We recommend leaving this on: load only\n# the core set and let the agent pull the rest as needed.\n#\n# Setting `lazy_tools = false` reverts to sending the FULL tool-schema set —\n# ALL ~95 tools (~20k tokens) — in EVERY single request, whether the turn uses\n# them or not. That overhead is counted by the provider on every call (real\n# cost, not just display). Only set false if a model in your setup struggles\n# to reach for `tool_search`.\n# lazy_tools = false\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n# Redact sensitive data from tool outputs and display (default: true).\n# When true, API keys, tokens, passwords, and IP addresses are redacted\n# from tool call displays and outputs. Set to false during sysadmin/devops\n# work where seeing IPs, tokens, and passwords is necessary.\n# redact_sensitive_data = false\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Browser automation (feature: browser)\n# ========================================\n# By default each profile launches its own headless Chromium (~250-300MB each).\n# To share ONE Chromium across multiple profiles (big memory win on small VDS),\n# start a standalone instance with remote debugging:\n#\n# chromium --remote-debugging-port=9222 --headless --no-sandbox\n#\n# then point every profile's config at it. Prefer the http:// form — OpenCrabs\n# queries /json/version to find the real devtools websocket URL. (A bare\n# ws://host:port is also accepted and normalized to http:// automatically.)\n# [browser]\n# cdp_endpoint = \"http://localhost:9222\"\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n\n[channels.whatsapp]\nenabled = false\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\n# Access control is purely phone-based — add numbers here to restrict who can message the bot.\nallowed_phones = [\"+15551234567\"]\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "f767f4effe1cfa7040ea9fde487c64b55c126c0c": {"t": 1785767768.9442213, "n": 23653, "h": "7af2ad688b2d6430", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Xiaomi MiMo ⭐ DEFAULT (opencrabs x Xiaomi collab)\n# ========================================\n# FREE + KEYLESS during the launch window (until 2026-06-25): leave api_key\n# unset. Requests go through our proxy, which supplies the key server-side, so\n# no key ever lives on your machine. This is the default provider for fresh\n# installs — new users land almost straight in chat.\n#\n# After the cutoff, set your own key in keys.toml ([providers.xiaomi] api_key).\n#\n# Models are fetched live from the proxy's /v1/models (chat models only), so the\n# /models picker always shows what's actually available. The list below is just\n# an offline fallback. Thinking is ON by default (the model streams its\n# reasoning); set enable_thinking = false to turn it off. Prompt caching is\n# automatic server-side — nothing to configure.\n[providers.xiaomi]\nenabled = true\nbase_url = \"https://xiaomi-collab.opencrabs.com/v1/chat/completions\"\ndefault_model = \"mimo-v2.5-pro\"\nmodels = [\"mimo-v2.5-pro\", \"mimo-v2-pro\", \"mimo-v2.5\", \"mimo-v2-omni\", \"mimo-v2-flash\"]\ncontext_window = 1000000\nvision_model = \"mimo-v2.5-pro\" # MiMo v2.5 is multimodal — analyze_image uses it natively (falls back to Gemini if image.vision is set)\n# enable_thinking = false # uncomment to disable the model's reasoning output\n\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M2.7\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M2.7\"\nmodels = [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M2.7\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for spawned sub-agents (e.g., research tasks, parallel tool calls).\n# Priority: subagent_provider > session's active provider.\n# Useful for routing sub-agents to a cheaper/faster model while keeping the main session on a premium one.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Lazy tool-schema loading (default: true — RECOMMENDED). Each request ships\n# only the CORE tool schemas (~4k tokens) plus `tool_search`. The agent calls\n# `tool_search(\"what I need\")` to discover and activate the extended tools\n# (browser, channels, sub-agents, media, system) on demand — they then ride on\n# subsequent requests for the session. We recommend leaving this on: load only\n# the core set and let the agent pull the rest as needed.\n#\n# Setting `lazy_tools = false` reverts to sending the FULL tool-schema set —\n# ALL ~95 tools (~20k tokens) — in EVERY single request, whether the turn uses\n# them or not. That overhead is counted by the provider on every call (real\n# cost, not just display). Only set false if a model in your setup struggles\n# to reach for `tool_search`.\n# lazy_tools = false\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n# Redact sensitive data from tool outputs and display (default: true).\n# When true, API keys, tokens, passwords, and IP addresses are redacted\n# from tool call displays and outputs. Set to false during sysadmin/devops\n# work where seeing IPs, tokens, and passwords is necessary.\n# redact_sensitive_data = false\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Browser automation (feature: browser)\n# ========================================\n# By default each profile launches its own headless Chromium (~250-300MB each).\n# To share ONE Chromium across multiple profiles (big memory win on small VDS),\n# start a standalone instance with remote debugging:\n#\n# chromium --remote-debugging-port=9222 --headless --no-sandbox\n#\n# then point every profile's config at it. Prefer the http:// form — OpenCrabs\n# queries /json/version to find the real devtools websocket URL. (A bare\n# ws://host:port is also accepted and normalized to http:// automatically.)\n# [browser]\n# cdp_endpoint = \"http://localhost:9222\"\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n\n[channels.whatsapp]\nenabled = false\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\n# Access control is purely phone-based — add numbers here to restrict who can message the bot.\nallowed_phones = [\"+15551234567\"]\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "fd02470348bb70df105c89b7aafccab628557fe0": {"t": 1785767770.331961, "n": 23516, "h": "107cc1a4f7c5c3a0", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Xiaomi MiMo ⭐ DEFAULT (opencrabs x Xiaomi collab)\n# ========================================\n# FREE + KEYLESS during the launch window (until 2026-06-25): leave api_key\n# unset. Requests go through our proxy, which supplies the key server-side, so\n# no key ever lives on your machine. This is the default provider for fresh\n# installs — new users land almost straight in chat.\n#\n# After the cutoff, set your own key in keys.toml ([providers.xiaomi] api_key).\n#\n# Models are fetched live from the proxy's /v1/models (chat models only), so the\n# /models picker always shows what's actually available. The list below is just\n# an offline fallback. Thinking is ON by default (the model streams its\n# reasoning); set enable_thinking = false to turn it off. Prompt caching is\n# automatic server-side — nothing to configure.\n[providers.xiaomi]\nenabled = true\nbase_url = \"https://xiaomi-collab.opencrabs.com/v1/chat/completions\"\ndefault_model = \"mimo-v2.5-pro\"\nmodels = [\"mimo-v2.5-pro\", \"mimo-v2-pro\", \"mimo-v2.5\", \"mimo-v2-omni\", \"mimo-v2-flash\"]\ncontext_window = 1000000\n# enable_thinking = false # uncomment to disable the model's reasoning output\n\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M2.7\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M2.7\"\nmodels = [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M2.7\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for spawned sub-agents (e.g., research tasks, parallel tool calls).\n# Priority: subagent_provider > session's active provider.\n# Useful for routing sub-agents to a cheaper/faster model while keeping the main session on a premium one.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Lazy tool-schema loading (default: true — RECOMMENDED). Each request ships\n# only the CORE tool schemas (~4k tokens) plus `tool_search`. The agent calls\n# `tool_search(\"what I need\")` to discover and activate the extended tools\n# (browser, channels, sub-agents, media, system) on demand — they then ride on\n# subsequent requests for the session. We recommend leaving this on: load only\n# the core set and let the agent pull the rest as needed.\n#\n# Setting `lazy_tools = false` reverts to sending the FULL tool-schema set —\n# ALL ~95 tools (~20k tokens) — in EVERY single request, whether the turn uses\n# them or not. That overhead is counted by the provider on every call (real\n# cost, not just display). Only set false if a model in your setup struggles\n# to reach for `tool_search`.\n# lazy_tools = false\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n# Redact sensitive data from tool outputs and display (default: true).\n# When true, API keys, tokens, passwords, and IP addresses are redacted\n# from tool call displays and outputs. Set to false during sysadmin/devops\n# work where seeing IPs, tokens, and passwords is necessary.\n# redact_sensitive_data = false\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Browser automation (feature: browser)\n# ========================================\n# By default each profile launches its own headless Chromium (~250-300MB each).\n# To share ONE Chromium across multiple profiles (big memory win on small VDS),\n# start a standalone instance with remote debugging:\n#\n# chromium --remote-debugging-port=9222 --headless --no-sandbox\n#\n# then point every profile's config at it. Prefer the http:// form — OpenCrabs\n# queries /json/version to find the real devtools websocket URL. (A bare\n# ws://host:port is also accepted and normalized to http:// automatically.)\n# [browser]\n# cdp_endpoint = \"http://localhost:9222\"\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n\n[channels.whatsapp]\nenabled = false\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\n# Access control is purely phone-based — add numbers here to restrict who can message the bot.\nallowed_phones = [\"+15551234567\"]\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "47b9737532ae5cf44869d7d4afc1776c572d0ebb": {"t": 1785767771.7371871, "n": 23204, "h": "202922e6bbb12b21", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Xiaomi MiMo ⭐ DEFAULT (opencrabs x Xiaomi collab)\n# ========================================\n# FREE + KEYLESS during the launch window (until 2026-06-25): leave api_key\n# unset. Requests go through our proxy, which supplies the key server-side, so\n# no key ever lives on your machine. This is the default provider for fresh\n# installs — new users land almost straight in chat.\n#\n# After the cutoff, set your own key in keys.toml ([providers.xiaomi] api_key).\n#\n# Models are fetched live from the proxy's /v1/models (chat models only), so the\n# /models picker always shows what's actually available. The list below is just\n# an offline fallback. Thinking is ON by default (the model streams its\n# reasoning); set enable_thinking = false to turn it off. Prompt caching is\n# automatic server-side — nothing to configure.\n[providers.xiaomi]\nenabled = true\nbase_url = \"https://xiaomi-collab.opencrabs.com/v1/chat/completions\"\ndefault_model = \"mimo-v2.5-pro\"\nmodels = [\"mimo-v2.5-pro\", \"mimo-v2-pro\", \"mimo-v2.5\", \"mimo-v2-omni\", \"mimo-v2-flash\"]\ncontext_window = 1000000\n# enable_thinking = false # uncomment to disable the model's reasoning output\n\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M2.7\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M2.7\"\nmodels = [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M2.7\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for spawned sub-agents (e.g., research tasks, parallel tool calls).\n# Priority: subagent_provider > session's active provider.\n# Useful for routing sub-agents to a cheaper/faster model while keeping the main session on a premium one.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Lazy tool-schema loading (default: true — RECOMMENDED). Each request ships\n# only the CORE tool schemas (~4k tokens) plus `tool_search`. The agent calls\n# `tool_search(\"what I need\")` to discover and activate the extended tools\n# (browser, channels, sub-agents, media, system) on demand — they then ride on\n# subsequent requests for the session. We recommend leaving this on: load only\n# the core set and let the agent pull the rest as needed.\n#\n# Setting `lazy_tools = false` reverts to sending the FULL tool-schema set —\n# ALL ~95 tools (~20k tokens) — in EVERY single request, whether the turn uses\n# them or not. That overhead is counted by the provider on every call (real\n# cost, not just display). Only set false if a model in your setup struggles\n# to reach for `tool_search`.\n# lazy_tools = false\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Browser automation (feature: browser)\n# ========================================\n# By default each profile launches its own headless Chromium (~250-300MB each).\n# To share ONE Chromium across multiple profiles (big memory win on small VDS),\n# start a standalone instance with remote debugging:\n#\n# chromium --remote-debugging-port=9222 --headless --no-sandbox\n#\n# then point every profile's config at it. Prefer the http:// form — OpenCrabs\n# queries /json/version to find the real devtools websocket URL. (A bare\n# ws://host:port is also accepted and normalized to http:// automatically.)\n# [browser]\n# cdp_endpoint = \"http://localhost:9222\"\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n\n[channels.whatsapp]\nenabled = false\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\n# Access control is purely phone-based — add numbers here to restrict who can message the bot.\nallowed_phones = [\"+15551234567\"]\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "8e89fd9c882c4033755870fd0953559ec773e79c": {"t": 1785767773.3606415, "n": 22513, "h": "16915b76ab34556b", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Xiaomi MiMo ⭐ DEFAULT (opencrabs x Xiaomi collab)\n# ========================================\n# FREE + KEYLESS during the launch window (until 2026-06-25): leave api_key\n# unset. Requests go through our proxy, which supplies the key server-side, so\n# no key ever lives on your machine. This is the default provider for fresh\n# installs — new users land almost straight in chat.\n#\n# After the cutoff, set your own key in keys.toml ([providers.xiaomi] api_key).\n#\n# Models are fetched live from the proxy's /v1/models (chat models only), so the\n# /models picker always shows what's actually available. The list below is just\n# an offline fallback. Thinking is ON by default (the model streams its\n# reasoning); set enable_thinking = false to turn it off. Prompt caching is\n# automatic server-side — nothing to configure.\n[providers.xiaomi]\nenabled = true\nbase_url = \"https://xiaomi-collab.opencrabs.com/v1/chat/completions\"\ndefault_model = \"mimo-v2.5-pro\"\nmodels = [\"mimo-v2.5-pro\", \"mimo-v2-pro\", \"mimo-v2.5\", \"mimo-v2-omni\", \"mimo-v2-flash\"]\ncontext_window = 1000000\n# enable_thinking = false # uncomment to disable the model's reasoning output\n\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M2.7\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M2.7\"\nmodels = [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M2.7\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for spawned sub-agents (e.g., research tasks, parallel tool calls).\n# Priority: subagent_provider > session's active provider.\n# Useful for routing sub-agents to a cheaper/faster model while keeping the main session on a premium one.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Lazy tool-schema loading (default: true — RECOMMENDED). Each request ships\n# only the CORE tool schemas (~4k tokens) plus `tool_search`. The agent calls\n# `tool_search(\"what I need\")` to discover and activate the extended tools\n# (browser, channels, sub-agents, media, system) on demand — they then ride on\n# subsequent requests for the session. We recommend leaving this on: load only\n# the core set and let the agent pull the rest as needed.\n#\n# Setting `lazy_tools = false` reverts to sending the FULL tool-schema set —\n# ALL ~95 tools (~20k tokens) — in EVERY single request, whether the turn uses\n# them or not. That overhead is counted by the provider on every call (real\n# cost, not just display). Only set false if a model in your setup struggles\n# to reach for `tool_search`.\n# lazy_tools = false\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n\n[channels.whatsapp]\nenabled = false\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\n# Access control is purely phone-based — add numbers here to restrict who can message the bot.\nallowed_phones = [\"+15551234567\"]\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "1c3266f531f226afcd44e8ab5b16438e3693d2e2": {"t": 1785767774.955348, "n": 22120, "h": "0343cc736e439c02", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Xiaomi MiMo ⭐ DEFAULT (opencrabs x Xiaomi collab)\n# ========================================\n# FREE + KEYLESS during the launch window (until 2026-06-25): leave api_key\n# unset. Requests go through our proxy, which supplies the key server-side, so\n# no key ever lives on your machine. This is the default provider for fresh\n# installs — new users land almost straight in chat.\n#\n# After the cutoff, set your own key in keys.toml ([providers.xiaomi] api_key).\n# Get one at https://platform.xiaomimimo.com\n[providers.xiaomi]\nenabled = true\nbase_url = \"https://xiaomi-collab.opencrabs.com/v1/chat/completions\"\ndefault_model = \"mimo-v2.5-pro\"\nmodels = [\"mimo-v2.5-pro\", \"mimo-v2-pro\", \"mimo-v2.5\", \"mimo-v2-omni\", \"mimo-v2-flash\"]\ncontext_window = 1000000\n\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M2.7\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M2.7\"\nmodels = [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M2.7\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for spawned sub-agents (e.g., research tasks, parallel tool calls).\n# Priority: subagent_provider > session's active provider.\n# Useful for routing sub-agents to a cheaper/faster model while keeping the main session on a premium one.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Lazy tool-schema loading (default: true — RECOMMENDED). Each request ships\n# only the CORE tool schemas (~4k tokens) plus `tool_search`. The agent calls\n# `tool_search(\"what I need\")` to discover and activate the extended tools\n# (browser, channels, sub-agents, media, system) on demand — they then ride on\n# subsequent requests for the session. We recommend leaving this on: load only\n# the core set and let the agent pull the rest as needed.\n#\n# Setting `lazy_tools = false` reverts to sending the FULL tool-schema set —\n# ALL ~95 tools (~20k tokens) — in EVERY single request, whether the turn uses\n# them or not. That overhead is counted by the provider on every call (real\n# cost, not just display). Only set false if a model in your setup struggles\n# to reach for `tool_search`.\n# lazy_tools = false\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n\n[channels.whatsapp]\nenabled = false\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\n# Access control is purely phone-based — add numbers here to restrict who can message the bot.\nallowed_phones = [\"+15551234567\"]\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "3e0c8f90fed22afa961ffbac37fb1cfe52fb8526": {"t": 1785767776.3931038, "n": 21321, "h": "c04732fdc83881ea", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M2.7\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M2.7\"\nmodels = [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M2.7\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for spawned sub-agents (e.g., research tasks, parallel tool calls).\n# Priority: subagent_provider > session's active provider.\n# Useful for routing sub-agents to a cheaper/faster model while keeping the main session on a premium one.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Lazy tool-schema loading (default: true — RECOMMENDED). Each request ships\n# only the CORE tool schemas (~4k tokens) plus `tool_search`. The agent calls\n# `tool_search(\"what I need\")` to discover and activate the extended tools\n# (browser, channels, sub-agents, media, system) on demand — they then ride on\n# subsequent requests for the session. We recommend leaving this on: load only\n# the core set and let the agent pull the rest as needed.\n#\n# Setting `lazy_tools = false` reverts to sending the FULL tool-schema set —\n# ALL ~95 tools (~20k tokens) — in EVERY single request, whether the turn uses\n# them or not. That overhead is counted by the provider on every call (real\n# cost, not just display). Only set false if a model in your setup struggles\n# to reach for `tool_search`.\n# lazy_tools = false\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n\n[channels.whatsapp]\nenabled = false\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\n# Access control is purely phone-based — add numbers here to restrict who can message the bot.\nallowed_phones = [\"+15551234567\"]\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "218688487d5ea68537f13c44248e951803ffd6d0": {"t": 1785767777.741738, "n": 21146, "h": "0a683a34b1f03c1e", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M2.7\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M2.7\"\nmodels = [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M2.7\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for spawned sub-agents (e.g., research tasks, parallel tool calls).\n# Priority: subagent_provider > session's active provider.\n# Useful for routing sub-agents to a cheaper/faster model while keeping the main session on a premium one.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Lazy tool-schema loading (default: false). When true, each request ships\n# only the CORE tool schemas (~4k tokens) plus `tool_search`, instead of all\n# ~95 (~20k tokens counted in every request's input). The agent calls\n# `tool_search(\"what I need\")` to discover and activate extended tools\n# (browser, channels, sub-agents, media, system) on demand — they then ride\n# on subsequent requests for the session. Saves ~16k tokens/turn on\n# tool-light turns. Trade-off: a model that fails to reach for `tool_search`\n# could stall a task that needs a non-core tool, so test on real workloads\n# before relying on it.\n# lazy_tools = true\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n\n[channels.whatsapp]\nenabled = false\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\n# Access control is purely phone-based — add numbers here to restrict who can message the bot.\nallowed_phones = [\"+15551234567\"]\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "dd81d8c8df4b12f689dbf0a7a54eb2aed10be11f": {"t": 1785767779.7460427, "n": 20512, "h": "821373aed4269b6f", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M2.7\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M2.7\"\nmodels = [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M2.7\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for spawned sub-agents (e.g., research tasks, parallel tool calls).\n# Priority: subagent_provider > session's active provider.\n# Useful for routing sub-agents to a cheaper/faster model while keeping the main session on a premium one.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n\n[channels.whatsapp]\nenabled = false\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\n# Access control is purely phone-based — add numbers here to restrict who can message the bot.\nallowed_phones = [\"+15551234567\"]\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "d5e96c357b453f24dafd0e4841a37735c96ff6c9": {"t": 1785767786.815029, "n": 20158, "h": "88d9a2861653e8e5", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M2.7\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M2.7\"\nmodels = [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M2.7\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for spawned sub-agents (e.g., research tasks, parallel tool calls).\n# Priority: subagent_provider > session's active provider.\n# Useful for routing sub-agents to a cheaper/faster model while keeping the main session on a premium one.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n\n[channels.whatsapp]\nenabled = false\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\n# Access control is purely phone-based — add numbers here to restrict who can message the bot.\nallowed_phones = [\"+15551234567\"]\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "ece9fb9f118030c4e047102b4a5b84287e3bc45f": {"t": 1785767789.0262144, "n": 18857, "h": "a340a72ae6cc87f4", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M2.7\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M2.7\"\nmodels = [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M2.7\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for spawned sub-agents (e.g., research tasks, parallel tool calls).\n# Priority: subagent_provider > session's active provider.\n# Useful for routing sub-agents to a cheaper/faster model while keeping the main session on a premium one.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n\n[channels.whatsapp]\nenabled = false\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\n# Access control is purely phone-based — add numbers here to restrict who can message the bot.\nallowed_phones = [\"+15551234567\"]\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "c4305d144dc07aab6784210e4a880d3b9dfb62a6": {"t": 1785767790.2375567, "n": 18095, "h": "485e3190fcd1ade8", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M2.7\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M2.7\"\nmodels = [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M2.7\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for spawned sub-agents (e.g., research tasks, parallel tool calls).\n# Priority: subagent_provider > session's active provider.\n# Useful for routing sub-agents to a cheaper/faster model while keeping the main session on a premium one.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n\n[channels.whatsapp]\nenabled = false\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\n# Access control is purely phone-based — add numbers here to restrict who can message the bot.\nallowed_phones = [\"+15551234567\"]\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "53d647d0920eb8d302f0a78bfeb07cbee8d8bc60": {"t": 1785767791.4175425, "n": 17228, "h": "565ccd599951bc10", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M2.7\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M2.7\"\nmodels = [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M2.7\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for spawned sub-agents (e.g., research tasks, parallel tool calls).\n# Priority: subagent_provider > session's active provider.\n# Useful for routing sub-agents to a cheaper/faster model while keeping the main session on a premium one.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n\n[channels.whatsapp]\nenabled = false\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\n# Access control is purely phone-based — add numbers here to restrict who can message the bot.\nallowed_phones = [\"+15551234567\"]\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls local vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# WIP: OpenAI-compatible embedding through API (or local) coming soon.\n#\n# [memory]\n# vector_enabled = false\n"}, "ecbf03508d08e4f7494b38834761fda2e543b6a3": {"t": 1785767792.6585505, "n": 16724, "h": "b9d8db6ea33deb30", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M2.7\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M2.7\"\nmodels = [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M2.7\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for spawned sub-agents (e.g., research tasks, parallel tool calls).\n# Priority: subagent_provider > session's active provider.\n# Useful for routing sub-agents to a cheaper/faster model while keeping the main session on a premium one.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n\n[channels.whatsapp]\nenabled = false\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\n# Access control is purely phone-based — add numbers here to restrict who can message the bot.\nallowed_phones = [\"+15551234567\"]\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n"}, "10a349c91fb1375cd3c87b9d74ef9057f6a95dd3": {"t": 1786067918.7619998, "n": 30543, "h": "ea825ec03e330254", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Xiaomi MiMo\n# ========================================\n# OpenAI-compatible, keyed. Get an API key (sk-...) at platform.xiaomimimo.com\n# and put it in keys.toml ([providers.xiaomi] api_key). With no key this section\n# is skipped and onboarding prompts you for one.\n#\n# base_url is optional — it defaults to the official endpoint below. Models are\n# fetched live from /v1/models (chat models only), so the /models picker shows\n# what's actually available; the list here is just an offline fallback. Thinking\n# is ON by default (the model streams its reasoning); set enable_thinking = false\n# to turn it off. Prompt caching is automatic server-side — nothing to configure.\n[providers.xiaomi]\nenabled = true\n# base_url = \"https://api.xiaomimimo.com/v1\" # optional — this is the default\ndefault_model = \"mimo-v2.5-pro\"\nmodels = [\"mimo-v2.5-pro\", \"mimo-v2-pro\", \"mimo-v2.5\", \"mimo-v2-omni\", \"mimo-v2-flash\"]\ncontext_window = 1000000 # compaction budget (auto-compacts at 65%/90%); default 200000; works on any provider\nvision_model = \"mimo-v2.5-pro\" # MiMo v2.5 is multimodal — analyze_image uses it natively (falls back to Gemini if image.vision is set)\n# enable_thinking = false # uncomment to disable the model's reasoning output\n# force_default = true # ENFORCE this provider's default pair on EVERY session.\n# By default a new default applies to NEW sessions only — existing/live\n# sessions keep their own provider+model. Set force_default = true on the\n# provider you want as the global default, and on config reload its\n# default_model pair is pushed to every non-archived session (only when this\n# section is the active default provider). Off/absent = new-sessions-only.\n\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = true\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M3\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# Command Code CLI — local `command-code` subprocess (also on PATH as `cmd`).\n# Uses your Command Code account (~/.commandcode/auth.json from `command-code\n# login`). No proxy, no API key.\n# Install: npm install -g command-code (then run `command-code login`)\n# Models per `command-code --list-models` — full ids or the short name after\n# the last `/` both work. Leave `models` unset to use the built-in list.\n[providers.command_code_cli]\nenabled = false\ndefault_model = \"deepseek/deepseek-v4-flash\"\nmodels = [\n \"claude-sonnet-5\",\n \"claude-opus-4-8\",\n \"gpt-5.5\",\n \"google/gemini-3.5-flash\",\n \"deepseek/deepseek-v4-flash\",\n \"moonshotai/Kimi-K2.7-Code\",\n \"zai-org/GLM-5.2\",\n \"Qwen/Qwen3.7-Max\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M3\"\nmodels = [\"MiniMax-M3\", \"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n[providers.moonshot]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default, api.moonshot.ai) or \"coding\" (api.kimi.com, Kimi token subscription)\ndefault_model = \"k3\"\nmodels = [\"k3\", \"kimi-for-coding\", \"kimi-for-coding-highspeed\"]\n# API key goes in keys.toml: [providers.moonshot] api_key = \"...\"\n# API plan key from platform.moonshot.ai; Coding plan key from kimi.com\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# Vision provider priority — overrides the default REGISTRATIONS scan\n# order for the analyze_image tool. Each entry is a provider name\n# (e.g. \"minimax\", \"anthropic\"). Resolution order:\n# 1. This list (first enabled match with vision_model wins)\n# 2. All enabled providers in REGISTRATIONS priority order\n# 3. Custom providers\n# 4. Gemini [image.vision] fallback\n# Empty or absent = scan all providers as before.\n# vision = [\"minimax\", \"anthropic\"]\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M3\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for the main chat session.\n# When set, new sessions inherit these values instead of the most recent session's provider/model.\n# Existing sessions pick up the new defaults on next resume (via sync_provider_for_session).\n# Useful for enforcing a specific model across all sessions without manual /models switching.\n# Priority: agent defaults > most recent session > config active provider.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# default_provider = \"xiaomi\"\n# default_model = \"mimo-v2.5-pro\"\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n\n# Lazy tool-schema loading (default: true — RECOMMENDED). Each request ships\n# only the CORE tool schemas (~4k tokens) plus `tool_search`. The agent calls\n# `tool_search(\"what I need\")` to discover and activate the extended tools\n# (browser, channels, sub-agents, media, system) on demand — they then ride on\n# subsequent requests for the session. We recommend leaving this on: load only\n# the core set and let the agent pull the rest as needed.\n#\n# Setting `lazy_tools = false` reverts to sending the FULL tool-schema set —\n# ALL ~95 tools (~20k tokens) — in EVERY single request, whether the turn uses\n# them or not. That overhead is counted by the provider on every call (real\n# cost, not just display). Only set false if a model in your setup struggles\n# to reach for `tool_search`.\n# lazy_tools = false\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n# Redact sensitive data from tool outputs and display (default: true).\n# When true, API keys, tokens, passwords, and IP addresses are redacted\n# from tool call displays and outputs. Set to false during sysadmin/devops\n# work where seeing IPs, tokens, and passwords is necessary.\n# redact_sensitive_data = false\n\n# Enable debug file logging from config, on top of the `--debug` CLI flag.\n# Lets you (or the agent, on request) turn detailed logs in ~/.opencrabs/logs/\n# on or off by flipping this to true/false. The change hot-reloads with no\n# restart. Effective state is `--debug OR debug_logs`, so the flag always wins.\ndebug_logs = false\n\n# Thinking-loop timeout in seconds (#890). If the model streams for this long\n# without emitting a single tool call, the stream is killed and retried with\n# multi-language phantom enforcement injected into the prompt. Catches the\n# failure mode where a reasoning model loops internally (thinking tokens\n# flowing, 0 tool calls) for an hour or more. Default 600 = 10 min.\n# Set to 0 to disable. Hot-reloads with no restart.\nthinking_loop_timeout_secs = 600\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Browser automation (feature: browser)\n# ========================================\n# By default each profile launches its own headless Chromium (~250-300MB each).\n# To share ONE Chromium across multiple profiles (big memory win on small VDS),\n# start a standalone instance with remote debugging:\n#\n# chromium --remote-debugging-port=9222 --headless --no-sandbox\n#\n# then point every profile's config at it. Prefer the http:// form — OpenCrabs\n# queries /json/version to find the real devtools websocket URL. (A bare\n# ws://host:port is also accepted and normalized to http:// automatically.)\n# [browser]\n# cdp_endpoint = \"http://localhost:9222\"\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n# \"auto\" — reply to all while there is at most one active sender, then switch\n# to mention-only once a second unique sender appears in the chat\n\n[channels.whatsapp]\nenabled = false\n# You pair the bot to a WhatsApp account by scanning its QR — it then runs AS\n# that account. It can be your own number (talk to it in \"Message Yourself\") or\n# any other number you own, including a WhatsApp Business account, to serve that\n# account's incoming DMs.\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\nallowed_phones = [\"+15551234567\"]\n# bot_owner = [\"+15551234567\"] # Operator phone(s) for owner-only commands. The operator can DM the\n # bot and is always allowed regardless of response_policy. Auto-seeded\n # from the first allowed_phones entry on first run; set explicitly to\n # pin a different operator than the paired account.\n# response_policy = \"auto\" # Who the bot answers. The paired account's own self-chat and bot_owner\n # are ALWAYS allowed. Options:\n # \"auto\" — legacy: open when allowed_phones is empty, else\n # owner/operator + allowed_phones (default)\n # \"owner_only\" — only the paired self-chat and bot_owner operators\n # \"allowlist\" — owner/operator + the contacts in allowed_phones\n # \"open\" — every incoming DM (business serving any customer)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789012345] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789] # Owner ID(s): owner-only commands (e.g. /cd) and gated actions.\n # Auto-seeded from the first allowed_users entry on first run; set it\n # explicitly to pin the owner instead of relying on list order.\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\" | \"auto\"\n# silence_group_start = true # Silently ignore /start from non-allowed users in groups (default: true)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n# rich_messages = true # Native rich messages — flow logs, collapsible tool calls,\n # status bubble with task preview. Default: true since v0.3.64.\n # Toggle available in the onboard dialog (/onboard:provider →\n # Telegram channel step). Set to false if your audience uses\n # Telegram Web or older clients (no HTML fallback).\n\n# Per-group access control (per-chat ACL). Tiers:\n# - allowed_users (above) = admins: may DM the bot and act in any chat.\n# - bot_owner = owner: always allowed everywhere.\n# - groups.<chat_id>.allowed_users = users allowed in THAT group ONLY. They are\n# refused in DMs unless they are also an admin/owner — this blocks the \"DM the\n# bot privately to escape group oversight\" bypass.\n# DMs are gated to admins + owner. If neither allowed_users nor bot_owner is set\n# the bot is unconfigured and stays open (no hard lockout); set either to lock down.\n# Each group may also override respond_to just for that group.\n# [channels.telegram.groups.-1001234567890]\n# allowed_users = [222333444, 555666777] # allowed in this group only, never via DM\n# respond_to = \"mention\" # per-group override of the global respond_to\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# bot_owner = [\"U12345678\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# bot_owner = [\"member_id\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}, "91202760486551343bd94810a474674fa571ce15": {"t": 1786068503.6431746, "n": 30807, "h": "bbed0afdb78f739a", "c": "# OpenCrabs Configuration File\n# Copy this file to one of these locations:\n# - Linux/macOS: ~/.opencrabs/config.toml\n# - Windows: %APPDATA%\\opencrabs\\config.toml or opencrabs\\config.toml\n#\n# IMPORTANT: API keys should NOT be stored here!\n# Instead, store API keys in keys.toml (chmod 600) for security:\n# - ~/.opencrabs/keys.toml\n# Keys in keys.toml take priority over this file.\n\n[database]\n# Database file location (stores conversation history)\n# path = \"~/.opencrabs/opencrabs.db\" # Default; only override if needed\n\n[providers]\n# ========================================\n# Xiaomi MiMo\n# ========================================\n# OpenAI-compatible, keyed. Get an API key (sk-...) at platform.xiaomimimo.com\n# and put it in keys.toml ([providers.xiaomi] api_key). With no key this section\n# is skipped and onboarding prompts you for one.\n#\n# base_url is optional — it defaults to the official endpoint below. Models are\n# fetched live from /v1/models (chat models only), so the /models picker shows\n# what's actually available; the list here is just an offline fallback. Thinking\n# is ON by default (the model streams its reasoning); set enable_thinking = false\n# to turn it off. Prompt caching is automatic server-side — nothing to configure.\n[providers.xiaomi]\nenabled = false\n# base_url = \"https://api.xiaomimimo.com/v1\" # optional — this is the default\ndefault_model = \"mimo-v2.5-pro\"\nmodels = [\"mimo-v2.5-pro\", \"mimo-v2-pro\", \"mimo-v2.5\", \"mimo-v2-omni\", \"mimo-v2-flash\"]\ncontext_window = 1000000 # compaction budget (auto-compacts at 65%/90%); default 200000; works on any provider\nvision_model = \"mimo-v2.5-pro\" # MiMo v2.5 is multimodal — analyze_image uses it natively (falls back to Gemini if image.vision is set)\n# enable_thinking = false # uncomment to disable the model's reasoning output\n# force_default = true # ENFORCE this provider's default pair on EVERY session.\n# By default a new default applies to NEW sessions only — existing/live\n# sessions keep their own provider+model. Set force_default = true on the\n# provider you want as the global default, and on config reload its\n# default_model pair is pushed to every non-archived session (only when this\n# section is the active default provider). Off/absent = new-sessions-only.\n\n# ========================================\n# Ollama Provider (Local + Cloud)\n# ========================================\n# Local: runs on localhost:11434 — no API key needed\n# Cloud: set base_url to your Ollama Cloud endpoint + optional API key\n# Models are fetched automatically from /api/tags\n# Requires: ollama serve (local) or a cloud endpoint\n[providers.ollama]\nenabled = false\nbase_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"llama3.1\" # Optional: override default\n# api_key = \"\" # Optional: only needed for Ollama Cloud\n\n# ========================================\n# Custom: OpenAI-Compatible Provider (Local LLMs, and any OpenAI Compatible model)\n# ========================================\n# Use this for LM Studio, Ollama, LocalAI, etc.\n# Every custom provider needs a name — the label after \"custom.\" (e.g. lm_studio, nvidia, groq).\n# You can define as many as you need and switch between them via /models.\n[providers.custom.lm_studio]\nenabled = false\nbase_url = \"http://localhost:1234/v1/chat/completions\" # LM Studio default\nmodels = [\"kimi-k2.5\", \"glm-5\", \"MiniMax-M3\", \"qwen3-coder\", \"gpt-oss-120b\", \"llama-4-70B\", \"mistral-Large-3\", \"qwen3-coder-next\"]\n\n# ⭐ IMPORTANT: Set this to match the model name loaded in LM Studio!\n# Common examples:\n# - qwen2.5-coder-7b-instruct\n# - codellama-7b-instruct\n# - deepseek-coder-6.7b-instruct\n# - llama-3.2-1b-instruct\ndefault_model = \"qwen3-coder-next\"\n\n# Other local LLM servers — just add another named section:\n#\n# [providers.custom.ollama]\n# enabled = false\n# base_url = \"http://localhost:11434/v1/chat/completions\"\n# default_model = \"mistral\"\n# models = [\"mistral\", \"llama3\", \"codellama\"]\n\n# ========================================\n# GitHub Copilot Provider\n# ========================================\n# Uses your GitHub Copilot subscription via OAuth device flow.\n# Run /onboard:provider and select GitHub Copilot to sign in.\n# base_url = \"https://api.githubcopilot.com/chat/completions\"\n[providers.github]\nenabled = false\ndefault_model = \"gpt-4o\"\n# Models are fetched live from the Copilot API\n\n# ========================================\n# Official OpenAI Provider\n# ========================================\n[providers.openai]\nenabled = false\ndefault_model = \"gpt-5-nano\" # Optional: override default model\n# vision_model = \"gpt-5-nano\" # Optional: describes images for the chat model when it lacks vision\n# generation_model = \"gpt-image-1\" # Optional: routes generate_image to OpenAI /v1/images/generations\n\n# ========================================\n# Anthropic Provider (Claude)\n# ========================================\n[providers.anthropic]\nenabled = false\ndefault_model = \"claude-sonnet-4-6\" # Optional: override default\n\n# ========================================\n# OpenRouter Provider (100+ models via OpenAI-compatible API)\n# ========================================\n[providers.openrouter]\nenabled = false\nbase_url = \"https://openrouter.ai/api/v1/chat/completions\"\ndefault_model = \"qwen/qwen3-coder-next\" # Many options at openrouter.ai/models\n\n# ========================================\n# OpenCode Provider (Go and Zen plans)\n# ========================================\n# Native API provider — no CLI subprocess needed.\n# Models are fetched live from opencode.ai/zen/go/v1/models\n# API key goes in keys.toml: [providers.opencode] api_key = \"...\"\n# Get key from: opencode.ai/settings\n[providers.opencode]\nenabled = false\nbase_url = \"https://opencode.ai/zen/go/v1/chat/completions\"\n# default_model = \"qwen3.6-plus\" # Optional: override default\n\n# ========================================\n# Google Gemini Provider\n# ========================================\n# Models fetched live from the Gemini API during onboarding and /models\n# API key goes in keys.toml under [providers.gemini]\n# Get key from: aistudio.google.com\n[providers.gemini]\nenabled = false\ndefault_model = \"gemini-2.5-flash\"\n# generation_model = \"imagen-4.0-generate-001\" # Optional: per-provider override for generate_image\n# (Gemini host is detected automatically — call stays on the Gemini wire, not /v1/images/generations.)\n\n# ========================================\n# Claude CLI (Max Subscription — no API key needed)\n# ========================================\n# Spawns the local 'claude' CLI directly — uses your Claude Max subscription.\n# No proxy, no API key. Just install Claude Code CLI and authenticate it.\n# Install: npm install -g @anthropic-ai/claude-code\n[providers.claude_cli]\nenabled = false\ndefault_model = \"sonnet\" # \"sonnet\", \"opus\", or \"haiku\"\n\n# ========================================\n# Codex CLI (ChatGPT/Codex Subscription — no API key needed)\n# ========================================\n# Spawns the local 'codex' CLI directly — piggybacks on the auth stored in\n# ~/.codex/auth.json by `codex login`. No proxy, no API key.\n# Install: npm install -g @openai/codex (then run `codex` once to sign in)\n# Models per developers.openai.com/codex/models. gpt-5.5 is ChatGPT-auth only;\n# fall back to gpt-5.4 if your account doesn't have 5.5 yet.\n[providers.codex_cli]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n]\n\n# Command Code CLI — local `command-code` subprocess (also on PATH as `cmd`).\n# Uses your Command Code account (~/.commandcode/auth.json from `command-code\n# login`). No proxy, no API key.\n# Install: npm install -g command-code (then run `command-code login`)\n# Models per `command-code --list-models` — full ids or the short name after\n# the last `/` both work. Leave `models` unset to use the built-in list.\n[providers.command_code_cli]\nenabled = false\ndefault_model = \"deepseek/deepseek-v4-flash\"\nmodels = [\n \"claude-sonnet-5\",\n \"claude-opus-4-8\",\n \"gpt-5.5\",\n \"google/gemini-3.5-flash\",\n \"deepseek/deepseek-v4-flash\",\n \"moonshotai/Kimi-K2.7-Code\",\n \"zai-org/GLM-5.2\",\n \"Qwen/Qwen3.7-Max\",\n]\n\n# ========================================\n# Codex (OAuth — no CLI needed)\n# ========================================\n# Authenticates directly with OpenAI Codex subscription via device-code\n# OAuth flow. Tokens stored in ~/.opencrabs/auth/codex.json with automatic\n# refresh. No `codex` CLI binary required — authenticate through the\n# onboarding wizard (/onboard:provider).\n# Uses the same public client ID as Codex CLI: app_EMoamEEZ73f0CkXaXp7hrann\n[providers.codex]\nenabled = false\ndefault_model = \"gpt-5.5\"\nmodels = [\n \"gpt-5.5\",\n \"gpt-5.4\",\n \"gpt-5.4-mini\",\n \"gpt-5.3-codex\",\n \"gpt-5.3-codex-spark\",\n \"gpt-5.2\",\n \"gpt-4o\",\n \"o3\",\n \"o4-mini\",\n]\n\n# ========================================\n# Minimax Provider (Chinese AI, OpenAI-compatible)\n# ========================================\n# Note: Minimax does NOT have a /models endpoint, so add models manually\n[providers.minimax]\nenabled = false\nbase_url = \"https://api.minimax.io/v1\"\ndefault_model = \"MiniMax-M3\"\nmodels = [\"MiniMax-M3\", \"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-Text-01\"]\nvision_model = \"MiniMax-Text-01\" # Describes images for the chat model when it lacks vision\n\n[providers.zhipu]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default) or \"coding\" for code-optimized endpoint\ndefault_model = \"glm-5.1\"\nmodels = [\"glm-5.1\", \"glm-5-turbo\", \"glm-5\", \"glm-4.7\", \"glm-4.6\", \"glm-4.5\", \"glm-4.5-air\"]\n# API key goes in keys.toml: [providers.zhipu] api_key = \"...\"\n# Get key from open.bigmodel.cn or z.ai\n\n[providers.moonshot]\nenabled = false\n# endpoint_type = \"coding\" # \"api\" (default, api.moonshot.ai) or \"coding\" (api.kimi.com, Kimi token subscription)\ndefault_model = \"k3\"\nmodels = [\"k3\", \"kimi-for-coding\", \"kimi-for-coding-highspeed\"]\n# API key goes in keys.toml: [providers.moonshot] api_key = \"...\"\n# API plan key from platform.moonshot.ai; Coding plan key from kimi.com\n\n# ========================================\n# Qwen / DashScope Provider (Alibaba Cloud Model Studio, OpenAI-compatible)\n# ========================================\n# DashScope OpenAI-compatible endpoints (use the one matching your API key's region):\n# - China (Beijing): https://dashscope.aliyuncs.com/compatible-mode/v1\n# - Singapore (intl): https://dashscope-intl.aliyuncs.com/compatible-mode/v1\n# - US (Virginia): https://dashscope-us.aliyuncs.com/compatible-mode/v1\n# - Alibaba Coding Plan (intl): https://coding-intl.dashscope.aliyuncs.com/v1\n# - Alibaba Coding Plan (CN): https://coding.dashscope.aliyuncs.com/v1\n# Regions are NOT interchangeable — match base_url to the region that issued your key.\n# API key goes in keys.toml: [providers.qwen] api_key = \"...\"\n# Get key from: bailian.console.aliyun.com (DashScope) or qwen.ai/apiplatform (Coding Plan)\n[providers.qwen]\nenabled = false\nbase_url = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\ndefault_model = \"qwen3.6-plus\"\nmodels = [\n \"qwen3.6-plus\",\n \"qwen3-max\",\n \"qwen3-coder-plus\",\n \"qwen3.5-plus\",\n \"qwen-max\",\n \"qwen-plus\",\n \"qwen-flash\",\n \"qwen-vl-max\",\n]\n# enable_thinking = true # opt-in to Qwen3 hybrid thinking mode\n\n# ========================================\n# Fallback Providers (automatic failover)\n# ========================================\n# When the primary provider fails, try these in order.\n# Each must already have API keys configured in keys.toml.\n# Supports single or multiple fallbacks.\n[providers.fallback]\nenabled = false\nproviders = [\"openrouter\", \"anthropic\"] # Tried in order on failure\n# provider = \"openrouter\" # Legacy: single fallback (use providers array instead)\n\n# Vision provider priority — overrides the default REGISTRATIONS scan\n# order for the analyze_image tool. Each entry is a provider name\n# (e.g. \"minimax\", \"anthropic\"). Resolution order:\n# 1. This list (first enabled match with vision_model wins)\n# 2. All enabled providers in REGISTRATIONS priority order\n# 3. Custom providers\n# 4. Gemini [image.vision] fallback\n# Empty or absent = scan all providers as before.\n# vision = [\"minimax\", \"anthropic\"]\n\n# ========================================\n# STT (Speech-to-Text) Providers\n# ========================================\n# Groq Whisper for transcription\n[providers.stt.groq]\nenabled = false\ndefault_model = \"whisper-large-v3-turbo\"\n\n# OpenAI-compatible STT (self-hosted Whisper, Together AI, etc.)\n[providers.stt.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\" # Ollama, LM Studio, or any OpenAI-compatible STT\nmodel = \"whisper-large-v3-turbo\"\n\n# Voicebox STT (local voice-to-text service)\n[providers.stt.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\n\n# ========================================\n# TTS (Text-to-Speech) Providers\n# ========================================\n# OpenAI TTS for voice output\n[providers.tts.openai]\nenabled = false\ndefault_model = \"gpt-4o-mini-tts\"\nvoice = \"ash\" # TTS voice name\nmodel = \"gpt-4o-mini-tts\" # TTS model\n\n# OpenAI-compatible TTS (self-hosted, Together AI, etc.)\n[providers.tts.openai_compatible]\nenabled = false\nbase_url = \"http://localhost:11434\"\nmodel = \"tts-1\"\nvoice = \"alloy\"\n\n# Voicebox TTS (local voice-to-text service)\n[providers.tts.voicebox]\nenabled = false\nbase_url = \"http://localhost:8000\"\nprofile_id = \"\"\n\n# ========================================\n# Image Generation & Vision (Google Gemini)\n# ========================================\n# API key goes in keys.toml under [image]\n# Get key from: aistudio.google.com\n# Use /onboard:image to configure via wizard\n\n# ========================================\n# Cron Job Defaults\n# ========================================\n# Default provider/model for cron jobs that don't specify their own.\n# Priority: per-job --provider > [cron] default > session's active provider.\n# Useful for routing cron jobs to a cheaper provider.\n[cron]\n# default_provider = \"minimax\"\n# default_model = \"MiniMax-M3\"\n\n# ========================================\n# Agent / Sub-Agent Defaults\n# ========================================\n# Default provider/model for the main chat session.\n# When set, new sessions inherit these values instead of the most recent session's provider/model.\n# Existing sessions pick up the new defaults on next resume (via sync_provider_for_session).\n# Useful for enforcing a specific model across all sessions without manual /models switching.\n# Priority: agent defaults > most recent session > config active provider.\n[agent]\n# context_limit = 200000 # Context window in tokens (default: 200000)\n# default_provider = \"xiaomi\"\n# default_model = \"mimo-v2.5-pro\"\n# subagent_provider = \"zhipu\"\n# subagent_model = \"GLM 5\"\n# Days to keep a spawned sub-agent's session before it is pruned, with its\n# messages, tool executions and plan files. 0 keeps them forever. They are\n# always hidden from the session list; this only decides when they are removed.\n# subagent_session_ttl_days = 7\n\n# Lazy tool-schema loading (default: true — RECOMMENDED). Each request ships\n# only the CORE tool schemas (~4k tokens) plus `tool_search`. The agent calls\n# `tool_search(\"what I need\")` to discover and activate the extended tools\n# (browser, channels, sub-agents, media, system) on demand — they then ride on\n# subsequent requests for the session. We recommend leaving this on: load only\n# the core set and let the agent pull the rest as needed.\n#\n# Setting `lazy_tools = false` reverts to sending the FULL tool-schema set —\n# ALL ~95 tools (~20k tokens) — in EVERY single request, whether the turn uses\n# them or not. That overhead is counted by the provider on every call (real\n# cost, not just display). Only set false if a model in your setup struggles\n# to reach for `tool_search`.\n# lazy_tools = false\n\n# Provider/model for Recursive Self-Improvement (RSI) cycles. The model is\n# paired with the provider, same as subagent_provider/subagent_model.\n# Unset self_improvement_provider → inherit the active provider; unset\n# self_improvement_model → use that provider's default model.\n# self_improvement_provider = \"zhipu\"\n# self_improvement_model = \"glm-5.1\"\n\n# Auto-install new releases on startup (default: true).\n# When true, OpenCrabs checks GitHub on startup and silently installs any\n# new release, then hot-restarts. Set to false if you prefer to be prompted\n# before each update (or to /evolve manually).\n# auto_update = true\n\n# Redact sensitive data from tool outputs and display (default: true).\n# When true, API keys, tokens, passwords, and IP addresses are redacted\n# from tool call displays and outputs. Set to false during sysadmin/devops\n# work where seeing IPs, tokens, and passwords is necessary.\n# redact_sensitive_data = false\n\n# Enable debug file logging from config, on top of the `--debug` CLI flag.\n# Lets you (or the agent, on request) turn detailed logs in ~/.opencrabs/logs/\n# on or off by flipping this to true/false. The change hot-reloads with no\n# restart. Effective state is `--debug OR debug_logs`, so the flag always wins.\ndebug_logs = false\n\n# Thinking-loop timeout in seconds (#890). If the model streams for this long\n# without emitting a single tool call, the stream is killed and retried with\n# multi-language phantom enforcement injected into the prompt. Catches the\n# failure mode where a reasoning model loops internally (thinking tokens\n# flowing, 0 tool calls) for an hour or more. Default 600 = 10 min.\n# Set to 0 to disable. Hot-reloads with no restart.\nthinking_loop_timeout_secs = 600\n\n[image.generation]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini image-gen model (\"Nano Banana\")\n# Override the model per-provider by setting `generation_model` under\n# `[providers.<name>]` — e.g. `imagen-4.0-generate-001` on gemini, or\n# `gpt-image-1` / `black-forest-labs/flux-1.1-pro` on any OpenAI-\n# compatible provider (openai, openrouter, custom, …). When the active\n# provider has the field set, generate_image picks the right wire\n# backend automatically: Gemini host → Gemini API, anything else →\n# `/v1/images/generations` with Bearer auth.\n\n# ========================================\n# Vision setup — two paths, pick one\n# ========================================\n#\n# Path A (preferred, simpler): set `vision_model = \"<model>\"` on your\n# active [providers.<name>] block above. Works for every built-in and\n# custom provider. The agent calls the vision model on the SAME\n# provider endpoint via the `analyze_image` tool, so no second API key\n# is needed. Pick a vision-capable model on that provider — DeepSeek\n# chat models like `deepseek-v4-flash` reject image_url content, so\n# point `vision_model` at a vision-capable variant of the same family\n# (every provider has at least one).\n#\n# Path B (fallback): enable Gemini globally below. Use this only when\n# your active provider has no vision-capable model.\n#\n# IMPORTANT: the api_key for vision must be set in `keys.toml`\n# `[image]` section, NOT here. The api_key field on `[image.vision]`\n# carries `#[serde(skip)]` and is silently dropped on load — put it in\n# keys.toml or it will look enabled but produce zero vision calls.\n#\n# When vision is unavailable for any reason, `is_vision_available`\n# now logs the exact reason at INFO level in\n# `~/.opencrabs/logs/opencrabs.YYYY-MM-DD` — search for `target=vision`.\n#\n# Easiest setup: run `/onboard:image` and it walks you through Gemini.\n\n[image.vision]\nenabled = false\nmodel = \"gemini-3.1-flash-image-preview\" # Gemini vision model\n\n# ========================================\n# Browser automation (feature: browser)\n# ========================================\n# By default each profile launches its own headless Chromium (~250-300MB each).\n# To share ONE Chromium across multiple profiles (big memory win on small VDS),\n# start a standalone instance with remote debugging:\n#\n# chromium --remote-debugging-port=9222 --headless --no-sandbox\n#\n# then point every profile's config at it. Prefer the http:// form — OpenCrabs\n# queries /json/version to find the real devtools websocket URL. (A bare\n# ws://host:port is also accepted and normalized to http:// automatically.)\n# [browser]\n# cdp_endpoint = \"http://localhost:9222\"\n\n# ========================================\n# Tips for Using Local LLMs\n# ========================================\n# 1. Make sure LM Studio is running before starting OpenCrabs\n# 2. Load a model in LM Studio first\n# 3. Set default_model to EXACTLY match the model name shown in LM Studio\n# 4. Increase context length in LM Studio if you get overflow errors:\n# - Recommended: 8192 or higher\n# - Location: LM Studio > Model Settings > Context Length\n\n# ==================================================\n# Channels (Telegram / WhatsApp / Slack / Discord / Trello)\n# ==================================================\n\n# respond_to controls which messages the bot replies to (applies to Telegram, Discord, Slack):\n# \"all\" — reply to every message in allowed channels (default)\n# \"dm_only\" — reply only to direct/private messages\n# \"mention\" — reply only when the bot is @mentioned or replied-to\n# \"auto\" — reply to all while there is at most one active sender, then switch\n# to mention-only once a second unique sender appears in the chat\n\n[channels.whatsapp]\nenabled = false\n# You pair the bot to a WhatsApp account by scanning its QR — it then runs AS\n# that account. It can be your own number (talk to it in \"Message Yourself\") or\n# any other number you own, including a WhatsApp Business account, to serve that\n# account's incoming DMs.\n# Phone numbers allowed to message the bot (E.164 format, leading + optional)\nallowed_phones = [\"+15551234567\"]\n# bot_owner = [\"+15551234567\"] # Operator phone(s) for owner-only commands. The operator can DM the\n # bot and is always allowed regardless of response_policy. Auto-seeded\n # from the first allowed_phones entry on first run; set explicitly to\n # pin a different operator than the paired account.\n# response_policy = \"auto\" # Who the bot answers. The paired account's own self-chat and bot_owner\n # are ALWAYS allowed. Options:\n # \"auto\" — legacy: open when allowed_phones is empty, else\n # owner/operator + allowed_phones (default)\n # \"owner_only\" — only the paired self-chat and bot_owner operators\n # \"allowlist\" — owner/operator + the contacts in allowed_phones\n # \"open\" — every incoming DM (business serving any customer)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.discord]\nenabled = false\nallowed_channels = [\"channel_id\"] # Where the bot operates (empty = all channels)\nallowed_users = [123456789012345] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789012345] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n[channels.telegram]\nenabled = false\nallowed_users = [123456789] # Who the bot replies to (numeric user ID, empty = everyone)\n# bot_owner = [123456789] # Owner ID(s): owner-only commands (e.g. /cd) and gated actions.\n # Auto-seeded from the first allowed_users entry on first run; set it\n # explicitly to pin the owner instead of relying on list order.\n# allowed_channels = [\"-100123456789\"] # Chat/group IDs to restrict to (empty = all chats)\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\" | \"auto\"\n# silence_group_start = true # Silently ignore /start from non-allowed users in groups (default: true)\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n# rich_messages = true # Native rich messages — flow logs, collapsible tool calls,\n # status bubble with task preview. Default: true since v0.3.64.\n # Toggle available in the onboard dialog (/onboard:provider →\n # Telegram channel step). Set to false if your audience uses\n # Telegram Web or older clients (no HTML fallback).\n\n# Per-group access control (per-chat ACL). Tiers:\n# - allowed_users (above) = admins: may DM the bot and act in any chat.\n# - bot_owner = owner: always allowed everywhere.\n# - groups.<chat_id>.allowed_users = users allowed in THAT group ONLY. They are\n# refused in DMs unless they are also an admin/owner — this blocks the \"DM the\n# bot privately to escape group oversight\" bypass.\n# DMs are gated to admins + owner. If neither allowed_users nor bot_owner is set\n# the bot is unconfigured and stays open (no hard lockout); set either to lock down.\n# Each group may also override respond_to just for that group.\n# [channels.telegram.groups.-1001234567890]\n# allowed_users = [222333444, 555666777] # allowed in this group only, never via DM\n# respond_to = \"mention\" # per-group override of the global respond_to\n\n[channels.slack]\nenabled = false\nallowed_channels = [\"C12345678\"] # Where the bot operates (Slack channel ID, empty = all)\nallowed_users = [\"U12345678\"] # Who the bot replies to (Slack user ID, empty = everyone)\n# bot_owner = [\"U12345678\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# respond_to = \"all\" # \"all\" | \"dm_only\" | \"mention\"\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Trello — board card management\n# ========================================\n# API keys/tokens go in keys.toml under [channels.trello]\n# Default mode: tool-only — no automatic polling. The AI acts on Trello only\n# when you explicitly ask it to via trello_send / trello_connect.\n# Opt-in polling: set poll_interval_secs > 0 to have the agent watch boards\n# for @mentions of the bot username and respond to them.\n[channels.trello]\nenabled = false\n# Board IDs or names to monitor — you can mix 24-char hex IDs and human-readable board names.\n# The agent resolves names at startup. Comma-separated in the wizard; TOML array here.\nboard_ids = [\"your-board-name\", \"abc123def456abc123def456\"]\nallowed_users = [] # Trello member IDs allowed to @mention the bot (empty = all)\n# bot_owner = [\"member_id\"] # Owner ID(s) for owner-only commands. Auto-seeded from the first\n # allowed_users entry on first run; set explicitly to pin the owner.\n# poll_interval_secs = 30 # Opt-in: poll boards every N seconds for @mentions. Default = disabled.\n# session_idle_hours = 24.0 # Archive inactive non-owner sessions after N hours (default: never)\n\n# ========================================\n# Daemon Mode (systemd / launchd service)\n# ========================================\n# Settings for `opencrabs daemon` headless mode.\n[daemon]\n# HTTP health check port. When set, GET /health returns 200 OK + JSON.\n# Useful for systemd watchdog, uptime monitors, and external health probes.\n# health_port = 8080\n\n# ========================================\n# Agent-to-Agent (A2A) Protocol\n# ========================================\n# Enables HTTP gateway for peer-to-peer agent communication.\n# Other A2A-compatible agents can send tasks, collaborate, and debate.\n[a2a]\nenabled = false\nbind = \"127.0.0.1\" # Loopback only by default for security\nport = 18790 # A2A gateway port\n# CORS allowed origins (empty = no cross-origin requests allowed)\n# allowed_origins = [\"http://localhost:3000\"]\n# API key for Bearer token auth on /a2a/v1 (optional, recommended for non-loopback)\n# Can also be set in keys.toml under [a2a] api_key = \"...\"\n# api_key = \"your-secret-key\"\n\n# ========================================\n# Web Search Providers (default to free Duck Duck Go, no need additional web search provider)\n# ========================================\n\n[providers.web_search.exa]\nenabled = true\n# MCP is enabled by default as its free. If want through API its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.exa] api_key = \"...\"\n\n[providers.web_search.duckduckgo]\nenabled = true\n# Completely free, enabled by default\"\n\n[providers.web_search.brave]\nenabled = false\n# Its free up to 1000 requests. API key goes in keys.toml: [providers.web_search.brave] api_key = \"...\"\n\n# ========================================\n# Memory / Embeddings\n# ========================================\n# Controls vector embeddings for semantic memory search.\n# When disabled, only FTS5 (keyword) search is used — no model download,\n# no llama.cpp init, zero GPU/CPU overhead.\n#\n# Automatically set to false on VPS/cloud (detected at startup).\n# You can also set it manually here.\n#\n# [memory]\n# vector_enabled = false\n\n# --------------------------------------------\n# OpenAI-compatible Embedding API\n# --------------------------------------------\n# When configured, embeddings are generated via API instead of the local\n# GGUF model (embeddinggemma-300M). This eliminates the ~300MB model\n# download and ~2.9GB RAM overhead of llama.cpp.\n#\n# Supports any OpenAI-compatible /v1/embeddings endpoint:\n# OpenAI, Ollama, LM Studio, localai, Jina, etc.\n#\n# Example: OpenAI\n# [memory.embedding]\n# url = \"https://api.openai.com/v1\"\n# model = \"text-embedding-3-small\"\n# # api_key goes in keys.toml: [providers.memory_embedding] api_key = \"sk-...\"\n# # dimensions = 1536 # auto-detected from first API response if unset\n#\n# Example: Ollama (local, free)\n# [memory.embedding]\n# url = \"http://localhost:11434/v1\"\n# model = \"nomic-embed-text\"\n#\n# Example: Jina\n# [memory.embedding]\n# url = \"https://api.jina.ai/v1\"\n# model = \"jina-embeddings-v3\"\n# # api_key goes in keys.toml\n"}}}}