-
-
Notifications
You must be signed in to change notification settings - Fork 1
Configuration
Eshan Roy edited this page Jul 5, 2026
·
4 revisions
M31 Autonomous (M31A) is configured via a TOML file at ~/.m31a/config.toml. Override the path with the M31A_CONFIG environment variable. Project-level config is m31a.toml in the project root.
Configuration is loaded in 6 layers, each overriding the previous:
-
Compiled defaults —
DefaultConfig()inloader.go -
Global TOML —
~/.m31a/config.toml -
Environment variables —
OPENROUTER_API_KEY,ZEN_API_KEY, etc. -
Project TOML —
m31a.tomlin project root -
Variable substitution —
${VAR}syntax in string values -
Validation —
ValidationErrortype for structured error reporting
M31A also auto-loads .env from the current directory (with security checks — skips group/world-writable files).
# ============================================================================
# Provider Configuration
# ============================================================================
[provider]
default = "openrouter" # Active provider: "openrouter", "zen", or "nvidia"
auto_fallback = true # Auto-switch to healthy provider on failure
fallback_priority = ["nvidia", "zen", "openrouter"] # Ordered fallback list
health_check_timeout_secs = 10 # Per-provider health check timeout
registration_order = ["openrouter", "zen", "nvidia"] # Provider registration order
[provider.openrouter]
api_key = "" # OpenRouter API key (prefer keychain)
[provider.zen]
api_key = "" # Zen API key (prefer keychain)
[provider.nvidia]
api_key = "" # NVIDIA NIM API key (prefer keychain)
# Custom base URLs for self-hosted or proxied gateways
# openrouter_base_url = ""
# zen_base_url = ""
# nvidia_base_url = ""
# HTTP headers for OpenRouter
# openrouter_referer = "https://github.com/eshanized/M31A"
# openrouter_title = "M31A"
# ============================================================================
# Model Configuration
# ============================================================================
[model]
default = "" # Default model ID (empty = prompt at startup)
context_warning_threshold = 0.8 # Warn when context usage exceeds this (0.0-1.0)
show_thinking_by_default = false
auto_collapse_tools = false
auto_arbitrage = false # Auto-switch to cheapest model per task
arbitrage_threshold = 0.1 # Minimum savings ratio to trigger switch
default_context_length = 128000 # Fallback context length when provider doesn't return one
token_ema_alpha = 0.3 # Token estimator EMA calibration rate
# ============================================================================
# Model Capabilities Configuration
# ============================================================================
[model_capabilities]
# Extra patterns appended to built-in lists (additive, never replaces defaults)
# extra_reasoning_patterns = []
# extra_tool_capable_patterns = []
# extra_completion_only_patterns = []
# extra_non_chat_patterns = []
# Known model capability overrides merged with built-in table
# [model_capabilities.known_capabilities]
# "custom-model" = { context_length = 128000, max_output = 8192, supports_tools = true, supports_reasoning = false }
# ============================================================================
# UI Configuration
# ============================================================================
[ui]
theme = "dark" # "dark", "light", or "auto"
compact_mode = false
show_token_usage = false
show_cost_estimate = true
max_iterations = 100 # Max workflow iterations (0 = unlimited)
leader_key = "ctrl+x" # Leader key for chord shortcuts
leader_timeout_ms = 1000 # Leader key timeout
sidebar_width_threshold = 120 # Min terminal width for sidebar auto-show
discuss_timeout = 300 # Discuss Q&A timeout in seconds
thinking_max_lines = 20 # Max lines for thinking block
permission_modal_width = 60 # Permission modal width in columns
sidebar_width = 42 # Sidebar width in columns
max_message_history = 1000 # Max message history entries
fallback_banner_timeout_secs = 15
default_log_lines = 20
session_list_limit = 20 # Max sessions in resume screen
thinking_opacity = 0.6
frecent_history_size = 100 # Frecent history max entries
# Accessibility
reduced_motion = false # Reduce animations for accessibility
zen_mode_key = "ctrl+z" # Key to toggle zen mode
# Layout thresholds
width_ultra_compact = 60 # Ultra-compact layout threshold
width_compact = 80 # Compact layout threshold
width_full = 120 # Full layout threshold
# History limits
max_messages = 2000 # Max message history
max_todo_items = 50 # Max todo items
# Sidebar
sidebar_refresh_secs = 30 # Sidebar refresh interval
# Welcome screen
welcome_two_col_threshold = 100 # Min width for two-column welcome
welcome_card_min_width = 20 # Min card width
welcome_card_max_width = 40 # Max card width
# Logo customization
logo_file = "" # Path to custom logo file (empty = embedded ASCII art)
logo_text = "" # Inline logo text (takes precedence over logo_file)
# Welcome suggestions
# welcome_suggestions = ["Fix a bug", "Add a feature", "Write tests"]
# Keyboard hints
# keyboard_hints = ["Ctrl+X: Leader key", "/help: Get help"]
# Unicode symbol overrides
# [ui.symbol_overrides]
# check = "✓"
# cross = "✗"
# warning = "⚠"
ascii_fallback = false # Use ASCII instead of Unicode (for poor Unicode terminals)
theme_file = "" # Path to custom theme file
# Toast type overrides
# [ui.toast_type_overrides]
# [ui.toast_type_overrides.success]
# icon = "OK"
# title = "Done"
# Theme and Colors
# accent_color = ""
# custom_background = ""
# border_style = ""
# Typography
# bold_headers = true
# italic_thinking = false
# tab_width = 4
# Layout
# sidebar_position = "right" # "left" or "right"
# sidebar_auto_show = true
# card_padding = 1
# welcome_screen = true
# Animation
# animation_speed = "normal" # "fast", "normal", "slow"
# spinner_style = ""
# transition_style = ""
# breathing_effects = false
# logo_animation = true
# Status Bar
# status_bar_style = ""
# status_bar_position = "bottom"
# show_spinner_in_status = true
# Tool Cards
# tool_card_style = ""
# tool_output_max_lines = 20
# syntax_highlight = true
# Toasts
# toast_position = "top-right"
# toast_duration_secs = 10
# toast_max_visible = 3
# ============================================================================
# Permissions Configuration
# ============================================================================
[permissions]
default_mode = "prompt" # "prompt", "allow", or "deny"
timeout_seconds = 300 # Permission modal timeout
# Permission rules (evaluated in order)
# [[permissions.rules]]
# tool = "Bash"
# pattern = "rm -rf"
# risk_level = "destructive"
# action = "deny"
# [[permissions.rules]]
# tool = "Bash"
# pattern = "go test"
# risk_level = "safe"
# action = "allow"
# Per-agent permission profiles
# [permissions.agents.build]
# default_action = "allow"
# [[permissions.agents.build.rules]]
# tool = "Bash"
# pattern = "go build"
# action = "allow"
# ============================================================================
# Features Configuration
# ============================================================================
[features]
auto_backup = true # Auto-backup files before edit/write
resume_on_startup = false # Auto-resume most recent session
workflow_mode = "" # "auto", "full", "fast", or "direct"
model_cache_ttl_minutes = 5 # Model cache TTL
model_cache_stale_hours = 24 # Stale cache fallback TTL
healthcheck_live_ms = 500 # Health check "live" threshold
healthcheck_slow_ms = 2000 # Health check "slow" threshold
session_id_length = 8 # Session ID length in hex chars
max_recent_models = 10 # Max recent models to remember
session_retention_days = 30 # Session retention period
health_check_timeout_secs = 10 # Health check timeout
rate_limit_backoff_secs = 120 # Rate limit backoff
budget_limit_usd = 0 # Per-session budget limit (0 = unlimited)
metrics_enabled = true # Enable metrics collection
# Plan phase enhancements
plan_research = true # Pre-plan research step
plan_check = true # Plan quality checker + revision loop
plan_check_max_iter = 3 # Max revision iterations
plan_security_gate = true # Security heuristic gate
plan_coverage_gate = true # Requirements coverage gate
plan_gap_analysis = true # Post-plan gap analysis
plan_chunked = true # Chunked plan generation
plan_chunk_threshold = 10 # Tasks threshold for auto-chunking
# Discuss phase enhancements
discuss_quality_check = true # Question quality checker
discuss_completeness = true # Answer completeness check
discuss_follow_ups = true # Follow-up question generation
# Execute phase enhancements
execute_preflight = true # Pre-execution validation
execute_quality_gate = true # Per-task acceptance criteria checks
execute_loop_detect = true # Tool call loop detection
# Verify + Ship phase enhancements
verify_report = true # Generate verification report
verify_security = true # Security file scanning
ship_preflight = true # Pre-ship checklist
ship_changelog = true # Changelog generation
# Initialize phase enhancements
init_deep_analysis = true # Deep project analysis
init_preflight = true # Environment pre-flight checks
# Intent classification
intent_classification = true # Pre-classify REPL input for routing
intent_classify_timeout_secs = 25 # Timeout for LLM classification
# Workflow thresholds
max_heal_attempts = 3 # Max healing attempts per phase
max_plan_retries = 3 # Max plan retry attempts
context_truncation_threshold = 0.8 # Context truncation threshold
# Retry policy
retry_max_attempts = 3 # Max retry attempts
retry_base_delay_ms = 1000 # Base delay between retries
retry_max_delay_ms = 30000 # Max delay between retries
retry_backoff_multiplier = 2.0 # Backoff multiplier
# Retry-after
max_retry_after_secs = 300 # Max retry-after header value
# Task runner
max_parallel_tasks = 4 # Max parallel tasks
# Coordinator
coordinator_timeout_secs = 60 # Coordinator timeout
# ============================================================================
# Instructions Configuration
# ============================================================================
[instructions]
enabled = true # Enable AGENTS.md discovery
disable_project = false # Disable project-level AGENTS.md
# ============================================================================
# Ledger Configuration
# ============================================================================
[ledger]
enabled = true # Enable cross-session learning ledger
max_entries = 100 # Max ledger entries
# ============================================================================
# Agents Configuration (per-phase model assignment)
# ============================================================================
[agents]
default = "" # Global agent default model
initialize = "" # Model for Initialize phase
research = "" # Model for Research phase
plan = "" # Model for Plan phase
execute = "" # Model for Execute phase
verify = "" # Model for Verify phase
runtime = "" # Model for Runtime phase
ship = "" # Model for Ship phase
discuss = "" # Model for Discuss phase
# Subagent profile overrides
# [agents.profiles]
# [agents.profiles.explore]
# description = "Custom explore agent"
# model = "gpt-4"
# allowed_tools = ["Glob", "Grep", "FileRead"]
# max_turns = 20
# ============================================================================
# Git Configuration
# ============================================================================
[git]
commit_prefix = "feat" # Default commit prefix
fix_prefix = "fix" # Prefix for fix commits
ship_prefix = "chore" # Prefix for ship commits
# user_name = "" # Git user.name override
# user_email = "" # Git user.email override
# ============================================================================
# Verify Configuration
# ============================================================================
[verify]
# build_command = "" # Custom build command (empty = auto-detect)
# test_command = "" # Custom test command (empty = auto-detect)
# ============================================================================
# Tools Configuration
# ============================================================================
[tools]
max_glob_results = 1000
max_grep_results = 100
bash_kill_grace_secs = 5
max_backups_per_file = 10
webfetch_max_redirects = 5
output_max_lines = 5000 # Max lines per tool output
output_max_bytes = 512000 # Max bytes per tool output
output_retention_days = 7 # Days to retain output files
# Rate limiting (two tiers)
rate_limit_burst = 20 # General rate limit burst
rate_limit_per_sec = 10 # General rate limit per second
dangerous_rate_limit_burst = 5 # Dangerous tool rate limit burst
dangerous_rate_limit_per_sec = 2 # Dangerous tool rate limit per second
max_concurrent = 8 # Max concurrent tool executions
# DNS caching
dns_cache_ttl_secs = 300 # DNS cache TTL
# Edit tool
fuzzy_threshold = 0.7 # Fuzzy match threshold
min_lines_for_fuzzy = 3 # Min lines for fuzzy matching
# Bash
bash_max_timeout_secs = 1800 # Max bash timeout (30 min)
# WebFetch
webfetch_max_retries = 3 # Max WebFetch retries
webfetch_retry_delay_ms = 500 # Retry delay in ms
# Execute phase
max_tool_concurrency = 4 # Max tool concurrency per task
loop_detect_window = 3 # Loop detection window
# Dangerous command extensions (additive to compiled baseline)
# additional_blocked_commands = ["docker rm", "kubectl delete", "terraform destroy"]
# additional_obfuscation_patterns = []
# webfetch_user_agent = ""
# skip_dirs = ["node_modules", "vendor"]
# websearch_base_url = "" # Custom SearXNG instance URL
# websearch_enabled = true
# ============================================================================
# Compaction Configuration
# ============================================================================
[compaction]
auto = true # Enable automatic session compaction
buffer = 20000 # Tokens reserved before compaction triggers
keep_tokens = 8000 # Tokens of recent history to preserve verbatim
proactive = false # Trigger compaction before phase transitions
tool_calls_threshold = 50 # Check compaction every N tool calls
phase_transition_pct = 80 # Trigger compaction at this % before phase transition
# summary_template = "" # Inline summary template override
# summary_template_file = "" # Path to summary template file
# ============================================================================
# Prompts Configuration
# ============================================================================
[prompts]
# system_prompt_file = "" # Path to custom system prompt (replaces base.md)
# project_prompt_dir = "" # Project-level prompt overrides (.m31a/prompts/)
# global_prompt_dir = "" # Global prompt overrides (~/.m31a/prompts/)
# Per-prompt overrides
# [prompts.overrides]
# "execute-task" = "/path/to/custom-execute.md"
# "plan-phase" = "/path/to/custom-plan.md"
# Per-model template overrides
# [prompts.model_template_overrides]
# "mistral" = "/path/to/mistral.txt"
# "deepseek" = "/path/to/deepseek.txt"
# ============================================================================
# Narrative Configuration
# ============================================================================
[narrative]
# Template overrides: map of NarrativeType to template text
# [narrative.template_overrides]
# "task_complete" = "Done! {description} completed successfully."
# Classification overrides: map of EventType to classification
# Valid values: "narrative", "grouped", "hidden", "expanded"
# [narrative.classification_overrides]
# "tool_call" = "expanded"
# ============================================================================
# Templates Configuration
# ============================================================================
[templates]
# external_dir = "" # External template directory
# website_framework = "nextjs" # Website framework: "nextjs", "vue", "svelte", "astro", "html"
# Custom design palettes
# [templates.custom_palettes]
# [templates.custom_palettes.custom]
# primary = "#FF5733"
# secondary = "#33FF57"
# ============================================================================
# Skills Configuration
# ============================================================================
[skills]
enabled = true # Enable skill discovery
# sources = [] # Skill discovery directories| Variable | Description |
|---|---|
M31A_CONFIG |
Override config file path |
OPENROUTER_API_KEY |
OpenRouter API key (alternative to keychain) |
ZEN_API_KEY |
Zen API key (alternative to keychain) |
NVIDIA_API_KEY |
NVIDIA NIM API key (alternative to keychain) |
USE_EFIE |
Enable EFIE code intelligence backend (1 to enable) |
M31A watches the config file for changes using fsnotify with 50ms debounce. When the file changes, the config is reloaded and applied at runtime without restarting. Falls back to 5-second polling when fsnotify is unavailable.
Source: internal/config/loader.go
M31A detects project type by scanning for marker files up to 3 parent directories deep (MaxProjectConfigDepth):
| Marker File | Detected Type |
|---|---|
go.mod |
Go project |
package.json |
Node.js project |
Cargo.toml |
Rust project |
pyproject.toml / requirements.txt
|
Python project |
Gemfile |
Ruby project |