Commit Graph

61 Commits

Author SHA1 Message Date
ShawnPana 566bca0a88 handle ping success:false case in ensure_daemon config check
Previous commit fixed the exception path. This fixes the case where
ping returns a response with success:false — same fallthrough bug.
2026-03-19 23:10:22 -07:00
ShawnPana edfd554f0f fix ensure_daemon falling through on ping failure with explicit config
When ping fails but daemon is alive, return instead of trying to spawn
a second daemon. The old daemon holds the socket so the new one can't
bind, causing silent config mismatch.
2026-03-19 23:06:31 -07:00
ShawnPana f29aa6b5bc fix os.kill(pid, 0) on Windows: use OpenProcess instead of TerminateProcess
On Windows, os.kill(pid, 0) calls TerminateProcess which kills the process
instead of checking liveness. Use ctypes OpenProcess for Windows, keeping
os.kill(pid, 0) for Unix. Affects list_sessions(), tunnel PID checks, and
_handle_sessions().
2026-03-19 22:17:31 -07:00
ShawnPana 54f3febdfa address PR review comments: fix cloud v2 --help, guard double signal, error to stderr, stale port
- Narrow cloud --help intercept to only fire when --help is immediately
  after 'cloud', so 'cloud v2 --help' still shows OpenAPI endpoints
- Guard signal handler against concurrent shutdown tasks on repeated signals
- Route error response bodies to stderr in cloud REST commands
- Replace stale port 49200 in README Windows troubleshooting
2026-03-19 22:04:34 -07:00
ShawnPana c26f228e5a fix cloud --help to show custom usage, tighten test assertions
- Intercept `cloud --help` early so it routes to _print_cloud_usage()
  instead of argparse's generic stub
- Remove permissive `or 'cloud'` fallback in epilog test assertion
- Delete no-op regex test that didn't verify actual code
- Tighten default socket path assertion to check 'default.sock'
2026-03-19 21:48:28 -07:00
ShawnPana 55665f70b8 fix socket FD leaks on connect() failure in CLI daemon infrastructure
Wrap socket creation + connect in try/finally across 5 locations to
ensure sockets are closed when connect() raises. Previously, failed
connections leaked file descriptors until GC ran.
2026-03-19 19:58:58 -07:00
ShawnPana 694a111fad add upload command to CLI, extract find_file_input_near_element to BrowserSession
- Add `browser-use upload <index> <path>` command for uploading files to
  file input elements via the CLI
- Extract find_file_input_near_element from nested closures in tools/service.py
  to a reusable method on BrowserSession, deduplicating two copies
- Add BrowserWrapper.upload() for the Python REPL
- Resolve file paths to absolute on the client side before sending to daemon
- Update SKILL.md files and README with upload command docs
2026-03-19 17:02:34 -07:00
ShawnPana c70e5029ae fix profile subcommand argparse passthrough
Use nargs=REMAINDER to capture profile-use args, matching the cloud
subcommand pattern. Without this, argparse rejects unknown args like
'browser-use profile update'.
2026-03-18 16:19:41 -07:00
ShawnPana d3e1818496 consolidate CLI files under ~/.browser-use/, add profile-use integration and doctor checks
Unify all CLI-managed files under ~/.browser-use/ (config, sockets, PIDs,
binaries, tunnels) instead of scattering across ~/.config/browser-use/ and
~/.browser-use/run/. Add profile-use Go binary as managed subcommand via
browser-use profile, with auto-download fallback and install.sh integration.
Wire cloudflared and profile-use availability checks into browser-use doctor.
2026-03-18 16:16:28 -07:00
ShawnPana bff2918558 add --connect flag for Chrome auto-discovery and fix daemon shutdown for external browsers
Adds `--connect` to auto-discover running Chrome instances via DevToolsActivePort
files and well-known port probing, eliminating manual CDP URL construction. Fixes
daemon process hanging on `close` when connected to external browsers (--connect,
--cdp-url, cloud) by calling stop() (disconnect) instead of kill() (terminate).
2026-03-18 09:41:58 -07:00
ShawnPana 3318f56318 simplify CLI infrastructure: single-session daemon, remove install modes, streamline setup
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 10:12:41 -07:00
ShawnPana 0dc2fc5a6f remove run command and agent infrastructure from CLI
The `run` command pulled in heavy SDK dependencies (openai, anthropic,
google), had a bug (await on sync get_llm), and is superseded by
`browser-use cloud` for agent execution. CLI is now purely a browser
automation interface.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 11:44:13 -07:00
ShawnPana 91e987acdc add browser-use cloud command: generic REST passthrough to Cloud API
Login/logout with API key persistence, versioned REST calls (v2/v3),
task polling, and OpenAPI-driven help. Stdlib only, no daemon needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 11:13:43 -07:00
ShawnPana 4be221386b changes 2026-03-11 12:57:50 -07:00
ShawnPana 859cb97063 simplify daemon architecture: single session, socket-as-liveness, no PID/lock files
Replace the multi-session server (server.py, SessionRegistry, portalocker locking,
PID files, orphan detection) with a minimal daemon (daemon.py) that holds one
BrowserSession in memory. Socket file existence = alive. Auto-exits when browser
dies via CDP watchdog.

-2277 lines, +142 lines across 20 files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 19:05:44 -08:00
ShawnPana 39698e58e4 strip cloud/remote commands from skill_cli
Remove all cloud API paths from the CLI while leaving core library
cloud support (BrowserSession(use_cloud=True), browser/cloud/) untouched.

Deleted: api_key.py, cloud_task.py, cloud_session.py
Removed: --browser remote, cloud-only run flags, task/session subcommands,
cloud profile ops (create/update/delete/sync), remote mode validation
Kept: tunnel (just Cloudflare), all local commands, install_config.py

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 15:56:31 -08:00
Saurav Panda 3f63677756 new direct cli mode 2026-02-19 10:18:12 -08:00
ShawnPana c8242e7edd fix(cli): prevent orphaned server processes with flock-based locking
The session server had a race condition where concurrent CLI calls could
spawn multiple server processes. The old server would be orphaned when
the new one overwrote the PID file and deleted its socket.

Changes:
- Add flock-based locking using portalocker (already a dependency)
- Server acquires exclusive lock before writing PID file
- CLI checks both is_server_running() AND is_session_locked()
- Add kill_orphaned_server() to clean up servers with PID but no lock
- Increase socket timeout from 0.1s to 0.5s for reliability
- cleanup_session_files() now removes .lock and .meta files

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-12 10:10:05 -08:00
ShawnPana 4d8c4e5e48 refactor(cli): consolidate tunnel code into single tunnel.py
- Rename tunnel_manager.py to tunnel.py
- Remove dead code: commands/tunnel.py (session-scoped implementation never reached)
- Remove TunnelInfo dataclass and tunnels field from sessions.py
- Remove tunnel routing from server.py (unreachable code path)
- Update imports in main.py, doctor.py, setup.py, and tests

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-12 02:09:55 -08:00
ShawnPana 7706c55532 refactor(cli): consolidate SDK/task/session files into cloud_task.py and cloud_session.py
- Create commands/utils.py with SDK singleton and format_duration helper
- Merge task_management.py into cloud_task.py (SDK wrappers + CLI handlers)
- Create cloud_session.py from session parts of cloud_task.py + session_management.py
- Delete sdk.py, task_management.py, session_management.py
- Update imports in main.py, agent.py, profile.py, __init__.py

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-12 01:47:44 -08:00
ShawnPana 5aeb6beeb5 style: fix ruff lint/format issues
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-12 01:07:22 -08:00
ShawnPana fae720ba77 fix(cli): address cubic review concerns
- Forward all cloud-only flags in _handle_remote_run_with_wait
  Previously only forwarded 6 params; now includes session_id, vision,
  metadata, secrets, allowed_domains, skill_ids, structured_output,
  judge, judge_ground_truth, plus session creation for profile/proxy

- Use asyncio.to_thread for blocking SDK call in poll_until_complete
  Prevents client.tasks.get_task from blocking the event loop while
  polling for task completion

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-11 23:53:25 -08:00
ShawnPana c5dcb52cc9 fix(cli): make poll_until_complete async and show task_id immediately with --wait
Changes:

1. cloud_task.py: Convert poll_until_complete to async
   - Use `await asyncio.sleep()` instead of blocking `time.sleep()`
   - Properly yields control to event loop during polling

2. agent.py: Simplify poll call
   - Just `await cloud_task.poll_until_complete()` directly
   - Remove unnecessary `asyncio.to_thread()` wrapper

3. main.py: Handle --wait directly for immediate feedback
   - Bypass server for remote + run + --wait
   - Print task_id and session_id immediately after task creation
   - Show "waiting... done." progress indicator
   - Handle Ctrl+C gracefully (task continues remotely)
   - Use asyncio.run() for clean event loop management

Before:
  $ browser-use -b remote run "task" --wait
  # (waits silently, then shows everything at once)

After:
  $ browser-use -b remote run "task" --wait
  mode: remote
  task_id: abc123
  session_id: xyz789
  waiting... done.
  status: finished
  output: result here

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-11 23:12:27 -08:00
ShawnPana 1a9f51c541 refactor(cli): use browser-use-sdk for all cloud operations
Replace custom HTTP client with browser-use-sdk for tasks and sessions,
completing the SDK migration started in 8a992229.

## SDK Migration
- Add `sdk.py` with singleton client factory (`get_sdk_client()`)
- Rewrite `cloud_task.py` to use SDK (-300 lines)
- All functions return typed SDK models (TaskView, SessionView, etc.)
- Add `_filter_none()` to omit None values (SDK sends null, API rejects)

## No Client-Side Defaults
- Remove hardcoded defaults from CLI (max_steps, proxy_country, etc.)
- Let API use its own defaults (documented at docs.cloud.browser-use.com)
- Only pass values user explicitly sets

## New CLI Features
- `session create` - create session without task
- `session share <id>` - create/delete public share URLs
- `task list --session <id>` - filter tasks by session
- New task flags: --metadata, --secret, --allowed-domain, --skill-id,
  --structured-output, --judge, --judge-ground-truth, --start-url

## Async by Default
- Change `--no-wait` to `--wait` (flip default behavior)
- Tasks return immediately with task_id by default
- Use `--wait` to block until completion

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-11 19:12:32 -08:00
ShawnPana 8a9922291d refactor(cli): use browser-use-sdk for cloud profile operations
Replace raw urllib HTTP calls with the official browser-use-sdk client
for all cloud profile API operations. This provides:

- Type-safe responses (ProfileView, ProfileListResponse)
- Cleaner error handling via SDK exceptions
- Consistent SDK usage pattern (matches skills/service.py)
- Removes 40 lines of manual HTTP/auth handling from main.py

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-11 16:39:08 -08:00
ShawnPana fd3db0615a fix(cli): hide server console window on Windows
Use CREATE_NO_WINDOW instead of DETACHED_PROCESS to prevent
a blank console window from appearing when the server starts.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-10 23:19:56 -08:00
ShawnPana 5e811e2ba4 fix(cli): Windows compatibility fixes for session server
- Use ctypes.OpenProcess on Windows for process existence check
  (os.kill raises WinError 87 or SystemError on Windows)
- Use 127.0.0.1 instead of localhost to avoid IPv6 binding issues
- Add reuse_address=True to asyncio.start_server for TCP port reuse

Fixes issues reported in:
- #3912 (os.kill fails on Windows)
- #3918 (WinError 87 in is_server_running)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-10 22:48:53 -08:00
ShawnPana d4b1a243c0 fix(cli): doctor command now shows check results
Previously doctor said "See details above" but never printed the actual
check results. Now prints each check with status icon and details.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-10 22:24:01 -08:00
ShawnPana 2ff264c6a6 fix(cli): use --mode instead of --profile for setup command handler
The setup command parser was changed to use --mode but the handler was
still passing args.profile and reading result["profile"]. Fixed both
to use mode consistently.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-10 15:41:22 -08:00
ShawnPana 723f3335b2 feat(cli): add token-efficient task monitoring with duration display
- Default task status shows only latest step (token efficient for agents)
- Add --compact/-c flag to show all steps with reasoning
- Add --verbose/-v flag to show all steps with URLs + actions
- Add --last/-n, --reverse/-r, --step/-s flags for navigating long tasks
- Display duration for tasks (e.g., "18s", "5m 13s") and sessions
- Format proxy cost to 2 decimal places in session output
- Update SKILL.md docs with recommended monitoring workflow
2026-02-10 14:39:20 -08:00
ShawnPana a568f45979 feat(cli): add cloud task/session management and subagent support
Cloud API Integration:
- Add cloud_task.py with full Cloud API client (tasks, sessions)
- Support for task creation, status polling, stopping, and logs
- Session management: create, list, get, stop, delete

Agent Task Options (remote mode):
- --llm: specify model (gpt-4o, claude-sonnet-4-20250514, gemini-2.0-flash)
- --proxy-country: proxy location (default: us)
- --session-id: reuse existing cloud session
- --keep-alive: preserve session after task
- --no-wait: async execution, return task_id immediately
- --stream: stream status updates
- --flash: fast execution mode
- --thinking: extended reasoning
- --vision/--no-vision: control vision capability

CLI Commands:
- task list [--limit N] [--status running|finished] [--json]
- task status <task-id> [--json]
- task stop <task-id>
- task logs <task-id>
- session list [--limit N] [--status active|stopped] [--json]
- session get <session-id> [--json]
- session stop <session-id> | --all

Documentation:
- Add comprehensive subagent examples to SKILL.md files
- Document session=agent, task=work mental model
- Examples for parallel agents, session reuse, agent management
2026-02-10 12:33:05 -08:00
ShawnPana 9420c90569 fix(cli): tunnel processes now survive CLI exit
- Spawn cloudflared as daemon with start_new_session=True
- Track tunnels via PID files in ~/.browser-use/tunnels/ instead of memory
- Properly add --all flag to tunnel argparser (fixes unrecognized args error)
- Clean up stale PID files when tunnel process has died

This fixes the issue where cloudflared would become a zombie/defunct process
immediately after browser-use tunnel returned, causing 530 errors.
2026-02-09 21:44:31 -08:00
ShawnPana c0dd7875b8 feat(install): mode-based installation with interactive TUI
Add installation mode selection that determines which browser modes are
available at runtime. This enables lightweight remote-only installs for
sandboxed agents (skipping ~300MB Chromium download).

## Install Modes

- `--remote-only`: Only remote mode, installs cloudflared, skips Chromium
- `--local-only`: Only local modes (chromium/real), skips cloudflared
- `--full`: All modes available (default interactive selection)

## Runtime Behavior

- Single installed mode becomes the default (no --browser flag needed)
- Requesting unavailable mode shows clear error with reinstall instructions
- No config file = all modes available (backward compat for pip users)

## Changes

**New: browser_use/skill_cli/install_config.py**
- Manages ~/.browser-use/install-config.json
- get_config(), save_config(), is_mode_available(), get_default_mode()
- get_mode_unavailable_error() for helpful reinstall guidance

**Modified: browser_use/skill_cli/main.py**
- build_parser() uses config for --browser choices and default
- Validates mode availability before starting session server

**Modified: browser_use/skill_cli/sessions.py**
- create_browser_session() validates mode before creation

**Modified: install.sh**
- Command-line flags: --full, --remote-only, --local-only, --api-key
- Interactive TUI with fallback: gum → whiptail → pure bash menu
- Conditional dependency installation based on selected modes
- Writes install-config.json with installed modes

**Updated: skills/remote-browser/SKILL.md**
- Simplified examples (no --browser remote needed with --remote-only)
- Updated setup instructions for mode-based installation

**New: tests/ci/test_install_config.py**
- 13 tests covering config module
2026-02-09 20:36:08 -08:00
ShawnPana 94c336407d fix(cli): make tunnel command independent of browser sessions
Previously, `browser-use tunnel 3000` would start a session server with
the default browser mode (chromium), which poisoned subsequent
`--browser remote` commands with a mode mismatch error.

Now tunnel commands are handled directly in main.py without starting a
browser session:

  npm run dev &
  browser-use tunnel 3000                          # No session created
  browser-use --browser remote open <tunnel-url>   # Works!

Changes:
- Move tunnel logic to standalone functions in tunnel_manager.py
- Handle tunnel commands in main.py before ensure_server()
- Tunnels persist across browser-use close (independent lifecycle)
- Add `browser-use tunnel stop --all` command

Breaking behavior change:
- `browser-use close` no longer stops tunnels
- Use `browser-use tunnel stop <port>` or `tunnel stop --all` explicitly

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-09 18:38:39 -08:00
ShawnPana 9f51461bbd fix(cli): error when requesting remote browser on local session + improve docs
When a session is started without --browser remote and a subsequent command
uses --browser remote, the CLI now errors with guidance instead of silently
using the local browser (which loses cloud features like live_url).

Code changes:
- Add session metadata file to track browser_mode per session
- Error only when remote requested but session is local
- Allow local-on-remote (user gets more features than requested)
- Clean up metadata on session close

SKILL.md improvements:
- Clarify that --browser remote only needed on FIRST command
- Add table showing session modes
- Add "What happens if you forget" section with error example
- Add troubleshooting entry for mode mismatch error

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-09 18:20:06 -08:00
ShawnPana 3c9b2501ac fix(cli): detect browser mode mismatch between existing session and requested mode
When a session is started with --browser chromium and a subsequent command
uses --browser remote (or vice versa), the CLI now detects the mismatch and
provides actionable error guidance instead of silently using the wrong mode.

Changes:
- Add get_session_metadata_path() to track session config in temp files
- Write browser_mode, headed, profile to metadata on server start
- Check metadata in ensure_server() and error if modes don't match
- Clean up metadata file on session close

Example error:
  Error: Session 'default' is running with --browser chromium,
  but --browser remote was requested.

  Options:
    1. Use existing browser: browser-use --browser chromium <command>
    2. Use different session: browser-use --browser remote --session other <command>
    3. Close existing session: browser-use close

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-09 18:10:46 -08:00
ShawnPana 9520a0b04e feat: frictionless installation system with setup/doctor commands
- Add TunnelManager for auto-install cloudflared via pycloudflared
- Add 'browser-use setup' command with profile-based configuration
- Add 'browser-use doctor' command for health checks
- Add install.sh bootstrap script (dev testing version)
- Add pycloudflared dependency
- Add comprehensive tests for new functionality
2026-02-09 16:09:38 -08:00
Gregor Žunič 9d7a0c74ed Add bu tunnel command and remote-browser skill
- New `tunnel` command: expose localhost ports via Cloudflare quick tunnels
  (`bu tunnel 3000` → trycloudflare.com URL, idempotent, auto-cleanup on session close)
- New `skills/remote-browser/SKILL.md`: guides sandboxed agents through
  cloud browser + tunnel workflow
- TunnelInfo dataclass on SessionInfo for tunnel lifecycle management
- Tunnel dispatch in both SessionServer and CLI arg parser

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 10:14:42 -08:00
ShawnPana 92de59c6cc fix(cli): fix pyright type errors in CLI
- Remove invalid cdp_url parameter from create_browser_session calls
- Replace deleted GetCookiesEvent with direct _cdp_get_cookies() call
- Add type assertion for cookies_file after error check
- Use unique variable names for CDP results to avoid type conflicts
- Add type ignores for CDP typed return values used as dicts
2026-02-02 13:05:11 -08:00
ShawnPana 4de76454a7 fix(cli): fix error check in profile sync and remove deleted event import 2026-02-02 10:57:21 -08:00
ShawnPana ad47a97518 style: apply ruff formatting 2026-02-02 10:51:08 -08:00
shawn pana 7d02013b71 Merge branch 'main' into main 2026-02-02 10:47:30 -08:00
ShawnPana 545004322b style: fix formatting 2026-01-31 22:29:57 -08:00
ShawnPana cddc00f6da fix: delegate --template flag to init_main for full template support 2026-01-31 22:24:23 -08:00
Gregor Žunič 0cb96ea5d0 fix: restore install, init, --mcp commands in skill_cli
PR #3911 changed the browser-use entry point to skill_cli/main.py but
didn't port the early command interception for install, init, --template,
and --mcp. This broke:

- `browser-use install` (installs Chromium via playwright)
- `browser-use init` (generates template files)
- `browser-use --template` (direct template generation)
- `browser-use --mcp` (MCP server mode)

This fix adds early command interception to skill_cli/main.py, matching
the behavior from browser_use/cli.py. Commands are handled before argparse
to avoid loading heavy dependencies for simple setup tasks.

Also adds tests to prevent regression.
2026-01-31 21:44:19 -08:00
Saurav Panda a7250241b2 Revert "feat(cli): add --cdp-url flag to connect to existing browser via CDP (#3927)"
This reverts commit e0504b1c7d, reversing
changes made to f798633548.
2026-01-31 21:11:54 -08:00
ShawnPana 2d992c3726 feat(cli): add cloud profile management and cookie sync
- Add cloud profile commands: list, create, get, update, delete
- Add profile sync command to sync local Chrome cookies to cloud
- Add profile cookies command to list cookies by domain
- Add cookies export/import commands for bulk transfer
- Optimize cookie import using Network.setCookies (bulk API)
- Real browser now runs headless by default (use --headed for visible)
- Support --domain flag for syncing specific domain cookies only
- Update SKILL.md with cloud profile workflow documentation
2026-01-31 20:02:50 -08:00
ShawnPana 2b2dc2b4e5 feat(cli): add profile list-local command and fix real browser profile loading
- Add `profile list-local` command to discover local Chrome profiles
- Fix real browser mode to properly pass `profile_directory` to BrowserSession
- Document profile management workflow in SKILL.md
2026-01-31 18:25:17 -08:00
ShawnPana 9abfc327cc feat(cli): add get command for info retrieval (title, html, text, value, attributes, bbox)
Adds information retrieval commands to the browser-use CLI:
- get title: page title
- get html: full page or element HTML via selector
- get text: text content of element by index
- get value: input/textarea value by index
- get attributes: all attributes of element by index
- get bbox: bounding box (x, y, width, height) of element
2026-01-31 17:34:33 -08:00
ShawnPana 3ca625b75e feat(cli): add hover, dblclick, rightclick interaction commands
Adds mouse interaction commands to the browser-use CLI:
- hover: move mouse over element (triggers CSS :hover effects)
- dblclick: double-click element
- rightclick: right-click element (context menu)
2026-01-31 17:28:20 -08:00