magi-code 0.80.0

Repository-aware CLI coding agent for terminal work
Documentation
# Runtime theming

Magi-code uses one Opaline semantic theme for Mission Control. Machine output, protocol output, sessions, provider requests, and tool payloads remain unstyled.

## Theme IDs and precedence

`matrix-green` is the embedded Matrix theme. Opaline built-ins use their registered IDs. Custom files are loaded from `$MC_HOME/themes/*.toml`; their ID is the exact, case-sensitive filename including extension (for example `Solarized.toml` has ID `custom:Solarized.toml`).

Resolution order is: explicit temporary `--theme ID`, saved `interface.appearance.theme`, then Matrix fallback. An invalid explicit theme is a launch error with exit code 2. An invalid saved theme emits a bounded warning and is not rewritten; runtime falls back to Matrix. A successful `/theme` save clears a temporary CLI override; cancel and save failure do not.

## Settings

```json
{
  "interface": {
    "appearance": { "theme": "matrix-green", "reduced_motion": false },
    "no_color": false
  }
}
```

Terminal color is disabled when saved `interface.no_color` is `true` **or** `NO_COLOR` is present (even empty); saved `false` does not override the environment. Otherwise terminal detection applies: truecolor when `COLORTERM` is `truecolor` or `24bit`, ANSI-256 when `TERM` contains `256color`, ANSI-16 for a color terminal, and None when color is disabled, stdout is not a TTY, or `TERM` is `dumb`. Unicode and animation are separate from color; there is no CLI color override.

During a live run, the prompt border shows a fixed-width ASCII scanner (`[>.....]`) moving back and forth; it yields space to status and cancel labels in narrow panes. Running tool/subagent cards use dot-orbit indicators. Successful live card indicators and the run-completion status receive a brief bold, underlined accent (650 ms); replay, errors, and cancellation do not trigger it. These cues hide behind modals and are disabled by `interface.appearance.reduced_motion`. They never change copied transcript text or session history.

## Complete custom theme example

Save this self-contained parser-valid file as `$MC_HOME/themes/Solarized.toml` (the ID is `custom:Solarized.toml`):

<!-- runtime-theme-example-start -->
```toml
[meta]
name = "Solarized"
author = "example"
variant = "dark"
version = "1.0"
description = "Complete custom theme"

[palette]
background = "#002b36"
panel = "#073642"
code = "#001f27"
highlight = "#0b4f5c"
selection = "#145b68"
primary = "#fdf6e3"
secondary = "#93a1a1"
muted = "#657b83"
dim = "#586e75"
accent = "#2aa198"
accent_secondary = "#268bd2"
accent_tertiary = "#b58900"
accent_deep = "#1b7770"
success = "#859900"
error = "#dc322f"
warning = "#b58900"
info = "#268bd2"

[tokens]
"text.primary" = "primary"
"text.secondary" = "secondary"
"text.muted" = "muted"
"text.dim" = "dim"
"bg.base" = "background"
"bg.panel" = "panel"
"bg.code" = "code"
"bg.highlight" = "highlight"
"bg.selection" = "selection"
"accent.primary" = "accent"
"accent.secondary" = "accent_secondary"
"accent.tertiary" = "accent_tertiary"
"accent.deep" = "accent_deep"
success = "success"
error = "error"
warning = "warning"
info = "info"
"border.focused" = "accent"
"border.unfocused" = "muted"
"code.keyword" = "accent"
"code.function" = "accent_secondary"
"code.string" = "accent_tertiary"
"code.number" = "warning"
"code.comment" = "muted"
"code.type" = "info"
"code.line_number" = "dim"
"magi.surface.background" = "background"
"magi.surface.panel" = "panel"
"magi.surface.panel_alt" = "highlight"
"magi.surface.overlay" = "highlight"
"magi.surface.selection" = "selection"
"magi.surface.code" = "code"
"magi.surface.success" = "highlight"
"magi.surface.pending" = "highlight"
"magi.surface.error" = "highlight"
"magi.text.primary" = "primary"
"magi.text.muted" = "muted"
"magi.text.dim" = "dim"
"magi.text.accent" = "accent"
"magi.text.title" = "accent"
"magi.text.prompt" = "primary"
"magi.text.status" = "secondary"
"magi.text.help" = "secondary"
"magi.text.metadata" = "muted"
"magi.text.command" = "accent_secondary"
"magi.text.command_active" = "accent"
"magi.border.default" = "muted"
"magi.border.active" = "accent"
"magi.border.alternate" = "accent_secondary"
"magi.border.command" = "muted"
"magi.border.command_active" = "accent"
"magi.border.error" = "error"
"magi.status.queued" = "muted"
"magi.status.running" = "warning"
"magi.status.writing" = "warning"
"magi.status.success" = "success"
"magi.status.failed" = "error"
"magi.status.canceled" = "muted"
"magi.status.tool" = "accent_secondary"
"magi.status.subagent" = "accent_tertiary"
"magi.status.assistant" = "accent"
"magi.status.diagnostic" = "info"
"magi.transcript.user" = "accent_secondary"
"magi.transcript.assistant" = "primary"
"magi.transcript.thinking" = "accent_tertiary"
"magi.transcript.tool" = "accent_secondary"
"magi.transcript.session" = "muted"
"magi.transcript.diagnostic" = "info"
"magi.transcript.heading" = "accent"
"magi.transcript.section" = "primary"
"magi.transcript.error_label" = "error"
"magi.transcript.error_body" = "primary"
"magi.diff.inserted" = "success"
"magi.diff.removed" = "error"
"magi.diff.changed" = "warning"
"magi.diff.context" = "primary"
"magi.diff.hunk_header" = "accent_secondary"
"magi.diff.file_header" = "accent"
"magi.diff.metadata" = "muted"
"magi.syntax.plain" = "primary"
"magi.syntax.keyword" = "accent"
"magi.syntax.string" = "accent_tertiary"
"magi.syntax.comment" = "muted"
"magi.syntax.number" = "warning"
"magi.syntax.function" = "accent_secondary"
"magi.syntax.type" = "info"
"magi.syntax.operator" = "accent_secondary"
"magi.syntax.punctuation" = "secondary"
"magi.syntax.code_fence" = "accent"
"magi.syntax.language_label" = "accent_secondary"
"magi.syntax.gutter" = "dim"
"magi.syntax.fallback" = "secondary"

[styles]
keyword = { fg = "accent", bold = true }
line_number = { fg = "dim" }
selected = { fg = "accent", bg = "selection" }
active_selected = { fg = "accent_tertiary", bg = "highlight", bold = true }
focused_border = { fg = "accent" }
unfocused_border = { fg = "muted" }
success_style = { fg = "success" }
error_style = { fg = "error" }
warning_style = { fg = "warning" }
info_style = { fg = "info" }
dimmed = { fg = "dim" }
muted = { fg = "muted" }
inline_code = { fg = "accent_tertiary", bg = "code" }

[gradients]
primary = ["accent", "accent_secondary"]
warm = ["warning", "accent_tertiary"]
success_gradient = ["success", "accent_secondary"]
error_gradient = ["error", "warning"]
aurora = ["accent", "accent_secondary", "accent_tertiary", "info"]
"magi.gradient.fast" = ["accent", "accent_secondary", "accent_tertiary"]
```
<!-- runtime-theme-example-end -->

## Trust and bounds

Only direct regular files in the themes directory are considered. Symlinks, non-regular entries, non-UTF-8 filenames, and files over 512 KiB are rejected. The scan accepts at most 128 custom files and scans at most 256 directory entries. A source is bounded to 512 KiB, with at most 4096 colors, 1024 styles, 256 gradients, 4096 gradient stops, and token-reference depth 64. Diagnostics are limited to 24 entries, sanitized of control characters, and truncated to 240 characters. Invalid siblings do not prevent valid themes from loading.

## Picker behavior

In Mission Control, `/theme` opens the picker. Type to search, use the arrows to select, and preview changes live. Enter starts saving the selected ID. Esc restores the exact opening appearance snapshot, installed with a fresh monotonic presentation revision. A failed save leaves the preview and picker available for retry; closing or canceling restores the opening state. Each open shows the cached catalog immediately and starts a background refresh; valid refreshes update the cache, and deleted or repaired custom files appear on the next refresh.

## Motion and output

`interface.no_color` disables colors. Mission Control retains style modifiers such as bold where they apply.

Mission Control applies semantic roles to headers, assistant and thinking bodies, tool bodies, metadata, diagnostic levels, Markdown, syntax, and diffs. Colors are lowered to truecolor, 256-color, or 16-color according to the detected depth. Theme data is display-only and never enters sessions, provider requests, tool arguments/results, or protocol output.

The PRD remains Active and pending final acceptance verification; implementation behavior is documented here: `docs/prd/0079-full-runtime-theming-custom-themes-and-reduced-motion.md`.