geminpy
Automated OAuth wrapper for Google's Gemini CLI on macOS
geminpy eliminates the manual authentication steps required by Google's gemini CLI tool. It automatically handles the entire OAuth flow - from browser management to account selection - letting you use Gemini programmatically without interruption.
Why It Exists
Google's official gemini CLI requires manual OAuth authentication through a web browser each time you use it. This makes automation impossible and interrupts workflows. geminpy solves this by:
- Automating the OAuth dance - No manual clicking through Google's authentication screens
- Managing browser contexts - Uses isolated Chrome for Testing to avoid conflicts
- Handling rate limits gracefully - Automatically retries with flash model when rate limited
- Providing clean outputs - Filters authentication noise from responses
What It Does
geminpy acts as a transparent wrapper around the official gemini CLI, adding automation capabilities:
- Drop-in CLI replacement: Use it exactly like the original
geminicommand - Programmatic API: Call Gemini from Python code with
ask()function - Multi-language support: Handles OAuth pages in 9+ languages
- Smart user detection: Remembers your preferred Google account
- Rate limit resilience: Automatic fallback to
gemini-2.5-flashwhen quota exceeded - Browser isolation: Uses Chrome for Testing to avoid disrupting your main browser
How It Works
Technical Architecture
The package orchestrates several components to achieve seamless automation:
User Request → GeminiClient → Browser Setup → OAuth Automation → Gemini CLI → Response
↓ ↓ ↓ ↓
BrowserManager ChromeManager OAuthAutomator GeminiExecutor
↓ ↓ ↓ ↓
macdefaultbrowsy Chrome CDP Playwright subprocess
Automation Flow
-
Browser Preparation
- Installs Chrome for Testing if needed (via
@puppeteer/browsers) - Saves current default browser
- Temporarily switches to Chrome for Testing
- Installs Chrome for Testing if needed (via
-
OAuth Automation
- Launches Chrome with remote debugging (
--remote-debugging-port=9222) - Starts
geminiCLI which opens OAuth URL - Playwright connects via Chrome DevTools Protocol
- Automatically clicks your Google account
- Detects and clicks sign-in button (multi-language, multi-strategy)
- Waits for authentication success
- Launches Chrome with remote debugging (
-
Execution & Monitoring
- Monitors gemini process output in real-time
- Detects rate limits (429, quota exceeded, etc.)
- Automatically retries with fallback model if needed
- Extracts clean response from CLI output
-
Cleanup
- Restores original default browser
- Optionally quits Chrome
- Returns pure response text
Key Components
browser.manager: Controls macOS default browser viamacdefaultbrowsybrowser.chrome: Manages Chrome for Testing installation and lifecyclebrowser.automation: Playwright-based OAuth flow automationgemini.client: Main orchestrator coordinating all componentsgemini.executor: Subprocess management with real-time monitoringgemini.parser: Response extraction and cleaning
Installation
Prerequisites
macOS only - Browser automation requires macOS-specific tools.
Install geminpy
uv pip install geminpy
One-time setup: Install Playwright browsers
playwright install chromium
Usage
CLI Usage
Use exactly like the original gemini CLI:
# Ask a question
geminpy -p "Explain Python decorators"
# Use specific model with new shortcuts
geminpy -P -p "Write a Python function" # Uses gemini-2.5-pro
geminpy -F -p "Quick question" # Uses gemini-2.5-flash
# Traditional model selection still works
geminpy -m "gemini-pro" -p "Complex analysis"
# Enable verbose logging
geminpy --verbose -p "Debug this"
# Quit Chrome after completion
geminpy --quit-chrome -p "One-off query"
Programmatic Usage
from geminpy import ask
# Simple question-answer
response = ask("Explain quantum computing")
print(response)
# Async usage with full control
import asyncio
from geminpy import call_gemini_cli
async def main():
response = await call_gemini_cli(
gemini_args=["-m", "gemini-pro", "-p", "Your prompt"],
user="your.email@gmail.com",
verbose=True,
quit_browser=True
)
print(response)
asyncio.run(main())
Configuration
User Account Resolution
geminpy determines which Google account to use in this priority order:
- CLI argument:
--user="you@gmail.com" - Environment variable:
GEMINI_CLI_USER="you@gmail.com" - Stored settings: From previous successful authentication
- First available: Uses first Google account found
Settings Storage
Settings are automatically persisted to:
~/Library/Application Support/com.twardoch.chrometesting/settings.json
Contains:
- Chrome for Testing executable path
- Last used Google account email
Advanced Features
Multi-Language OAuth Support
Detects sign-in buttons in multiple languages:
- English, Polish, French, German, Spanish
- Italian, Russian, Japanese, Chinese
- Falls back to attribute and style-based detection
Rate Limit Handling
Automatic detection and retry logic:
Original request → Rate limit detected → Retry with gemini-2.5-flash → Final response
Browser Isolation
- Uses dedicated Chrome for Testing instance
- Preserves your regular browser state
- No profile contamination
- Clean OAuth every time
Troubleshooting
Common Issues
"Chrome CDP did not become available"
- Check if port 9222 is available:
lsof -i :9222 - Look at Chrome logs:
/tmp/gemini_chrome_stderr.log
"Could not find sign-in button"
- Enable verbose mode:
--verbose - Check screenshots:
oauth_error.png,oauth_error_no_signin.png - Ensure your Google account has Gemini access
Debug Mode
Enable comprehensive logging:
geminpy --verbose -p "Your question"
Shows:
- Chrome installation progress
- Browser switching operations
- OAuth automation steps
- Gemini CLI interactions
- Response parsing details
Development
Project Structure
src/geminpy/
├── browser/ # Browser automation components
│ ├── automation.py # OAuth flow automation
│ ├── chrome.py # Chrome for Testing management
│ └── manager.py # Default browser control
├── gemini/ # Gemini CLI integration
│ ├── client.py # Main orchestrator
│ ├── executor.py # Process management
│ └── parser.py # Response extraction
├── core/ # Core utilities
│ ├── config.py # Configuration
│ ├── constants.py # Constants
│ └── exceptions.py # Custom exceptions
├── utils/ # Utilities
│ ├── platform.py # Platform checks
│ └── storage.py # Settings persistence
├── api.py # Public API
└── cli.py # CLI interface
Running Tests
# Run all tests
uvx hatch run test
# Run with coverage
uvx hatch run test-cov
# Type checking
uvx hatch run type-check
# Linting
uvx hatch run lint
Building
# Build package
uvx hatch build
# Install locally
uv pip install --system -e .
Security
- No credential storage - Only stores email preference
- Local automation only - All OAuth happens on your machine
- Temporary browser access - Restored after each use
- Process isolation - Chrome runs in separate process
Requirements
- Platform: macOS (Darwin) only
- Python: 3.10, 3.11, or 3.12
- Browser: Chrome for Testing (auto-installed)
License
MIT License - see LICENSE file for details.
Release files for geminpy 1.4.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| geminpy-1.4.1.tar.gz | 25.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| geminpy-1.4.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 53.2 kB
Release files / geminpy-1.4.1.tar.gz
| Download URL | geminpy-1.4.1.tar.gz |
|---|---|
| Size | 25.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
45ef173d1fa2928a7ab89a8f6523802288dfb155ceee7e128db13f960ec992e7
|
|
BLAKE2b-256 checksum How to use checksums |
1013f46cc4fc0d9e64330d2fe6ac060f8af2f3f3e818d33de68ce7b496a57713
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
python-httpx/0.28.1
|
Release files / geminpy-1.4.1-py3-none-any.whl
| Download URL | geminpy-1.4.1-py3-none-any.whl |
|---|---|
| Size | 27.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
295c717dfb840294d5051984dcbbba8abede6a1058324ef81ca72bd9058ee429
|
|
BLAKE2b-256 checksum How to use checksums |
9107a65a3aaa2b38eed2f6cad3b133fdb139b5b733667c613901d3c790da4fca
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
python-httpx/0.28.1
|