# Providers and Transports


A provider is a named catalogue of models that share a base URL, a credential, and one wire transport. kli's built-in providers resolve credentials through env-var, stored-key, and OAuth modes; each provider speaks exactly one transport.

Models are addressed as `<provider-id>/<model-id>` in `/model`. The `/providers` command lists registered providers with their auth status; `/models` lists the models you currently have credentials for, with compact option markers for models that declare semantic options.

## Providers

| Provider id | Display name | Transport | Auth | Base URL |
|---|---|---|---|---|
| `anthropic` | Anthropic | `anthropic-messages` | env var, stored key | `https://api.anthropic.com` |
| `openai` | OpenAI | `openai-responses` | env var, stored key | `https://api.openai.com/v1` |
| `openai-codex` | ChatGPT (Codex) | `openai-responses` | OAuth | `https://chatgpt.com/backend-api` |
| `compatible` | (per-entry id) | `openai-completions` or `openai-responses` | env var, stored key | declared per entry |

`anthropic` and `openai` register a default environment-variable credential reference (`ANTHROPIC_API_KEY` and `OPENAI_API_KEY`); either can also resolve a stored static key. `openai-codex` authenticates only through OAuth and carries a ChatGPT account id on its requests; it has no environment credential. `compatible` is not a single provider but every user-defined entry in `~/.config/kli/providers.json`, each registered under its own id.

### compatible entries

Each key in `~/.config/kli/providers.json` is a provider id mapping to an object:

| Field | Type | Default | Effect |
|---|---|---|---|
| `base-url` | string | — | Endpoint root the transport posts to. |
| `api` | string | `openai-completions` | Transport. One of `openai-completions` or `openai-responses`; any other value is an error. |
| `key-env` | string | absent | Environment variable holding the API key. When absent, the entry resolves a stored key only. |
| `url-path` | string | `/responses` | Request path, used only when `api` is `openai-responses`. |
| `headers` | object | none | Extra request headers, sent verbatim. |
| `options` | object | none | Provider-level semantic option schemas inherited by every model. |
| `models` | array | empty | Model entries: `id` (required), `name` (defaults to `id`), `context-window`, and optional model-level `options`. |

Secrets never live in `providers.json`. The file names the key's environment variable; the value comes from that variable or a stored static key.

A provider-level `options` object is inherited by each model. A model-level `options` object merges over it: redeclaring an option replaces just that option's schema, and `null` removes an inherited option from that model. This lets one provider declare common OpenAI-family options once while excluding or narrowing them for models that do not support them.

## Transports

A transport is the request shape and stream decoder for one model API. The transport is fixed by the provider, not chosen per request.

| Transport | API | Request path | Used by |
|---|---|---|---|
| `anthropic-messages` | Anthropic Messages | `/v1/messages` | `anthropic` |
| `openai-responses` | OpenAI Responses | `/responses` (or `url-path`) | `openai`, `openai-codex`, `compatible` (opt-in) |
| `openai-completions` | OpenAI Chat Completions | `/chat/completions` | `compatible` (default) |

Providers that share a transport share one stream adapter. Removing one such provider leaves the others working.

## Auth modes

Credentials resolve in one mode per provider. The `/auth` command registers and inspects them; stored credentials persist to `~/.config/kli/credentials.json`.

| Mode | Registered by | Source of the key | Persisted |
|---|---|---|---|
| Environment variable | `/auth env <provider> <ENV_VAR>` | the named environment variable, read at request time | no — only the variable name is recorded |
| Stored key | `/auth key <provider> <KEY>` | a static string in the credential store | yes, in `credentials.json` |
| OAuth | `/auth login <provider>` then `/auth code <code-or-url>` | access and refresh tokens from the provider's token endpoint | yes, in `credentials.json` |

Availability is presence, not a secret read. An environment reference is available when its variable is set and non-empty; a stored key when the string is non-empty; an OAuth credential when it holds a refresh or access token. An expired OAuth access token with a refresh token is still available and refreshes on the next request. `/auth logout <provider>` forgets a stored credential.

The built-in providers register a default credential reference at install: `anthropic` and `openai` an environment reference, `openai-codex` an OAuth restore. A `compatible` entry registers an environment reference only when it names `key-env`.

## Semantic options

Semantic model options are kli-level capability settings on a model selection. They are stored by semantic id in the session, shown by `/models` as compact `options ...` markers, and configured at startup with `settings.json` `defaultOptions`. They are not raw provider request fields; the selected transport lowers each option to the provider-specific wire shape it supports.

Built-in semantic option ids:

| Option id | Values | Supported transports | Wire lowering |
|---|---|---|---|
| `reasoning-effort` | `off`, `minimal`, `low`, `medium`, `high`, `xhigh` | `anthropic-messages`, `openai-responses`, `openai-completions` | OpenAI-family transports send reasoning effort fields; Anthropic sends a `thinking` config using either effort hints or token budgets. `off` disables or omits reasoning according to the transport. |
| `text-verbosity` | `low`, `medium`, `high` | `openai-responses`, `openai-completions` | Responses sends `text.verbosity`; Chat Completions sends `verbosity`. |
| `service-tier` | `auto`, `default`, `flex`, `priority` | `openai-responses`, `openai-completions` | Sends `service_tier`. |
| `prompt-cache-retention` | `off`, `in-memory`, `24h` | `openai-responses`, `openai-completions` | Sends `prompt_cache_retention` for retaining prompt-cache state; `off` omits the retention field. |

A model must declare an option schema before that option can be set. Schema values may narrow the global enum values, and a default may be supplied. For `compatible` providers, schemas are declared in `providers.json`; built-in provider catalogues declare their own schemas.

### Reasoning effort and `/thinking`

`/thinking <level>` is the interactive command for `reasoning-effort`. It sets that semantic option on the current model selection, or shows the current value when called without an argument. `/model provider/model high` is shorthand for selecting the model and setting `reasoning-effort` at the same time.

The word `thinking` still appears in UI text and Anthropic wire docs because those are the user-facing command name and provider API terms. The stored/session-facing option id is `reasoning-effort`.

### Option schema fields

A `providers.json` option schema may carry these fields:

| Field | Type | Effect |
|---|---|---|
| `type` | string | One of `enum`, `boolean`, `integer`, `number`, or `string`. Usually omitted for built-in semantic ids because their global type is known. |
| `values` | array | Allowed enum values. Required for enum schemas. |
| `default` | scalar | Default value when selecting the model without an explicit assignment. |
| `min` | number | Lower bound for `integer` and `number` schemas. |
| `max` | number | Upper bound for `integer` and `number` schemas. |

## See also

- [Connect a Provider](/kli/guides/connect-a-provider)
- [Models](/kli/models)
- [Settings Reference](/kli/config/settings)
