diff --git a/browser_cli/cli.py b/browser_cli/cli.py index d865e1e..93426c4 100755 --- a/browser_cli/cli.py +++ b/browser_cli/cli.py @@ -181,6 +181,8 @@ def main(ctx, browser, remote, token): ctx.obj["browser_explicit"] = browser is not None if browser: os.environ["BROWSER_CLI_PROFILE"] = browser + ctx.obj["remote"] = remote + ctx.obj["token"] = token if remote: os.environ["BROWSER_CLI_REMOTE"] = remote if token: @@ -211,29 +213,41 @@ def clients_group(ctx): if ctx.invoked_subcommand is not None: return - profiles: dict[str, str] = {} - if REGISTRY_PATH.exists(): - try: - profiles = json.loads(REGISTRY_PATH.read_text()) - except Exception: - pass - all_clients = [] - for profile_name, sock_path in profiles.items(): - display_profile = display_browser_name(profile_name, sock_path) + + remote = (ctx.obj or {}).get("remote") or os.environ.get("BROWSER_CLI_REMOTE") + if remote: try: - result = send_command("clients.list", profile=profile_name) + result = send_command("clients.list", profile=(ctx.obj or {}).get("browser")) for c in (result or []): - c["profile"] = display_profile + c["profile"] = c.get("profile") or (ctx.obj or {}).get("browser") or "remote" all_clients.append(c) - except (BrowserNotConnected, RuntimeError): - # Socket registered but browser no longer connected - all_clients.append({ - "profile": display_profile, - "name": "—", - "version": "—", - "extensionVersion": "disconnected", - }) + except (BrowserNotConnected, RuntimeError) as e: + console.print(f"[red]Error:[/red] {e}") + sys.exit(1) + else: + profiles: dict[str, str] = {} + if REGISTRY_PATH.exists(): + try: + profiles = json.loads(REGISTRY_PATH.read_text()) + except Exception: + pass + + for profile_name, sock_path in profiles.items(): + display_profile = display_browser_name(profile_name, sock_path) + try: + result = send_command("clients.list", profile=profile_name) + for c in (result or []): + c["profile"] = display_profile + all_clients.append(c) + except (BrowserNotConnected, RuntimeError): + # Socket registered but browser no longer connected + all_clients.append({ + "profile": display_profile, + "name": "—", + "version": "—", + "extensionVersion": "disconnected", + }) if not all_clients: console.print("[yellow]No browser clients found. Start a browser with the extension enabled first.[/yellow]") diff --git a/extension/manifest.json b/extension/manifest.json index 523f29d..72b5ede 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "browser-cli", - "version": "0.7.1", + "version": "0.8.1", "description": "Control your browser from the terminal via browser-cli", "permissions": [ "tabs", diff --git a/pyproject.toml b/pyproject.toml index 168111f..bcd9744 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "browser-cli" -version = "0.8.0" +version = "0.8.1" description = "Control your real running browser from the terminal via a browser extension" requires-python = ">=3.10" dependencies = [ diff --git a/tests/test_cli.py b/tests/test_cli.py index a11a074..c472a5f 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,5 +1,6 @@ from pathlib import Path from types import SimpleNamespace +import os import sys from click.testing import CliRunner @@ -140,6 +141,32 @@ def test_clients_exits_cleanly_when_registry_is_missing(): assert result.exit_code == 1 assert "No browser clients found" in result.output +def test_clients_remote_uses_remote_endpoint_without_local_registry(): + def fake_send_command(command, args=None, profile=None): + assert command == "clients.list" + assert profile is None + return [{"name": "Chrome", "version": "1", "extensionVersion": "2.3.4"}] + + with patch.dict(os.environ, {}, clear=True), patch( + "browser_cli.cli.REGISTRY_PATH", Path("/nonexistent/browser-cli-registry.json") + ), patch("browser_cli.cli.send_command", side_effect=fake_send_command) as send_command: + result = CliRunner().invoke(main, ["--remote", "127.0.0.1:8765", "--token", "test", "clients"]) + + assert result.exit_code == 0 + send_command.assert_called_once() + assert "remote" in result.output + assert "Chrome" in result.output + assert "2.3.4" in result.output + + +def test_clients_remote_respects_global_browser_route(): + with patch.dict(os.environ, {}, clear=True), patch("browser_cli.cli.send_command", return_value=[]) as send_command: + result = CliRunner().invoke(main, ["--remote", "127.0.0.1:8765", "--browser", "work", "clients"]) + + assert result.exit_code == 1 + send_command.assert_called_once_with("clients.list", profile="work") + + def test_clients_shows_named_profile_and_uses_socket_uuid_for_default(tmp_path): registry_path = tmp_path / "registry.json" default_socket = tmp_path / "550e8400-e29b-41d4-a716-446655440000.sock" diff --git a/uv.lock b/uv.lock index 0cde72e..25322ed 100644 --- a/uv.lock +++ b/uv.lock @@ -4,7 +4,7 @@ requires-python = ">=3.10" [[package]] name = "browser-cli" -version = "0.8.0" +version = "0.8.1" source = { editable = "." } dependencies = [ { name = "click" },