diff --git a/crates/openshell-bootstrap/src/lib.rs b/crates/openshell-bootstrap/src/lib.rs index b6423aae..343653f9 100644 --- a/crates/openshell-bootstrap/src/lib.rs +++ b/crates/openshell-bootstrap/src/lib.rs @@ -49,8 +49,9 @@ pub use crate::docker::{ }; pub use crate::metadata::{ GatewayMetadata, clear_active_gateway, extract_host_from_ssh_destination, get_gateway_metadata, - list_gateways, load_active_gateway, load_gateway_metadata, load_last_sandbox, - remove_gateway_metadata, resolve_ssh_hostname, save_active_gateway, save_last_sandbox, + clear_last_sandbox_if_matches, list_gateways, load_active_gateway, load_gateway_metadata, + load_last_sandbox, remove_gateway_metadata, resolve_ssh_hostname, save_active_gateway, + save_last_sandbox, store_gateway_metadata, }; diff --git a/crates/openshell-bootstrap/src/metadata.rs b/crates/openshell-bootstrap/src/metadata.rs index bd49ba8c..15f79c08 100644 --- a/crates/openshell-bootstrap/src/metadata.rs +++ b/crates/openshell-bootstrap/src/metadata.rs @@ -271,6 +271,20 @@ pub fn load_last_sandbox(gateway: &str) -> Option { if name.is_empty() { None } else { Some(name) } } +/// Clear the last-used sandbox record for a gateway if it matches the given name. +/// +/// This should be called after a sandbox is deleted so that subsequent commands +/// don't try to connect to a sandbox that no longer exists. +pub fn clear_last_sandbox_if_matches(gateway: &str, sandbox: &str) { + if let Some(current) = load_last_sandbox(gateway) { + if current == sandbox { + if let Ok(path) = last_sandbox_path(gateway) { + let _ = std::fs::remove_file(path); + } + } + } +} + /// List all gateways that have stored metadata. /// /// Scans `$XDG_CONFIG_HOME/openshell/gateways/` for subdirectories containing diff --git a/crates/openshell-cli/src/main.rs b/crates/openshell-cli/src/main.rs index 84a323b5..6572a286 100644 --- a/crates/openshell-cli/src/main.rs +++ b/crates/openshell-cli/src/main.rs @@ -2058,7 +2058,8 @@ async fn main() -> Result<()> { run::sandbox_list(endpoint, limit, offset, ids, names, &tls).await?; } SandboxCommands::Delete { names, all } => { - run::sandbox_delete(endpoint, &names, all, &tls).await?; + run::sandbox_delete(endpoint, &names, all, &tls, &ctx.name) + .await?; } SandboxCommands::Connect { name, editor } => { let name = resolve_sandbox_name(name, &ctx.name)?; diff --git a/crates/openshell-cli/src/run.rs b/crates/openshell-cli/src/run.rs index 37f11fcb..68dc4a68 100644 --- a/crates/openshell-cli/src/run.rs +++ b/crates/openshell-cli/src/run.rs @@ -18,7 +18,8 @@ use miette::{IntoDiagnostic, Result, WrapErr}; use openshell_bootstrap::{ DeployOptions, GatewayMetadata, RemoteOptions, clear_active_gateway, container_name, extract_host_from_ssh_destination, get_gateway_metadata, list_gateways, load_active_gateway, - remove_gateway_metadata, resolve_ssh_hostname, save_active_gateway, save_last_sandbox, + clear_last_sandbox_if_matches, remove_gateway_metadata, resolve_ssh_hostname, + save_active_gateway, save_last_sandbox, store_gateway_metadata, }; use openshell_core::proto::{ @@ -2743,6 +2744,7 @@ pub async fn sandbox_delete( names: &[String], all: bool, tls: &TlsOptions, + gateway: &str, ) -> Result<()> { let mut client = grpc_client(server, tls).await?; @@ -2783,6 +2785,7 @@ pub async fn sandbox_delete( let deleted = response.into_inner().deleted; if deleted { + clear_last_sandbox_if_matches(gateway, name); println!("{} Deleted sandbox {name}", "✓".green().bold()); } else { println!("{} Sandbox {name} not found", "!".yellow());