init commit
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
browser-cli — Control your running browser from the terminal.
|
||||
"""
|
||||
import click
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
import stat
|
||||
from pathlib import Path
|
||||
from rich.console import Console
|
||||
|
||||
from browser_cli.commands.navigate import cmd_open, cmd_reload, cmd_hard_reload, cmd_back, cmd_forward, cmd_focus
|
||||
from browser_cli.commands.tabs import tabs_group
|
||||
from browser_cli.commands.groups import group_group
|
||||
from browser_cli.commands.windows import windows_group
|
||||
from browser_cli.commands.dom import dom_group
|
||||
from browser_cli.commands.extract import extract_group
|
||||
from browser_cli.commands.session import session_group
|
||||
from browser_cli.client import send_command, BrowserNotConnected
|
||||
|
||||
console = Console()
|
||||
|
||||
NATIVE_HOST_NAME = "com.browsercli.host"
|
||||
|
||||
NATIVE_HOST_DIRS = {
|
||||
"chrome": {
|
||||
"linux": [Path.home() / ".config/google-chrome/NativeMessagingHosts"],
|
||||
"darwin": [Path.home() / "Library/Application Support/Google/Chrome/NativeMessagingHosts"],
|
||||
},
|
||||
"chromium": {
|
||||
"linux": [Path.home() / ".config/chromium/NativeMessagingHosts"],
|
||||
"darwin": [Path.home() / "Library/Application Support/Chromium/NativeMessagingHosts"],
|
||||
},
|
||||
"brave": {
|
||||
"linux": [Path.home() / ".config/BraveSoftware/Brave-Browser/NativeMessagingHosts"],
|
||||
"darwin": [Path.home() / "Library/Application Support/BraveSoftware/Brave-Browser/NativeMessagingHosts"],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@click.group()
|
||||
def main():
|
||||
"""Control your running browser from the terminal via a Chrome extension."""
|
||||
|
||||
|
||||
# ── Top-level navigation commands ─────────────────────────────────────────────
|
||||
main.add_command(cmd_open, name="open")
|
||||
main.add_command(cmd_reload, name="reload")
|
||||
main.add_command(cmd_hard_reload, name="hard-reload")
|
||||
main.add_command(cmd_back, name="back")
|
||||
main.add_command(cmd_forward, name="forward")
|
||||
main.add_command(cmd_focus, name="focus")
|
||||
|
||||
# ── Sub-command groups ─────────────────────────────────────────────────────────
|
||||
main.add_command(tabs_group)
|
||||
main.add_command(group_group)
|
||||
main.add_command(windows_group)
|
||||
main.add_command(dom_group)
|
||||
main.add_command(extract_group)
|
||||
main.add_command(session_group)
|
||||
|
||||
|
||||
# ── clients ────────────────────────────────────────────────────────────────────
|
||||
|
||||
@main.command("clients")
|
||||
def cmd_clients():
|
||||
"""Show connected browser clients."""
|
||||
try:
|
||||
clients = send_command("clients.list")
|
||||
except BrowserNotConnected as e:
|
||||
console.print(f"[red]Error:[/red] {e}")
|
||||
sys.exit(1)
|
||||
|
||||
from rich.table import Table
|
||||
table = Table(show_header=True, header_style="bold cyan")
|
||||
table.add_column("Browser")
|
||||
table.add_column("Version")
|
||||
table.add_column("Platform")
|
||||
for c in (clients or []):
|
||||
table.add_row(c.get("name", ""), c.get("version", ""), c.get("platform", ""))
|
||||
console.print(table)
|
||||
|
||||
|
||||
# ── install ────────────────────────────────────────────────────────────────────
|
||||
|
||||
@main.command("install")
|
||||
@click.argument("browser", type=click.Choice(["chrome", "chromium", "brave"]), default="chrome")
|
||||
def cmd_install(browser):
|
||||
"""Register the native messaging host and print extension load instructions."""
|
||||
|
||||
# Find the native_host.py path
|
||||
native_host_script = Path(__file__).parent / "native_host.py"
|
||||
if not native_host_script.exists():
|
||||
console.print(f"[red]Cannot find native_host.py at {native_host_script}[/red]")
|
||||
sys.exit(1)
|
||||
|
||||
# Build a wrapper shell script so it's executable by Chrome
|
||||
wrapper_path = Path(__file__).parent.parent / "browser-cli-native-host"
|
||||
python_exe = sys.executable
|
||||
wrapper_content = f"""#!/bin/sh
|
||||
exec "{python_exe}" "{native_host_script}" "$@"
|
||||
"""
|
||||
wrapper_path.write_text(wrapper_content)
|
||||
wrapper_path.chmod(wrapper_path.stat().st_mode | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH)
|
||||
|
||||
# Ask for extension ID
|
||||
ext_url = "brave://extensions" if browser == "brave" else "chrome://extensions"
|
||||
console.print("\n[bold]Step 1:[/bold] Load the extension in your browser")
|
||||
console.print(f" 1. Open [cyan]{ext_url}[/cyan]")
|
||||
console.print(" 2. Enable [bold]Developer mode[/bold] (top-right toggle)")
|
||||
console.print(f" 3. Click [bold]Load unpacked[/bold] → select: [cyan]{Path(__file__).parent.parent / 'extension'}[/cyan]")
|
||||
console.print(" 4. Copy the [bold]Extension ID[/bold] shown on the extension card\n")
|
||||
|
||||
extension_id = click.prompt("Paste your extension ID here")
|
||||
extension_id = extension_id.strip()
|
||||
|
||||
# Build native messaging manifest
|
||||
manifest = {
|
||||
"name": NATIVE_HOST_NAME,
|
||||
"description": "browser-cli native messaging host",
|
||||
"path": str(wrapper_path),
|
||||
"type": "stdio",
|
||||
"allowed_origins": [f"chrome-extension://{extension_id}/"],
|
||||
}
|
||||
|
||||
# Write to OS native messaging dirs
|
||||
platform = "darwin" if sys.platform == "darwin" else "linux"
|
||||
dirs = NATIVE_HOST_DIRS[browser][platform]
|
||||
|
||||
installed = []
|
||||
for d in dirs:
|
||||
try:
|
||||
d.mkdir(parents=True, exist_ok=True)
|
||||
manifest_path = d / f"{NATIVE_HOST_NAME}.json"
|
||||
manifest_path.write_text(json.dumps(manifest, indent=2))
|
||||
installed.append(manifest_path)
|
||||
except Exception as e:
|
||||
console.print(f"[yellow]Could not write to {d}: {e}[/yellow]")
|
||||
|
||||
if not installed:
|
||||
console.print("[red]Failed to install native host manifest[/red]")
|
||||
sys.exit(1)
|
||||
|
||||
for p in installed:
|
||||
console.print(f"[green]✓[/green] Wrote native host manifest: {p}")
|
||||
|
||||
console.print("\n[bold]Step 2:[/bold] Restart Chrome completely (Cmd/Ctrl+Q, then reopen)")
|
||||
console.print("\n[green bold]✓ Installation complete![/green bold]")
|
||||
console.print(" After restarting Chrome, try: [cyan]browser-cli tabs list[/cyan]")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user