magi-code 0.77.1

Repository-aware CLI coding agent for terminal work
Documentation
# Provider authentication

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

## Connect a provider

Run `/login` in Mission Control. Choose OpenAI Codex for ChatGPT OAuth, Anthropic for Messages API access billed through Anthropic API credits, or Custom Provider for an OpenAI-compatible service.

Never commit credentials, copied tokens, account ids, terminal auth output, or transcripts containing secrets. Settings contain non-secret options only; credentials belong in the provider's environment variable or private `auth.json` under `~/.magi-code` (or `$MC_HOME`).

### OpenAI Codex

```text
/login openai-codex
```

Complete the ChatGPT browser OAuth flow, then check access:

```sh
magi-code --provider openai-codex --model gpt-5.5 --prompt "Reply with only: ok"
```

`openai-codex` requires provider-keyed OAuth credentials and a ChatGPT account id. It calls `https://chatgpt.com/backend-api/codex/responses`. Inference and model discovery do not use `--api-key`, `MC_API_KEY`, `OPENAI_API_KEY`, or custom-provider keys. Do not pass OAuth tokens through those options: runtime-token/API-key auth is refused for Codex.

Login displays an authorization URL and binds `127.0.0.1:1455` for the registered redirect URI `http://localhost:1455/auth/callback`. Credentials are saved in `auth.json`. The visible URL is transient and redacted from logs/debug output. Manual redirect/code input is visually redacted, never stored in settings or sessions or sent to the model, and goes to the token exchange only when explicitly submitted.

```text
/logout openai-codex
```

Logout removes the local OAuth record only. It does not revoke remote tokens or sign out browser sessions.

### Anthropic

```sh
export ANTHROPIC_API_KEY="<ANTHROPIC_API_KEY>"
magi-code --provider anthropic --model claude-sonnet-4-5-20250929 --prompt "Reply with only: ok"
```

Auth checks `ANTHROPIC_API_KEY` first, then the provider-keyed `anthropic` API-key record in `auth.json`. OAuth and no-auth configurations are rejected. Anthropic ignores `--api-key`, `MC_API_KEY`, and OpenAI keys such as `OPENAI_API_KEY`.

To save the model selection without storing a key:

```json
{
  "agent": { "model": {
    "provider": "anthropic",
    "model": "claude-sonnet-4-5-20250929"
  }
  } }
```

After catalog discovery, use `/setmodel anthropic/<model-name>`. Missing Anthropic auth does not block Codex or custom-provider catalogs. `/logout anthropic` removes only the local API-key record; it cannot unset or override `ANTHROPIC_API_KEY`.

#### Migrating retired `claude-code` selections

Claude Code subscription/OAuth support is retired. A stale `claude-code/<model>` selection fails rather than being remapped. Select `anthropic/<model>` and supply an Anthropic API key. Models and credentials are not migrated automatically; Claude Code OAuth/subscription credentials are not reused.

### Custom OpenAI-compatible providers

Use `/login custom-provider` to enter a label, API-root base URL, and optional API-key environment-variable name. Setup saves non-secret metadata, never a key value. Provider ids use lowercase slugs such as `local-provider`; `openai-codex` is reserved. An id such as `openai` can use the custom-provider workflow.

If you configure an API-key variable, only that named variable is read and it must be non-empty for the provider to be ready. Without one, you can use a no-auth local provider:

```sh
# No-auth local provider:
magi-code --provider local-provider --model model-name --prompt "Reply with only: ok"

# Env-var-backed provider:
export HOSTED_PROVIDER_API_KEY="<CUSTOM_PROVIDER_API_KEY>"
magi-code --provider hosted-provider --model model-name --prompt "Reply with only: ok"
```

Custom requests use `{base_url}/chat/completions` by default. The URL is a normalized API root, not a request endpoint. Model discovery uses `{base_url}/models`. Edit `providers.custom.<id>` in `settings.json` for options not prompted by login:

| Option | Behavior |
| --- | --- |
| `use_responses_endpoint: true` | Uses `{base_url}/responses`; discovery stays on `/models`. There is no automatic endpoint detection. Codex is unaffected. |
| `supports_text_verbosity: true` | Declares Responses `text.verbosity` support; defaults `false`. Emission also requires Responses mode and shared `providers.openai_responses.text_verbosity`. |
| `fast_mode` | Explicit service tier and exact model ids, or sole `"*"` entry. No capability inference from names. See [Fast mode](#fast-mode). |
| `extra_models` | Adds provider-local model ids omitted by `/models`; dedupes against discovered ids and does not change the endpoint. |
| `models_dev_provider` | Exact `models.dev` namespace for matching context/reasoning/output-token metadata, not auth. Defaults to the provider id. |

For a Z.ai Coding Plan model omitted by `/models`:

```json
{
  "providers": { "custom": {
    "zai": {
      "label": "Z.ai",
      "base_url": "https://api.z.ai/api/coding/paas/v4",
      "api_key_env_var": "ZAI_API_KEY",
      "extra_models": ["glm-5.2"]
    }
  }
  } }
```

Use `glm-5.2`, not `zai/glm-5.2`, in `extra_models`. Catalog enrichment requires an exact namespace and model id match, never a label, host, prefix, or base-URL guess. For example, id `openai` uses namespace `openai`; id `custom-openai` needs `models_dev_provider: "openai"` to use that metadata. An explicit namespace always wins.

`/logout <custom-provider-id>` removes local custom-provider metadata. It leaves credentials, sessions, unrelated settings, and other providers untouched.

## Mission Control login controls

`/login` opens the staged **Connect Provider** modal with provider status. Use `Up`/`Down` and `Enter` to choose.

- Codex: `Ctrl-Y` copies the URL, `Ctrl-O` opens it, and `Enter` submits a redirect URL or authorization code in the transient redacted fallback field. `Esc` cancels active OAuth.
- API keys: the modal shows environment setup instructions, not a key-entry field.
- Custom providers: `Tab`/`Shift-Tab` move between fields. Reusing an id requires confirmation: `Enter` replaces; `Esc` returns to the form.
- Success: `Enter` or `Esc` closes. Errors: `Enter` retries, `Backspace` or `Left` goes back, and `Esc` closes.

Cancelling before Saving preserves existing credentials and settings. Once durable custom-provider saving begins, it cannot be cancelled; the modal stays open until completion is reconciled.

## Fast mode

Use `/fast on` or set global `agent.fast.enabled: true`. It defaults off, ignores project overrides, and applies to eligible primary turns, subagents, and manual or automatic blocking compaction, not session titles.

Codex selects the exact catalog-advertised Fast tier id. Discovery reads `service_tiers` and legacy `additional_speed_tiers`, matching Fast display/name case-insensitively. Explicit tier metadata without Fast keeps the request Standard. Only missing tier metadata or a missing catalog entry permits the fallback: strictly normalized Codex GPT versions `>=5.4` use `fast`. Unsupported models/providers request no Fast tier.

Codex OAuth Responses requests include a Codex-only `x-codex-routing-hint: model=<normalized-model>`, even with Fast off, unless it is invalid as an HTTP header value. With a selected Fast tier, it adds `;tier=<service-tier-id>` and the body includes the exact `service_tier`. The hint is not sent to catalogs or custom providers.

Custom providers require explicit `providers.custom.<id>.fast_mode`, for example `{"service_tier":"priority","models":["model-name"]}`. The tier is trimmed; model ids are preserved exactly. Ids must contain 1 to 200 Unicode characters without whitespace, control characters, or secret-like values. `"*"` must be the sole entry. See [Configuration](configuration.md) for schema validation rules.

Fast is not an entitlement check or speed guarantee. The provider controls access, routing, speed, and billing/credits. A ChatGPT-auth response may report a different tier such as `default`; the reported tier does not prove faster execution. In Mission Control, an unacknowledged Fast persistence-worker failure without an event blocks retry until restart; a delivered failure is cleared when its matching event is handled.

## Response detail

`providers.openai_responses.text_verbosity` accepts `low`, `medium`, or `high`. Codex uses it first, then legacy `providers.openai_codex.text_verbosity` (default `low`). Custom Responses providers never inherit the legacy value: they require the shared value plus both `use_responses_endpoint` and `supports_text_verbosity`. Otherwise they omit the field.

Verbosity affects visible detail, output size, latency, and cost. It does not control reasoning effort, expose hidden/encrypted reasoning, control tool calls, or impose a hard output-token limit or exact answer length.

## Credential storage and refresh

`auth.json` is private and owner-only on Unix. Provider records may sit alongside internal non-secret `revision` and `provider_generations` metadata; do not edit that metadata. Writes preserve unrelated provider records.

Before Codex use, including applicable auxiliary work such as model discovery, near-expired or expired credentials refresh if a refresh token is available. Network exchange runs outside auth locks. Saving reacquires the in-process lock, then the cross-process file lock, and requires the same provider generation and full source record to still match. Stale/competing responses cannot overwrite newer auth; stale errors are checked against current state so newer usable credentials can win. Generations survive logout, protecting removed and recreated records from delayed refreshes.

See [Configuration](configuration.md) for file limits, paths, and credential boundaries.