diff --git a/README.md b/README.md index d05e9eb..f2ab4a8 100644 --- a/README.md +++ b/README.md @@ -93,14 +93,24 @@ agent-browser screenshot ./page.png The agent operates in your Chrome — you'll see tabs opening, pages loading, clicks happening in real time. You can take over at any point (e.g. solve a CAPTCHA), then let the agent continue. -### Standalone mode +### Standalone mode (`--launch`) -If you need a separate browser (CI, testing, etc.): +Spawn a separate browser instead of attaching to your running Chrome: ```bash +# Throwaway: fresh, EMPTY profile — no cookies, no login (good for CI/testing) agent-browser --launch open https://example.com + +# Keep your login: launch with your real Chrome profile (cookies/sessions intact) +agent-browser --launch --profile auto open https://x.com/home +# or name it explicitly: --profile Default / --profile "Profile 1" ``` +> ⚠️ Plain `--launch` (no `--profile`) uses a **temporary empty profile** — you will +> NOT be logged into anything. For logged-in sites use `--profile auto` (picks the +> Chrome profile you used most recently) or `--profile `. agent-browser prints +> a warning when you `--launch` without a profile. + In CI environments, standalone mode is used automatically. ## Anti-detection diff --git a/cli/src/main.rs b/cli/src/main.rs index 7fc0e2b..e6c65c3 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -531,6 +531,18 @@ fn main() { let mut flags = parse_flags(&args); let clean = clean_args(&args); + // Loudly warn when launching a fresh browser with no profile: it gets a + // temporary EMPTY profile (no cookies / no login). For logged-in sites the + // user almost always wants --profile auto (their real Chrome profile). + // Skipped under CI (force_launch is implicit there and login isn't expected). + if flags.force_launch && flags.profile.is_none() && env::var("CI").is_err() { + eprintln!( + "⚠ --launch uses a temporary EMPTY browser profile (no cookies, no login). \ + For logged-in sites, add `--profile auto` (or `--profile Default`) to reuse \ + your real Chrome session." + ); + } + let has_help = args.iter().any(|a| a == "--help" || a == "-h"); let has_version = args.iter().any(|a| a == "--version" || a == "-V"); diff --git a/cli/src/native/actions.rs b/cli/src/native/actions.rs index 14c2bac..d72974a 100644 --- a/cli/src/native/actions.rs +++ b/cli/src/native/actions.rs @@ -1609,9 +1609,12 @@ async fn auto_launch(state: &mut DaemonState) -> Result<(), String> { "Could not connect to your Chrome browser.\n\n\ If Chrome showed an \"Allow remote debugging?\" dialog, click \ Allow and re-run — that consent is what lets agent-browser attach.\n\n\ - Otherwise, to let agent-browser work with your existing Chrome (recommended):\n\ + Otherwise, to let agent-browser reuse your logged-in Chrome (recommended):\n\ {}\n\n\ - Or start a standalone browser with: agent-browser --launch open \n\n\ + Or launch a separate browser that KEEPS your login state:\n \ + agent-browser --launch --profile auto open \n\ + (plain `--launch` alone uses a temporary EMPTY profile — no cookies, \ + no logged-in sessions.)\n\n\ Note: remote debugging is a startup flag, not a Chrome setting — \ chrome://inspect/#remote-debugging only enables target discovery and \ does NOT expose the CDP HTTP API on /json/version. \ @@ -2172,9 +2175,12 @@ async fn handle_launch(cmd: &Value, state: &mut DaemonState) -> Result\n\n\ + Or launch a separate browser that KEEPS your login state:\n \ + agent-browser --launch --profile auto open \n\ + (plain `--launch` alone uses a temporary EMPTY profile — no cookies, \ + no logged-in sessions.)\n\n\ Note: remote debugging is a startup flag, not a Chrome setting — \ chrome://inspect/#remote-debugging only enables target discovery and \ does NOT expose the CDP HTTP API on /json/version. \ diff --git a/cli/src/native/cdp/chrome.rs b/cli/src/native/cdp/chrome.rs index a8192be..bb5394d 100644 --- a/cli/src/native/cdp/chrome.rs +++ b/cli/src/native/cdp/chrome.rs @@ -917,6 +917,18 @@ pub fn list_chrome_profiles(user_data_dir: &Path) -> Vec { /// 3. Case-insensitive directory name match /// /// Returns the resolved directory name, or an error with available profiles. +/// Read `profile.last_used` (the directory name of the profile Chrome opened +/// most recently) from a user-data dir's `Local State`. Used to resolve +/// `--profile auto`. +fn read_last_used_profile(user_data_dir: &Path) -> Option { + let content = std::fs::read_to_string(user_data_dir.join("Local State")).ok()?; + let json: serde_json::Value = serde_json::from_str(&content).ok()?; + json.get("profile")? + .get("last_used")? + .as_str() + .map(String::from) +} + pub fn resolve_chrome_profile(user_data_dir: &Path, input: &str) -> Result { let profiles = list_chrome_profiles(user_data_dir); @@ -928,6 +940,21 @@ pub fn resolve_chrome_profile(user_data_dir: &Path, input: &str) -> Result