Configuration
Three places to configure MateClaw: application.yml, environment variables, and the database.
Most settings live in application.yml (Spring Boot's default config file), with sensitive values overridden by environment variables. Anything you want to change at runtime — model providers, search keys, feature toggles — lives in the mate_system_setting table and is edited through the Settings page.
Deep-dive topics have their own pages — Tool Guard rules in Security & Approval, model providers in Models, memory tuning in Memory.
Profiles
| Profile | Database | Activated by |
|---|---|---|
default | H2 file at ./data/mateclaw | No action needed |
mysql | MySQL 8.0+ | spring.profiles.active=mysql or SPRING_PROFILES_ACTIVE=mysql |
Docker deployments activate mysql automatically. Desktop builds use default.
Core application.yml sections
Server
server:
port: 18088 # HTTP port
servlet:
context-path: /Database — H2 (development)
spring:
datasource:
url: jdbc:h2:file:./data/mateclaw;MODE=MYSQL
username: sa
password:
driver-class-name: org.h2.Driver
h2:
console:
enabled: true # Available at /h2-console (disable in production)Database — MySQL (production)
spring:
profiles:
active: mysql
datasource:
url: jdbc:mysql://localhost:3306/mateclaw?useSSL=false&serverTimezone=UTC
username: root
password: ${MYSQL_ROOT_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.DriverAI model — managed in the UI, not YAML
TIP
Model configuration is 100% UI-driven. Don't put spring.ai.* blocks in application.yml — every provider, key, and model config lives in Settings → Models, backed by the mate_model_provider and mate_model_config tables.
LLM API keys are not read from environment variables — DASHSCOPE_API_KEY / OPENAI_API_KEY / etc. have no effect. A fresh install starts with no providers configured; log in and add your first one under Settings → Models → Add Provider. Full reference in Models.
Virtual threads (JDK 21)
spring:
threads:
virtual:
enabled: trueEnabled by default. Tomcat request threads, @Scheduled tasks, and @Async methods all run on virtual threads. SSE long-connections no longer hold platform threads, and I/O-bound async tasks (memory extraction, auditing, skill install, etc.) no longer queue behind a 16-thread pool.
Spring AI Observability
spring:
ai:
chat:
observations:
log-prompt: false # don't write prompt content into spans (security)
log-completion: false # don't write completion content into spansWhen enabled, /actuator/metrics/gen_ai.client.operation and /actuator/metrics/gen_ai.client.token.usage automatically record latency and token usage for every LLM call. Requires spring-boot-starter-actuator (already included).
Context window
mate:
agent:
conversation:
window:
default-max-input-tokens: 128000
compact-trigger-ratio: 0.75
preserve-recent-pairs: 2
summary-max-tokens: 300Details in Memory.
Memory extraction and consolidation
mate:
memory:
auto-summarize-enabled: true
min-messages-for-summarize: 4
min-user-message-length: 10
skip-cron-conversations: true
summary-max-tokens: 1000
max-transcript-messages: 30
cooldown-minutes: 5
emergence-enabled: true
emergence-day-range: 7LLM Wiki
mate:
wiki:
chunk-size: 1200
chunk-overlap: 200
digestion-concurrency: 2
llm-model-config-id: 1
min-concept-occurrences: 2
max-page-backlinks: 50
lock-on-manual-edit: true
rebuild-sources-on-update: trueEight knobs. Details in LLM Wiki.
Tool Guard (rule-based)
mateclaw:
tool:
guard:
enabled: true
default-policy: require_approval # `allow` / `deny` / `require_approval`
approval-timeout-seconds: 600
rules:
- tool: ShellExecuteTool
arg-pattern: "^(ls|cat|grep|find)\\s"
action: allow
priority: 100
- tool: ShellExecuteTool
action: require_approval
priority: 50Details in Security & Approval.
File Guard
mateclaw:
security:
file-guard:
enabled: true
allowed-paths:
- "${user.dir}/workspace"
- "${java.io.tmpdir}/mateclaw"
denied-paths:
- "/etc"
- "/usr"
- "${user.home}/.ssh"
- "${user.home}/.config"JWT authentication
mateclaw:
auth:
jwt:
secret: ${JWT_SECRET:your-secret-key-at-least-32-characters-long}
expiration: 86400000
sliding-window: trueWARNING
Change the default JWT secret in production. Must be at least 32 characters. Use an environment variable; never commit it.
Skill workspace
mateclaw:
skill:
workspace:
root: ${user.home}/.mateclaw/skills
auto-init: true
delete-policy: archive
bundled-skills-path: skillsMultimodal default providers
mate:
image:
default-provider: dashscope
video:
default-provider: dashscope
tts:
default-provider: cosyvoice
stt:
default-provider: paraformer
music:
default-provider: dashscopeDetails in Multimodal.
Environment variables
LLM keys are not read from env
DashScope / OpenAI / Anthropic / DeepSeek / Kimi and other provider API keys are not configured via environment variables. The container starts with zero LLM keys; after login, add your first provider under Settings → Models → Add Provider.
| Variable | Required | Purpose |
|---|---|---|
SERPER_API_KEY | — | Google Serper search key (search tools not yet UI-managed) |
TAVILY_API_KEY | — | Tavily search key (same as above) |
JWT_SECRET | — | JWT signing secret (recommended in production) |
MATECLAW_CORS_ALLOWED_ORIGINS | — | CORS allowlist (recommended in production) |
DB_PASSWORD / DB_ROOT_PASSWORD | Docker | MySQL app user / root password |
SPRING_PROFILES_ACTIVE | — | Set to mysql for production |
Setting them
Linux / macOS:
export JWT_SECRET=your-production-secret-at-least-32-chars
export SERPER_API_KEY=your-serper-key # optionalWindows (PowerShell):
$env:JWT_SECRET = "your-production-secret-at-least-32-chars"Docker (.env file):
DB_PASSWORD=secure-password-here
DB_ROOT_PASSWORD=different-secure-password-here
JWT_SECRET=your-production-secret-at-least-32-charsAfter startup, open http://localhost:18080, sign in as admin / admin123, and add your first LLM provider under Settings → Models → Add Provider.
Database schema init
MateClaw uses Flyway for schema migrations:
db/migration/h2/V*__*.sql— H2-dialect migration scriptsdb/migration/mysql/V*__*.sql— MySQL-dialect migration scripts- After migrations, seed data is loaded from
db/data-*.sql— idempotent
Flyway auto-selects the correct dialect path based on the active Spring profile. Every startup runs a repair before migrate, self-healing checksum drift and partially-failed migrations (especially important for desktop users upgrading offline).
Table conventions
- All tables prefixed
mate_ snake_casecolumns,camelCaseJava fields (auto-mapped by MyBatis Plus)- Every table has
create_time,update_time,deleted - Logical delete:
deleted = 0active,deleted = 1soft-deleted
H2 console in dev
http://localhost:18088/h2-console:
| Field | Value |
|---|---|
| JDBC URL | jdbc:h2:file:./data/mateclaw |
| Username | sa |
| Password | (empty) |
Switching to MySQL
CREATE DATABASE mateclaw CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;export SPRING_PROFILES_ACTIVE=mysql
export MYSQL_ROOT_PASSWORD=your-password
mvn spring-boot:runRuntime settings (mate_system_setting)
Things you want to change without restarting:
| Key | Type | Purpose |
|---|---|---|
default_agent_id | Long | Agent used when none specified |
default_model_config_id | Long | Default model configuration |
max_conversation_turns | Integer | Max turns per conversation |
enable_memory | Boolean | Enable memory extraction |
search_enabled | Boolean | Global web search toggle |
search_provider | String | serper / tavily / duckduckgo / searxng |
search_fallback_enabled | Boolean | Fall through to next provider on failure |
serper_api_key | String | Serper key (masked in UI) |
tavily_api_key | String | Tavily key (masked in UI) |
language | String | zh-CN / en-US default UI language |
stream_enabled | Boolean | SSE streaming output |
debug_mode | Boolean | Show extra debug info in UI |
All editable from Settings → System. Changes take effect immediately.
Search service configuration
Web search config has been migrated from application.yml to the System Settings page. Changes take effect immediately without restart.
TIP
API keys are displayed masked. When saving, keys are only overwritten when a new value is entered. Blank input means "keep existing key".
Logging
logging:
level:
vip.mate: INFO
vip.mate.agent: DEBUG
vip.mate.agent.graph: DEBUG
org.springframework.ai: INFO
root: INFOFor deep debugging, set vip.mate: TRACE. Log volume is high — don't leave it on in production.
CORS
Development: Vite's dev server handles CORS via its proxy. Production: frontend is embedded in the JAR, no CORS needed.
If you deploy the frontend separately:
mateclaw:
cors:
allowed-origins:
- http://localhost:5173
- https://your-domain.comConfiguration precedence
Settings resolve in this order (highest priority first):
- Environment variables
- Command-line arguments (
--server.port=9090) application-{profile}.ymlapplication.yml- Database
mate_system_setting(for runtime-configurable values)
Next
- Models — provider and model config in detail
- Security & Approval — JWT, Tool Guard, File Guard, audit log
- Memory — memory tuning parameters
- LLM Wiki —
mate.wikiblock explained - Channels — channel-specific configuration
