Esprit CLI supports multiple authentication methods depending on the provider. Most providers use OAuth for secure account linking, while some support direct API keys.
Authentication Methods
class AuthMethod ( str , Enum ):
"""OAuth authorization method."""
CODE = "code" # Authorization code flow
DEVICE = "device" # Device code flow
Esprit uses two OAuth flows:
Authorization Code Flow : User visits a URL and grants permission (Anthropic, Google)
Device Code Flow : User enters a code on the provider’s website (GitHub Copilot, OpenAI)
Esprit Cloud Authentication
Login to Esprit
esprit provider login esprit
Opens your browser to authenticate with your Esprit account.
Authorize the CLI
Grant permission in your browser. The CLI will automatically receive credentials.
Verify Subscription
Shows your plan (FREE, PRO, TEAM, ENTERPRISE) and available features.
Subscription Verification
esprit/auth/credentials.py
def verify_subscription (
access_token : str | None = None ,
* ,
force_refresh : bool = False ,
) -> SubscriptionVerification:
"""Verify subscription status with the Esprit API."""
token = access_token or get_auth_token()
if not token:
return {
"valid" : False ,
"plan" : "free" ,
"quota_remaining" : { "scans" : 0 , "tokens" : 0 },
"cloud_enabled" : False ,
"available_models" : [],
"error" : "No authentication token available." ,
}
headers = { "Authorization" : f "Bearer { token } " }
response = requests.get(
f " { API_BASE_URL } /subscription/verify" ,
headers = headers,
timeout = 15 ,
)
Esprit credentials are stored in ~/.esprit/credentials.json with restricted permissions (0600).
OAuth Authentication
Anthropic (Claude Pro/Max)
Start OAuth Flow
esprit provider login anthropic
Authorize in Browser
The CLI opens your browser to Claude’s authorization page. Sign in with your Claude Pro/Max account.
Complete Authorization
After granting permission, the CLI automatically receives and stores your credentials. ✓ Successfully logged in to Anthropic (Claude Pro/Max)
OpenAI (ChatGPT Plus/Pro)
OpenAI supports multi-account authentication:
Start Device Flow
esprit provider login openai
Displays a device code: Opening browser to: https://auth.openai.com/activate
Enter this code: ABCD-EFGH
Waiting for authorization...
Enter Code
Visit the URL in your browser and enter the device code.
Add More Accounts
esprit provider login openai
If you already have accounts:
OpenAI accounts are stored in the account pool at ~/.esprit/providers/account_pool.json and automatically rotate based on rate limits.
GitHub Copilot
Start Authentication
esprit provider login github-copilot
For GitHub Enterprise: esprit provider login github-copilot
# When prompted:
Are you using GitHub Enterprise? [y/N]: y
Enter your GitHub Enterprise URL: https://github.enterprise.com
Authorize Device
Opening browser to: https://github.com/login/device
Enter this code: 1234-5678
Grant Access
Sign in to GitHub and authorize the Esprit CLI to use your Copilot subscription.
Google Gemini
Start OAuth
esprit provider login google
Authorize Access
Sign in with your Google account and grant permission to access Gemini.
Antigravity (Free)
Antigravity supports multi-account authentication:
Login
esprit provider login antigravity
Complete OAuth
Follow the OAuth flow in your browser.
Add Multiple Accounts
Add multiple accounts for automatic rotation: esprit provider login antigravity
# Add as many accounts as needed
API Key Authentication
OpenCode Zen
Interactive
Environment Variable
esprit provider api-key opencode
Enter your API key when prompted (input is hidden): Enter API key for OpenCode Zen: ****************
✓ API key saved for OpenCode Zen
export LLM_API_KEY = "your-opencode-api-key"
Environment variable takes precedence over stored credentials.
Direct API Keys (Any Provider)
For providers that support API keys:
esprit provider api-key < provider-i d >
API keys are stored in plaintext at ~/.esprit/providers/token_store.json. Use OAuth when available for better security.
Credential Storage
esprit/auth/credentials.py
class Credentials ( TypedDict , total = False ):
"""Stored credential structure."""
access_token: str
refresh_token: str
expires_at: int # Unix timestamp
user_id: str
email: str
full_name: str | None
plan: str # 'free', 'pro', 'team'
Stored at: ~/.esprit/credentials.json
OAuth Credentials (Other Providers)
@dataclass
class OAuthCredentials :
type : str # "oauth" or "api"
access_token: str
refresh_token: str | None = None
expires_at: int | None = None # Unix timestamp
account_id: str | None = None
extra: dict[ str , Any] | None = None
Single-account providers: ~/.esprit/providers/token_store.json
Multi-account providers: ~/.esprit/providers/account_pool.json
Token Management
Automatic Token Refresh
Esprit automatically refreshes expired tokens:
def is_expired ( self ) -> bool :
"""Check if the access token has expired."""
if not self .expires_at:
return False
now = int (datetime.now( tz = timezone.utc).timestamp())
# Refresh 5 minutes before expiry
return now >= ( self .expires_at - 300 )
Manual Token Refresh
If you see token expiration warnings:
# Re-authenticate
esprit provider login < provider-i d >
Account Pool (Multi-Account)
For providers that support multiple accounts:
esprit/providers/account_pool.py
class AccountPool :
"""Manages multiple OAuth accounts per provider."""
def add_account (
self ,
provider_id : str ,
credentials : OAuthCredentials,
email : str ,
) -> None :
"""Add an account to the pool."""
def get_best_account (
self ,
provider_id : str ,
) -> StoredAccount | None :
"""Get the best available account (enabled, not rate limited)."""
The account pool automatically rotates between accounts when rate limits are hit.
Logout
Single Provider
Multi-Account Provider
Interactive
esprit provider logout < provider-i d >
Example: esprit provider logout anthropic
esprit provider logout openai
Choose which account to remove: Shows all logged-in providers and lets you select one.
Troubleshooting
Token Expired
Solution : Re-authenticate with the provider
esprit provider login < provider-i d >
No Authentication Token
error: No authentication token available
Solution : Login to a provider first
OAuth Flow Timeout
error: Authorization timed out
Solution : Try again and complete authorization within 5 minutes
Rate Limited
Solution :
For multi-account providers, add another account
Wait for rate limit to reset
Switch to a different provider
Security Best Practices
Never commit credentials to version control Add to .gitignore: ~/.esprit/credentials.json
~/.esprit/providers/
Credentials are stored with restricted permissions (0600 on Unix)
Tokens are automatically refreshed before expiry
Use OAuth when available instead of API keys
Remove unused accounts with esprit provider logout
Next Steps
Providers Learn about supported LLM providers
Environment Variables Configure settings via environment variables