pub mod openclaw;
use std::path::PathBuf;
use tracing::debug;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MigrateMode {
Seamless,
Import,
New,
}
impl MigrateMode {
pub fn from_str_loose(s: &str) -> Option<Self> {
match s.to_ascii_lowercase().as_str() {
"seamless" => Some(Self::Seamless),
"import" | "migrate" => Some(Self::Import),
"new" | "fresh" | "clean" => Some(Self::New),
_ => None,
}
}
pub fn label(&self) -> &'static str {
match self {
Self::Seamless => "seamless",
Self::Import => "import",
Self::New => "new",
}
}
}
const OPENCLAW_DIR_CANDIDATES: &[&str] = &[".openclaw", "bak.openclaw"];
pub fn detect_openclaw_dir() -> Option<PathBuf> {
if let Ok(val) = std::env::var("OPENCLAW_CONFIG_PATH") {
let config_path = PathBuf::from(&val);
if config_path.is_file() {
if let Some(dir) = config_path.parent() {
debug!(path = %dir.display(), env = "OPENCLAW_CONFIG_PATH", "found OpenClaw via config path env");
return Some(dir.to_path_buf());
}
}
}
if let Ok(val) = std::env::var("OPENCLAW_HOME") {
let dir = PathBuf::from(val);
if dir.is_dir() {
let has_config = dir.join("openclaw.json").is_file();
let has_agents = dir.join("agents").is_dir();
if has_config || has_agents {
debug!(path = %dir.display(), env = "OPENCLAW_HOME", "found OpenClaw via home env");
return Some(dir);
}
}
}
let home = dirs_next::home_dir()?;
for candidate in OPENCLAW_DIR_CANDIDATES {
let dir = home.join(candidate);
if dir.is_dir() {
let has_config = dir.join("openclaw.json").is_file();
let has_agents = dir.join("agents").is_dir();
if has_config || has_agents {
debug!(path = %dir.display(), "found OpenClaw data directory");
return Some(dir);
}
}
}
None
}
pub fn openclaw_dir_exists() -> bool {
detect_openclaw_dir().is_some()
}
pub fn rsclaw_dir_exists() -> bool {
if let Some(home) = dirs_next::home_dir() {
home.join(".rsclaw").is_dir()
} else {
false
}
}
pub fn maybe_print_openclaw_notice() -> bool {
if openclaw_dir_exists() && !rsclaw_dir_exists() {
println!(" Detected OpenClaw installation. Run `rsclaw migrate` for options.");
true
} else {
false
}
}
pub fn check_needs_setup() -> bool {
let base = crate::config::loader::base_dir();
let config_path = base.join("rsclaw.json5");
if config_path.is_file() {
return false;
}
println!();
if openclaw_dir_exists() {
println!(" First time? Run `rsclaw setup` to get started.");
println!(" OpenClaw data detected -- setup will offer to import your data.");
} else {
println!(" First time? Run `rsclaw setup` to create config and data directories.");
}
println!();
true
}