(skip_confirm: bool)
| 1762 | } |
| 1763 | |
| 1764 | fn cmd_uninstall(skip_confirm: bool) -> Result<(), Box<dyn std::error::Error>> { |
| 1765 | tui::print_banner("Uninstall"); |
| 1766 | |
| 1767 | if !nix::unistd::getuid().is_root() { |
| 1768 | tui::print_callout( |
| 1769 | "Administrative Privileges Required", |
| 1770 | &[ |
| 1771 | "This process needs to remove secured files and the", |
| 1772 | "system user safely.", |
| 1773 | "", |
| 1774 | "Please re-run with sudo:", |
| 1775 | "", |
| 1776 | " $ sudo clawshell uninstall", |
| 1777 | ], |
| 1778 | ); |
| 1779 | std::process::exit(1); |
| 1780 | } |
| 1781 | |
| 1782 | ensure_default_config_migrated_if_present()?; |
| 1783 | |
| 1784 | tui::print_warning("Administrative privileges in use — removing secured files safely."); |
| 1785 | println!(); |
| 1786 | |
| 1787 | let exe_path = std::env::current_exe()?; |
| 1788 | let config_dir = PathBuf::from(process::CONFIG_DIR); |
| 1789 | let log_dir = process::log_file_path() |
| 1790 | .parent() |
| 1791 | .map(|p| p.to_path_buf()) |
| 1792 | .unwrap_or_else(|| PathBuf::from("/var/log/clawshell")); |
| 1793 | |
| 1794 | let service_path = std::path::Path::new(crate::onboard::autostart_service_path()); |
| 1795 | let service_exists = service_path.exists(); |
| 1796 | let clawshell_config_file = config_dir.join("config.json"); |
| 1797 | let openclaw_path = if clawshell_config_file.exists() { |
| 1798 | try_read_openclaw_config_path(&clawshell_config_file) |
| 1799 | } else { |
| 1800 | None |
| 1801 | }; |
| 1802 | // Build (skill_name, skill_dir, inspection) triples for every managed |
| 1803 | // OpenClaw skill, so the preview and removal blocks can iterate. Stats |
| 1804 | // is listed first so it's still cleaned up even if the email skill is |
| 1805 | // absent (or vice-versa). |
| 1806 | let openclaw_skill_entries: Vec<(&'static str, PathBuf, onboard::ManagedSkillInspection)> = |
| 1807 | if let Some(openclaw_path) = openclaw_path.as_ref() { |
| 1808 | let skills_root = onboard::openclaw_config_root(openclaw_path).join("skills"); |
| 1809 | [ |
| 1810 | onboard::ADMIN_STATS_SKILL_NAME, |
| 1811 | onboard::EMAIL_MESSAGES_SKILL_NAME, |
| 1812 | ] |
| 1813 | .into_iter() |
| 1814 | .map(|name| { |
| 1815 | let skill_dir = skills_root.join(name); |
| 1816 | let manifest = if clawshell_config_file.exists() { |
| 1817 | onboard::read_managed_skill_manifest_entry(&clawshell_config_file, name) |
| 1818 | } else { |
| 1819 | None |
| 1820 | }; |
| 1821 | let inspection = onboard::inspect_managed_skill_for_uninstall( |
no test coverage detected