mirror of
https://github.com/browser-use/browser-use
synced 2026-05-06 17:52:15 +02:00
Implements a fast, persistent browser automation CLI per CLI_SPEC.md: - Fast CLI layer using stdlib only (<50ms startup) - Session server with Unix socket IPC (TCP on Windows) - Browser modes: chromium, real, remote - Commands: open, click, type, input, scroll, back, screenshot, state, switch, close-tab, keys, select, eval, extract - Python execution with persistent namespace (Jupyter-like REPL) - Agent task execution (requires API key) - JSON output mode The CLI maintains browser sessions across commands, enabling complex multi-step workflows. Includes Claude skill description for AI-assisted browser automation. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
126 lines
4.0 KiB
Python
126 lines
4.0 KiB
Python
"""API key management for browser-use CLI."""
|
|
|
|
import json
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
|
|
class APIKeyRequired(Exception):
|
|
"""Raised when API key is required but not provided."""
|
|
|
|
pass
|
|
|
|
|
|
def get_config_path() -> Path:
|
|
"""Get browser-use config file path."""
|
|
if sys.platform == 'win32':
|
|
base = Path(os.environ.get('APPDATA', Path.home()))
|
|
else:
|
|
base = Path(os.environ.get('XDG_CONFIG_HOME', Path.home() / '.config'))
|
|
return base / 'browser-use' / 'config.json'
|
|
|
|
|
|
def require_api_key(feature: str = 'this feature') -> str:
|
|
"""Get API key or raise helpful error.
|
|
|
|
Checks in order:
|
|
1. BROWSER_USE_API_KEY environment variable
|
|
2. Config file (~/.config/browser-use/config.json)
|
|
3. Interactive prompt (if TTY)
|
|
4. Raises APIKeyRequired with helpful message
|
|
"""
|
|
# 1. Check environment
|
|
key = os.environ.get('BROWSER_USE_API_KEY')
|
|
if key:
|
|
return key
|
|
|
|
# 2. Check config file
|
|
config_path = get_config_path()
|
|
if config_path.exists():
|
|
try:
|
|
config = json.loads(config_path.read_text())
|
|
if key := config.get('api_key'):
|
|
return key
|
|
except Exception:
|
|
pass
|
|
|
|
# 3. Interactive prompt (if TTY)
|
|
if sys.stdin.isatty() and sys.stdout.isatty():
|
|
return prompt_for_api_key(feature)
|
|
|
|
# 4. Error with helpful message
|
|
raise APIKeyRequired(
|
|
f"""
|
|
╭─────────────────────────────────────────────────────────────╮
|
|
│ 🔑 Browser-Use API Key Required │
|
|
│ │
|
|
│ {feature} requires an API key. │
|
|
│ │
|
|
│ Get yours at: https://browser-use.com/dashboard │
|
|
│ │
|
|
│ Then set it via: │
|
|
│ export BROWSER_USE_API_KEY=your_key_here │
|
|
│ │
|
|
│ Or add to {config_path}: │
|
|
│ {{"api_key": "your_key_here"}} │
|
|
╰─────────────────────────────────────────────────────────────╯
|
|
"""
|
|
)
|
|
|
|
|
|
def prompt_for_api_key(feature: str) -> str:
|
|
"""Interactive prompt for API key."""
|
|
print(
|
|
f"""
|
|
╭─────────────────────────────────────────────────────────────╮
|
|
│ 🔑 Browser-Use API Key Required │
|
|
│ │
|
|
│ {feature} requires an API key. │
|
|
│ Get yours at: https://browser-use.com/dashboard │
|
|
╰─────────────────────────────────────────────────────────────╯
|
|
"""
|
|
)
|
|
|
|
try:
|
|
key = input('Enter API key: ').strip()
|
|
except (EOFError, KeyboardInterrupt):
|
|
raise APIKeyRequired('No API key provided')
|
|
|
|
if not key:
|
|
raise APIKeyRequired('No API key provided')
|
|
|
|
try:
|
|
save = input('Save to config? [y/N]: ').strip().lower()
|
|
if save == 'y':
|
|
save_api_key(key)
|
|
except (EOFError, KeyboardInterrupt):
|
|
pass
|
|
|
|
return key
|
|
|
|
|
|
def save_api_key(key: str) -> None:
|
|
"""Save API key to config file."""
|
|
config_path = get_config_path()
|
|
config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
|
|
config: dict = {}
|
|
if config_path.exists():
|
|
try:
|
|
config = json.loads(config_path.read_text())
|
|
except Exception:
|
|
pass
|
|
|
|
config['api_key'] = key
|
|
config_path.write_text(json.dumps(config, indent=2))
|
|
print(f'Saved to {config_path}')
|
|
|
|
|
|
def get_api_key() -> str | None:
|
|
"""Get API key if available, without raising error."""
|
|
try:
|
|
return require_api_key('API key check')
|
|
except APIKeyRequired:
|
|
return None
|