magi-code 0.77.1

Repository-aware CLI coding agent for terminal work
Documentation
# Mission Control TUI

[Feature docs index](README.md) · [Repository README](../../README.md)

## Purpose

Use Mission Control to edit prompts, follow tools and subagents, inspect captured output, and change settings without leaving the terminal.

```sh
magi-code
magi-code --prompt "Summarize this repository."
```

Mission Control is the default interface. Both stdin and stdout must be TTYs. Use `--app service` for non-interactive frontend clients; see [Application service](application-service.md). `--prompt` rejects whitespace-only input.

## Details

### Startup and readiness

You can edit the focused prompt as soon as Mission Control draws its first frame, before execution readiness completes. CLI setup happens earlier: settings/config, instructions, skill discovery, and session setup/discovery. Background session pruning is scheduled before TUI entry on an unjoined thread; it may overlap startup and does not block readiness.

Execution waits for the current settings/policy snapshot, selected primary agent (or explicit None), enabled subagent profiles, and every enabled MCP server's connection, initialization, and `tools/list`. Selected-profile, enabled-subagent, or strict MCP startup failures block execution. Non-selected/disabled profile diagnostics only warn. Autocomplete, titles, Git/branch data, and other decoration are best effort and do not block. This MCP gate is stricter than `magi-code mcp list`; see [MCP tools](mcp-stdio-tools.md).

The controlled `TestBackend` responsiveness gate is strictly `<50 ms>` from process-side edit receipt through bounded event draining/state projection to completed Ratatui draw. It does not measure whole-process startup or physical terminal write/flush. The `<16 ms>` physical-terminal target remains non-gating and unverified; no physical TTY test has been performed.

### Startup prompt queue

During readiness, one normal prompt can be queued. It becomes immutable and the editor clears for a separate draft. A second submission is rejected without replacing either. `Alt-C` cancels the queue and preserves the draft. `/help` and `/quit` work immediately; other slash commands are blocked until ready.

After readiness, an input fence checks for later queue decisions before running the prompt exactly once. An untouched `--prompt` uses this same path. Critical startup failure restores the terminal, exits nonzero, and never runs the queue. Startup queuing is separate from active-run steering.

### Provider connection

`/login` opens Connect Provider, listing Codex, Anthropic, and Custom Provider with their current status. Select with `Up`/`Down`, then `Enter`.

- Codex OAuth stays in the modal. `Ctrl-Y` copies its URL; `Ctrl-O` opens it. Paste a final redirect URL or authorization code into the transient, redacted fallback field and press `Enter`. `Esc` cancels OAuth.
- Anthropic shows environment/API-key setup guidance; it does not request or store a key.
- Custom Provider accepts a label, base URL, and optional API-key environment-variable name, never the key value. `Tab`/`Shift-Tab` moves fields. Reusing an ID requires explicit confirmation: `Enter` replaces it, `Esc` returns to the form.
- On success, `Enter`/`Esc` closes. On error, `Enter` retries, `Backspace`/`Left` goes back, and `Esc` closes. Cancellation before Saving preserves settings and credentials. Saving is non-cancellable once durable custom-provider persistence starts; the modal stays open until completion is reconciled.

### Prompt editing and paste

`Enter` submits and `Shift-Enter` inserts a newline. Autocomplete and modals take precedence over editing. The prompt grows from 1 to 5 visual rows. Use cursor keys for longer prompts: mouse-wheel events over Prompt do nothing.

Paste normalizes CRLF and lone CR to `\n`, keeps tabs/newlines, and strips other C0 controls, `ESC`, and `DEL`. Explicit `Crossterm Event::Paste` and the Windows text-burst fallback use the same policy. At least 3 logical lines or more than 800 UTF-8 bytes collapse to `[Pasted #N · X lines]`. Slash-leading text after optional whitespace and bang-leading text stay ordinary text so commands still work. Thresholds are fixed, not configurable.

The expanded normalized prompt, including hidden paste payloads, is capped at 1 MiB. An oversized edit is rejected whole, not truncated, with `Prompt is limited to 1 MiB; edit rejected`.

Collapsed pastes are indivisible for cursor movement, deletion, selection, mouse hit-testing, and undo/redo. Submit, selected copy, restored history, and provider input use the full normalized payload. Rejected submissions restore label and payload together. Autocomplete sees only visible text/offsets, never hidden payloads. Labels contain only local IDs and line counts, and debug output excludes payloads. Typed text resembling a paste label remains ordinary text.

#### Editor implementation limits

One `PromptEditor` wraps the canonical `TextArea`, which owns visible text, cursor, selection, viewport mapping, and native edit state. Paste payloads live in a private sidecar. The dependency is pinned:

```toml
tui-textarea = { package = "tui-textarea-2", version = "=0.13.2", default-features = false, features = ["no-backend", "search"] }
```

Ordinary drafts use its bounded 50-entry native history. With a collapsed paste, semantic history uses the same 50-edit limit and restores each payload as one edit, without an application-level mirrored history index. Startup queuing, the paint fence, active steering, and rejected-submit restoration remain application behavior. Rendering uses the visible projection, preserves focus/blink behavior, and uses the rendered textarea mapping for mouse selection. Selected non-empty text copies through OSC52.

Movement is character-based, not guaranteed grapheme-safe. Logical text, cursor, selection, and history are lossless, but measured screen rows/private viewport coordinates use `u16`. Beyond `u16::MAX` rendered rows, the visible window, native cursor, or mouse hit-testing may be wrong. The internal `search` fallback handles logical zero-width scalar positions and clears its temporary pattern after movement; it does not fix viewport limits or grapheme handling. The exact pin stays until a reviewed upstream lossless viewport-row fix permits enabling the ignored real-render diagnostic. Wheel scrolling is disabled because the public scroll API changes cursor/selection and exposes no independent viewport control.

### Follow activity

The right column is visible by default. Its far-right rail, when space allows, selects Activity or Summary. Activity contains the tree and Selected Activity Detail; Summary contains the summary log and Session files. `Alt-1` selects Activity without moving focus, unless Summary is focused; then it restores the last Activity pane's focus because Summary is now hidden. `Alt-2` selects Summary and returns focus to the prompt when visible. Clicking a rail label does the same. `Alt-A` hides/shows the entire column and rail without persisting the choice. The hidden column's show action appears in the transcript title.

Normal `Tab` cycles Prompt, Transcript, and Activity Tree, or Prompt, Transcript, Summary, and Session files when Summary is selected, revealing the right column when needed. Modals/autocomplete use their own Tab behavior. `Ctrl-T` focuses the Activity Tree.

The prompt border shows running/cancel status and Bash Mode upper-left, with provider/model/thinking controls and agent selection upper-right. Lower-left shows `Session:  123k(in)│  18k(out)│ 76%(cache) • Current Context: 62% [######..|.] 200k • Compact at 80%`. Session usage fields have fixed widths and theme colors; unknown context shows `—% [..........] —`. Session totals include primary and subagent activity and persist across resume and compaction. Cache share is total cached input divided by total input. While usage is incomplete, the display retains this session's last known cache percentage; `—` appears only before a known value. There is no partial indicator. Older history cannot recover usage that was never recorded.

The bar shows the primary agent's current context against its full window; `|` marks the configured auto-compaction threshold. This is not an exact countdown: compaction checks projected next-request input. Disabled compaction shows `Auto off`. Provider controls show idle `[Alt-M]`, or a login fallback. Narrow layouts omit the bar before clipping text. Context refreshes with estimates; model/session switches hide it until recalculated. The prompt's lower-right border shows `MAGI-CODE vX.Y.Z`. The transcript header shows `Cwd: <cwd> • Branch: <branch>` when available.

Transcript cards have full-width role headers and status marks. The title is inset at the top, with one blank row before content when space permits. A visual scrollbar replaces textual position labels. Tool cards show bounded, sanitized summaries tailored to browser, bash, read, grep/AST grep, web/code search, find, list-files, write, `hash_edit`, and `view_image`. Write/edit cards update in place from running to success/cancelled/failed. Successful `hash_edit` shows at most four changed diff lines, marked as a limited preview.

#### Inspect complete tool output

Selected Activity Detail has `Status`, `Tool • <actual name> • <label>`, `Metadata / Params`, and `Sanitized Output`. A successful live `hash_edit` may add `Applied Diff`. Click `▸ Metadata / Params` (or other activities' `▸ Metadata`) to expand; click `▾` to collapse. Selecting another activity resets it to collapsed.

Detail retains all submitted parameters and result-metadata fields with recursive credential redaction and terminal-control sanitization. Output is complete up to each tool's native capture limit; expanded metadata retains truncation details. Parent `subagents` output is not compacted here. Applied diffs are display-only and absent after session hydration. Provider-visible compression is unchanged.

There is no separate Git list/diff pane. Generic diffs remain in activity detail; branch status, `#git-status`, and Git-aware autocomplete remain available.

#### Follow subagents

Live subagent cards show aggregate settled/running/failed/waiting counts, clickable task chips, selected intent, recent activity, and `[View Subagent ↗]`. `interface.tui.subagent_card_rows` controls recent activity rows: default `16`, range `1` to `50`.

Chips prefer configured agent names, falling back to task identity. The selection also shows identity and resolved provider/model/reasoning when available. The first task is selected initially; selecting a chip keeps that task selected until another chip is chosen. Activity updates do not switch tasks. View Subagent opens a live, display-only viewer for that task and its batch siblings, with tabs and bounded timeline scrolling. Closing leaves the underlying selection/scroll unchanged. Stalled tasks suppress late start events after terminal failure. None of these controls changes provider or session data.

#### Show hooks and injected context

`automation.hooks.show_in_tui=true` shows matching before/after hooks under their tool with running/success/failure status and sanitized phase/label/tool metadata. Default `false` keeps successful hooks quiet.

Provider-injection visibility uses separate `automation.hooks.injected_content` settings: `show_in_transcript` adds local/system rows; `show_in_activity_tree` places rows under the related tool/message, or at the root. Both default to `false`. `style` defaults to `content` (redacted/truncated text); `metadata` shows only label, status, item count, and byte count. These settings affect display only and do not enable injection itself.

### Autocomplete

- `/` as the first character suggests slash commands, including `/help`, `/login`, `/logout`, `/fast`, `/setmodel`, `/models`, `/skills`, `/sessions`, `/system-prompt`, `/new`, `/export`, and `/quit`.
- `@` anywhere suggests regular files under cwd and inserts slash-normalized relative tags such as `@src/lib.rs`.
- `$` anywhere suggests enabled skills and inserts literal tags such as `$rust-dev`. Tags do not auto-load skills or add provider/session metadata.
- `#` anywhere suggests `#tree` and `#git-status`. Acceptance only inserts text; it does not run commands or submit. After top-level submission in Mission Control, exact tags expand through guarded bash in cwd into bounded context, including failures. See [prompt context](commands-and-interfaces.md#add-prompt-context).

### Updates

After the first frame and every four hours, a bounded background check announces newer stable crates.io versions. `/update` requires idle state, leaves the TUI for Cargo's build output, and reopens the exact session only after cleanup and a successful update. It never replays the initial prompt. See [Installation and updates](installation-and-updates.md#update-with-cargo) for platform behavior, supported installations, and recovery.

### Fast mode

`/fast`, `/fast on`, and `/fast off` change the global setting while idle; `/fast status` and invalid usage work during a run. Writes run off the UI loop; memory changes only after disk success. Pending writes block another mutation, new prompt, or compaction and restore input, while status/help/quit stay usable. Accepted writes settle during cleanup. The startup snapshot is authoritative and successful writes update it for later work.

An unacknowledged persistence-worker failure with no event blocks retry until restart. A delivered failure clears when its matching event is handled.

Fast mode highlights the provider/model label instead of showing a separate `Fast:` marker. Use `/fast status` to inspect its state. Eligibility follows Codex catalog/fallback rules or explicit custom-provider `fast_mode` metadata; see [Configuration](configuration.md). It applies to eligible primary turns, subagents, and blocking compaction, not title requests. Color terminals may animate only provider/model text right-to-left in rainbow colors about every 83 ms. Without color, bold and underline mark the label. Thinking, context, separators, spaces, and hotkeys keep normal styles. `Alt-M` is hidden during a run while animation stays paced.

### Switch or export a session

`/sessions` shows newest-first sessions, marks the current one, and previews the selection in a second column when space allows. Bounded reads find first and most recent conversational user/assistant messages; tool-only, hook, context-cache, title, and diagnostic events are ignored. Preview text is sanitized/redacted.

`Tab`/terminal-delivered `Shift-Tab` switches list/preview focus; arrows move the list or scroll the preview. Wheel scrolls the hovered column, `Enter` switches from either focus, and `Esc` closes without switching.

`/export` requires an idle run and active persisted session. It rejects arguments and duplicates, runs off the UI loop, and writes a private ZIP under `$MC_HOME/exports` without overwriting. Completion appears in normal status and is ignored if it belongs to a session changed during export. The unencrypted archive contains raw session data and a manifest and may be sensitive; see [export contents and safety](sessions-context-cache.md#export-a-session).

### Exit and cleanup limits

The terminal is restored before worker cleanup. Cancellation is requested first; each critical startup/provider worker gets a 2 s join before detach/error. Non-cooperative detached workers may still have side effects. Decoration gets only a short grace before detach. Accepted Fast persistence has no fixed total join bound if filesystem work stalls after lock acquisition. Export workers are cancelled and joined so publication cannot continue after teardown.

In-flight blocking HTTP MCP POST/body operations, including `notifications/initialized`, cannot be interrupted. A worker detached after 2 s may remain in that call until the configured timeout (default 30 s, maximum 300 s). Cancellation before request start and stdio/pending-response paths remain responsive.

## Controls

| Key | Action |
| --- | --- |
| `Enter` | Submit from Prompt, queue during startup, or accept visible autocomplete. |
| `Shift-Enter` | Insert a newline. |
| `Left` / `Right` | Move the prompt cursor by character. |
| `Up` / `Down` | Move cursor vertically in Prompt; otherwise move selection/scroll by focused pane or modal. |
| Mouse wheel over Prompt | Ignored; use cursor keys. |
| `Ctrl-Z` / `Ctrl-Y` | Undo/redo in Prompt; OAuth uses `Ctrl-Y` to copy its URL. |
| `Ctrl-O` | Open the OAuth URL during provider connection. |
| `Ctrl-Left` / `Ctrl-Right` | Move by word. |
| `Ctrl-Backspace` / `Ctrl-Delete` | Delete previous/next word. |
| `Shift-Arrow` | Extend prompt selection. |
| `Ctrl-A` | Select all prompt text. |
| `Ctrl-C` | Copy non-empty selection through OSC52; otherwise clear input, or exit if empty. |
| `Ctrl-D` | Exit. |
| `Alt-A` | Hide/show right column and rail; hiding moves its focus to Transcript, showing keeps focus. Not persisted. |
| `Alt-P` | Focus Prompt and close help. |
| `Esc` | Focus Prompt, close help/modal, or cancel a modal action; provider Saving cannot be cancelled. |
| `Tab` | Cycle Prompt/Transcript/Activity Tree or Prompt/Transcript/Summary/Session files, revealing the column if hidden; accept autocomplete; move modal focus. |
| `Alt-1` / `Alt-2` | Select Activity/Summary; Activity preserves focus unless leaving focused Summary, Summary returns focus to Prompt. |
| `Shift-Tab` | Cycle primary agent; previous custom-provider field or session-list focus in modals (requires terminal `BackTab`). |
| `Ctrl-T` | Focus Activity Tree. |
| `Ctrl-Shift-Right` / `Ctrl-Shift-Left` | Activity-focused/transcript-focused columns; `Alt-Right`/`Alt-Left` are terminal-dependent aliases. |
| `F1` or `/help` | Toggle/open help. |
| `Alt-E` / `Alt-C` | Expand/collapse activities; during startup `Alt-C` cancels the queue, during a run it requests cancellation. Never submits editor text. |
| `Alt-F` / `Alt-R` | Select first failed/running activity. |
| Left click / drag | Position/select prompt text; elsewhere select transcript text, disclose metadata, or use subagent controls. Live viewer consumes mouse input: wheel scrolls and clicks switch sibling tabs. |
| Terminal paste | Apply the normalization, collapse, and byte-limit rules above. |

While cancellation is actionable, the prompt border shows `[Alt-C] to cancel`. Cancellation settles at safe runtime boundaries; an already-started blocking provider request or tool may finish its call before the next prompt is accepted.