Signing in
Every provider loop supports, where to get the key, and how subscriptions, OAuth, and custom gateways work.
loop ships no models. You bring one — a subscription you already pay for, an API key, a local daemon, or your company's gateway. You can sign in to as many as you like and switch between them mid-session with /model.
The short version
loop login
Picks a provider from a list, then walks you through it. Or name one directly:
loop login xai
loop login anthropic
loop login custom
Inside the TUI it's /login. loop whoami shows who you're signed in to and which provider is active; loop logout [provider] removes credentials.
Sign in with a subscription you already have
Three providers bill against a plan instead of per token. No API key involved.
xAI / SuperGrok
loop login xai
Choose OAuth subscription. A browser opens, you approve, and you're done. Requests bill to your SuperGrok plan. Grok is loop's default model (xai/grok-build-0.1), so this is the shortest path to a working setup.
ChatGPT (Codex)
loop login openai
Choose Sign in with ChatGPT. Browser sign-in, billed to your ChatGPT plan. The other option on that menu is a pay-as-you-go OPENAI_API_KEY.
GitHub Copilot
loop login github-copilot
Uses GitHub's device flow: loop prints a code, you paste it into the page that opens, and requests bill against your Copilot subscription.
Sign in with an API key
Every other built-in provider takes a key. loop login <provider> prompts for it and stores it in ~/.loop/auth.json (mode 600).
| Provider | loop login id | Where the key comes from |
|---|---|---|
| xAI (Grok) | xai | console.x.ai → API Keys |
| Anthropic | anthropic | console.anthropic.com → Settings → API Keys |
| OpenAI | openai | platform.openai.com → API keys |
| Google Gemini | google | aistudio.google.com → Get API key |
| OpenRouter | openrouter | openrouter.ai → Settings → Keys |
| DeepSeek | deepseek | platform.deepseek.com → API keys |
| Mistral | mistral | console.mistral.ai → API Keys |
| Zhipu GLM | glm | open.bigmodel.cn → 用户中心 / User Center → API Keys |
| Z.AI | zai | z.ai → API Keys (the international GLM endpoint) |
| Kimi (Moonshot) | kimi | platform.moonshot.ai → Console → API Keys |
| Groq | groq | console.groq.com → API Keys |
| Cerebras | cerebras | cloud.cerebras.ai → API Keys |
| ZenMux | zenmux | zenmux.ai → Settings → API Keys |
| Vercel AI Gateway | vercel | vercel.com → AI Gateway → API Keys |
A key you paste is stored on disk. If you'd rather it never be written down, use the environment-variable path below, or a custom provider with a key-helper command.
Providers that need no login
Ollama — local models, no key, no bill
Install Ollama, pull a model, and leave the daemon running. loop detects it and lists your local models automatically.
ollama pull qwen3-coder
loop
Point loop at a non-default host with LOOP_OLLAMA_BASE_URL.
AWS Bedrock
No loop login step. Bedrock is detected from whatever AWS credentials the machine already has — the aws CLI, environment variables, or an SSO session. If aws sts get-caller-identity works, Bedrock models show up in /model.
Environment variables
If a provider has no stored credential, loop falls back to an environment variable at request time. Nothing is written to disk.
export ANTHROPIC_API_KEY=sk-ant-...
export OPENAI_API_KEY=sk-...
loop
The name is the provider id, uppercased, plus _API_KEY: XAI_API_KEY, ANTHROPIC_API_KEY, OPENAI_API_KEY, GOOGLE_API_KEY, OPENROUTER_API_KEY, DEEPSEEK_API_KEY, MISTRAL_API_KEY, GLM_API_KEY, ZAI_API_KEY, KIMI_API_KEY, GROQ_API_KEY, CEREBRAS_API_KEY, ZENMUX_API_KEY.
Vercel is the one exception: it reads AI_GATEWAY_API_KEY, Vercel's own name for gateway keys. VERCEL_API_KEY is deliberately not used — that name means a deploy token, which is not a gateway key.
This is the right path for CI: set the variable in the job environment and never run loop login at all.
Custom providers and gateways
loop login custom
For anything speaking an OpenAI-, Anthropic-, or Google-compatible API — Bifrost, LiteLLM, an internal proxy, a self-hosted model server, a vendor not in the built-in list. The wizard asks for a name, a base URL, an API shape, an auth method, and a model list. The result is saved to ~/.loop/ and behaves exactly like a built-in provider.
API shapes
- Anthropic-compatible — the Claude API shape (
/v1/messages) - OpenAI-compatible — chat completions (
/v1/chat/completions) - Google-compatible — the Gemini API shape (
/v1beta)
The six auth methods
| Method | What it does | Use it for |
|---|---|---|
| API key | Stored key, sent in the vendor header (x-api-key / Bearer / x-goog-api-key) | Ordinary keys |
| Bearer token | Always Authorization: Bearer | Gateways with their own tokens |
| OAuth / SSO | Browser sign-in (PKCE); tokens refresh automatically | Corporate SSO in front of a gateway |
| Environment variable | Read at request time, nothing stored | CI, shared machines |
| Command (key helper) | Runs a shell command; stdout is the key | Vault reads, short-lived SSO tokens |
| None / headers only | No credential | mTLS, custom headers, open endpoints |
OAuth endpoints auto-discover from the base URL's .well-known metadata. If the server publishes none, the wizard asks for the authorization and token endpoints (and a client id, when the server doesn't support dynamic registration). Add the offline_access scope if the server needs it to issue refresh tokens.
Key helpers re-run on a 5-minute TTL and on any 401. If your command knows the real expiry, print JSON instead of a bare key and loop will use it:
{ "key": "sk-...", "expiresAt": 1793107200000 }
apiKey and token work as aliases for key, and expiresInMs as an alias for expiresAt. Keys persist in ~/.loop/auth.json across restarts until they actually expire.
Headers and values support ${env:VAR} placeholders, resolved at connect time, so secrets stay out of the config file.
Switching between them
Once you're signed in to more than one:
/model— searchable picker across every provider you can use/provider— switch the active providerCtrl+P— cycle recent models without opening a picker/scoped-models— pin a specific model per agent (a cheap one for subagents, an expensive one for the main loop)
A model missing from the picker usually means it's new. Adding a model covers that.
Signing out
loop logout # every provider
loop logout anthropic # just one
In the TUI, /logout offers the same, plus an "all providers" entry.