Skip to content

Add browser manager and explicit browser selection#454

Open
gregpr07 wants to merge 15 commits into
mainfrom
codex/browser-manager-impl
Open

Add browser manager and explicit browser selection#454
gregpr07 wants to merge 15 commits into
mainfrom
codex/browser-manager-impl

Conversation

@gregpr07

@gregpr07 gregpr07 commented Jun 18, 2026

Copy link
Copy Markdown
Member

Summary by cubic

Adds manager mode with explicit browser ids and isolated runtimes: create with browser_new("private" | "cloud"), then select with browser(id) before using page helpers. Also adds PyPI packaging with uv install, a browser-harness skill command, XDG-based workspace paths, cloud auth login/import with leaner status, a repo-local ./browser-harness launcher, tighter diagnostics and JS evaluation, and opt‑out telemetry.

  • New Features

    • Manager daemon/client manage create/list/switch/close across isolated runtime/tmp/download/artifact dirs with safe cleanup; multiple clients can select the same browser via an active binding context.
    • Local profiles: browser_profiles([verbose]) lists stable ids (e.g. google-chrome:Default), browser_use_profile(id) selects one; the CLI subcommand browser-harness profiles [--verbose] runs without starting the daemon.
    • Cloud auth: auth login/status/logout/import using OAuth PKCE, device code, or safe stdin key import; prefers BROWSER_USE_API_KEY, otherwise stores a scoped key under BH_AUTH_PATH; cloud responses include a live_url when available; status output trimmed to essentials.
    • Packaging and install: published to PyPI with a release workflow; install via uv tool install browser-harness; browser-harness skill prints the canonical skill body; materializes SKILL.md in packages for non-symlink installs; new docs/browser-connection.md; shorter install guide.
    • Filesystem: default workspace and runtime live under ${XDG_CONFIG_HOME:-~/.config}/browser-harness/; override with BH_HOME, BH_CONFIG_DIR, or BH_RUNTIME_DIR; manager endpoint via BH_MANAGER_ROOT/BH_MANAGER_SOCKET.
    • Dev experience: repo-local ./browser-harness launcher runs the working tree without a venv and uses a checkout-specific manager root under /tmp; new browser-harness-manager entrypoint.
    • Reliability: JS helpers retry only on CDP “Illegal return statement”; press_key no longer emits a stray char with modifiers; treat explicit BU_CDP_URL as remote; clearer Chrome permission popup guidance; manager mode skips legacy daemon auto-start.
    • Telemetry: low-cardinality, best-effort, opt-out telemetry; disable with BH_TELEMETRY=0 or BROWSER_HARNESS_TELEMETRY=0.
  • Migration

    • Update scripts to browser_new("private" | "cloud") → keep the returned id → browser(id) before page helpers.
    • Replace list_local_profiles() with browser_profiles() and use_local_profile(id) with browser_use_profile(id).
    • Workspace paths now default to ${XDG_CONFIG_HOME:-~/.config}/browser-harness/agent-workspace/; adjust any hard-coded references or set BH_CONFIG_DIR/BH_HOME.
    • Remote CDP flows are unchanged; set BU_CDP_WS or BU_CDP_URL to use a specific endpoint.
    • For cloud browsers, set BROWSER_USE_API_KEY, run browser-harness auth login (supports device code and stdin), or browser-harness auth import once.

Written for commit 07e56f7. Summary will update on new commits.

Review in cubic

@browser-harness-review

browser-harness-review Bot commented Jun 18, 2026

Copy link
Copy Markdown

⛔ Skill review blocked

An automated security review found 1 finding(s) across 1 file(s).

  • interaction-skills/profile-sync.mdmalicious_code

Skill authorship is restricted to maintainers. Please do not attempt to self-fix — a maintainer will review and follow up.

Comment thread src/browser_harness/auth.py Fixed
Comment thread src/browser_harness/auth.py Fixed
Comment thread src/browser_harness/auth.py Fixed
Comment thread src/browser_harness/auth.py Fixed

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 5 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/browser_harness/auth.py">

<violation number="1" location="src/browser_harness/auth.py:457">
P2: TTY API-key entry can crash on aborted input because `EOFError` from `getpass` is not handled. Convert prompt failures to `AuthError` so CLI exits cleanly with error status.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread src/browser_harness/auth.py Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

6 issues found and verified against the latest diff

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="tests/unit/test_run_manager_mode.py">

<violation number="1" location="tests/unit/test_run_manager_mode.py:42">
P2: All three tests leak BH_MANAGER_MODE into os.environ — run.main() calls setdefault('BH_MANAGER_MODE', '1') but no test cleans it up. Can cause test-order-dependent failures in any test that reads BH_MANAGER_MODE.</violation>
</file>

Tip: instead of fixing issues one by one fix them all with cubic

Re-trigger cubic

Comment thread src/browser_harness/manager_client.py Outdated
Comment thread src/browser_harness/manager_daemon.py Outdated
Comment thread src/browser_harness/auth.py
Comment thread tests/unit/test_run_manager_mode.py Outdated
Comment thread src/browser_harness/manager_helpers.py Outdated
Comment thread src/browser_harness/helpers.py Outdated
@gregpr07 gregpr07 changed the title Codex/browser manager impl Add browser manager and explicit browser selection Jun 19, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 issues found across 34 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name=".github/workflows/release.yml">

<violation number="1" location=".github/workflows/release.yml:16">
P1: Release workflow uses mutable action tags instead of immutable commit SHAs, creating CI/CD supply-chain risk for PyPI publishing.</violation>
</file>

<file name="install.md">

<violation number="1" location="install.md:14">
P2: Install instructions use unconditional `rm -rf` on generic skill directory names, risking deletion of legitimate user skills</violation>
</file>

<file name="src/browser_harness/manager_client.py">

<violation number="1" location="src/browser_harness/manager_client.py:97">
P2: `stop_manager_if_running` ignores the response from `send_request` and unconditionally returns `True` on successful transport, misleading callers if the daemon rejects shutdown.</violation>
</file>

<file name="src/browser_harness/local_profiles.py">

<violation number="1" location="src/browser_harness/local_profiles.py:86">
P2: Changing profile_config_path() to return settings.json risks silent data loss because set_default_profile_id() overwrites the entire file without reading existing content. The docs describe settings.json as "selected local Chrome profile and future preferences", indicating it is a shared settings document. Future preferences stored there will be clobbered on every profile change.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

contents: read
id-token: write
steps:
- uses: actions/checkout@v4

@cubic-dev-ai cubic-dev-ai Bot Jun 21, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Release workflow uses mutable action tags instead of immutable commit SHAs, creating CI/CD supply-chain risk for PyPI publishing.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/release.yml, line 16:

<comment>Release workflow uses mutable action tags instead of immutable commit SHAs, creating CI/CD supply-chain risk for PyPI publishing.</comment>

<file context>
@@ -0,0 +1,25 @@
+      contents: read
+      id-token: write
+    steps:
+      - uses: actions/checkout@v4
+      - uses: actions/setup-python@v5
+        with:
</file context>
Fix with cubic

Comment thread install.md
uv tool install -e .
command -v browser-harness
uv tool install browser-harness
for root in "${CODEX_HOME:-$HOME/.codex}/skills" "$HOME/.agents/skills"; do

@cubic-dev-ai cubic-dev-ai Bot Jun 21, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Install instructions use unconditional rm -rf on generic skill directory names, risking deletion of legitimate user skills

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At install.md, line 14:

<comment>Install instructions use unconditional `rm -rf` on generic skill directory names, risking deletion of legitimate user skills</comment>

<file context>
@@ -1,176 +1,79 @@
-uv tool install -e .
-command -v browser-harness
+uv tool install browser-harness
+for root in "${CODEX_HOME:-$HOME/.codex}/skills" "$HOME/.agents/skills"; do
+  rm -rf "$root/browser-harness" "$root/browser" "$root/browser-use"
+done
</file context>
Fix with cubic

except (FileNotFoundError, ConnectionRefusedError, TimeoutError, OSError, ValueError, KeyError, TypeError):
return False
try:
manager_runtime.send_request(sock, token, {"meta": "shutdown"})

@cubic-dev-ai cubic-dev-ai Bot Jun 21, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: stop_manager_if_running ignores the response from send_request and unconditionally returns True on successful transport, misleading callers if the daemon rejects shutdown.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/browser_harness/manager_client.py, line 97:

<comment>`stop_manager_if_running` ignores the response from `send_request` and unconditionally returns `True` on successful transport, misleading callers if the daemon rejects shutdown.</comment>

<file context>
@@ -87,6 +87,24 @@ def _manager_socket_alive(path: Path) -> bool:
+    except (FileNotFoundError, ConnectionRefusedError, TimeoutError, OSError, ValueError, KeyError, TypeError):
+        return False
+    try:
+        manager_runtime.send_request(sock, token, {"meta": "shutdown"})
+        return True
+    except (OSError, ValueError, AttributeError):
</file context>
Fix with cubic



def profile_config_path() -> Path:
return config_dir() / "settings.json"

@cubic-dev-ai cubic-dev-ai Bot Jun 21, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Changing profile_config_path() to return settings.json risks silent data loss because set_default_profile_id() overwrites the entire file without reading existing content. The docs describe settings.json as "selected local Chrome profile and future preferences", indicating it is a shared settings document. Future preferences stored there will be clobbered on every profile change.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/browser_harness/local_profiles.py, line 86:

<comment>Changing profile_config_path() to return settings.json risks silent data loss because set_default_profile_id() overwrites the entire file without reading existing content. The docs describe settings.json as "selected local Chrome profile and future preferences", indicating it is a shared settings document. Future preferences stored there will be clobbered on every profile change.</comment>

<file context>
@@ -77,18 +79,14 @@ def payload(self) -> dict:
 
 
 def profile_config_path() -> Path:
+    return config_dir() / "settings.json"
+
+
</file context>
Fix with cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants