real-browser-cli 0.14.2__tar.gz → 0.15.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- real_browser_cli-0.15.1/PKG-INFO +633 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/README.md +9 -8
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/cli.py +2 -1
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/commands/doctor.py +2 -2
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/commands/install.py +27 -11
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/constants.py +8 -1
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/version_manager.py +2 -2
- real_browser_cli-0.15.1/dist_w/.gitignore +1 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/AMO_BUILD_README.md +87 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/LICENSE +75 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/PRIVACY.md +23 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/README.md +540 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/__init__.py +164 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/async_sdk.py +237 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/auth.py +263 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/cli.py +152 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/client/__init__.py +47 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/client/auth.py +63 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/client/core.py +200 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/client/messages.py +45 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/client/targets.py +95 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/command_security.py +119 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/commands/__init__.py +81 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/commands/auth.py +157 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/commands/clients.py +173 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/commands/completion.py +56 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/commands/doctor.py +90 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/commands/dom.py +191 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/commands/events.py +52 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/commands/extension.py +42 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/commands/extract.py +70 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/commands/groups.py +108 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/commands/install.py +137 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/commands/navigate.py +96 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/commands/page.py +26 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/commands/perf.py +47 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/commands/raw.py +23 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/commands/remote.py +68 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/commands/script.py +68 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/commands/search.py +79 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/commands/serve.py +117 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/commands/serve_http.py +115 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/commands/session.py +163 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/commands/storage.py +36 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/commands/tabs.py +252 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/commands/watch.py +60 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/commands/windows.py +87 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/commands/workspace.py +91 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/compat/__init__.py +4 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/compat/auth.py +44 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/compat/commands.py +43 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/constants.py +102 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/endpoints.py +55 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/errors.py +9 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/framing.py +83 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/local_transport.py +64 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/markdown/__init__.py +8 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/markdown/html.py +259 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/markdown/render.py +188 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/models.py +182 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/native/__init__.py +1 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/native/host.py +211 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/native/local_server.py +111 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/native/protocol.py +30 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/platform.py +34 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/registry.py +99 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/remote/__init__.py +1 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/remote/registry.py +53 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/remote/transport.py +230 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/sdk/__init__.py +48 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/sdk/base.py +116 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/sdk/browser_data.py +37 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/sdk/decorators.py +107 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/sdk/dom.py +169 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/sdk/extension.py +24 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/sdk/factories.py +103 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/sdk/groups.py +51 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/sdk/navigation.py +122 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/sdk/perf.py +23 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/sdk/routing.py +149 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/sdk/session.py +72 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/sdk/tabs.py +213 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/sdk/windows.py +26 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/sdk/workflow_decorators.py +200 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/serve/__init__.py +0 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/serve/auth.py +107 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/serve/control.py +59 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/serve/logging.py +16 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/serve/proxy.py +79 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/serve/runtime.py +196 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/transport.py +214 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/browser_cli/version_manager.py +17 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/extension/background.js +1639 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/extension/content-dispatch.js +546 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/manifest.json +7 -1
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/commands/autosave.ts +3 -3
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/commands/dom.ts +4 -1
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/commands/groups.ts +11 -11
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/commands/navigation.ts +4 -4
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/commands/session-snapshot.ts +2 -2
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/commands/session.ts +3 -3
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/commands/tabs.ts +2 -2
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/core/group-helpers.ts +2 -1
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/core/index.ts +1 -0
- real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1/extension/src/core/tab-groups.ts +55 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/package.json +2 -1
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/pyproject.toml +8 -1
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/scripts/package_extension.py +21 -10
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/test_cli.py +26 -1
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/test_extension_error_page_handling.py +16 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/test_extension_packaging.py +21 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/uv.lock +40 -40
- real_browser_cli-0.15.1/dist_w/browser-cli-amo-source-v0.15.1.zip +0 -0
- real_browser_cli-0.15.1/dist_w/browser-cli-extension-firefox-v0.15.0.zip +0 -0
- real_browser_cli-0.15.1/dist_w/browser-cli-extension-firefox-v0.15.1.zip +0 -0
- real_browser_cli-0.15.1/dist_w/browser-cli-extension-testing-v0.15.1.zip +0 -0
- real_browser_cli-0.15.1/dist_w/browser-cli-extension-webstore-v0.15.1.zip +0 -0
- real_browser_cli-0.15.1/dist_w/extension-package-firefox/background.js +1639 -0
- real_browser_cli-0.15.1/dist_w/extension-package-firefox/content-dispatch.js +546 -0
- real_browser_cli-0.15.1/dist_w/extension-package-firefox/content.js +9 -0
- real_browser_cli-0.15.1/dist_w/extension-package-firefox/icon.svg +31 -0
- real_browser_cli-0.15.1/dist_w/extension-package-firefox/icons/icon-128.png +0 -0
- real_browser_cli-0.15.1/dist_w/extension-package-firefox/icons/icon-16.png +0 -0
- real_browser_cli-0.15.1/dist_w/extension-package-firefox/icons/icon-32.png +0 -0
- real_browser_cli-0.15.1/dist_w/extension-package-firefox/icons/icon-48.png +0 -0
- real_browser_cli-0.15.1/dist_w/extension-package-firefox/manifest.json +49 -0
- real_browser_cli-0.15.1/dist_w/extension-package-testing/background.js +1639 -0
- real_browser_cli-0.15.1/dist_w/extension-package-testing/content-dispatch.js +546 -0
- real_browser_cli-0.15.1/dist_w/extension-package-testing/content.js +9 -0
- real_browser_cli-0.15.1/dist_w/extension-package-testing/icon.svg +31 -0
- real_browser_cli-0.15.1/dist_w/extension-package-testing/icons/icon-128.png +0 -0
- real_browser_cli-0.15.1/dist_w/extension-package-testing/icons/icon-16.png +0 -0
- real_browser_cli-0.15.1/dist_w/extension-package-testing/icons/icon-32.png +0 -0
- real_browser_cli-0.15.1/dist_w/extension-package-testing/icons/icon-48.png +0 -0
- real_browser_cli-0.15.1/dist_w/extension-package-testing/manifest.json +41 -0
- real_browser_cli-0.15.1/dist_w/extension-package-webstore/background.js +1639 -0
- real_browser_cli-0.15.1/dist_w/extension-package-webstore/content-dispatch.js +546 -0
- real_browser_cli-0.15.1/dist_w/extension-package-webstore/content.js +9 -0
- real_browser_cli-0.15.1/dist_w/extension-package-webstore/icon.svg +31 -0
- real_browser_cli-0.15.1/dist_w/extension-package-webstore/icons/icon-128.png +0 -0
- real_browser_cli-0.15.1/dist_w/extension-package-webstore/icons/icon-16.png +0 -0
- real_browser_cli-0.15.1/dist_w/extension-package-webstore/icons/icon-32.png +0 -0
- real_browser_cli-0.15.1/dist_w/extension-package-webstore/icons/icon-48.png +0 -0
- real_browser_cli-0.15.1/dist_w/extension-package-webstore/manifest.json +40 -0
- real_browser_cli-0.15.1/dist_w/real_browser_cli-0.14.3-py3-none-any.whl +0 -0
- real_browser_cli-0.15.1/dist_w/real_browser_cli-0.14.3.tar.gz +0 -0
- real_browser_cli-0.15.1/dist_w/real_browser_cli-0.15.1-py3-none-any.whl +0 -0
- real_browser_cli-0.15.1/dist_w/real_browser_cli-0.15.1.tar.gz +0 -0
- real_browser_cli-0.15.1/examples/demo.py +109 -0
- real_browser_cli-0.15.1/examples/demo.sh +88 -0
- real_browser_cli-0.15.1/extension/content.js +9 -0
- real_browser_cli-0.15.1/extension/icon.svg +31 -0
- real_browser_cli-0.15.1/extension/icons/icon-128.png +0 -0
- real_browser_cli-0.15.1/extension/icons/icon-16.png +0 -0
- real_browser_cli-0.15.1/extension/icons/icon-32.png +0 -0
- real_browser_cli-0.15.1/extension/icons/icon-48.png +0 -0
- real_browser_cli-0.15.1/extension/manifest.json +41 -0
- real_browser_cli-0.15.1/extension/src/classes/CommandGroup.ts +21 -0
- real_browser_cli-0.15.1/extension/src/classes/CommandRegistry.ts +94 -0
- real_browser_cli-0.15.1/extension/src/classes/JobManager.ts +160 -0
- real_browser_cli-0.15.1/extension/src/classes/NativeConnection.ts +152 -0
- real_browser_cli-0.15.1/extension/src/commands/autosave.ts +84 -0
- real_browser_cli-0.15.1/extension/src/commands/browser-data.ts +49 -0
- real_browser_cli-0.15.1/extension/src/commands/dom.ts +182 -0
- real_browser_cli-0.15.1/extension/src/commands/extension.ts +43 -0
- real_browser_cli-0.15.1/extension/src/commands/groups.ts +114 -0
- real_browser_cli-0.15.1/extension/src/commands/injected.ts +4 -0
- real_browser_cli-0.15.1/extension/src/commands/navigation.ts +122 -0
- real_browser_cli-0.15.1/extension/src/commands/perf.ts +38 -0
- real_browser_cli-0.15.1/extension/src/commands/session-snapshot.ts +54 -0
- real_browser_cli-0.15.1/extension/src/commands/session.ts +177 -0
- real_browser_cli-0.15.1/extension/src/commands/tabs-query.ts +95 -0
- real_browser_cli-0.15.1/extension/src/commands/tabs.ts +176 -0
- real_browser_cli-0.15.1/extension/src/commands/windows.ts +45 -0
- real_browser_cli-0.15.1/extension/src/content/dispatch.ts +51 -0
- real_browser_cli-0.15.1/extension/src/content/dom-ops.ts +114 -0
- real_browser_cli-0.15.1/extension/src/content/extract.ts +45 -0
- real_browser_cli-0.15.1/extension/src/content/markdown.ts +404 -0
- real_browser_cli-0.15.1/extension/src/content/page-info.ts +14 -0
- real_browser_cli-0.15.1/extension/src/content-dispatch.ts +7 -0
- real_browser_cli-0.15.1/extension/src/core/errors.ts +35 -0
- real_browser_cli-0.15.1/extension/src/core/group-helpers.ts +16 -0
- real_browser_cli-0.15.1/extension/src/core/index.ts +7 -0
- real_browser_cli-0.15.1/extension/src/core/scripting.ts +23 -0
- real_browser_cli-0.15.1/extension/src/core/storage.ts +30 -0
- real_browser_cli-0.15.1/extension/src/core/tab-groups.ts +55 -0
- real_browser_cli-0.15.1/extension/src/core/tab-helpers.ts +123 -0
- real_browser_cli-0.15.1/extension/src/core/throttle.ts +117 -0
- real_browser_cli-0.15.1/extension/src/index.ts +23 -0
- real_browser_cli-0.15.1/extension/src/types/command-args.ts +95 -0
- real_browser_cli-0.15.1/extension/src/types/index.ts +6 -0
- real_browser_cli-0.15.1/extension/src/types/jobs.ts +28 -0
- real_browser_cli-0.15.1/extension/src/types/json.ts +23 -0
- real_browser_cli-0.15.1/extension/src/types/messages.ts +27 -0
- real_browser_cli-0.15.1/extension/src/types/session.ts +21 -0
- real_browser_cli-0.15.1/extension/src/types/tabs.ts +6 -0
- real_browser_cli-0.15.1/extension/test/autosave.test.ts +127 -0
- real_browser_cli-0.15.1/extension/test/chrome-mock.ts +55 -0
- real_browser_cli-0.15.1/extension/test/jobs.test.ts +146 -0
- real_browser_cli-0.15.1/justfile +81 -0
- real_browser_cli-0.15.1/package-lock.json +548 -0
- real_browser_cli-0.15.1/package.json +19 -0
- real_browser_cli-0.15.1/pyproject.toml +44 -0
- real_browser_cli-0.15.1/scripts/gen_extension_key.py +74 -0
- real_browser_cli-0.15.1/scripts/package_extension.py +89 -0
- real_browser_cli-0.15.1/shell.nix +20 -0
- real_browser_cli-0.15.1/tests/conftest.py +52 -0
- real_browser_cli-0.15.1/tests/test_api.py +1212 -0
- real_browser_cli-0.15.1/tests/test_auth.py +199 -0
- real_browser_cli-0.15.1/tests/test_cli.py +714 -0
- real_browser_cli-0.15.1/tests/test_client.py +557 -0
- real_browser_cli-0.15.1/tests/test_commands_cli.py +946 -0
- real_browser_cli-0.15.1/tests/test_dom.py +267 -0
- real_browser_cli-0.15.1/tests/test_extension_error_page_handling.py +208 -0
- real_browser_cli-0.15.1/tests/test_extension_packaging.py +78 -0
- real_browser_cli-0.15.1/tests/test_extract.py +58 -0
- real_browser_cli-0.15.1/tests/test_framing.py +59 -0
- real_browser_cli-0.15.1/tests/test_groups.py +190 -0
- real_browser_cli-0.15.1/tests/test_native_host.py +420 -0
- real_browser_cli-0.15.1/tests/test_nav.py +102 -0
- real_browser_cli-0.15.1/tests/test_new_feature_commands.py +105 -0
- real_browser_cli-0.15.1/tests/test_page.py +39 -0
- real_browser_cli-0.15.1/tests/test_perf.py +72 -0
- real_browser_cli-0.15.1/tests/test_performance_integration.py +157 -0
- real_browser_cli-0.15.1/tests/test_platform.py +30 -0
- real_browser_cli-0.15.1/tests/test_refactor_boundaries.py +123 -0
- real_browser_cli-0.15.1/tests/test_registry.py +30 -0
- real_browser_cli-0.15.1/tests/test_remote_protocol_matrix.py +213 -0
- real_browser_cli-0.15.1/tests/test_serve.py +530 -0
- real_browser_cli-0.15.1/tests/test_session.py +112 -0
- real_browser_cli-0.15.1/tests/test_storage.py +54 -0
- real_browser_cli-0.15.1/tests/test_tabs.py +158 -0
- real_browser_cli-0.15.1/tests/test_transport.py +117 -0
- real_browser_cli-0.15.1/tests/test_windows.py +59 -0
- real_browser_cli-0.15.1/tsconfig.json +15 -0
- real_browser_cli-0.15.1/uv.lock +670 -0
- real_browser_cli-0.14.2/PKG-INFO +0 -87
- real_browser_cli-0.14.2/webstore-assets/icon-128.png +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/.claude/settings.local.json +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/.gitea/workflows/package-extension.yml +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/.gitea/workflows/publish.yml +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/.gitea/workflows/testing.yml +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/.gitignore +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/.python-version +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/CLAUDE.md +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/LICENSE +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/PRIVACY.md +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/__init__.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/async_sdk.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/auth.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/client/__init__.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/client/auth.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/client/core.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/client/messages.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/client/targets.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/command_security.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/commands/__init__.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/commands/auth.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/commands/clients.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/commands/completion.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/commands/dom.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/commands/events.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/commands/extension.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/commands/extract.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/commands/groups.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/commands/navigate.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/commands/page.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/commands/perf.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/commands/raw.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/commands/remote.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/commands/script.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/commands/search.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/commands/serve.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/commands/serve_http.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/commands/session.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/commands/storage.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/commands/tabs.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/commands/watch.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/commands/windows.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/commands/workspace.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/compat/__init__.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/compat/auth.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/compat/commands.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/endpoints.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/errors.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/framing.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/local_transport.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/markdown/__init__.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/markdown/html.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/markdown/render.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/models.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/native/__init__.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/native/host.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/native/local_server.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/native/protocol.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/platform.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/registry.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/remote/__init__.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/remote/registry.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/remote/transport.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/sdk/__init__.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/sdk/base.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/sdk/browser_data.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/sdk/decorators.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/sdk/dom.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/sdk/extension.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/sdk/factories.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/sdk/groups.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/sdk/navigation.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/sdk/perf.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/sdk/routing.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/sdk/session.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/sdk/tabs.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/sdk/windows.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/sdk/workflow_decorators.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/serve/__init__.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/serve/auth.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/serve/control.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/serve/logging.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/serve/proxy.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/serve/runtime.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/browser_cli/transport.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/examples/demo.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/examples/demo.sh +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/content.js +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/icon.svg +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/icons/icon-128.png +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/icons/icon-16.png +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/icons/icon-32.png +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/icons/icon-48.png +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/classes/CommandGroup.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/classes/CommandRegistry.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/classes/JobManager.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/classes/NativeConnection.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/commands/browser-data.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/commands/extension.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/commands/injected.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/commands/perf.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/commands/tabs-query.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/commands/windows.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/content/dispatch.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/content/dom-ops.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/content/extract.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/content/markdown.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/content/page-info.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/content-dispatch.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/core/errors.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/core/scripting.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/core/storage.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/core/tab-helpers.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/core/throttle.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/index.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/types/command-args.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/types/index.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/types/jobs.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/types/json.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/types/messages.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/types/session.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/src/types/tabs.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/test/autosave.test.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/test/chrome-mock.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/extension/test/jobs.test.ts +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/justfile +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/package-lock.json +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/scripts/gen_extension_key.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/shell.nix +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/conftest.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/test_api.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/test_auth.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/test_client.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/test_commands_cli.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/test_dom.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/test_extract.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/test_framing.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/test_groups.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/test_native_host.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/test_nav.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/test_new_feature_commands.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/test_page.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/test_perf.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/test_performance_integration.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/test_platform.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/test_refactor_boundaries.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/test_registry.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/test_remote_protocol_matrix.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/test_serve.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/test_session.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/test_storage.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/test_tabs.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/test_transport.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tests/test_windows.py +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1/dist_w/amo-source-browser-cli-v0.15.1}/tsconfig.json +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/webstore-assets/screenshots/screenshot-1.png +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/webstore-assets/screenshots/screenshot-2.png +0 -0
- {real_browser_cli-0.14.2 → real_browser_cli-0.15.1}/webstore-assets/screenshots/screenshot-3.png +0 -0
|
@@ -0,0 +1,633 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: real-browser-cli
|
|
3
|
+
Version: 0.15.1
|
|
4
|
+
Summary: Control your real running browser from the terminal or Python SDK
|
|
5
|
+
Project-URL: Homepage, https://git.yiprawr.dev/Automatisation/browser-cli
|
|
6
|
+
Project-URL: Repository, https://git.yiprawr.dev/Automatisation/browser-cli
|
|
7
|
+
Project-URL: Issues, https://git.yiprawr.dev/Automatisation/browser-cli/issues
|
|
8
|
+
Author: Daniel Dolezal
|
|
9
|
+
License: # PolyForm Noncommercial License 1.0.0
|
|
10
|
+
|
|
11
|
+
Required Notice: Copyright (c) 2026 Daniel Dolezal
|
|
12
|
+
|
|
13
|
+
## Acceptance
|
|
14
|
+
|
|
15
|
+
In order to get any license under these terms, you must agree to them as both strict obligations and conditions to all your licenses.
|
|
16
|
+
|
|
17
|
+
## Copyright License
|
|
18
|
+
|
|
19
|
+
The licensor grants you a copyright license for the software to do everything you might do with the software that would otherwise infringe the licensor's copyright in it for any permitted purpose. However, you may only distribute the software according to [Distribution License](#distribution-license) and make changes or new works based on the software according to [Changes and New Works License](#changes-and-new-works-license).
|
|
20
|
+
|
|
21
|
+
## Distribution License
|
|
22
|
+
|
|
23
|
+
The licensor grants you an additional copyright license to distribute copies of the software. Your license to distribute covers distributing the software with changes and new works permitted by [Changes and New Works License](#changes-and-new-works-license).
|
|
24
|
+
|
|
25
|
+
## Notices
|
|
26
|
+
|
|
27
|
+
You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms or the URL for them above, as well as copies of any plain-text lines beginning with `Required Notice:` that the licensor provided with the software. For example:
|
|
28
|
+
|
|
29
|
+
> Required Notice: Copyright Yoyodyne, Inc. (http://example.com)
|
|
30
|
+
|
|
31
|
+
## Changes and New Works License
|
|
32
|
+
|
|
33
|
+
The licensor grants you an additional copyright license to make changes and new works based on the software for any permitted purpose.
|
|
34
|
+
|
|
35
|
+
## Patent License
|
|
36
|
+
|
|
37
|
+
The licensor grants you a patent license for the software that covers patent claims the licensor can license, or becomes able to license, that you would infringe by using the software.
|
|
38
|
+
|
|
39
|
+
## Noncommercial Purposes
|
|
40
|
+
|
|
41
|
+
Any noncommercial purpose is a permitted purpose.
|
|
42
|
+
|
|
43
|
+
## Personal Uses
|
|
44
|
+
|
|
45
|
+
Personal use for research, experiment, and testing for the benefit of public knowledge, personal study, private entertainment, hobby projects, amateur pursuits, or religious observance, without any anticipated commercial application, is use for a permitted purpose.
|
|
46
|
+
|
|
47
|
+
## Noncommercial Organizations
|
|
48
|
+
|
|
49
|
+
Use by any charitable organization, educational institution, public research organization, public safety or health organization, environmental protection organization, or government institution is use for a permitted purpose regardless of the source of funding or obligations resulting from the funding.
|
|
50
|
+
|
|
51
|
+
## Fair Use
|
|
52
|
+
|
|
53
|
+
You may have "fair use" rights for the software under the law. These terms do not limit them.
|
|
54
|
+
|
|
55
|
+
## No Other Rights
|
|
56
|
+
|
|
57
|
+
These terms do not allow you to sublicense or transfer any of your licenses to anyone else, or prevent the licensor from granting licenses to anyone else. These terms do not imply any other licenses.
|
|
58
|
+
|
|
59
|
+
## Patent Defense
|
|
60
|
+
|
|
61
|
+
If you make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.
|
|
62
|
+
|
|
63
|
+
## Violations
|
|
64
|
+
|
|
65
|
+
The first time you are notified in writing that you have violated any of these terms, or done anything with the software not covered by your licenses, your licenses can nonetheless continue if you come into full compliance with these terms, and take practical steps to correct past violations, within 32 days of receiving notice. Otherwise, all your licenses end immediately.
|
|
66
|
+
|
|
67
|
+
## No Liability
|
|
68
|
+
|
|
69
|
+
***As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.***
|
|
70
|
+
|
|
71
|
+
## Definitions
|
|
72
|
+
|
|
73
|
+
The **licensor** is the individual or entity offering these terms, and the **software** is the software the licensor makes available under these terms.
|
|
74
|
+
|
|
75
|
+
**You** refers to the individual or entity agreeing to these terms.
|
|
76
|
+
|
|
77
|
+
**Your company** is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization.
|
|
78
|
+
|
|
79
|
+
**Control** means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.
|
|
80
|
+
|
|
81
|
+
**Your licenses** are all the licenses granted to you for the software under these terms.
|
|
82
|
+
|
|
83
|
+
**Use** means anything you do with the software requiring one of your licenses.
|
|
84
|
+
License-File: LICENSE
|
|
85
|
+
Requires-Python: >=3.10
|
|
86
|
+
Requires-Dist: click>=8
|
|
87
|
+
Requires-Dist: cryptography>=48
|
|
88
|
+
Requires-Dist: msgpack>=1
|
|
89
|
+
Requires-Dist: rich>=13
|
|
90
|
+
Provides-Extra: fast
|
|
91
|
+
Requires-Dist: zstandard>=0.22; extra == 'fast'
|
|
92
|
+
Description-Content-Type: text/markdown
|
|
93
|
+
|
|
94
|
+
# browser-cli
|
|
95
|
+
Control your real, running browser from the terminal or the Python SDK — no headless browser, no Playwright, no virtual display. Your actual open tabs, windows, and tab groups respond to your commands.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## What it does
|
|
100
|
+
You have 40 tabs open. You want to close all the duplicates, group the GitHub ones, save your session before a meeting, and open a few URLs into a specific group — all from a script. That is what browser-cli is for.
|
|
101
|
+
|
|
102
|
+
It works by pairing a small browser extension with a Python package that provides both a CLI and SDK. The extension has full access to your browser's tabs, windows, groups, and page DOM. The CLI and SDK talk to it in real time over a local IPC channel.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## How it works
|
|
107
|
+
```
|
|
108
|
+
terminal / python script
|
|
109
|
+
│
|
|
110
|
+
│ Local IPC (Unix socket on Linux/macOS, named pipe on Windows)
|
|
111
|
+
▼
|
|
112
|
+
Native Messaging Host (Python process, launched by the browser)
|
|
113
|
+
│
|
|
114
|
+
│ Native Messaging Protocol (stdin/stdout, 4-byte length prefix + JSON)
|
|
115
|
+
▼
|
|
116
|
+
Browser Extension (background worker/page)
|
|
117
|
+
│
|
|
118
|
+
│ extension APIs
|
|
119
|
+
▼
|
|
120
|
+
Your running browser
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
1. The extension calls `chrome.runtime.connectNative('com.browsercli.host')` on startup.
|
|
124
|
+
2. The browser launches the native host Python process (registered in the OS).
|
|
125
|
+
3. The native host opens a local IPC endpoint for the CLI.
|
|
126
|
+
4. CLI commands connect to that socket, send a JSON command, and wait for the result.
|
|
127
|
+
5. The native host relays the command to the extension via stdout, receives the result via stdin, and sends it back to the CLI.
|
|
128
|
+
|
|
129
|
+
No server needs to be running beforehand. The browser manages the native host's lifecycle.
|
|
130
|
+
|
|
131
|
+
**Message format**
|
|
132
|
+
|
|
133
|
+
Every command is a JSON object:
|
|
134
|
+
```json
|
|
135
|
+
{ "id": "uuid", "command": "tabs.list", "args": {} }
|
|
136
|
+
```
|
|
137
|
+
Every response:
|
|
138
|
+
```json
|
|
139
|
+
{ "id": "uuid", "success": true, "data": [...] }
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Installation
|
|
145
|
+
|
|
146
|
+
**Requirements:** Python 3.10+, [uv](https://github.com/astral-sh/uv), Chrome, Chromium, Brave, Edge, Vivaldi, or Firefox
|
|
147
|
+
|
|
148
|
+
### Install with uv
|
|
149
|
+
Once published on PyPI, install the CLI as a uv tool:
|
|
150
|
+
|
|
151
|
+
```sh
|
|
152
|
+
uv tool install real-browser-cli
|
|
153
|
+
browser-cli --version
|
|
154
|
+
browser-cli install brave # or: chrome, chromium, edge, vivaldi, firefox
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
The PyPI package is named `real-browser-cli`; the installed command is still `browser-cli`.
|
|
158
|
+
|
|
159
|
+
For better remote-response compression, install the optional `fast` extra:
|
|
160
|
+
|
|
161
|
+
```sh
|
|
162
|
+
uv tool install "real-browser-cli[fast]"
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
To upgrade later:
|
|
166
|
+
|
|
167
|
+
```sh
|
|
168
|
+
uv tool upgrade real-browser-cli
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Install from source
|
|
172
|
+
```sh
|
|
173
|
+
git clone <repo>
|
|
174
|
+
cd browser-cli
|
|
175
|
+
uv sync
|
|
176
|
+
uv run browser-cli install brave # or: chrome, chromium, edge, vivaldi, firefox
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
The `install` command will:
|
|
180
|
+
1. Ask you to load the browser-specific extension package
|
|
181
|
+
2. Show the stable extension ID used by that browser family
|
|
182
|
+
3. Write the native messaging manifest to your OS so the browser can find the host
|
|
183
|
+
4. Copy the native host into an internal `libexec` directory and create a small wrapper outside your `PATH`
|
|
184
|
+
|
|
185
|
+
After install, **fully restart your browser** (Quit and reopen — not just close the window). The extension will connect to the native host automatically on startup.
|
|
186
|
+
|
|
187
|
+
Only the `browser-cli` command needs to be on your `PATH`. The browser launches the native host wrapper directly from its absolute path in the native messaging manifest, and that wrapper imports the installed `browser_cli.native.host` entry point. On Windows the install command also registers the host in the current user's Registry for the selected browser.
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Project structure
|
|
192
|
+
|
|
193
|
+
```text
|
|
194
|
+
browser-cli/
|
|
195
|
+
├── browser_cli/
|
|
196
|
+
│ ├── __init__.py # Python SDK — BrowserCLI class and SDK entry point
|
|
197
|
+
│ ├── cli.py # Click CLI entry point
|
|
198
|
+
│ ├── client/ # Client-side command routing used by CLI and SDK
|
|
199
|
+
│ │ ├── core.py # send_command and remote command routing
|
|
200
|
+
│ │ ├── targets.py # Browser target discovery and socket resolution
|
|
201
|
+
│ │ ├── auth.py # Remote auth fields and key lookup
|
|
202
|
+
│ │ └── messages.py # Request/response helpers
|
|
203
|
+
│ ├── models.py # Tab and Group helper models
|
|
204
|
+
│ ├── native/ # Native messaging host internals
|
|
205
|
+
│ │ ├── host.py # Browser-launched native host entry point
|
|
206
|
+
│ │ ├── local_server.py # Local CLI IPC server
|
|
207
|
+
│ │ └── protocol.py # Chrome Native Messaging framing
|
|
208
|
+
│ ├── remote/ # Client-side remote browser support
|
|
209
|
+
│ │ ├── transport.py # TCP/TLS remote transport
|
|
210
|
+
│ │ └── registry.py # Saved remote endpoints/keys
|
|
211
|
+
│ └── commands/
|
|
212
|
+
│ ├── navigate.py # nav open/reload/back/forward/focus
|
|
213
|
+
│ ├── search.py # search engine shortcuts
|
|
214
|
+
│ ├── tabs.py # tab management
|
|
215
|
+
│ ├── groups.py # tab group management
|
|
216
|
+
│ ├── windows.py # window management
|
|
217
|
+
│ ├── dom.py # DOM querying and interaction
|
|
218
|
+
│ ├── extract.py # content extraction
|
|
219
|
+
│ └── session.py # session save/load
|
|
220
|
+
├── extension/
|
|
221
|
+
│ ├── manifest.json # MV3 extension manifest
|
|
222
|
+
│ ├── content.js # Content-script helpers
|
|
223
|
+
│ └── src/ # TypeScript source split by command area
|
|
224
|
+
│ ├── index.ts # Builds generated extension/background.js
|
|
225
|
+
│ └── content/ # Builds generated extension/content-dispatch.js
|
|
226
|
+
├── examples/
|
|
227
|
+
│ ├── demo.py # Python SDK walkthrough
|
|
228
|
+
│ └── demo.sh # Bash CLI walkthrough
|
|
229
|
+
├── tests/
|
|
230
|
+
│ ├── conftest.py # shared pytest fixtures
|
|
231
|
+
│ ├── test_api.py
|
|
232
|
+
│ ├── test_cli.py
|
|
233
|
+
│ ├── test_dom.py
|
|
234
|
+
│ ├── test_extract.py
|
|
235
|
+
│ ├── test_groups.py
|
|
236
|
+
│ ├── test_nav.py
|
|
237
|
+
│ ├── test_session.py
|
|
238
|
+
│ ├── test_tabs.py
|
|
239
|
+
│ └── test_windows.py
|
|
240
|
+
├── com.browsercli.host.json # native messaging manifest template
|
|
241
|
+
├── pyproject.toml # package metadata and CLI entry point
|
|
242
|
+
└── uv.lock # locked dependencies for uv
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## CLI reference
|
|
248
|
+
|
|
249
|
+
All commands are run with `uv run browser-cli [--browser ALIAS] <command>`.
|
|
250
|
+
|
|
251
|
+
If exactly one browser instance is connected, commands auto-target it. Use `--browser ALIAS` when multiple browser instances are connected. `tabs list`, `tabs count`, `groups list`, `groups count`, `windows list`, and `session list` aggregate across all active browsers when `--browser` is omitted; in that mode they show the source browser alias or UUID. You can inspect the active instances with `browser-cli clients` and assign a persistent profile alias from inside the target browser with `browser-cli clients rename --browser <current-alias> <new-alias>`. Closed browsers are removed from the client registry automatically.
|
|
252
|
+
|
|
253
|
+
Important: profile aliases are browser-instance aliases, not window aliases. Window aliases created with `windows rename` are only for targeting windows in commands like `nav open --window work`. If a browser instance has no explicit profile alias set, the native host gives it a generated UUID alias so multiple unaliased browsers stay distinct.
|
|
254
|
+
|
|
255
|
+
### Navigation (`nav`)
|
|
256
|
+
|
|
257
|
+
```sh
|
|
258
|
+
# Open a URL (no focus stealing by default)
|
|
259
|
+
browser-cli nav open https://example.com
|
|
260
|
+
browser-cli nav open https://example.com --focus # bring opened tab/window forward
|
|
261
|
+
browser-cli nav open https://example.com --window work # into a named window
|
|
262
|
+
browser-cli nav open https://example.com --group research # into a tab group (name or ID)
|
|
263
|
+
|
|
264
|
+
# Reload
|
|
265
|
+
browser-cli nav reload # reload active tab
|
|
266
|
+
browser-cli nav reload 1234 # reload tab by ID
|
|
267
|
+
browser-cli nav hard-reload # bypass cache
|
|
268
|
+
|
|
269
|
+
# Navigate history
|
|
270
|
+
browser-cli nav back
|
|
271
|
+
browser-cli nav forward 1234 # forward in specific tab
|
|
272
|
+
|
|
273
|
+
# Jump to a tab by URL pattern
|
|
274
|
+
browser-cli nav focus github # focuses first tab whose URL contains "github"
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Search
|
|
278
|
+
|
|
279
|
+
Each search command opens the search results in your browser using the same flags as `nav open`.
|
|
280
|
+
|
|
281
|
+
```sh
|
|
282
|
+
browser-cli search google openai api
|
|
283
|
+
browser-cli search brave rust iterators
|
|
284
|
+
browser-cli search ddg tab groups --window work
|
|
285
|
+
browser-cli search youtube browser automation
|
|
286
|
+
browser-cli search yt lo fi
|
|
287
|
+
browser-cli search spotify aphex twin
|
|
288
|
+
browser-cli search amazon mechanical keyboard
|
|
289
|
+
browser-cli search ecosia native messaging
|
|
290
|
+
browser-cli search furaffinity dragons
|
|
291
|
+
browser-cli search fa dragons
|
|
292
|
+
browser-cli search bing browser cli
|
|
293
|
+
browser-cli search github browser-cli
|
|
294
|
+
browser-cli search wikipedia native messaging
|
|
295
|
+
browser-cli search wiki native messaging
|
|
296
|
+
browser-cli search reddit chrome extensions
|
|
297
|
+
browser-cli search stackoverflow click choices
|
|
298
|
+
browser-cli search so click choices
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Tabs
|
|
302
|
+
|
|
303
|
+
```sh
|
|
304
|
+
browser-cli tabs list # list all open tabs (all windows)
|
|
305
|
+
browser-cli tabs count # count all tabs
|
|
306
|
+
browser-cli tabs count youtube # count tabs matching URL pattern
|
|
307
|
+
browser-cli tabs filter youtube # list tabs matching URL pattern
|
|
308
|
+
browser-cli tabs query "pull request" # search tabs by URL or title
|
|
309
|
+
|
|
310
|
+
browser-cli tabs active 1234 # switch browser focus to tab
|
|
311
|
+
browser-cli tabs html # print full HTML of active tab
|
|
312
|
+
browser-cli tabs html 1234 # print HTML of specific tab
|
|
313
|
+
|
|
314
|
+
browser-cli tabs close 1234 # close specific tab
|
|
315
|
+
browser-cli tabs close --inactive # close all inactive tabs
|
|
316
|
+
browser-cli tabs close --duplicates # close duplicate URLs (keep first)
|
|
317
|
+
browser-cli tabs dedupe # same as close --duplicates
|
|
318
|
+
|
|
319
|
+
browser-cli tabs move 1234 --window 2 # move tab to another window
|
|
320
|
+
browser-cli tabs move 1234 --group 42 # move tab into a group
|
|
321
|
+
|
|
322
|
+
browser-cli tabs sort --by domain # sort tabs within each window
|
|
323
|
+
browser-cli tabs sort --by title
|
|
324
|
+
browser-cli tabs sort --by time
|
|
325
|
+
|
|
326
|
+
browser-cli tabs merge-windows # pull all tabs into the current window
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### Tab groups
|
|
330
|
+
|
|
331
|
+
```sh
|
|
332
|
+
browser-cli groups list # list all tab groups
|
|
333
|
+
browser-cli groups count # count groups
|
|
334
|
+
browser-cli groups query "work" # search groups by name
|
|
335
|
+
browser-cli groups tabs 42 # list tabs inside group ID 42
|
|
336
|
+
|
|
337
|
+
browser-cli groups create "research" # create a new group
|
|
338
|
+
browser-cli groups add-tab research # open a blank tab in the group
|
|
339
|
+
browser-cli groups add-tab research https://example.com # open URL in the group
|
|
340
|
+
browser-cli groups add-tab 42 https://example.com # by group ID
|
|
341
|
+
|
|
342
|
+
browser-cli groups close 42 # ungroup the group
|
|
343
|
+
browser-cli groups move research --forward # move group right
|
|
344
|
+
browser-cli groups move research --right # same as --forward
|
|
345
|
+
browser-cli groups move research -r # short right alias
|
|
346
|
+
browser-cli groups move 42 --backward # move group left
|
|
347
|
+
browser-cli groups move 42 --left # same as --backward
|
|
348
|
+
browser-cli groups move 42 -l # short left alias
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### Windows
|
|
352
|
+
|
|
353
|
+
```sh
|
|
354
|
+
browser-cli windows list # list all windows
|
|
355
|
+
browser-cli windows open # open a new window
|
|
356
|
+
browser-cli windows open https://example.com # open a new window on a URL
|
|
357
|
+
browser-cli windows rename 1 "work" # give a window a local alias
|
|
358
|
+
browser-cli windows close 1 # close a window
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### DOM
|
|
362
|
+
|
|
363
|
+
These commands run on the **active tab**. The tab must be on a regular `http://` or `https://` page — not a browser internal page like `brave://newtab`.
|
|
364
|
+
|
|
365
|
+
```sh
|
|
366
|
+
browser-cli dom query "h1" # return elements matching CSS selector
|
|
367
|
+
browser-cli dom text "h1" # get text content of matching elements
|
|
368
|
+
browser-cli dom attr "a" href # get attribute value from elements
|
|
369
|
+
browser-cli dom exists ".modal-banner" # exits 0 if found, 1 if not
|
|
370
|
+
browser-cli dom click ".accept-button" # click an element
|
|
371
|
+
browser-cli dom type "#search" "hello" # type text into an input
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### Extract
|
|
375
|
+
|
|
376
|
+
```sh
|
|
377
|
+
browser-cli extract links # all <a href> links on the page
|
|
378
|
+
browser-cli extract images # all <img> tags (src + alt)
|
|
379
|
+
browser-cli extract text # all visible text (innerText)
|
|
380
|
+
browser-cli extract json "#data" # parse JSON inside a CSS selector
|
|
381
|
+
browser-cli extract html # full HTML of the active tab
|
|
382
|
+
browser-cli extract markdown # main page content as Markdown
|
|
383
|
+
browser-cli extract markdown --selector "article" # specific DOM subtree as Markdown
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### Sessions
|
|
387
|
+
|
|
388
|
+
A session is a snapshot of all open tab URLs, stored inside the extension via `chrome.storage.local`. Sessions survive browser restarts but are lost if the extension is uninstalled or extension data is cleared.
|
|
389
|
+
|
|
390
|
+
```sh
|
|
391
|
+
browser-cli session save before-meeting # save current tabs as a named session
|
|
392
|
+
browser-cli session load before-meeting # reopen all saved tabs
|
|
393
|
+
browser-cli session list # list all saved sessions (name, tab count, date)
|
|
394
|
+
browser-cli session remove before-meeting # delete a saved session
|
|
395
|
+
browser-cli session diff session-a session-b # show which URLs were added / removed
|
|
396
|
+
browser-cli session auto-save on # auto-save after every tab change
|
|
397
|
+
browser-cli session auto-save off
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### Misc
|
|
401
|
+
|
|
402
|
+
```sh
|
|
403
|
+
browser-cli clients # show connected browser info from the registry
|
|
404
|
+
browser-cli clients rename --browser abcd1234 work # rename one connected browser instance
|
|
405
|
+
browser-cli --browser abcd1234 clients rename work # equivalent global form
|
|
406
|
+
browser-cli install brave # (re)register the native host
|
|
407
|
+
browser-cli completion zsh # print setup instructions
|
|
408
|
+
browser-cli completion zsh --script # output raw completion script
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
|
|
413
|
+
## Python SDK
|
|
414
|
+
|
|
415
|
+
```python
|
|
416
|
+
from browser_cli import AsyncBrowserCLI, BrowserCLI
|
|
417
|
+
|
|
418
|
+
b = BrowserCLI()
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
Commands are grouped into namespaces on the client (`b.tabs`, `b.dom`, `b.session`, ...). Each sync call blocks until the browser responds and returns the data directly as a Python object. For asyncio programs, `AsyncBrowserCLI` exposes the same namespaces as native awaitable methods over async Unix/TCP transport.
|
|
422
|
+
|
|
423
|
+
```python
|
|
424
|
+
# Navigation ── b.nav
|
|
425
|
+
b.nav.open("https://example.com")
|
|
426
|
+
b.nav.open("https://example.com", background=True)
|
|
427
|
+
b.nav.open("https://example.com", window="work")
|
|
428
|
+
b.nav.reload()
|
|
429
|
+
b.nav.hard_reload()
|
|
430
|
+
b.nav.back()
|
|
431
|
+
b.nav.forward(tab_id=1234)
|
|
432
|
+
b.nav.focus("github")
|
|
433
|
+
b.nav.to(1234, "https://example.com") # navigate a specific tab in place
|
|
434
|
+
b.nav.search("google", "python asyncio")
|
|
435
|
+
|
|
436
|
+
# Tabs ── b.tabs
|
|
437
|
+
tabs = b.tabs.list() # list[Tab]; in multi-browser mode each tab.browser is set
|
|
438
|
+
tab = b.tabs.open("https://example.com") # returns a bound Tab object
|
|
439
|
+
tab = b.tabs.open("https://example.com", wait=True, timeout=10)
|
|
440
|
+
active = b.tabs.active() # active Tab object
|
|
441
|
+
tab = b.tabs.get(1234) # tab by ID
|
|
442
|
+
tab = b.tabs.first("github") # first matching tab or None
|
|
443
|
+
b.tabs.activate(1234)
|
|
444
|
+
b.tabs.close(1234)
|
|
445
|
+
b.tabs.close(tab_ids=[1, 2, 3]) # close many in one round-trip (IDs or Tab objects)
|
|
446
|
+
b.tabs.close_inactive()
|
|
447
|
+
b.tabs.close_duplicates()
|
|
448
|
+
b.tabs.filter("youtube") # list of matching tabs
|
|
449
|
+
b.tabs.query("pull request")
|
|
450
|
+
counts = b.tabs.count("github") # int, or BrowserCounts(total=..., by_browser=...) in multi-browser mode
|
|
451
|
+
html = b.tabs.html() # full HTML string of active tab
|
|
452
|
+
b.tabs.sort(by="domain")
|
|
453
|
+
b.tabs.merge_windows()
|
|
454
|
+
b.tabs.dedupe()
|
|
455
|
+
|
|
456
|
+
# Bound Tab helpers
|
|
457
|
+
tab = b.tabs.active()
|
|
458
|
+
tab.pin()
|
|
459
|
+
tab.screenshot()
|
|
460
|
+
tab.refresh()
|
|
461
|
+
tab.wait_for_load(timeout=10)
|
|
462
|
+
tab.watch_url(r"/done$")
|
|
463
|
+
|
|
464
|
+
# Tab groups ── b.groups
|
|
465
|
+
groups = b.groups.list() # list[Group]; in multi-browser mode each group.browser is set
|
|
466
|
+
b.groups.create("research") # creates group, returns Group
|
|
467
|
+
b.groups.close(42)
|
|
468
|
+
b.groups.tabs(42) # tabs inside a group
|
|
469
|
+
b.groups.add_tab(42, "https://example.com")
|
|
470
|
+
b.groups.count() # int, or BrowserCounts(...) in multi-browser mode
|
|
471
|
+
|
|
472
|
+
# Windows ── b.windows
|
|
473
|
+
windows = b.windows.list() # in multi-browser mode each dict has a "browser" key
|
|
474
|
+
b.windows.rename(1, "work")
|
|
475
|
+
b.windows.open()
|
|
476
|
+
b.windows.open("https://example.com")
|
|
477
|
+
b.windows.close(1)
|
|
478
|
+
|
|
479
|
+
# DOM ── b.dom (active tab must be http/https)
|
|
480
|
+
elements = b.dom.query("h2") # list of { tag, text, attrs }
|
|
481
|
+
texts = b.dom.text(".article p") # list of strings
|
|
482
|
+
attrs = b.dom.attr("a", "href") # list of strings
|
|
483
|
+
exists = b.dom.exists(".modal-banner") # bool
|
|
484
|
+
b.dom.click(".accept-button")
|
|
485
|
+
b.dom.type("#search", "hello world")
|
|
486
|
+
b.dom.wait_for("#results", visible=True, timeout=10)
|
|
487
|
+
b.dom.eval("document.title")
|
|
488
|
+
|
|
489
|
+
# Extract ── b.extract
|
|
490
|
+
links = b.extract.links() # list of { text, href }
|
|
491
|
+
images = b.extract.images() # list of { alt, src }
|
|
492
|
+
text = b.extract.text() # string
|
|
493
|
+
data = b.extract.json("#app-data") # parsed Python object
|
|
494
|
+
md = b.extract.markdown("article")
|
|
495
|
+
|
|
496
|
+
# Page / storage
|
|
497
|
+
info = b.page.info()
|
|
498
|
+
b.storage.set("token", "abc")
|
|
499
|
+
val = b.storage.get("token")
|
|
500
|
+
|
|
501
|
+
# Sessions ── b.session
|
|
502
|
+
b.session.save("before-meeting")
|
|
503
|
+
b.session.load("before-meeting")
|
|
504
|
+
sessions = b.session.list() # [{ name, tabs, savedAt }, ...]
|
|
505
|
+
b.session.remove("before-meeting")
|
|
506
|
+
diff = b.session.diff("session-a", "session-b")
|
|
507
|
+
# diff = { "added": [...urls], "removed": [...urls] }
|
|
508
|
+
b.session.auto_save(True)
|
|
509
|
+
|
|
510
|
+
# Performance + extension
|
|
511
|
+
b.perf.status()
|
|
512
|
+
b.perf.set_profile("gentle")
|
|
513
|
+
b.extension.reload()
|
|
514
|
+
|
|
515
|
+
# Workflow decorators ── b.decorators
|
|
516
|
+
@b.decorators.new_tab("https://example.com", wait=True, close=True)
|
|
517
|
+
def scrape(*, tab):
|
|
518
|
+
return b.extract.markdown("article")
|
|
519
|
+
|
|
520
|
+
@b.decorators.wait_for_selector("#ready", visible=True)
|
|
521
|
+
def run_after_page_ready():
|
|
522
|
+
return b.dom.text("#ready")
|
|
523
|
+
|
|
524
|
+
@b.decorators.performance_profile("ultra")
|
|
525
|
+
def restore_big_session():
|
|
526
|
+
return b.session.load("work", lazy=True)
|
|
527
|
+
|
|
528
|
+
@b.decorators.retry(times=3, delay=1)
|
|
529
|
+
@b.decorators.save_session_before("before-risky-step")
|
|
530
|
+
def risky_workflow():
|
|
531
|
+
b.tabs.close_duplicates()
|
|
532
|
+
|
|
533
|
+
# Async SDK: same namespaces, native awaitable methods
|
|
534
|
+
async def async_example():
|
|
535
|
+
ab = AsyncBrowserCLI()
|
|
536
|
+
tabs = await ab.tabs.list()
|
|
537
|
+
|
|
538
|
+
@ab.decorators.new_tab("https://example.com", wait=True, close=True)
|
|
539
|
+
async def scrape(*, tab):
|
|
540
|
+
return await ab.extract.markdown("article")
|
|
541
|
+
|
|
542
|
+
return tabs, await scrape()
|
|
543
|
+
|
|
544
|
+
# Misc
|
|
545
|
+
clients = b.clients()
|
|
546
|
+
raw = b.command("tabs.count", {"pattern": "github"}) # escape hatch for raw commands
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
**Error handling**
|
|
550
|
+
|
|
551
|
+
```python
|
|
552
|
+
from browser_cli import BrowserCLI, BrowserNotConnected
|
|
553
|
+
|
|
554
|
+
b = BrowserCLI()
|
|
555
|
+
try:
|
|
556
|
+
tabs = b.tabs.list()
|
|
557
|
+
except BrowserNotConnected:
|
|
558
|
+
print("Browser is not running or extension is not loaded")
|
|
559
|
+
except RuntimeError as e:
|
|
560
|
+
print(f"Browser returned an error: {e}")
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
```python
|
|
564
|
+
from browser_cli import BrowserCLI, BrowserCounts
|
|
565
|
+
|
|
566
|
+
b = BrowserCLI()
|
|
567
|
+
|
|
568
|
+
tabs = b.tabs.list()
|
|
569
|
+
for tab in tabs:
|
|
570
|
+
print(tab.browser, tab.title)
|
|
571
|
+
|
|
572
|
+
counts = b.tabs.count()
|
|
573
|
+
if isinstance(counts, BrowserCounts):
|
|
574
|
+
print(counts.total)
|
|
575
|
+
print(counts.by_browser)
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
---
|
|
579
|
+
|
|
580
|
+
## Example scripts
|
|
581
|
+
|
|
582
|
+
See `examples/demo.py` (Python) and `examples/demo.sh` (Bash) for full walkthroughs covering tabs, groups, DOM extraction, and session management.
|
|
583
|
+
|
|
584
|
+
```sh
|
|
585
|
+
uv run python examples/demo.py
|
|
586
|
+
bash examples/demo.sh
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
---
|
|
590
|
+
|
|
591
|
+
## Development
|
|
592
|
+
|
|
593
|
+
```sh
|
|
594
|
+
npm ci
|
|
595
|
+
npm run check:extension # type-check, build extension bundles, syntax-check bundle
|
|
596
|
+
uv run pytest -q
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
On NixOS or hosts without global Node/npm:
|
|
600
|
+
|
|
601
|
+
```sh
|
|
602
|
+
nix-shell # automatically runs npm ci when node_modules is missing/outdated
|
|
603
|
+
npm run check:extension
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
The extension source lives in `extension/src/`. `extension/background.js` and `extension/content-dispatch.js` are generated and ignored by git. Run `npm run build:extension` before using `Load unpacked` with `extension/`. On NixOS, use `nix-shell` first if npm is not installed globally.
|
|
607
|
+
|
|
608
|
+
Packaging:
|
|
609
|
+
|
|
610
|
+
```bash
|
|
611
|
+
npm run package:extension # testing/unpacked zip, keeps manifest.key for stable Chromium native-messaging ID
|
|
612
|
+
npm run package:extension:webstore # Chrome Web Store zip, strips manifest.key
|
|
613
|
+
npm run package:extension:firefox # Firefox zip, strips manifest.key and Firefox-incompatible permissions
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
Chrome Web Store rejects `manifest.key`, so upload the `*-webstore-*` zip from `dist/`. For Firefox, use the `*-firefox-*` zip.
|
|
617
|
+
|
|
618
|
+
---
|
|
619
|
+
|
|
620
|
+
## Limitations
|
|
621
|
+
|
|
622
|
+
- **Browser internal pages** (`chrome://`, `brave://`, `edge://`, `about:`) cannot be scripted. DOM and extract commands only work on regular `http://` and `https://` pages.
|
|
623
|
+
- **Multiple browser instances can be auto-distinguished, but generated aliases are temporary**. Unaliased browsers get UUID aliases from the native host, which avoids collisions but is less ergonomic than setting a stable alias with `browser-cli clients rename --browser <current-alias> <new-alias>`.
|
|
624
|
+
- **Supported install targets are explicit, not “all Chromium browsers”**. The installer currently supports Chrome, Chromium, Brave, Edge, Vivaldi, and Firefox. Other Chromium-based browsers may use different or shared native messaging manifest locations, so they need browser-specific verification before being added safely.
|
|
625
|
+
- **Firefox support is experimental**. Basic tab/window/navigation/native-messaging support is wired, including tab-group APIs on supported Firefox versions.
|
|
626
|
+
|
|
627
|
+
---
|
|
628
|
+
|
|
629
|
+
## License
|
|
630
|
+
|
|
631
|
+
PolyForm Noncommercial License 1.0.0. See [LICENSE](LICENSE).
|
|
632
|
+
|
|
633
|
+
Commercial use is not permitted under this license. For commercial licensing, contact the project maintainer.
|
|
@@ -50,7 +50,7 @@ Every response:
|
|
|
50
50
|
|
|
51
51
|
## Installation
|
|
52
52
|
|
|
53
|
-
**Requirements:** Python 3.10+, [uv](https://github.com/astral-sh/uv), Chrome, Chromium, Brave, Edge, Vivaldi
|
|
53
|
+
**Requirements:** Python 3.10+, [uv](https://github.com/astral-sh/uv), Chrome, Chromium, Brave, Edge, Vivaldi, or Firefox
|
|
54
54
|
|
|
55
55
|
### Install with uv
|
|
56
56
|
Once published on PyPI, install the CLI as a uv tool:
|
|
@@ -58,7 +58,7 @@ Once published on PyPI, install the CLI as a uv tool:
|
|
|
58
58
|
```sh
|
|
59
59
|
uv tool install real-browser-cli
|
|
60
60
|
browser-cli --version
|
|
61
|
-
browser-cli install brave # or: chrome, chromium, edge, vivaldi
|
|
61
|
+
browser-cli install brave # or: chrome, chromium, edge, vivaldi, firefox
|
|
62
62
|
```
|
|
63
63
|
|
|
64
64
|
The PyPI package is named `real-browser-cli`; the installed command is still `browser-cli`.
|
|
@@ -80,12 +80,12 @@ uv tool upgrade real-browser-cli
|
|
|
80
80
|
git clone <repo>
|
|
81
81
|
cd browser-cli
|
|
82
82
|
uv sync
|
|
83
|
-
uv run browser-cli install brave # or: chrome, chromium, edge, vivaldi
|
|
83
|
+
uv run browser-cli install brave # or: chrome, chromium, edge, vivaldi, firefox
|
|
84
84
|
```
|
|
85
85
|
|
|
86
86
|
The `install` command will:
|
|
87
87
|
1. Ask you to load the browser-specific extension package
|
|
88
|
-
2.
|
|
88
|
+
2. Show the stable extension ID used by that browser family
|
|
89
89
|
3. Write the native messaging manifest to your OS so the browser can find the host
|
|
90
90
|
4. Copy the native host into an internal `libexec` directory and create a small wrapper outside your `PATH`
|
|
91
91
|
|
|
@@ -515,11 +515,12 @@ The extension source lives in `extension/src/`. `extension/background.js` and `e
|
|
|
515
515
|
Packaging:
|
|
516
516
|
|
|
517
517
|
```bash
|
|
518
|
-
npm run package:extension # testing/unpacked zip, keeps manifest.key for stable native-messaging ID
|
|
518
|
+
npm run package:extension # testing/unpacked zip, keeps manifest.key for stable Chromium native-messaging ID
|
|
519
519
|
npm run package:extension:webstore # Chrome Web Store zip, strips manifest.key
|
|
520
|
+
npm run package:extension:firefox # Firefox zip, strips manifest.key and Firefox-incompatible permissions
|
|
520
521
|
```
|
|
521
522
|
|
|
522
|
-
Chrome Web Store rejects `manifest.key`, so upload the `*-webstore-*` zip from `dist/`.
|
|
523
|
+
Chrome Web Store rejects `manifest.key`, so upload the `*-webstore-*` zip from `dist/`. For Firefox, use the `*-firefox-*` zip.
|
|
523
524
|
|
|
524
525
|
---
|
|
525
526
|
|
|
@@ -527,8 +528,8 @@ Chrome Web Store rejects `manifest.key`, so upload the `*-webstore-*` zip from `
|
|
|
527
528
|
|
|
528
529
|
- **Browser internal pages** (`chrome://`, `brave://`, `edge://`, `about:`) cannot be scripted. DOM and extract commands only work on regular `http://` and `https://` pages.
|
|
529
530
|
- **Multiple browser instances can be auto-distinguished, but generated aliases are temporary**. Unaliased browsers get UUID aliases from the native host, which avoids collisions but is less ergonomic than setting a stable alias with `browser-cli clients rename --browser <current-alias> <new-alias>`.
|
|
530
|
-
- **Supported install targets are explicit, not “all Chromium browsers”**. The installer currently supports Chrome, Chromium, Brave, Edge, and
|
|
531
|
-
- **
|
|
531
|
+
- **Supported install targets are explicit, not “all Chromium browsers”**. The installer currently supports Chrome, Chromium, Brave, Edge, Vivaldi, and Firefox. Other Chromium-based browsers may use different or shared native messaging manifest locations, so they need browser-specific verification before being added safely.
|
|
532
|
+
- **Firefox support is experimental**. Basic tab/window/navigation/native-messaging support is wired, including tab-group APIs on supported Firefox versions.
|
|
532
533
|
|
|
533
534
|
---
|
|
534
535
|
|