Skip to main content

rustyclaw_core/
args.rs

1use crate::config::Config;
2use clap::{ArgAction, Args};
3use std::path::PathBuf;
4
5// Global flags shared across every subcommand.
6//
7// Mirrors openclaw's global options:
8//   --profile <name>   Isolate state under ~/.rustyclaw-<name>
9//   --no-color         Disable coloured terminal output
10//   -c / --config      Path to a config.toml file
11//   --settings-dir     Root state directory override
12#[derive(Debug, Clone, Args)]
13pub struct CommonArgs {
14    /// Path to a config.toml file
15    #[arg(short = 'c', long, value_name = "PATH", env = "RUSTYCLAW_CONFIG", global = true)]
16    pub config: Option<PathBuf>,
17
18    /// Settings directory (default: ~/.rustyclaw)
19    #[arg(long, value_name = "DIR", env = "RUSTYCLAW_SETTINGS_DIR", global = true)]
20    pub settings_dir: Option<PathBuf>,
21
22    /// Isolate state under ~/.rustyclaw-<PROFILE>
23    #[arg(long, value_name = "PROFILE", env = "RUSTYCLAW_PROFILE", global = true)]
24    pub profile: Option<String>,
25
26    /// Disable coloured terminal output
27    #[arg(long = "no-color", action = ArgAction::SetTrue, env = "NO_COLOR", global = true)]
28    pub no_color: bool,
29
30    /// Path to SOUL.md
31    #[arg(long, value_name = "PATH", env = "RUSTYCLAW_SOUL", global = true)]
32    pub soul: Option<PathBuf>,
33
34    /// Skills directory
35    #[arg(long = "skills", value_name = "DIR", env = "RUSTYCLAW_SKILLS", global = true)]
36    pub skills_dir: Option<PathBuf>,
37
38    /// Disable secrets storage
39    #[arg(long = "no-secrets", action = ArgAction::SetTrue, global = true)]
40    pub no_secrets: bool,
41
42    /// Gateway WebSocket URL (ws://…)
43    #[arg(long = "gateway", value_name = "WS_URL", env = "RUSTYCLAW_GATEWAY", global = true)]
44    pub gateway: Option<String>,
45}
46
47impl CommonArgs {
48    /// Resolve the effective settings directory, honouring `--profile`.
49    pub fn effective_settings_dir(&self) -> Option<PathBuf> {
50        if let Some(dir) = &self.settings_dir {
51            return Some(dir.clone());
52        }
53        if let Some(profile) = &self.profile {
54            let home = dirs::home_dir().unwrap_or_else(|| PathBuf::from("."));
55            return Some(home.join(format!(".rustyclaw-{}", profile)));
56        }
57        None
58    }
59
60    pub fn config_path(&self) -> Option<PathBuf> {
61        if let Some(config) = &self.config {
62            return Some(config.clone());
63        }
64
65        if let Some(settings_dir) = self.effective_settings_dir() {
66            return Some(settings_dir.join("config.toml"));
67        }
68
69        None
70    }
71
72    pub fn apply_overrides(&self, config: &mut Config) {
73        if let Some(settings_dir) = self.effective_settings_dir() {
74            config.settings_dir = settings_dir;
75        }
76
77        if let Some(soul) = &self.soul {
78            config.soul_path = Some(soul.clone());
79        }
80
81        if let Some(skills_dir) = &self.skills_dir {
82            config.skills_dir = Some(skills_dir.clone());
83        }
84
85        if self.no_secrets {
86            config.use_secrets = false;
87        }
88
89        if let Some(gateway) = &self.gateway {
90            config.gateway_url = Some(gateway.clone());
91        }
92    }
93}