# Configuration
[Feature docs index](README.md) · [Repository README](../../README.md)
## Purpose
Configure local runtime state, settings precedence, non-secret options, selected-model defaults, compaction model overrides, context limits, autocomplete, session titles, skill discovery roots, token-triggered streaming reminder rules, and auth-record boundaries.
## Details
Runtime state lives under `~/.magi-code` by default. Set absolute `MC_HOME` to isolate runs for tests or separate profiles. Existing `~/.mc` auto-migrates on first launch only when `MC_HOME` is unset and `~/.magi-code` does not exist; if both directories exist, no migration occurs and `~/.magi-code` is used. Config/auth diagnostics name the resolved file under active `MC_HOME`.
```sh
MC_HOME=/tmp/mc-local cargo run --bin magi-code -- --no-session
```
Important paths:
| Path | Purpose |
| --- | --- |
| `~/.magi-code/settings.json` | Non-secret selected-model, output, compaction, context, TUI autocomplete, Herdr opt-in, tool, model availability, MCP stdio/HTTP server, session-title, TTSR, custom-provider, instruction discovery, skill discovery/disabled-skill, and selected-primary-agent settings. Startup adds `$schema: "./state/settings.schema.json"` metadata when safe. |
| `.magi-code/settings.json` | Cwd-local project settings. Same schema as global `settings.json`; overrides global settings for current cwd only. Hand-edit or commit per project. |
| `~/.magi-code/state/settings.schema.json` | Generated JSON Schema for `settings.json`, produced from Rust settings structs during startup. Non-secret and safe to regenerate. |
| `~/.magi-code/auth.json` | Provider-keyed credentials. Keep private; CLI writes use owner-only permissions on Unix. |
| `~/.magi-code/AGENTS.md` | User-level instructions. |
| `~/.magi-code/prompts/*.md` | Optional user overrides for bundled prompt fragments, including `compact.md` for `/compact` summaries. |
| `~/.magi-code/skills/<skill-name>/SKILL.md` | User-level skills. |
| `~/.magi-code/skills/<folder>/<skill-name>/SKILL.md` | User-level skills grouped one folder deep; skill name remains `<skill-name>`. |
| `~/.magi-code/subagents/<identity-id>.md` | Optional discoverable subagent identity profiles. |
| `~/.magi-code/primary-agents/<agent-id>.md` | Optional discoverable primary-agent profiles for Mission Control main-assistant selection. |
| `~/.magi-code/cache` | Local context/cache data, including sanitized model catalogs. |
| `~/.magi-code/sessions` | JSONL session artifacts. |
| `~/.magi-code/state` | Runtime state, including generated `settings.schema.json`. |
Configuration precedence:
1. CLI flags: `--provider`, `--model`, `--api-key`, `--color`.
2. Environment variables: `MC_PROVIDER`, `MC_MODEL`, `NO_COLOR`, `MC_API_KEY`.
3. Local `.magi-code/settings.json` in cwd for project-scoped non-secret overrides.
4. Global `$MC_HOME/settings.json` or `~/.magi-code/settings.json` for non-secret settings and provider-keyed `$MC_HOME/auth.json` or `~/.magi-code/auth.json` for credentials.
5. Runtime defaults: provider `openai-codex`, model `gpt-5.5`, color auto by stdout TTY, and `file_autocomplete_respects_gitignore: true`.
Project-scoped settings:
- Path: `<cwd>/.magi-code/settings.json`.
- Schema: same as global `~/.magi-code/settings.json`.
- Lookup: cwd only; no parent-directory traversal.
- Creation: not auto-created at startup. Mission Control `/skills`, `/tools`, `/subagents`, and `/models` create it on first Project-scope mutation.
- Writes: most CLI/settings writes remain global-only. Mission Control `/skills`, `/tools`, `/subagents`, and `/models` use `[Tab]` to choose Global or Project scope and write only selected scope.
- Invalid JSON: startup fails and names the local file path.
- Merge: defaults load first, then global, then local, then env/CLI. Objects deep-merge recursively; arrays replace entirely; scalars replace.
- Maps: `mcp_servers` and `custom_providers` union by key; same key uses local value.
Global plus local merge example:
Global `~/.magi-code/settings.json`:
```json
{
"selected_model": { "provider": "openai-codex", "model": "gpt-5.5" },
"tools": { "bash": { "absolute_paths": true, "shell_expansion": true }, "disabled": ["write"] },
"mcp_servers": { "global_docs": { "type": "stdio", "command": "docs-mcp" } },
"custom_providers": { "local-ai": { "label": "Local AI", "base_url": "http://localhost:11434/v1" } },
"skills": { "disabled": ["slow-skill"] },
"subagents": { "disabled": ["reviewer"], "schema_validation_max_retries": 2 }
}
```
Local `<cwd>/.magi-code/settings.json`:
```json
{
"selected_model": { "model": "repo-model" },
"tools": { "bash": { "shell_expansion": false }, "disabled": [] },
"mcp_servers": { "repo_docs": { "type": "stdio", "command": "repo-mcp" } },
"custom_providers": { "local-ai": { "label": "Repo Local AI", "base_url": "http://127.0.0.1:11434/v1" } },
"skills": { "disabled": [] },
"subagents": { "disabled": [], "schema_validation_max_retries": 2 }
}
```
Effective settings: `selected_model.provider` stays `openai-codex`; `selected_model.model` becomes `repo-model`; `tools.bash.absolute_paths` stays `true`; `tools.bash.shell_expansion` becomes `false`; `tools.disabled`, `skills.disabled`, and `subagents.disabled` become empty arrays for this cwd; `mcp_servers` contains `global_docs` and `repo_docs`; `custom_providers.local-ai` uses local value.
Provider-specific auth exceptions: `openai-codex` ignores API keys and requires provider-keyed OAuth; `anthropic` uses `ANTHROPIC_API_KEY` or provider-keyed API-key auth; `claude-code` reads Claude Code OAuth from Keychain/`~/.claude/.credentials.json` first and uses only explicit provider-keyed `claude-code` API-key fallback, not `--api-key`, `MC_API_KEY`, or ambient `ANTHROPIC_API_KEY`.
### Example `~/.magi-code/settings.json`
```json
{
"$schema": "./state/settings.schema.json",
"selected_model": {
"provider": "openai-codex",
"model": "gpt-5.5",
"thinking_level": "default"
},
"no_color": false,
"openai_codex": {
"text_verbosity": "low"
},
"openai_responses": {
"text_verbosity": "medium"
},
"anthropic_cache_ttl": "5m",
"file_autocomplete_respects_gitignore": true,
"integrations": {
"herdr": {
"enabled": false
}
},
"session_titles": {
"enabled": false,
"provider": "local-provider",
"model": "small-title-model"
},
"compaction": {
"provider": "local-provider",
"model": "small-summary-model"
},
"context": {
"enabled": true,
"max_tokens": 128000,
"reserve_tokens": 16384,
"keep_recent_tokens": 20000,
"model_overrides": {
"openai-codex/gpt-5.5": { "max_tokens": 400000 },
"local-provider/small-summary-model": {
"max_tokens": 256000,
"reserve_tokens": 32768
}
}
},
"ttsr": {
"enabled": true,
"rules": [
{ "pattern": "(?i)force push", "reminder": "Do not force-push unless explicitly requested in the current turn." }
]
},
"tools": {
"read": { "absolute_paths": true },
"view_image": {
"absolute_paths": true,
"max_image_bytes": 5242880,
"vision_model": { "provider": "local-provider", "model": "vision-model-id" }
},
"hash_edit": { "absolute_paths": true },
"write": { "absolute_paths": true },
"ffgrep": { "absolute_paths": true },
"bash": { "absolute_paths": true, "shell_expansion": true },
"parallel_subagents": { "absolute_paths": true, "max_depth": 2 },
"output_compression": { "enabled": false }
},
"hooks": {
"enabled": false,
"show_in_tui": false,
"injected_content": {
"show_in_transcript": false,
"show_in_activity_tree": false,
"style": "content"
},
"payload": "redacted",
"timeout_seconds": 5,
"stdout_max_bytes": 8192,
"stderr_max_bytes": 8192,
"failure_policy": "warn",
"before_tool": [
{
"label": "audit-before",
"command": "./scripts/magi-hook-before.sh",
"include_tools": ["bash", "write"]
}
],
"after_tool": [
{
"label": "audit-after",
"command": "./scripts/magi-hook-after.sh",
"failure_policy": "ignore"
}
]
},
"skills": {
"additional_paths": ["/Users/example/Dev/magi-skills/skills"],
"disabled": ["example-skill-name"]
},
"instructions": {
"subdir_discovery": true,
"additional_markdown_paths": [
"/Users/example/.magi-code/prompt-packs/team-rules.md",
"/Users/example/Dev/shared-instructions/review-checklist.md"
]
},
"mcp_servers": {
"filesystem": {
"type": "stdio",
"command": "node",
"args": ["/path/to/server.js"],
"env": { "MCP_ROOT": "/tmp/mcp-root" },
"enabled": true,
"timeout": 30
},
"remote_search": {
"type": "http",
"url": "https://mcp.example.com/mcp",
"headers": {
"Authorization": "{env:MCP_REMOTE_SEARCH_TOKEN}",
"X-Team": "platform"
},
"enabled": true,
"timeout": 30
},
"oauth_search": {
"type": "http",
"url": "https://mcp.example.com/mcp",
"oauth": {
"client_id": "your-client-id",
"scopes": ["read", "tools"],
"authorization_server": "https://auth.example.com"
},
"enabled": true,
"timeout": 30
}
},
"custom_providers": {
"local-provider": {
"label": "Local Provider",
"base_url": "http://localhost:11434/v1"
},
"hosted-provider": {
"label": "Hosted Provider",
"base_url": "https://provider.example/v1",
"api_key_env_var": "HOSTED_PROVIDER_API_KEY",
"models_dev_provider": "openrouter",
"use_responses_endpoint": true,
"supports_text_verbosity": true,
"extra_models": ["provider-private-model"]
}
},
"models": {
"disabled": ["openai-codex/example-model"]
},
"selected_primary_agent": "tars"
}
```
Notes:
- Startup generates `$MC_HOME/state/settings.schema.json` (or `~/.magi-code/state/settings.schema.json` when `MC_HOME` is unset) from Rust settings structs and adds `$schema: "./state/settings.schema.json"` to `settings.json` when the file is missing or already valid. Existing custom `$schema` values and unknown top-level fields are preserved. Malformed JSON, non-object JSON, serde-invalid settings, or custom-provider-invalid settings are not rewritten; runtime validation remains authoritative.
- `no_color` disables ANSI color when `--color` is absent. Color precedence is `--color <auto|always|never>` > `settings.no_color` > `NO_COLOR` > auto stdout TTY detection. `NO_COLOR` is color-only; it does not disable Unicode marks or the line editor.
- `openai_codex.text_verbosity` is optional and non-secret. Accepted values are `low`, `medium`, and `high`; default is `low`. It applies only to OpenAI Codex Responses API request `text.verbosity` as a provider output-style hint. It does not control reasoning effort, expose chain-of-thought, reveal encrypted reasoning, or guarantee exact output length.
- `openai_responses.text_verbosity` is optional and accepts `low`, `medium`, or `high`. It overrides legacy `openai_codex.text_verbosity` for Codex; legacy remains Codex fallback with default `low`. Custom Responses providers emit `text.verbosity` only when this shared value exists and `custom_providers.<id>.use_responses_endpoint` plus `supports_text_verbosity` are true. Otherwise field stays omitted. Verbosity affects visible detail, output size, latency, and cost; it does not control reasoning effort, hidden chain-of-thought, tool calls, or hard output-token limits.
- `$schema` is editor metadata ignored by the settings parser. It does not validate `auth.json`, replace runtime validation, or allow credential fields in settings.
- Legacy flat settings keys `provider`, `model`, `thinking_level`, `herdr`, and `disabled_skills` are still read for existing files. Canonical writes use `selected_model`, `integrations.herdr`, and `skills.disabled` and do not re-emit those legacy flat keys.
- MCP HTTP settings require HTTPS for remote servers and OAuth endpoints; HTTP is limited to `localhost`, `127.0.0.0/8`, and `[::1]`. MCP and OAuth HTTP clients reject redirects, and URL userinfo is invalid. Keep bearer tokens, API keys, and OAuth credentials in environment references or protected token storage, never settings.
- `instructions.additional_markdown_paths` is optional and non-secret. Each entry must be an absolute path to a readable UTF-8 `.md` file. Files append after `~/.magi-code/AGENTS.md` and active-working-directory `AGENTS.md` in configured order, and inherited subagents receive the same content. Invalid relative, non-markdown, missing, directory, unreadable, or non-UTF-8 entries fail locally before any provider request. Do not put API keys, OAuth tokens, bearer headers, account ids, or private auth output in configured instruction files.
- `instructions.subdir_discovery` defaults to `false`. Set `true` to load subdirectory `AGENTS.md` files when path-aware built-in tools touch paths: `read`, `view_image`, `hash_edit`, `write`, `list_files`, plus explicit-path `grep`, `find`, and `ast_grep`. Discovery walks upward from touched path nearest-first, stays inside active project root, stops before root `AGENTS.md`, is symlink-safe, caps files at 256KB, and injects each canonical file once per session as provider-visible transcript/activity context. Existing startup instruction paths and replayed `SubdirInstructionLoad` audit events seed dedupe. Excludes `bash`, browser, web/code search, MCP, skills, and subagents.
- `skills.additional_paths` is optional and non-secret. Each entry must be an absolute directory path containing direct `<skill-name>/SKILL.md` children or one-level `<folder>/<skill-name>/SKILL.md` grouped children. Relative entries are skipped and reported as skill-discovery diagnostics. Configured roots are discovered after legacy `~/.agents/skills` and `~/.magi-code/skills`, before active-repository `.agents/skills`; later configured roots override earlier configured roots for same-name skills. Skill discovery does not recurse beyond one grouping folder.
- `selected_model.thinking_level` is optional and non-secret. Parseable values are `default`, `low`, `medium`, `high`, `xhigh`, and `max`; the active provider/model determines which values are selectable/effective. `openai-codex/gpt-5.5` supports `default|low|medium|high|xhigh`; `zai/glm-5.2` supports `default|high|max`; existing `openai-codex` `gpt-5*` and `o*` models except `gpt-5.5` keep `default|low|medium|high`. Unsupported selected values clamp to `default`, which sends no explicit provider reasoning-effort parameter. Catalog `reasoning.efforts` metadata can provide exact custom-provider lists; legacy boolean reasoning metadata maps only to `default|low|medium|high`. This controls effort only; it does not expose chain-of-thought, hidden reasoning, encrypted reasoning, or raw provider payloads.
- `mcp_servers` is optional and non-secret. It supports stdio tool servers (`type`, `command`, optional `args`, non-secret `env`, `enabled`, `timeout`) and Streamable HTTP tool servers (`type: "http"`, `url`, optional `headers`, optional `oauth`, `enabled`, `timeout`). HTTP URLs must use HTTPS except `localhost`/loopback HTTP. Sensitive static HTTP headers (`Authorization`, `Proxy-Authorization`, names containing `token`, `secret`, or `api-key`) must use `{env:VAR_NAME}`; non-sensitive headers may use literals. OAuth config supports placeholder/public `client_id`, `scopes`, and optional `authorization_server`; tokens are stored under `$MC_HOME/mcp-tokens/<server>.json` after `magi-code mcp login <server>`, never in settings. OAuth is mutually exclusive with static `Authorization` / `Proxy-Authorization` headers. Header values and OAuth tokens are redacted in output. Server ids and tool names are exposed as `mcp__server__tool`; ids must be provider-safe and cannot contain `__`. Diagnose with `magi-code mcp list` and `magi-code mcp test <server>`. Client Credentials, Device Code, legacy SSE, WebSocket, resources, and prompts are not supported. See [MCP stdio and HTTP tools](mcp-stdio-tools.md).
- `custom_providers.<id>.models_dev_provider` is optional, non-secret `models.dev` provider namespace metadata. Explicit values override provider-id fallback. When omitted, magi-code uses the custom provider id (`custom_providers.<id>`) as the exact `models.dev` namespace; a custom provider id `openai` therefore uses namespace `openai`. Enrichment still requires an exact namespace and exact model id match in `models.dev`; magi-code does not infer namespaces from labels, hosts, model prefixes, or base URLs. If your provider id differs from the desired `models.dev` namespace, set `models_dev_provider` explicitly; for example, provider id `custom-openai` using the OpenAI API root needs `models_dev_provider: "openai"` to use OpenAI metadata. `limit.context`/`limit.input` can update context budget metadata; `limit.output` is stored as output-token metadata and never used as context budget.
- `custom_providers.<id>.extra_models` is optional, non-secret provider-local model ids appended to discovered `/models` results for catalog validation. Use it when a compatible provider accepts a model before listing it, for example `"extra_models": ["glm-5.2"]` under provider id `zai`. Entries are model ids only, not `provider/model` strings. Overrides augment discovered models, dedupe against live `/models`, participate in catalog cache invalidation, and do not replace the OpenAI-compatible `/models` parser.
- `custom_providers.<id>.use_responses_endpoint` is optional, non-secret, provider-local endpoint metadata. Omitted or `false` sends runtime requests to `{base_url}/chat/completions`; `true` sends runtime requests to `{base_url}/responses`. Model discovery still uses `{base_url}/models`. `base_url` remains an API root URL such as `/v1`, `/v4`, `/api`, or a bare HTTPS host, not an endpoint URL. `/login custom-provider` does not prompt for this field; edit `settings.json` to opt in. `openai-codex` is separate and unaffected.
- `custom_providers.<id>.supports_text_verbosity` is optional, non-secret, and defaults to `false`. Set it only when provider accepts OpenAI Responses `text.verbosity`; endpoint selection alone does not prove field support.
- `custom_providers.<id>.reasoning_protocol` is optional, non-secret, and defaults to `gpt-like` when omitted. This selects request-field dialect, not model capability. For `gpt-like`, exact non-empty catalog `reasoning_efforts` metadata wins; otherwise `supports_reasoning: true` exposes `default|low|medium|high`, while missing or false metadata exposes only `default`. `anthropic-like` keeps selectable levels intersected with `default|high|max` and emits enabled `thinking` fields for `high`/`max` with budgets clamped below output limits. Unsupported persisted levels clamp non-destructively to `default`; no endpoint, label, alias, base URL, or `extra_models` inference is used.
- `session_titles` is disabled by default. AI-generated friendly titles run only when `enabled: true` and both `provider` and `model` are explicit, non-blank strings; there is no fallback to the active assistant provider/model, CLI flags, or environment defaults. Disabled settings may retain provider/model for later reuse.
- `compaction` is optional and non-secret. When absent, `/compact` inherits the active assistant provider/model for the current run. When present, both `compaction.provider` and `compaction.model` must be non-blank strings; setting only one field or leaving either blank fails locally before writing a checkpoint. Credentials stay in provider-keyed `auth.json` records or configured environment variables only; never store API keys, OAuth tokens, bearer headers, or custom-provider secret values under `compaction`.
- When enabled for a new persisted session, title generation starts best-effort in the background after the first durable user message. Titles are sanitized, capped at 50 characters, stored as append-only session metadata, and do not rename session IDs/files. This may incur separate provider network/cost.
- Mission Control displays a friendly title when present and falls back to the short session ID otherwise.
- `file_autocomplete_respects_gitignore` defaults to `true`. Mission Control `@filename` autocomplete stays cwd-scoped and bounded, includes dotfiles when they are not ignored, and excludes files matched by repository `.gitignore` patterns. Set it to `false` to include gitignored files in autocomplete candidates without changing file-tool permissions or attaching file contents.
- `integrations.herdr.enabled` is disabled by default. Set `"integrations": { "herdr": { "enabled": true } }` to opt in to best-effort local agent-state reporting when magi-code is already running inside Herdr. Runtime env must also provide `HERDR_ENV=1` and `HERDR_PANE_ID`; optional `HERDR_SOCKET_PATH` overrides the Unix socket path, otherwise magi-code uses `~/.config/herdr/herdr.sock`. The integration sends only coarse lifecycle status (`thinking`, tool running, done, stopped) through Herdr-valid agent states, never launches Herdr, never changes stdout/stderr, and never writes Herdr data into provider requests, prompts, tool payloads, or session replay. Socket/reporting failures are ignored and never fail agent execution.
- TachyonFX Mission Control effects and the supported `tui.effects` setting were removed by issue #128 / ADR-0040. `settings.json` currently has no documented Mission Control effects setting; any leftover nested `tui.effects` value from older files is historical and has no active user-facing behavior.
- `context.model_overrides` is optional and non-secret. Keys must exactly match the active `provider/model` string, for example `openai-codex/gpt-5.5` or `zai/glm-5.2`; magi-code does not trim, normalize, infer, or validate model existence from these keys. Matching overrides apply after global context settings and cached catalog context-window metadata, so explicit local settings win when upstream metadata is missing, stale, or wrong. Overrides can set `max_tokens`, `reserve_tokens`, and `keep_recent_tokens`; oversizing `max_tokens` only changes local budgeting and can still be rejected by the provider.
- `context.keep_recent_tokens` is legacy compatibility config. Active provider requests replay full structured session history and fail over budget instead of recent-slicing history.
- `ttsr.enabled` defaults to `false`. When enabled, `ttsr.rules` accepts up to 128 optional non-secret `{ "pattern", "reminder" }` objects. `pattern` must be non-empty valid regex; `reminder` must be non-empty. Rules inspect assistant text deltas and completed tool-call arguments during streaming; a match aborts the stream, records hidden local `ttsr_injection`, injects the reminder, and retries the turn. Built-in defaults cover destructive commands, secret exfiltration, credential routing, cwd widening, and force push. TTSR is mid-stream control, separate from hook phase-boundary execution.
- `tools.<tool>.absolute_paths` defaults to `true` for `read`, `hash_edit`, `write`, `ffgrep`, `bash`, and `parallel_subagents`. Relative paths are resolved from the runtime cwd and cannot escape it; absolute paths may target locations outside cwd. Set an individual tool to `false` to restore cwd-bounded absolute-path behavior for that tool.
- `tools.view_image.vision_model` selects the explicit provider/model used by the `view_image` vision tool; it does not fall back to the active chat model. `tools.view_image.max_image_bytes` bounds image payload size. See [Tools and safety model](tools-and-safety.md).
- `tools.parallel_subagents.max_depth` defaults to `2`, allowing one nested subagent batch from a child and hiding the `parallel_subagents` provider schema at the limit. Accepted settings are bounded to `1` through `4`; set `1` to restore top-level-only subagents. Mission Control subagent task activity includes depth metadata for nested visibility.
- `subagents.schema_validation_max_retries` defaults to `2` and is bounded `0` through `5`. It controls retries after a child profile `output_schema` validation failure; validation details are returned to the child for repair, and valid output returns structured data to the parent.
- `tools.output_compression.enabled` defaults to `false`. Set it to `true` to send curated provider-visible summaries for recognized `bash` outputs (`git status`, `git diff`, `cargo check`, `cargo test`) while preserving raw local/session tool results. See [Tool output compression](tool-output-compression.md).
- `tools.bash.shell_expansion` defaults to `true`, so the `bash` / `shell` tool permits normal shell expansion such as `$VAR`, `~`, command substitution, and brace expansion. Set it to `false` to restore the stricter cwd preflight that rejects `$`, `~`, backticks, `{`, and `}` before execution.
- `bash` / `shell` still runs through the host shell with configurable preflight and is not an OS sandbox; `tools.bash.absolute_paths` and `tools.bash.shell_expansion` only control pre-execution checks, not OS-level isolation.
- `hooks.show_in_tui` is optional, non-secret, and defaults to `false`. It only affects Mission Control display for already-enabled matching hook lifecycle rows: `true` shows hook running/success/failure activity rows; it does not make hooks execute when `hooks.enabled` is `false`, and it does not control provider context injection visibility.
- `hooks.injected_content` is optional, non-secret, and controls Mission Control visibility for provider context injection only. `show_in_transcript` and `show_in_activity_tree` both default to `false`; enable either surface gate to display provider context injection rows without changing provider injection behavior. `style` defaults to `content`, which shows redacted/truncated injected content; set `style: "metadata"` to hide injected content and show only label, status, item count, and byte count.
- `skills.disabled` is normally maintained by `/skills` in Mission Control TUI. It stores skill names only; skill files are not edited or deleted.
- `models.disabled` is normally maintained by `/models` in Mission Control TUI. It stores canonical `provider/model` ids only. Disabled models are marked and blocked in `/setmodel`; active model is not auto-switched, and CLI `--model` bypasses this list.
- `selected_primary_agent` is optional. Mission Control TUI writes a primary-agent profile id there, or `null` when cycling back to `None`.
- API-key values, OAuth tokens, refresh tokens, account ids, bearer headers, primary-agent prompt bodies, and auth metadata do not belong in `settings.json`.
## Settings, env vars, and auth records
| Environment variable | `settings.json` field | `auth.json` field/source | Classification |
| --- | --- | --- | --- |
| `MC_PROVIDER` | `selected_model.provider` | None | Non-secret runtime option. |
| `MC_MODEL` | `selected_model.model` | None | Non-secret runtime option. |
| `NO_COLOR` | `no_color` | None | Non-secret ANSI color option. Precedence: `--color` > `settings.no_color` > `NO_COLOR` > auto TTY. Does not disable Unicode marks or line editor. |
| `MC_HOME` | None | None | Bootstrap path selector for config/state location. Must be absolute when set; resolved paths are used in diagnostics. |
| OpenAI Codex text verbosity | `openai_codex.text_verbosity` (`"low"`, `"medium"`, or `"high"`) | None | Optional non-secret Codex response text verbosity hint. Defaults `low`; does not control reasoning effort or hidden chain-of-thought. |
| Anthropic prompt-cache TTL | `anthropic_cache_ttl` (`"5m"` or `"1h"`) | None | Optional non-secret request-cache setting for `anthropic` and direct `claude-code` providers only. Claude Code sends no cache control when absent; cache writes can increase cost and savings are not guaranteed. |
| `MC_API_KEY` | None | Provider-keyed credential records where applicable. | Secret process credential; never store in settings. Not used for `openai-codex`. |
| Custom provider metadata namespace | `custom_providers.<id>.models_dev_provider` | `custom_providers.<id>` | Optional non-secret exact `models.dev` provider namespace for catalog enrichment; explicit values override provider-id fallback; never a credential. |
| Custom provider catalog override models | `custom_providers.<id>.extra_models` | None | Optional non-secret provider-local model ids appended to discovered `/models` results for validation; for example `glm-5.2` under `zai`. |
| Custom provider endpoint mode | `custom_providers.<id>.use_responses_endpoint` | None | Optional non-secret provider-local metadata. Omitted/false uses `{base_url}/chat/completions`; true uses `{base_url}/responses`; no `auth.json` source. |
| Custom provider key env var | `custom_providers.<id>.api_key_env_var` stores the variable name only. | None | Secret value is read only from the named environment variable at runtime. |
| MCP stdio server env | `mcp_servers.<id>.env` | None | Optional non-secret child-process environment values. Child receives these plus minimal `PATH` only; never store API keys, OAuth tokens, bearer headers, or provider credentials here. |
| MCP HTTP header env reference | `mcp_servers.<id>.headers.<name>` stores `{env:VAR_NAME}` only. | None | Secret header value is read only from the named environment variable at runtime. Required for sensitive header names; all header values are redacted in diagnostics. |
| MCP HTTP OAuth config | `mcp_servers.<id>.oauth.client_id`, `scopes`, `authorization_server` | `$MC_HOME/mcp-tokens/<id>.json` after `magi-code mcp login <id>` | Settings fields are non-secret placeholders/public ids only. Access tokens, refresh tokens, client secrets, auth codes, PKCE verifier/state values, and bearer headers never belong in settings. |
| `EXA_API_KEY` | None | None | Secret process credential for `web_search` and `code_search`. Never store in `settings.json`, `auth.json`, sessions, hooks, fixtures, or prompts. |
| Session-title provider/model | `session_titles.provider`, `session_titles.model` | Existing provider-keyed/custom-provider auth only. | Non-secret ids; used only when `session_titles.enabled` is `true`. No fallback to active assistant provider/model. |
| Compaction provider/model | `compaction.provider`, `compaction.model` | Existing provider-keyed/custom-provider auth or configured provider environment variable only. | Optional non-secret ids for `/compact`; absent settings inherit the active assistant provider/model, while partial or blank overrides fail locally. |
| Thinking level selected in settings or Mission Control | `selected_model.thinking_level` | None | Optional non-secret reasoning-effort label: `default`, `low`, `medium`, `high`, `xhigh`, or `max`; active model clamps unsupported values to `default`. |
| Herdr agent-state reporting | `integrations.herdr.enabled` | None | Optional local integration. Requires `HERDR_ENV=1` and `HERDR_PANE_ID`; `HERDR_SOCKET_PATH` optionally selects Unix socket. Disabled by default and best-effort only. |
| Skill additional discovery roots | `skills.additional_paths` | None | Optional non-secret absolute directory paths containing direct `<skill-name>/SKILL.md` children or one-level `<folder>/<skill-name>/SKILL.md` grouped children; relative entries are skipped with diagnostics. |
| Configured markdown instructions | `instructions.additional_markdown_paths` | None | Optional non-secret absolute `.md` file paths appended after `AGENTS.md` in configured order and inherited by subagents. Invalid paths fail locally before provider requests. |
| Disabled skill names | `skills.disabled` | None | Optional non-secret skill-name list maintained by `/skills`; skill files are not edited or deleted. |
| Disabled model ids | `models.disabled` | None | Optional non-secret `provider/model` list maintained by `/models`; `/setmodel` marks and blocks these rows; CLI `--model` bypasses. |
| Per-model context budget overrides | `context.model_overrides.<provider/model>.max_tokens`, `reserve_tokens`, `keep_recent_tokens` | None | Optional non-secret local budget overrides. Exact `provider/model` key matches only; applied after cached catalog metadata; does not change provider-side model capability. |
| Token-triggered streaming reminders | `ttsr.enabled`, `ttsr.rules[]` | None | Optional non-secret mid-stream safety reminders. Defaults disabled; set `ttsr.enabled: true` to inspect assistant deltas or completed tool-call arguments, abort current stream on match, record hidden local `ttsr_injection`, inject reminder, and retry. |
| Bash shell expansion policy | `tools.bash.shell_expansion` | None | Optional non-secret tool setting. Defaults `true`; set `false` to reject `$`, `~`, backticks, `{`, and `}` in `bash` / `shell` commands before execution. |
| Parallel subagent max depth | `tools.parallel_subagents.max_depth` | None | Optional non-secret tool limit. Defaults `2`, bounded `1`–`4`; set `1` for top-level-only subagents. |
| Parallel subagent schema retries | `subagents.schema_validation_max_retries` | None | Optional non-secret retry limit for `output_schema` validation failures. Defaults `2`, bounded `0`–`5`; invalid child output receives validation details and retries until limit. |
| Tool output compression | `tools.output_compression.enabled` | None | Optional non-secret provider-visible compression flag. Defaults off; when true, recognized `bash` commands send curated summaries to provider while raw local/session tool results stay preserved. |
| Hook TUI visibility | `hooks.show_in_tui` | None | Optional non-secret display flag. Defaults off; only shows already-enabled hook lifecycle activity in Mission Control. Does not control provider context injection visibility. |
| Provider context injection UI visibility | `hooks.injected_content.show_in_transcript`, `hooks.injected_content.show_in_activity_tree`, `hooks.injected_content.style` | None | Optional non-secret Mission Control display settings. Surface gates default off; style defaults `content`, or `metadata` to hide injected content text. Does not enable provider context injection itself. |
| Primary-agent profile id selected in Mission Control | `selected_primary_agent` | None | Optional non-secret id only; prompt bodies and credentials are never stored in settings. |
Search tool setup uses environment only:
```sh
EXA_API_KEY=<EXA_API_KEY> magi-code --print "Use web_search for current Rust release notes, cite sources."
```
`EXA_API_KEY` is never a `settings.json` or `auth.json` field. Search tools never reuse `OPENAI_API_KEY`, `MC_API_KEY`, provider OAuth tokens, bearer headers, or custom-provider keys.
For `openai-codex`, durable credentials belong only in provider-keyed OAuth records in `~/.magi-code/auth.json`, for example:
```json
{
"openai-codex": {
"type": "oauth",
"access": "<CODEX_ACCESS_TOKEN>",
"refresh": "<OPTIONAL_REFRESH_TOKEN>",
"expires": 1999999999,
"accountId": "<CHATGPT_ACCOUNT_ID>"
}
}
```
Codex model discovery uses this OAuth auth path. It does not use `--api-key`, `MC_API_KEY`, `OPENAI_API_KEY`, or custom-provider credentials.
## Related docs
- [Tool-call bash hooks](tool-call-hooks.md)
- [Provider authentication](provider-authentication.md)
- [Tool output compression](tool-output-compression.md)
- [Tools and safety model](tools-and-safety.md)
---
[Back to feature docs](README.md) · [Back to repository README](../../README.md)