remove the --profile flag on windows open and add opening a new window with a url

This commit is contained in:
2026-04-10 13:06:53 +02:00
parent 61b774a7a4
commit 362b53a384
8 changed files with 40 additions and 14 deletions
+2 -2
View File
@@ -223,7 +223,7 @@ browser-cli group move 42 --backward # move group left
```sh ```sh
browser-cli windows list # list all windows browser-cli windows list # list all windows
browser-cli windows open # open a new window browser-cli windows open # open a new window
browser-cli windows open --profile Default # request a specific Chrome profile name browser-cli windows open https://example.com # open a new window on a URL
browser-cli windows rename 1 "work" # give a window a local alias browser-cli windows rename 1 "work" # give a window a local alias
browser-cli windows close 1 # close a window browser-cli windows close 1 # close a window
``` ```
@@ -326,6 +326,7 @@ b.group_count() # int, or BrowserCounts(...) in multi-browser mode
windows = b.windows_list() # in multi-browser mode each dict has a "browser" key windows = b.windows_list() # in multi-browser mode each dict has a "browser" key
b.windows_rename(1, "work") b.windows_rename(1, "work")
b.windows_open() b.windows_open()
b.windows_open("https://example.com")
b.windows_close(1) b.windows_close(1)
# DOM (active tab must be http/https) # DOM (active tab must be http/https)
@@ -400,7 +401,6 @@ bash examples/demo.sh
## Limitations ## Limitations
- **Chrome internal pages** (`chrome://`, `brave://`, `about:`) cannot be scripted. DOM and extract commands only work on regular `http://` and `https://` pages. - **Chrome internal pages** (`chrome://`, `brave://`, `about:`) cannot be scripted. DOM and extract commands only work on regular `http://` and `https://` pages.
- **Profile switching** via `windows open --profile` depends on browser support and does not replace launching a separate browser profile externally with `--profile-directory`.
- **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 rename-profile --browser <current-alias> <new-alias>`. - **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 rename-profile --browser <current-alias> <new-alias>`.
- **Supported install targets are explicit, not “all Chromium browsers”**. The installer currently supports Chrome, Chromium, Brave, Edge, and Vivaldi. Other Chromium-based browsers may use different or shared native messaging manifest locations, so they need browser-specific verification before being added safely. - **Supported install targets are explicit, not “all Chromium browsers”**. The installer currently supports Chrome, Chromium, Brave, Edge, and Vivaldi. Other Chromium-based browsers may use different or shared native messaging manifest locations, so they need browser-specific verification before being added safely.
- **Linux and macOS only** — Windows native messaging paths are not yet handled. - **Linux and macOS only** — Windows native messaging paths are not yet handled.
+3 -2
View File
@@ -293,8 +293,9 @@ class BrowserCLI:
def windows_close(self, window_id: int) -> None: def windows_close(self, window_id: int) -> None:
self._cmd("windows.close", {"windowId": window_id}) self._cmd("windows.close", {"windowId": window_id})
def windows_open(self, profile: str | None = None) -> dict: def windows_open(self, url: str | None = None) -> dict:
return self._cmd("windows.open", {"profile": profile}) """Open a new browser window, optionally on a URL."""
return self._cmd("windows.open", {"url": url})
# ── DOM ─────────────────────────────────────────────────────────────── # ── DOM ───────────────────────────────────────────────────────────────
+4 -4
View File
@@ -100,9 +100,9 @@ def windows_close(window_id):
@windows_group.command("open") @windows_group.command("open")
@click.option("--profile", default=None, help="Open with a specific Chrome profile name") @click.argument("url", required=False)
def windows_open(profile): def windows_open(url):
"""Open a new browser window.""" """Open a new browser window."""
result = _handle("windows.open", {"profile": profile}) result = _handle("windows.open", {"url": url})
wid = result.get("id") if isinstance(result, dict) else result wid = result.get("id") if isinstance(result, dict) else result
console.print(f"[green]Opened new window[/green] (id: {wid})" + (f" with profile '{profile}'" if profile else "")) console.print(f"[green]Opened new window[/green] (id: {wid})" + (f" with {url}" if url else ""))
+4 -4
View File
@@ -545,10 +545,10 @@ async function windowsClose({ windowId }) {
return { windowId }; return { windowId };
} }
async function windowsOpen({ profile }) { async function windowsOpen({ url }) {
// profile support requires launching Chrome with --profile-directory which const createData = { focused: true };
// isn't possible from within an extension — we open a plain new window. if (url) createData.url = url;
const w = await chrome.windows.create({ focused: true }); const w = await chrome.windows.create(createData);
return { id: w.id }; return { id: w.id };
} }
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"manifest_version": 3, "manifest_version": 3,
"name": "browser-cli", "name": "browser-cli",
"version": "0.5.4", "version": "0.5.5",
"description": "Control your browser from the terminal via browser-cli", "description": "Control your browser from the terminal via browser-cli",
"permissions": [ "permissions": [
"tabs", "tabs",
+1 -1
View File
@@ -1,6 +1,6 @@
[project] [project]
name = "browser-cli" name = "browser-cli"
version = "0.5.4" version = "0.5.5"
description = "Control your real running browser from the terminal via a Chrome extension" description = "Control your real running browser from the terminal via a Chrome extension"
requires-python = ">=3.10" requires-python = ">=3.10"
dependencies = [ dependencies = [
+16
View File
@@ -471,6 +471,22 @@ class TestWindows:
{"id": 2, "tabCount": 3, "state": "maximized", "browser": "work"}, {"id": 2, "tabCount": 3, "state": "maximized", "browser": "work"},
] ]
def test_windows_open_without_url(self, b, mock_send):
mock_send.return_value = {"id": 5}
result = b.windows_open()
assert result == {"id": 5}
mock_send.assert_called_once_with("windows.open", {"url": None}, profile=None)
def test_windows_open_with_url(self, b, mock_send):
mock_send.return_value = {"id": 9}
result = b.windows_open("https://example.com")
assert result == {"id": 9}
mock_send.assert_called_once_with("windows.open", {"url": "https://example.com"}, profile=None)
# ── Tab model ───────────────────────────────────────────────────────────────── # ── Tab model ─────────────────────────────────────────────────────────────────
+9
View File
@@ -203,6 +203,15 @@ def test_windows_list_multi_browser_shows_browser_column():
assert "uuid-1" in result.output assert "uuid-1" in result.output
assert "work" in result.output assert "work" in result.output
def test_windows_open_passes_url():
with patch("browser_cli.commands.windows.send_command", return_value={"id": 7}) as send_command:
result = CliRunner().invoke(main, ["windows", "open", "https://example.com"])
assert result.exit_code == 0
assert "https://example.com" in result.output
send_command.assert_called_once_with("windows.open", {"url": "https://example.com"}, profile=None)
def test_extract_markdown_command(): def test_extract_markdown_command():
with patch("browser_cli.commands.extract.send_command", return_value="# Title\n") as send_command: with patch("browser_cli.commands.extract.send_command", return_value="# Title\n") as send_command:
result = CliRunner().invoke(main, ["extract", "markdown"]) result = CliRunner().invoke(main, ["extract", "markdown"])