Providers & Models
PizzaPi is built on the pi coding agent, which supports 30+ AI providers out of the box. You can authenticate with a paid subscription via OAuth, set API keys, or add custom providers like Ollama or LM Studio for local models.
Supported Providers
Section titled “Supported Providers”Subscription Providers (OAuth)
Section titled “Subscription Providers (OAuth)”These providers use OAuth — authenticate with /login inside a session:
| Provider | Subscription |
|---|---|
| Anthropic | Claude Pro / Max |
| OpenAI | ChatGPT Plus / Pro |
| GitHub Copilot | Copilot subscription |
Pi 1.0’s native OpenAI ChatGPT login supersedes the older inherited OpenAI Codex subscription provider for new sign-ins. Existing legacy entries may still appear from older runner auth state, but prefer OpenAI for ChatGPT-backed sessions.
API Key Providers
Section titled “API Key Providers”These are the most commonly used API-key providers. Many other built-in providers (DeepSeek, Fireworks, Together, Moonshot AI, Ollama Cloud, Cloudflare, OpenCode, and more) are also available — run pizza models to see the providers configured on your system and their required env vars.
| Provider | Environment Variable |
|---|---|
| Anthropic | ANTHROPIC_API_KEY |
| OpenAI | OPENAI_API_KEY |
| Google Gemini | GEMINI_API_KEY |
| Azure OpenAI | AZURE_OPENAI_API_KEY |
| Google Vertex AI | GOOGLE_CLOUD_API_KEY |
| Amazon Bedrock | AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY |
| Mistral | MISTRAL_API_KEY |
| Groq | GROQ_API_KEY |
| Cerebras | CEREBRAS_API_KEY |
| xAI | XAI_API_KEY |
| OpenRouter | OPENROUTER_API_KEY |
| Vercel AI Gateway | AI_GATEWAY_API_KEY |
| Hugging Face | HF_TOKEN |
| Kimi For Coding | KIMI_API_KEY |
| MiniMax | MINIMAX_API_KEY |
Authentication
Section titled “Authentication”Using /login (Subscriptions)
Section titled “Using /login (Subscriptions)”Inside a PizzaPi session, type /login in the chat input. You’ll be prompted to select a provider and complete the OAuth flow in your browser. Tokens are stored in ~/.pizzapi/auth.json and auto-refresh when they expire.
The web UI’s Runner Settings → Model providers panel drives the same runner login flow. It supports ordinary browser redirects, provider selection prompts, and copy-code/manual-code prompts such as Anthropic’s headless login flow. It handles provider credentials only; configure MCP connections separately through PizzaPi’s MCP settings.
OpenAI ChatGPT login uses a stable installation deviceId in the runner’s settings.json. The web login flow and pizza auth openai create and reuse this ID through Pi’s settings manager, just like terminal /login.
Use /logout to clear stored credentials.
Using API Keys
Section titled “Using API Keys”Set the provider’s environment variable before starting PizzaPi:
export ANTHROPIC_API_KEY=sk-ant-...Or store it in the auth file at ~/.pizzapi/auth.json:
{ "anthropic": { "type": "api_key", "key": "sk-ant-..." }, "openai": { "type": "api_key", "key": "sk-..." }}The auth file is created with 0600 permissions (user read/write only). Auth file credentials take priority over environment variables.
Key Resolution
Section titled “Key Resolution”The key field in auth.json supports three formats:
| Format | Example | Description |
|---|---|---|
| Shell command | "!security find-generic-password -ws 'anthropic'" |
Executes command, uses stdout |
| Environment variable | "$MY_ANTHROPIC_KEY" or "${MY_ANTHROPIC_KEY}" |
Reads the named env var. A $ prefix (or ${...}) is required for interpolation; a bare name is treated as a literal value. |
| Literal value | "sk-ant-..." |
Used directly |
Shell commands are useful for pulling keys from password managers:
{ "anthropic": { "type": "api_key", "key": "!op read 'op://vault/item/credential'" }}Credential Priority
Section titled “Credential Priority”When multiple sources provide credentials for the same provider:
- CLI
--api-keyflag (highest priority) auth.jsonentry (API key or OAuth token)- Custom provider keys from
models.json - Environment variable (final fallback)
Switching Models
Section titled “Switching Models”In the Web UI
Section titled “In the Web UI”Use the /model command in the chat input to open the model selector. This shows all available models across your authenticated providers.
In the PizzaPi web UI you can also use /cycle_model (alias of /model) to cycle through a subset of models, and /effort (or /cycle_effort) to change reasoning effort.
Pi 1.0 model catalogs can include chat, image, and classifier operations. PizzaPi’s chat model picker and runner model defaults intentionally show chat models only; image and classifier models are used programmatically through codemode or extensions and are not selectable as the session’s chat model.
Virtual models remain selectable like normal chat models. When Pi reports a concrete responseModel different from the selected model, PizzaPi shows both on that assistant message (selected → response) so you can distinguish the requested model from the model that answered.
Setting Defaults
Section titled “Setting Defaults”Set your preferred default model in ~/.pizzapi/settings.json:
{ "defaultProvider": "anthropic", "defaultModel": "claude-sonnet-4-20250514", "defaultThinkingLevel": "medium"}Scoped Model Cycling
Section titled “Scoped Model Cycling”Limit which models appear when cycling:
{ "enabledModels": ["claude-*", "gpt-4o", "gemini-2*"]}Hidden models
Section titled “Hidden models”The web UI’s model-visibility preference syncs hidden models to the runner as PIZZAPI_HIDDEN_MODELS, a JSON array of provider/modelId keys:
export PIZZAPI_HIDDEN_MODELS='["openrouter/vendor/model","ollama-cloud/glm-5.2"]'Workers read this list when listing, switching, cycling, and spawning model-aware helpers. Mid-session changes arrive through a relay hidden_models_update and refresh the worker’s environment. This is a UI preference and hard block by model name; it is not a security boundary.
Fallback models
Section titled “Fallback models”fallbackModels is an ordered chain in ~/.pizzapi/settings.json:
{ "fallbackModels": [ "openai-codex:gpt-5.5", "ollama-cloud:glm-5.2" ]}Fallback runs only when the current assistant turn ends with stopReason: "error" and the error text matches a usage-limit, quota, rate-limit, or provider-capacity condition. Context-window exhaustion is not a rate limit. PizzaPi records the last user input for the session, switches to the next authenticated fallback model, and re-sends that input as a steer message.
Cascade behavior:
- If the current model is in the fallback chain, PizzaPi starts after that entry.
- Otherwise it starts at the beginning of the chain.
- Models that cannot be resolved, have already been tried for this prompt, or lack configured auth are skipped.
- The process repeats until a fallback succeeds or the chain is exhausted.
The UI receives a visible fallback_status notice such as “Primary model hit a provider limit. Retrying with …”. If no captured input exists, PizzaPi sends a generic retry instruction instead of silently doing nothing.
Wait for rate limits to return
Section titled “Wait for rate limits to return”Enable Runner → Settings → Models → Wait for rate limits to return, or set "waitForRateLimits": true in ~/.pizzapi/settings.json. It defaults to false; saved settings apply on the next session start.
After a usage-limit failure exhausts the fallback chain (including an empty chain), PizzaPi can wait for the current model’s subscription quota to recover. It checks quota before waiting, waits until the latest applicable exhausted window resets, then checks again before continuing. Anthropic model-family windows are matched to the selected model. Missing, stale, malformed, or unknown quota is not evidence that usage is available. If recovery cannot be verified, waiting stops with a visible reason rather than retrying blindly.
Use these commands in the TUI or web session composer:
| Command | Effect |
|---|---|
/rate-limit-wait on |
Enable waiting for this session; start waiting if there is a pending usage-limit failure. |
/rate-limit-wait off |
Disable waiting for this session and cancel any current wait. |
/rate-limit-wait cancel |
Cancel the current wait without changing the setting. |
/rate-limit-wait status |
Show whether waiting is disabled, enabled, or active. |
New input, a model change, or session shutdown cancels an active wait. Stop also cancels automatic waiting during a running task. For a wait started by /rate-limit-wait on after the task has already ended, use /rate-limit-wait cancel; there is no running task to stop. Waiting does not survive a worker restart. Automatic recovery is limited to three attempts per input. The automatic recovery path continues the interrupted conversation instead of re-sending the original task. It does not handle context-length errors, fix authentication, or guarantee recovery from API billing/spend caps or provider overload.
Bundled provider extensions
Section titled “Bundled provider extensions”PizzaPi adds a few provider helpers on top of pi’s built-in catalog.
| Provider | Auth | Catalog behavior |
|---|---|---|
ollama-cloud |
OLLAMA_API_KEY or an ollama-cloud API-key entry in ~/.pizzapi/auth.json |
Registered by a PizzaPi extension with a static fallback catalog; the runner/worker refreshes a live cache at ~/.pizzapi/ollama-cloud-models-cache.json. |
openrouter |
pi-ai’s OpenRouter auth (OPENROUTER_API_KEY and supported stored auth) |
Fetches https://openrouter.ai/api/v1/models, keeps tool-capable models, maps pricing/context/modality metadata, and caches for 24 hours at ~/.pizzapi/openrouter-models-cache.json. |
nvidia |
NVIDIA_API_KEY |
Fetches https://integrate.api.nvidia.com/v1/models, filters obvious non-chat models, unions live IDs with pi-ai’s static catalog, applies NVIDIA reasoning-effort constraints, and caches for 24 hours at ~/.pizzapi/nvidia-models-cache.json. |
OpenRouter and NVIDIA keep pi-ai’s native auth and streaming behavior; PizzaPi swaps the model catalog used by the runtime. If a live fetch fails or no cache exists, the provider falls back to the static pi-ai catalog.
Usage and cost tracking
Section titled “Usage and cost tracking”PizzaPi tracks two related things:
| Data | Source | Where it appears |
|---|---|---|
| Tokens and cost | Assistant and tool-result usage fields (including codemode model calls), plus standalone usage entries |
Session totals and usage dashboards. |
| Subscription quota windows | Provider usage APIs for Anthropic and OpenAI Codex | Usage indicator badges in the web UI. |
format-usage.ts maps display providers to quota providers: claude-subscription uses Anthropic quota, openai/openai-codex use OpenAI Codex quota, and Google/Gemini CLI providers map to google-gemini-cli when usage data exists.
remote-provider-usage.ts caches quota windows in the worker and, under the runner daemon, reads the daemon’s shared usage cache file instead of every worker polling providers independently. Anthropic usage is cached for 15 minutes; other usage data uses a 5-minute cache. Snapshots carry per-provider freshness timestamps; refreshing the shared file does not make old quota fresh. Forced refresh requests go through runner IPC; runner-managed workers do not fall back to independent provider requests when IPC is slow or unavailable. Failed checks have a 60-second cooldown, including manual refreshes. The usage badge displays UNKNOWN, rather than disappearing or implying 100% availability, when quota cannot be verified. Anthropic credential discovery includes the anthropic and claude-subscription providers and Claude Code’s stored OAuth credentials.
Provider request logging
Section titled “Provider request logging”Set PIZZAPI_LOG_PROVIDER_REQUEST=1 to log summarized outbound Anthropic /v1/messages requests for diagnostics:
PIZZAPI_LOG_PROVIDER_REQUEST=1 pizzapiThe logger wraps globalThis.fetch and only matches https://api.anthropic.com/v1/messages... by exact hostname and path prefix. It logs request URL, headers, and a summarized body: system block count/characters, message count, tool names, and other top-level fields. Authorization is not printed raw; bearer tokens are reduced to a short fingerprint.
Custom Models
Section titled “Custom Models”Add local or custom models (Ollama, vLLM, LM Studio, proxies) via ~/.pizzapi/models.json. The file reloads each time you open /model — edit it mid-session without restarting.
Minimal Example (Ollama)
Section titled “Minimal Example (Ollama)”{ "providers": { "ollama": { "baseUrl": "http://localhost:11434/v1", "api": "openai-completions", "models": [ { "id": "llama3.1:8b" }, { "id": "qwen2.5-coder:7b" } ] } }}Full Model Configuration
Section titled “Full Model Configuration”{ "providers": { "ollama": { "baseUrl": "http://localhost:11434/v1", "api": "openai-completions", "apiKey": "ollama", "models": [ { "id": "llama3.1:8b", "name": "Llama 3.1 8B (Local)", "reasoning": false, "input": ["text"], "contextWindow": 128000, "maxTokens": 32000, "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 } } ] } }}Supported API Types
Section titled “Supported API Types”| API | Use For |
|---|---|
openai-completions |
Most compatible — Ollama, vLLM, LM Studio, OpenRouter |
openai-responses |
OpenAI Responses API |
openai-codex-responses |
OpenAI Codex CLI agent API |
anthropic-messages |
Anthropic Messages API |
azure-openai-responses |
Azure OpenAI Responses API |
google-generative-ai |
Google Generative AI |
google-vertex |
Google Vertex AI |
mistral-conversations |
Mistral chat completions |
bedrock-converse-stream |
Amazon Bedrock Converse |
Provider Configuration Fields
Section titled “Provider Configuration Fields”| Field | Description |
|---|---|
baseUrl |
API endpoint URL |
api |
API type (see above) |
apiKey |
API key (supports shell command, env var, or literal) |
headers |
Custom headers (same resolution as apiKey) |
authHeader |
Set true to add Authorization: Bearer <apiKey> |
models |
Array of model definitions |
modelOverrides |
Per-model overrides for built-in models |
Model Fields
Section titled “Model Fields”| Field | Required | Default | Description |
|---|---|---|---|
id |
Yes | — | Model identifier passed to the API |
name |
No | id |
Human-readable label |
api |
No | provider’s | Override API type for this model |
reasoning |
No | false |
Supports extended thinking |
thinkingLevelMap |
No | — | Map of thinking levels to API parameter values |
input |
No | ["text"] |
Input types: ["text"] or ["text", "image"] |
contextWindow |
No | 128000 |
Context window (tokens) |
maxTokens |
No | 16384 |
Max output tokens |
cost |
No | all zeros | Per-million-token costs |
headers |
No | — | Per-model custom headers |
compat |
No | — | OpenAI compatibility overrides |
baseUrl |
No | provider’s | Override endpoint for this model |
OpenAI Compatibility
Section titled “OpenAI Compatibility”For servers with partial OpenAI compatibility, use the compat field at the provider or model level:
{ "providers": { "local-llm": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "compat": { "supportsDeveloperRole": false, "supportsReasoningEffort": false }, "models": [{ "id": "my-model" }] } }}This commonly applies to Ollama, vLLM, SGLang, and similar servers that don’t understand the developer role or reasoning_effort parameter.
Cloud Provider Setup
Section titled “Cloud Provider Setup”Azure OpenAI
Section titled “Azure OpenAI”export AZURE_OPENAI_API_KEY=...# Use either the full base URL...export AZURE_OPENAI_BASE_URL=https://your-resource.openai.azure.com# ...or just the resource name as a shorthandexport AZURE_OPENAI_RESOURCE_NAME=your-resource
# Optional (defaults to v1)export AZURE_OPENAI_API_VERSION=v1export AZURE_OPENAI_DEPLOYMENT_NAME_MAP=gpt-4=my-gpt4,gpt-4o=my-gpt4oAmazon Bedrock
Section titled “Amazon Bedrock”# Option 1: AWS Profileexport AWS_PROFILE=your-profile
# Option 2: IAM Keysexport AWS_ACCESS_KEY_ID=AKIA...export AWS_SECRET_ACCESS_KEY=...
# Optional region (defaults to us-east-1)export AWS_REGION=us-west-2Google Vertex AI
Section titled “Google Vertex AI”# Option 1: Application Default Credentialsgcloud auth application-default loginexport GOOGLE_CLOUD_PROJECT=your-projectexport GOOGLE_CLOUD_LOCATION=us-central1
# Option 2: API keyexport GOOGLE_CLOUD_API_KEY=...Overriding Built-in Providers
Section titled “Overriding Built-in Providers”Route a built-in provider through a proxy without redefining its models:
{ "providers": { "anthropic": { "baseUrl": "https://my-proxy.example.com/v1" } }}All built-in Anthropic models remain available — only the endpoint changes.