feat!: harden raw browser control and packaging
Testing / remote-protocol-compat (0.9.3) (push) Successful in 40s
Testing / remote-protocol-compat (0.9.5) (push) Successful in 38s
Testing / test (push) Failing after 1m3s
Package Extension / package-extension (push) Successful in 29s
Build & Publish Package / publish (push) Successful in 33s

- Add safe-by-default policy gates for raw command surfaces: command, script, and serve-http /command.

- Require explicit opt-ins for page reads, browser control, and high-risk commands such as dom.eval, storage.*, and screenshots.

- Remove all cookies support from CLI, SDK, extension commands, permissions, constants, docs, and tests.

- Add diagnostic, events, watch, workspace, remote, raw command, script, HTTP gateway, tree-view, session import/export, and extension info/capability commands.

- Add Chrome Web Store packaging that strips manifest.key while keeping local packages with a stable native-messaging extension ID.

- Bump browser-cli and extension version to 0.14.1 and cover the new behavior with pytest and extension packaging tests.

BREAKING CHANGE: cookies commands and the b.cookies SDK namespace have been removed; generic raw command execution now blocks non-safe commands unless explicitly allowed.
This commit is contained in:
2026-06-14 14:33:15 +02:00
parent 3e3b8d529c
commit 5cec57e06d
43 changed files with 1184 additions and 375 deletions
+10 -4
View File
@@ -13,10 +13,13 @@ def nav_group():
@click.option("--focus", is_flag=True, help="Bring the opened tab/window to the front")
@click.option("--window", "window_name", default=None, help="Open in named window")
@click.option("--group", "group_name", default=None, help="Open directly into a tab group (name or ID)")
@click.option("--reuse", is_flag=True, help="Reuse an existing tab with exactly this URL")
@click.option("--reuse-domain", is_flag=True, help="Reuse an existing tab with the same domain")
@click.option("--reuse-title", default=None, metavar="TEXT", help="Reuse an existing tab whose title contains TEXT")
@handle_errors
def cmd_open(url, focus, window_name, group_name):
def cmd_open(url, focus, window_name, group_name, reuse, reuse_domain, reuse_title):
"""Open URL in a new tab without stealing focus by default."""
client_from_ctx().nav.open(url, focus=focus, window=window_name, group=group_name)
client_from_ctx().nav.open(url, focus=focus, window=window_name, group=group_name, reuse=reuse, reuse_domain=reuse_domain, reuse_title=reuse_title)
suffix = ""
if group_name:
suffix = f" in group '{group_name}'"
@@ -73,10 +76,13 @@ def cmd_focus(pattern):
@click.option("--focus", is_flag=True, help="Bring the opened tab/window to the front")
@click.option("--window", "window_name", default=None, help="Open in named window")
@click.option("--group", "group_name", default=None, help="Open in tab group")
@click.option("--reuse", is_flag=True, help="Reuse an existing tab with exactly this URL")
@click.option("--reuse-domain", is_flag=True, help="Reuse an existing tab with the same domain")
@click.option("--reuse-title", default=None, metavar="TEXT", help="Reuse an existing tab whose title contains TEXT")
@handle_errors
def cmd_open_wait(url, timeout, focus, window_name, group_name):
def cmd_open_wait(url, timeout, focus, window_name, group_name, reuse, reuse_domain, reuse_title):
"""Open URL in a new tab and wait until fully loaded."""
tab = client_from_ctx().nav.open_wait(url, timeout=timeout, focus=focus, window=window_name, group=group_name)
tab = client_from_ctx().nav.open_wait(url, timeout=timeout, focus=focus, window=window_name, group=group_name, reuse=reuse, reuse_domain=reuse_domain, reuse_title=reuse_title)
console.print(f"[green]Loaded:[/green] {url}" + (f"{tab.title}" if tab.title else ""))
@nav_group.command("wait")