diff --git a/README.md b/README.md index 1b614c468..cd0584787 100644 --- a/README.md +++ b/README.md @@ -448,6 +448,8 @@ The profile directory stores: **Tip**: Use different profile paths for different projects to keep their browser state isolated. +**Sessions with profiles**: When `--session` is combined with `--profile`, each session stores its Chrome data in a separate subdirectory: `//`. This ensures that concurrent sessions using the same base profile path each get their own isolated Chrome instance. For example, `--profile ~/.myapp-profile --session work` uses `~/.myapp-profile/work/` and `--session personal` uses `~/.myapp-profile/personal/`. + ## Session Persistence Alternatively, use `--session-name` to automatically save and restore cookies and localStorage across browser restarts: diff --git a/cli/src/native/actions.rs b/cli/src/native/actions.rs index bebffc207..ef3c77d39 100644 --- a/cli/src/native/actions.rs +++ b/cli/src/native/actions.rs @@ -942,6 +942,19 @@ async fn auto_launch(state: &mut DaemonState) -> Result<(), String> { Ok(()) } +/// Returns the effective Chrome user-data-dir path for a session. +/// +/// Appends the session ID as a subdirectory under the base profile path so +/// that each `--session` daemon gets its own independent Chrome instance even +/// when `--profile` is shared across sessions. Chrome enforces a singleton +/// constraint per `--user-data-dir`, so without this isolation the second +/// daemon silently connects to the first daemon's Chrome instance instead of +/// launching a new one. +fn session_scoped_profile(profile: &str, session_id: &str) -> String { + let profile = profile.trim_end_matches('/'); + format!("{}/{}", profile, session_id) +} + fn launch_options_from_env() -> LaunchOptions { let headed = env::var("AGENT_BROWSER_HEADED") .map(|v| v == "1" || v == "true") @@ -959,7 +972,12 @@ fn launch_options_from_env() -> LaunchOptions { executable_path: env::var("AGENT_BROWSER_EXECUTABLE_PATH").ok(), proxy: env::var("AGENT_BROWSER_PROXY").ok(), proxy_bypass: env::var("AGENT_BROWSER_PROXY_BYPASS").ok(), - profile: env::var("AGENT_BROWSER_PROFILE").ok(), + profile: env::var("AGENT_BROWSER_PROFILE").ok().map(|p| { + match env::var("AGENT_BROWSER_SESSION").ok() { + Some(session) => session_scoped_profile(&p, &session), + None => p, + } + }), allow_file_access: env::var("AGENT_BROWSER_ALLOW_FILE_ACCESS") .map(|v| v == "1" || v == "true") .unwrap_or(false), @@ -1148,7 +1166,7 @@ async fn handle_launch(cmd: &Value, state: &mut DaemonState) -> Result Persist login sessions across restarts (cookies, IndexedDB, cache) (or AGENT_BROWSER_PROFILE env) + When used with --session, data is stored in // --session-name Auto-save/restore cookies and localStorage by name (or AGENT_BROWSER_SESSION_NAME env) --state Load saved auth state (cookies + storage) from JSON file diff --git a/docs/src/app/sessions/page.mdx b/docs/src/app/sessions/page.mdx index 1fe44c74f..3cf0e154b 100644 --- a/docs/src/app/sessions/page.mdx +++ b/docs/src/app/sessions/page.mdx @@ -57,6 +57,16 @@ The profile directory stores: - Browser cache - Login sessions +**Using `--profile` with `--session`**: When combining `--profile` with `--session`, each session stores its Chrome data in a separate subdirectory (`//`). This ensures that concurrent sessions sharing the same base profile path each launch their own independent Chrome instance. For example: + +```bash +# Two independent Chrome instances, each with their own persisted data +agent-browser --profile ~/.myapp-profile --session work open app.example.com +agent-browser --profile ~/.myapp-profile --session personal open app.example.com +# work data -> ~/.myapp-profile/work/ +# personal data -> ~/.myapp-profile/personal/ +``` + ## Import auth from your browser If you are already logged in to a site in Chrome, you can grab that auth state and reuse it in agent-browser. This is the fastest way to bypass login flows, OAuth, SSO, or 2FA. diff --git a/skills/agent-browser/SKILL.md b/skills/agent-browser/SKILL.md index 73bd7848c..fb45d9728 100644 --- a/skills/agent-browser/SKILL.md +++ b/skills/agent-browser/SKILL.md @@ -72,6 +72,8 @@ agent-browser --profile ~/.myapp open https://app.example.com/login agent-browser --profile ~/.myapp open https://app.example.com/dashboard ``` +When using `--profile` with `--session`, each session stores its Chrome data in a separate subdirectory (`//`) so that concurrent sessions with the same base profile path run independent Chrome instances without conflict. + **Option 3: Session name (auto-save/restore cookies + localStorage)** ```bash