From ce952bfda6b451cccf32d6dfad3c6d45714965d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Yesid=20Corrales=20L=C3=B3pez?= Date: Tue, 12 May 2026 23:44:07 +0200 Subject: [PATCH] feat: stop a single browser by name `Command::Stop` now takes an optional NAME positional argument. dev-browser stop # daemon-wide stop (unchanged) dev-browser stop # stop just that browser, leave the daemon up The daemon's `browser-stop` IPC message and the corresponding `browserManager.stopBrowser(name)` method already existed and are covered by daemon tests; this just exposes them on the CLI. Stopping an unknown name is a silent no-op, matching the daemon's idempotent behavior. Motivated by the fact that there was previously no way to dispose a single managed browser without killing the daemon (and every other browser it manages), which makes timestamped or per-test `--browser` names accumulate forever in `dev-browser browsers`. --- cli/src/main.rs | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index b6d1d3e0..721a3f44 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -195,10 +195,16 @@ enum Command { )] Status, #[command( - about = "Stop the daemon and all browsers", - long_about = "Stop the daemon and all browsers.\n\nThis stops the background daemon process and closes every browser instance it currently manages." + about = "Stop the daemon, or a single managed browser", + long_about = "Stop the daemon and all browsers, or stop a single named browser.\n\nWithout an argument, stops the background daemon process and closes every browser instance it currently manages.\n\nWith a NAME argument, stops only that named browser instance while leaving the daemon and other browsers running. Use `dev-browser browsers` to find the name.\n\nStopping an unknown name is a no-op." )] - Stop, + Stop { + #[arg( + value_name = "NAME", + help = "Optional name of a managed browser to stop. Without this, stops the daemon and all browsers." + )] + name: Option, + }, } #[derive(Debug, Deserialize)] @@ -277,12 +283,29 @@ fn run() -> Result> { ResultMode::Status, ) } - Some(Command::Stop) => { + Some(Command::Stop { name }) => { if !is_daemon_running() { println!("Daemon is not running."); return Ok(0); } + if let Some(name) = name { + let exit_code = send_request( + json!({ + "id": request_id("browser-stop"), + "type": "browser-stop", + "browser": name, + }), + ResultMode::None, + )?; + + if exit_code == 0 { + println!("Stopped browser '{name}'."); + } + + return Ok(exit_code); + } + let daemon_pid = current_daemon_pid(); let exit_code = send_request(