Skip to main content
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

esprit/providers/base.py
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

1

Login to Esprit

esprit provider login esprit
Opens your browser to authenticate with your Esprit account.
2

Authorize the CLI

Grant permission in your browser. The CLI will automatically receive credentials.
3

Verify Subscription

esprit provider status
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)

1

Start OAuth Flow

esprit provider login anthropic
2

Authorize in Browser

The CLI opens your browser to Claude’s authorization page. Sign in with your Claude Pro/Max account.
3

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:
1

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...
2

Enter Code

Visit the URL in your browser and enter the device code.
3

Add More Accounts

esprit provider login openai
If you already have accounts:
Existing accounts for OpenAI:
  ✓ 1. [email protected]

Add another account? [Y/n]:
OpenAI accounts are stored in the account pool at ~/.esprit/providers/account_pool.json and automatically rotate based on rate limits.

GitHub Copilot

1

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
2

Authorize Device

Opening browser to: https://github.com/login/device

Enter this code: 1234-5678
3

Grant Access

Sign in to GitHub and authorize the Esprit CLI to use your Copilot subscription.

Google Gemini

1

Start OAuth

esprit provider login google
2

Authorize Access

Sign in with your Google account and grant permission to access Gemini.
3

Verify

esprit provider status

Antigravity (Free)

Antigravity supports multi-account authentication:
1

Login

esprit provider login antigravity
2

Complete OAuth

Follow the OAuth flow in your browser.
3

Add Multiple Accounts

Add multiple accounts for automatic rotation:
esprit provider login antigravity
# Add as many accounts as needed

API Key Authentication

OpenCode Zen

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

Direct API Keys (Any Provider)

For providers that support API keys:
esprit provider api-key <provider-id>
API keys are stored in plaintext at ~/.esprit/providers/token_store.json. Use OAuth when available for better security.

Credential Storage

Platform Credentials (Esprit)

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)

esprit/providers/base.py
@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:
esprit/providers/base.py
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-id>

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

esprit provider logout <provider-id>
Example:
esprit provider logout anthropic

Troubleshooting

Token Expired

⚠ Token expired
Solution: Re-authenticate with the provider
esprit provider login <provider-id>

No Authentication Token

error: No authentication token available
Solution: Login to a provider first
esprit provider login

OAuth Flow Timeout

error: Authorization timed out
Solution: Try again and complete authorization within 5 minutes

Rate Limited

warning: Rate limit exceeded for [email protected]
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 controlAdd 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

Build docs developers (and LLMs) love