Authentication Methods
/auth login. All other providers — GoogleAI, xAI, ZAI, MiniMax, Moonshot (Kimi), StackSpot, and Ollama — require authentication via API key (set in .env or environment variables)./auth Commands
All authentication commands have auto-completion — just type /auth and press Tab.
View Status
Login via OAuth
Browser opens automatically
Authorize access
Provider available immediately
/switch — no app restart needed.Supported Providers
Logout
Technical Details of OAuth Flows
This section describes how each OAuth flow works internally, including URLs, parameters, and ChatCLI behavior.Anthropic OAuth (PKCE + Manual Code)
The Anthropic flow uses OAuth 2.0 with PKCE (Proof Key for Code Exchange) and a manual copy-paste mechanism for the authorization code.PKCE generation and browser launch
code_verifier and computes the code_challenge using SHA-256 (method S256). The browser opens to the authorization URL with the required parameters.User authorizes in browser
code#state.User pastes code in terminal
# is the state parameter, used in the token exchange.Code exchanged for tokens
http.Client and the same User-Agent, for the same reason.
OpenAI Codex OAuth (PKCE + Localhost Callback)
The OpenAI flow uses OAuth 2.0 with PKCE and a local HTTP server to automatically capture the callback.Local server starts on port 1455
http://localhost:1455 to receive the OAuth callback.Browser opens to authorization page
state parameter for CSRF validation.User authorizes in browser
http://localhost:1455/auth/callback with the authorization code.CSRF validation and token exchange
state parameter against the originally generated value (CSRF protection), exchanges the code for tokens, and shuts down the server.GitHub Copilot Device Flow (RFC 8628)
GitHub Copilot uses the Device Authorization Grant (RFC 8628), a flow designed for devices without an integrated browser, such as CLI terminals.Request device code
device_code and a user_code from the GitHub endpoint.Display code in terminal
user_code and the verification URL (https://github.com/login/device) to the user.User authorizes in browser
user_code, and authorizes ChatCLI access.Polling until authorization
Complete Flow: From Zero to First Prompt
If you are starting without any configured credentials, follow these steps:Start ChatCLI
Log in via OAuth
Authorize in the browser
Switch to the provider
Send your first prompt
Automatic Endpoint Routing (OpenAI)
ChatCLI automatically detects the credential type and routes requests to the correct endpoint:originator plus a Codex User-Agent). Newer model slugs — such as the GPT-5.6 family (gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna) — are only served when both headers are present; without them the backend answers 404 Model not found (Luna, for example, has no server-side fallback).Credential Storage
OAuth credentials are saved with AES-256-GCM encryption at:Encryption Details
~/.chatcli/.auth-key. Unencrypted data from previous versions is automatically detected (absence of the chatcli-enc:v1: prefix) and migrated to the encrypted format on the next save.
Each stored profile contains:
- Access token (encrypted)
- Refresh token (encrypted, when applicable)
- Expiry (timestamp in milliseconds)
- Account ID and email from the provider
- Provider type (anthropic, openai-codex, github-copilot)
Token Validation
ChatCLI implements strict OAuth token validation to prevent use of invalid or expired credentials:Access Token Validation
- Empty access token rejection — Tokens with an empty access token are rejected immediately, without attempting requests. This prevents confusing “unauthorized” errors when credentials are corrupted.
- Expiry validation — The
expiryfield is checked before each request. Expired tokens trigger the refresh flow automatically.
Maximum Token Lifetime (CHATCLI_MAX_TOKEN_LIFETIME)
For production environments with compliance requirements, you can limit the maximum token lifetime:/auth login. This ensures periodic credential rotation even when the refresh token is still valid.Automatic Token Refresh
ChatCLI automatically renews expired tokens in two layers:Proactive Refresh
IsExpired()) or about to expire (IsExpiringSoon() with a 5-minute margin). If so, the refresh is executed before the request.Reactive Refresh
External CLI Sync
ChatCLI can import credentials from external CLIs viaSyncExternalCliCreds():
Credential Resolution Priority
When determining which credential to use for a provider, ChatCLI follows this priority order:Auth-profiles store (OAuth/Token)
auth-profiles.json, including profiles synced from external CLIs. Automatic refresh is applied at this layer.Environment variables
ANTHROPIC_OAUTH_TOKEN, ANTHROPIC_API_KEY, OPENAI_API_KEY, and GITHUB_COPILOT_TOKEN.Advanced Configuration
Troubleshooting
Authentication error when clicking the OAuth link (OpenAI)
Authentication error when clicking the OAuth link (OpenAI)
Anthropic: 403 error or connection refused during token exchange
Anthropic: 403 error or connection refused during token exchange
http.Client for Anthropic token exchange to avoid TLS fingerprinting by Cloudflare. If you are developing, ensure that the exchangeAnthropicToken function uses a client without a custom transport.Provider does not appear in /switch after login
Provider does not appear in /switch after login
/auth status to verify that the token was saved correctly. If needed, try /auth logout <provider> followed by /auth login <provider>.GitHub Copilot: device code expired
GitHub Copilot: device code expired
/auth login github-copilot again to generate a new code.Expired token
Expired token
- Proactively: when resolving credentials, if the token is expired or within the 5-minute margin, a refresh is attempted before the request.
- Reactively: if a request returns a 401 error, ChatCLI invalidates the credential cache, attempts to refresh the OAuth token, recreates the client, and retries the request automatically.
/auth login.GitHub Copilot tokens (Device Flow) do not expire and do not have a refresh token — they are persistent until manually revoked.