diff --git a/src/channels/matrix.rs b/src/channels/matrix.rs index 38a299716..8e5ad0e4a 100644 --- a/src/channels/matrix.rs +++ b/src/channels/matrix.rs @@ -765,8 +765,11 @@ impl Channel for MatrixChannel { // Download media to workspace if present let body = if let Some((url, filename)) = media_download { let workspace = std::path::PathBuf::from( - std::env::var("ZEROCLAW_WORKSPACE") - .unwrap_or_else(|_| "/tmp/zeroclaw-uploads".to_string()), + shellexpand::tilde( + &std::env::var("ZEROCLAW_WORKSPACE") + .unwrap_or_else(|_| "/tmp/zeroclaw-uploads".to_string()), + ) + .as_ref(), ); let _ = tokio::fs::create_dir_all(&workspace).await; let dest = workspace.join(&filename); diff --git a/src/config/schema.rs b/src/config/schema.rs index 5a738b2df..7eb477337 100644 --- a/src/config/schema.rs +++ b/src/config/schema.rs @@ -4090,7 +4090,8 @@ async fn load_persisted_workspace_dirs( return Ok(None); } - let parsed_dir = PathBuf::from(raw_config_dir); + let expanded_dir = shellexpand::tilde(raw_config_dir); + let parsed_dir = PathBuf::from(expanded_dir.as_ref()); let config_dir = if parsed_dir.is_absolute() { parsed_dir } else { @@ -4233,7 +4234,7 @@ async fn resolve_runtime_config_dirs( if let Ok(custom_config_dir) = std::env::var("ZEROCLAW_CONFIG_DIR") { let custom_config_dir = custom_config_dir.trim(); if !custom_config_dir.is_empty() { - let zeroclaw_dir = PathBuf::from(custom_config_dir); + let zeroclaw_dir = PathBuf::from(shellexpand::tilde(custom_config_dir).as_ref()); return Ok(( zeroclaw_dir.clone(), zeroclaw_dir.join("workspace"), @@ -4244,8 +4245,9 @@ async fn resolve_runtime_config_dirs( if let Ok(custom_workspace) = std::env::var("ZEROCLAW_WORKSPACE") { if !custom_workspace.is_empty() { + let expanded = shellexpand::tilde(&custom_workspace); let (zeroclaw_dir, workspace_dir) = - resolve_config_dir_for_workspace(&PathBuf::from(custom_workspace)); + resolve_config_dir_for_workspace(&PathBuf::from(expanded.as_ref())); return Ok(( zeroclaw_dir, workspace_dir, @@ -5094,8 +5096,9 @@ impl Config { // Workspace directory: ZEROCLAW_WORKSPACE if let Ok(workspace) = std::env::var("ZEROCLAW_WORKSPACE") { if !workspace.is_empty() { + let expanded = shellexpand::tilde(&workspace); let (_, workspace_dir) = - resolve_config_dir_for_workspace(&PathBuf::from(workspace)); + resolve_config_dir_for_workspace(&PathBuf::from(expanded.as_ref())); self.workspace_dir = workspace_dir; } } diff --git a/src/onboard/wizard.rs b/src/onboard/wizard.rs index e90913f24..85ca050a2 100644 --- a/src/onboard/wizard.rs +++ b/src/onboard/wizard.rs @@ -425,7 +425,7 @@ fn resolve_quick_setup_dirs_with_home(home: &Path) -> (PathBuf, PathBuf) { if let Ok(custom_config_dir) = std::env::var("ZEROCLAW_CONFIG_DIR") { let trimmed = custom_config_dir.trim(); if !trimmed.is_empty() { - let config_dir = PathBuf::from(trimmed); + let config_dir = PathBuf::from(shellexpand::tilde(trimmed).as_ref()); return (config_dir.clone(), config_dir.join("workspace")); } } @@ -433,8 +433,9 @@ fn resolve_quick_setup_dirs_with_home(home: &Path) -> (PathBuf, PathBuf) { if let Ok(custom_workspace) = std::env::var("ZEROCLAW_WORKSPACE") { let trimmed = custom_workspace.trim(); if !trimmed.is_empty() { + let expanded = shellexpand::tilde(trimmed); return crate::config::schema::resolve_config_dir_for_workspace(&PathBuf::from( - trimmed, + expanded.as_ref(), )); } }