Skip to main content

sync_auth/providers/
gemini.rs

1//! Gemini CLI auth provider.
2
3use crate::{AuthProvider, CredentialFile, ValidationResult};
4use std::path::PathBuf;
5
6/// Provider for Google Gemini CLI credentials.
7///
8/// Gemini CLI stores config in `~/.gemini/`.
9/// Key files: `.env` (API key), `oauth_creds.json` (OAuth tokens),
10/// `mcp-oauth-tokens.json` (MCP OAuth tokens).
11#[derive(Debug, Clone, Default)]
12pub struct GeminiProvider;
13
14#[async_trait::async_trait]
15impl AuthProvider for GeminiProvider {
16    fn name(&self) -> &str {
17        "gemini"
18    }
19
20    fn display_name(&self) -> &str {
21        "Gemini CLI"
22    }
23
24    fn credential_files(&self) -> Vec<CredentialFile> {
25        let home = dirs::home_dir().unwrap_or_else(|| PathBuf::from("~"));
26        vec![CredentialFile {
27            relative_path: "gemini/dot-gemini".to_string(),
28            local_path: home.join(".gemini"),
29            is_dir: true,
30        }]
31    }
32
33    async fn validate(&self) -> ValidationResult {
34        let home = dirs::home_dir().unwrap_or_else(|| PathBuf::from("~"));
35        let gemini_dir = home.join(".gemini");
36        // Check for either API key env file or OAuth credentials
37        if gemini_dir.join(".env").exists() || gemini_dir.join("oauth_creds.json").exists() {
38            ValidationResult::Valid
39        } else {
40            ValidationResult::Missing
41        }
42    }
43}