Start here
Models and keys
Connect a model provider, choose models per role and control how 0 routes model calls.
0 uses your own model provider. Connect one in the browser or with an environment variable, then pick a model.
Connect in the browser
Section titled “Connect in the browser”- Run
0and open Settings → Models. - Pick a provider. Paste an API key or follow its sign-in flow.
- A connected provider gets its default model automatically. To change it, open Settings → Models and pick a Default model, or pick a model in a thread with the model picker.
The model list comes from your connections. Models lists every model they serve and flags a connection that needs attention. Under Providers on the Models page, you can turn off single models of a connection. Public catalogs add price and context data but do not grant access; a listed model can still be unavailable to your account.
Connect from a shell
Section titled “Connect from a shell”Export a provider key, then run any command:
export ANTHROPIC_API_KEY="sk-ant-..."0 scan source ./your-repo --runtime api --depth quick --cost-ceiling 2| Provider | Environment |
|---|---|
| Anthropic | ANTHROPIC_API_KEY |
| OpenAI | OPENAI_API_KEY |
| ChatGPT Codex | codex login, or ZERO_CHATGPT_ACCESS_TOKEN / ZERO_CHATGPT_OAUTH_REFRESH_TOKEN |
| OpenRouter | OPENROUTER_API_KEY |
| Azure OpenAI | AZURE_OPENAI_API_KEY, plus endpoint and deployment (details) |
| DeepSeek | DEEPSEEK_API_KEY |
| Z.ai GLM | Z_AI_API_KEY |
| Moonshot Kimi | KIMI_API_KEY |
| Alibaba Qwen | QWEN_API_KEY and QWEN_BASE_URL |
| xAI Grok | XAI_API_KEY |
| OpenCode Zen | OPENCODE_API_KEY (OPENCODE_BASE_URL to change endpoint) |
| Together AI | TOGETHER_API_KEY (details) |
Pass ZERO_* variables with env, for example env ZERO_CHATGPT_OAUTH_REFRESH_TOKEN=... 0 doctor.
Check what 0 found:
0 doctor
0 doctor prints the CLI version, runtime, platform and Node.js check, then the API provider status: configured, bad (found but unusable, with the reason) or missing. It also lists claude, codex and gemini CLIs found on PATH. It checks local configuration only. The first model request proves the key, model access and quota.
Choose a model
Section titled “Choose a model”- Browser: the model picker in a thread changes that thread’s model while it is idle. Settings → Models → Default model sets the default for new threads. Existing threads keep their connection until you change it.
- CLI: pass
--model <id>or setZERO_MODEL.--modelwins.
Use an exact model ID your account supports:
env ZERO_SELECTED_PROVIDER=openai ZERO_MODEL=<model-id> \ 0 scan source ./authorized-repo --runtime apiAgent workflows need a model that supports tool calling.
Role models
Section titled “Role models”0 can use different models for different jobs. The roles are discovery, attack, verify, report, audit and review.
In the browser, open Models → Advanced:
- Use one model for everything sends every role to the main model.
- Pick models per task automatically lets 0 choose among models your connection can reach.
- Each role has its own model select. Auto follows the main model or the automatic choice.
On 0 scan web, use --task-model <role=model> (repeatable) for discovery, attack, verify and report, or --single-model to use one model throughout.
Role models stay on the parent’s connection. Child agents use the same provider, endpoint and credentials, and do not inherit a failover chain. Choose models that same account serves. Connecting a second provider does not make roles cross accounts. Role changes apply after the current step finishes. Role routing is not failover and does not add an independent verification stage on its own.
Custom and local providers
Section titled “Custom and local providers”Any OpenAI-compatible Chat Completions server works, local or remote.
On the Models page, in Providers, choose OpenAI / Custom AI Provider. Enter the base URL with its version path (for example http://localhost:20128/v1), the Custom model ID and the API key. HTTP and HTTPS both work. The model does not need to be in any catalog.
In a shell:
export OPENAI_API_KEY="your-provider-key"export OPENAI_BASE_URL="http://localhost:20128/v1"export OPENAI_MODEL="your-provider/model-id"export ZERO_SELECTED_PROVIDER="openai"00 appends /chat/completions to the base URL. Set OPENAI_WIRE_API=responses for servers that need the Responses API. Exported values override saved connection settings, and an explicit model choice overrides OPENAI_MODEL.
For OpenCode Go, use its published base URL, such as https://opencode.ai/inference/go/openai/v1.
Ollama for source review
Section titled “Ollama for source review”scan source can call a local Ollama server directly:
OLLAMA_HOST=http://localhost:11434 \ 0 scan source ./authorized-repo --runtime ollama --model gemma4:27bThe model comes from --model, then ZERO_OLLAMA_MODEL, then gemma4:27b. OLLAMA_HOST defaults to http://localhost:11434. Pull a model that supports tool calling first. A remote OLLAMA_HOST receives your source context.
ChatGPT Codex
Section titled “ChatGPT Codex”
On the Models page, in Providers, select ChatGPT Codex and follow the device sign-in. It runs codex login --device-auth and reloads the auth file when done.
From a shell, run codex login. 0 reads tokens from ~/.codex/auth.json at startup when no ZERO_CHATGPT_* token is set. A signed-in Codex session takes priority over stale OPENAI_API_KEY or AZURE_OPENAI_API_KEY values in your shell.
| Variable | Use |
|---|---|
ZERO_CODEX_AUTH_JSON_PATH | Read a different auth file. ZERO_CHATGPT_AUTH_FILE is a deprecated alias. |
ZERO_CHATGPT_ACCESS_TOKEN, ZERO_CHATGPT_OAUTH_REFRESH_TOKEN | Supply tokens directly. The access token is read first. |
ZERO_CHATGPT_ACCOUNT_ID | Set the account ID. Otherwise it comes from the auth file. |
Codex uses its own auth file, not 0’s credential store. It rejects a generic --api-key. Choose OpenAI for an API-key connection.
Provider notes
Section titled “Provider notes”Azure OpenAI
Section titled “Azure OpenAI”
Supply the key, the endpoint and the deployment ID, and pin the provider:
export AZURE_OPENAI_API_KEY="your-azure-key"export AZURE_OPENAI_BASE_URL="https://your-resource.openai.azure.com/openai/v1"export AZURE_OPENAI_WIRE_API="responses"env ZERO_SELECTED_PROVIDER=azure ZERO_MODEL="your-deployment-id" \ 0 scan source ./authorized-repo --runtime api --cost-ceiling 5| Setting | Resolution |
|---|---|
| Endpoint | AZURE_OPENAI_BASE_URL, then OPENAI_BASE_URL, then the Azure section of ~/.codex/config.toml |
| Model | --model, then ZERO_MODEL. Without a pin, AZURE_OPENAI_MODEL or an Azure-backed Codex config model also works. |
| Wire | AZURE_OPENAI_WIRE_API: chat_completions (default) or responses |
Include /openai/v1 in a Responses base URL. The model picker lists deployments from your Azure resource through an existing Azure CLI sign-in; it never starts a login. With a key alone, enter the deployment ID by hand. 0 probes the endpoint once for its region; that is a diagnostic, not a residency guarantee.
Together AI
Section titled “Together AI”Connect Together AI or export TOGETHER_API_KEY. The default endpoint is https://api.together.ai/v1; set TOGETHER_BASE_URL to change it.
Together model IDs look like other providers’ IDs (Qwen/..., deepseek-ai/...), so 0 never routes to Together by model name. Select it explicitly:
env ZERO_SELECTED_PROVIDER=together ZERO_MODEL=openai/gpt-oss-120b \ 0 scan source ./authorized-repo --runtime api# or, with no provider pin:0 scan source ./authorized-repo --runtime api --model together/openai/gpt-oss-120bThe together/ prefix is removed once before the request. The default model is openai/gpt-oss-120b. The picker lists chat models with published prices; set TOGETHER_MODEL_LIST=all to list every chat model your key can see. Unlisted IDs, including dedicated endpoints, still work with --model.
Alibaba Qwen
Section titled “Alibaba Qwen”Set QWEN_API_KEY and QWEN_BASE_URL for the same product and region shown in your account. QwenCloud, Model Studio, Coding Plan and Token Plan keys are not interchangeable, and 0 does not infer the region. Qwen OAuth is discontinued upstream.
OpenRouter, xAI and Kimi sign-in
Section titled “OpenRouter, xAI and Kimi sign-in”
- OpenRouter: the browser sign-in provisions an API key for you. When OpenRouter is the selected provider,
--model freemaps tonvidia/nemotron-3-super-120b-a12b:free. - xAI and Kimi: browser sign-in needs a client registered for 0 in
ZERO_XAI_OAUTH_CLIENT_IDorZERO_KIMI_OAUTH_CLIENT_IDbefore the app starts. Otherwise use an API key.
OpenAI, OpenRouter, xAI and Azure accept OPENAI_WIRE_API, OPENROUTER_WIRE_API, XAI_WIRE_API and AZURE_OPENAI_WIRE_API set to chat_completions or responses.
How 0 picks a provider
Section titled “How 0 picks a provider”With several keys set, 0 resolves the provider in this order:
- A pin.
ZERO_SELECTED_PROVIDERselects the provider outright. SetZERO_MODELwith it. - The model name.
--modelorZERO_MODELroutes by prefix when that provider has a key. - Ambient priority. Otherwise the first configured key in the list below wins.
Connection health
Section titled “Connection health”A connection is only Connected (green) after the provider accepted its key. 0 checks each connection once when you open Connections or Models and when you start a thread, with a short request that never blocks the page, and reuses the answer for about five minutes. The states are:
| Badge | Meaning |
|---|---|
| Connected | The provider accepted the key. |
| Key rejected | The provider answered 401 or 403. For a key from the environment the row says which variable to set; for a saved key it says to update it. |
| Can’t reach | The provider did not answer in time. Check your network or the API endpoint. |
| Connected (grey) | A key is present but the provider has no cheap check (for example Azure OpenAI), so it is not verified. |
A rejected or unreachable provider is never picked as the default model for new threads, and a remembered model from it is skipped. If a message still fails with a rejected key, the thread names the provider and model and offers Switch to a model on a working connection (this resends your message) or Manage connection. The same states show on Settings → Diagnostics.
Pin a provider
Section titled “Pin a provider”ZERO_SELECTED_PROVIDER accepts openrouter, anthropic, openai, azure, deepseek, chatgpt-codex, z-ai, kimi, qwen, xai, opencode and together.
env ZERO_SELECTED_PROVIDER=deepseek ZERO_MODEL=deepseek-flash \ 0 scan web --target https://example.com --scope ./scope.json --runtime apiPin when you need a predictable bill, especially with Azure deployment names. ZERO_FORCE_PROVIDER is a benchmark override; setting it to a different value than ZERO_SELECTED_PROVIDER is an error.
Routing by model name
Section titled “Routing by model name”| Model ID | Provider |
|---|---|
together/<org>/<model> | Together AI (prefix removed) |
openrouter/* | OpenRouter |
glm-*, z-ai/*, IDs containing glm | Z.ai GLM |
qwen* | Alibaba Qwen |
k3*, kimi* | Moonshot Kimi |
grok*, xai/*, x-ai/* | xAI Grok |
opencode/*, muse-spark*, mimo*, ling*, big-pickle, nemotron*, minimax* | OpenCode Zen |
gpt-*, o1 to o4 | ChatGPT Codex when signed in, else OpenAI |
claude*, anthropic/*, IDs containing sonnet, opus or haiku | Anthropic, else OpenRouter |
Exact deepseek-flash, deepseek-v4-flash | DeepSeek |
| Known Azure Foundry deployment IDs | Azure |
A match without that provider’s key falls through to ambient priority. These are routing rules, not an availability check.
Ambient priority
Section titled “Ambient priority”- ChatGPT Codex (
ZERO_CHATGPT_*tokens or~/.codex/auth.json) - DeepSeek
- OpenRouter
- Azure OpenAI
- OpenAI
- Z.ai GLM
- Moonshot Kimi
- Alibaba Qwen
- xAI Grok
- OpenCode Zen
- Anthropic
- Together AI
An explicit --api-key without a pin picks by shape: sk-or- selects OpenRouter, sk-ant- selects Anthropic, and anything else selects OpenAI-compatible access. Prefer environment variables; command-line secrets end up in shell history and process lists.
Failover
Section titled “Failover”ZERO_LLM_FALLBACK lists backup routes for when the primary runs out of retries or hits a plan quota:
env ZERO_LLM_FALLBACK=deepseek:deepseek-flash,azure:gpt-5-deployment \ 0 scan source ./authorized-repo --runtime apiEach entry is <provider>:<model>, comma-separated, tried in order. Entries without credentials (or, for Azure, without an endpoint) are skipped. Failover changes who receives your context and who bills you. A cyber access program request disables failover.
Advanced settings
Section titled “Advanced settings”| Variable | Default | Effect |
|---|---|---|
ZERO_RUNTIME | auto | Provider client. auto uses the pi-ai layer for the routes it serves and the built-in client for the rest. legacy always uses the built-in client. pi-ai forces pi-ai and fails on routes it cannot serve. |
ZERO_RUNTIME_TRACE | unset | 1 prints the chosen client, provider and model to stderr. |
ZERO_MAX_COMPLETION_TOKENS | 8192 | Completion tokens requested per call. Positive integer; values above 131072 are clamped. Very small values truncate tool calls. |
If a provider misbehaves under auto, set ZERO_RUNTIME=legacy and report it.
CLI runtimes
Section titled “CLI runtimes”--runtime chooses how a scan reaches a model. The default is auto.
| Runtime | Uses |
|---|---|
api | Direct HTTP calls with the provider rules above. |
claude | The installed, signed-in Claude Code CLI. |
codex | Source reviews keep 0’s own tool boundary. Live scans use the ChatGPT Codex provider directly. |
gemini | The installed, signed-in Gemini CLI, for source work. |
ollama | A local Ollama server, for scan source. |
0 scan web --target https://api.example.com --scope ./scope.json --runtime claude0 scan source ./my-repo --runtime codexUse --runtime api when you want the provider rules on this page instead of auto. External CLIs make their own network calls, which 0 does not control.
Cyber access programs
Section titled “Cyber access programs”OpenAI’s Daybreak programs need an explicit request. A model name alone does not select one.
- Browser: use the Daybreak control beside the model settings. Automatic clears the request.
- CLI:
0 scan sourceand0 scan webaccept--cyber-access-program standard|daybreak_blue|daybreak_red. It requires--runtime apiand--provider openaior--provider chatgpt-codex.
# OpenAI API project with approved access:env OPENAI_WIRE_API=responses \ 0 scan source ./authorized-repo --runtime api --provider openai \ --model <approved-model> --cyber-access-program daybreak_blue
# Existing ChatGPT/Codex sign-in:0 scan source ./authorized-repo --runtime api --provider chatgpt-codex \ --model <model> --cyber-access-program daybreak_blueThe flag requests access; it does not grant it. Reports keep the requested program separate from what the provider confirmed. Program-bound calls never fall back to another provider. Do not pass --api-key with ChatGPT sign-in.
Keep model traffic in one region
Section titled “Keep model traffic in one region”Pin the provider and its endpoint with ZERO_SELECTED_PROVIDER and ZERO_MODEL, as in the Azure OpenAI example, and leave ZERO_LLM_FALLBACK unset.
- Setting a provider’s variables alone does not prove all traffic goes there. Ambient priority and failover can pick other routes.
- Other lookups still leave: the GitHub API, OSV, package registries, Microsoft Graph, web search and out-of-band testing services.
- The
claude,codexandgeminiruntimes call third-party CLIs whose traffic 0 does not control. Use--runtime api.
Manage connections from a shell
Section titled “Manage connections from a shell”The same actions as Settings → Connections and Models are available as commands. Keys come from an environment variable or stdin, never from an argument.
0 models connections add openai --key-env MY_OPENAI_KEY0 models connections test openai0 models list --provider openai0 models default --provider openai gpt-5.4-mini0 models connections remove openai --yes
Where credentials live
Section titled “Where credentials live”Keys saved under Providers on the Models page are stored in plaintext at ~/.0/credentials.json, with 0600 file and 0700 folder permissions. Keep that file out of source control and bug reports. A nonblank environment variable wins over the saved key for that provider; Connections marks such a row From environment and the saved key Not in use. For CI and other automation, pass credentials in the environment.
Limits
Section titled “Limits”- Billing, model access and rate limits belong to your provider account.
- Shown prices are estimates. Unknown prices are unknown, not zero, so a cost ceiling cannot bound that model. See Costs and budgets.
- A model connection does not authorize a target. See Scope and authorization.