From 601404ba726dcc721b1973889ae41104791ef601 Mon Sep 17 00:00:00 2001 From: leeguooooo Date: Thu, 18 Jun 2026 14:44:35 +0900 Subject: [PATCH] feat(session): session stop + session prune + lifecycle docs (#48) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Explicit daemon reclamation to go with the v1.5.25 idle auto-shutdown: - `session stop [name]` — stop one session daemon (default: current), graceful (SIGTERM → the daemon's shutdown runs close(), tidying the tabs it created). - `session prune` — stop ALL session daemons now (clears the pile of idle daemons left after an automation/debug round; they respawn clean on next use). The __nm-host relay isn't a tracked session daemon, so the live-Chrome connection survives. - --help Sessions section now documents the daemon lifecycle: spawn → 10-min idle auto-shutdown (AGENT_BROWSER_IDLE_TIMEOUT_MS / 0 to disable) → keep / stop / prune. Closes #48. Verified live: session stop reclaimed a test daemon. 870 tests pass. --- cli/Cargo.lock | 2 +- cli/Cargo.toml | 2 +- cli/src/main.rs | 43 +++++++++++++++++++++++++++++++++++++++++++ cli/src/output.rs | 10 ++++++++++ package.json | 2 +- 5 files changed, 56 insertions(+), 3 deletions(-) diff --git a/cli/Cargo.lock b/cli/Cargo.lock index ba8231f..de4f6ea 100644 --- a/cli/Cargo.lock +++ b/cli/Cargo.lock @@ -290,7 +290,7 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrome-use" -version = "1.5.25" +version = "1.5.26" dependencies = [ "aes", "aes-gcm", diff --git a/cli/Cargo.toml b/cli/Cargo.toml index deb65d6..e391236 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chrome-use" -version = "1.5.25" +version = "1.5.26" edition = "2021" description = "Fast browser automation CLI for AI agents" license = "Apache-2.0" diff --git a/cli/src/main.rs b/cli/src/main.rs index b3c051c..9febd40 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -305,6 +305,49 @@ fn run_session(args: &[String], session: &str, json_mode: bool) { } } } + // Stop a specific session daemon (issue #48). Graceful: kill_stale_daemon + // sends SIGTERM first, so the daemon's shutdown handler runs `close()` and + // tidies the tabs IT created (its tab group) before exiting. + Some("stop") => { + let target = args.get(2).map(|s| s.as_str()).unwrap_or(session); + connection::kill_stale_daemon(target); + if json_mode { + print_json_value(json!({ "success": true, "data": { "stopped": target } })); + } else { + println!( + "{} stopped session daemon: {}", + color::success_indicator(), + target + ); + } + } + // Reclaim ALL session daemons now (issue #48) — for clearing the pile of + // idle daemons left after a round of automation/debugging without waiting + // for the idle timeout. Each is stopped gracefully (closes its own tabs); + // they respawn clean on next use. The `__nm-host` relay is not a tracked + // session daemon, so the extension/live-Chrome connection survives. + Some("prune") => { + let sessions: Vec = walk_daemons() + .sessions + .into_iter() + .map(|s| s.name) + .collect(); + for s in &sessions { + connection::kill_stale_daemon(s); + } + if json_mode { + print_json_value(json!({ "success": true, "data": { "pruned": sessions } })); + } else if sessions.is_empty() { + println!("No session daemons to prune"); + } else { + println!( + "{} pruned {} session daemon(s): {}", + color::success_indicator(), + sessions.len(), + sessions.join(", ") + ); + } + } None | Some(_) => { // Just show current session if json_mode { diff --git a/cli/src/output.rs b/cli/src/output.rs index e2132c0..09f4ccf 100644 --- a/cli/src/output.rs +++ b/cli/src/output.rs @@ -3455,11 +3455,21 @@ Confirmation: Sessions: session Show current session name session list List active sessions + session stop [name] Stop one session daemon (default: current) — graceful, + closes the tabs it created + session prune Stop ALL session daemons now (closes their tabs; they + respawn clean on next use). For clearing idle daemons. sessions List running session daemons (alias of daemon status) daemon status List running session daemons (+ relay state) daemon restart Kill all session daemons; keeps the extension relay up. Clears stale/cross-leaked state after an upgrade. + Lifecycle: each --session spawns a background daemon that drives that + session's tabs. A daemon auto-shuts-down after 10 min idle (no commands) — + AGENT_BROWSER_IDLE_TIMEOUT_MS overrides, 0 disables — and on shutdown closes + the scratch tabs IT created (its tab group). Use `keep` to leave a tab for the + user (exempt from auto-close), `session stop/prune` to reclaim now. + Chat (AI): chat Send a natural language instruction (single-shot) chat Start interactive chat (REPL mode when stdin is a TTY) diff --git a/package.json b/package.json index 811fc7b..aab0ee0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "chrome-use", - "version": "1.5.25", + "version": "1.5.26", "description": "chrome-use — drive your real, logged-in Chrome from any AI agent, stealth by default", "type": "module", "packageManager": "pnpm@11.1.3",