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(
16        short = 'c',
17        long,
18        value_name = "PATH",
19        env = "RUSTYCLAW_CONFIG",
20        global = true
21    )]
22    pub config: Option<PathBuf>,
23
24    /// Settings directory (default: ~/.rustyclaw)
25    #[arg(
26        long,
27        value_name = "DIR",
28        env = "RUSTYCLAW_SETTINGS_DIR",
29        global = true
30    )]
31    pub settings_dir: Option<PathBuf>,
32
33    /// Isolate state under ~/.rustyclaw-<PROFILE>
34    #[arg(long, value_name = "PROFILE", env = "RUSTYCLAW_PROFILE", global = true)]
35    pub profile: Option<String>,
36
37    /// Disable coloured terminal output
38    #[arg(long = "no-color", action = ArgAction::SetTrue, env = "NO_COLOR", global = true)]
39    pub no_color: bool,
40
41    /// Path to SOUL.md
42    #[arg(long, value_name = "PATH", env = "RUSTYCLAW_SOUL", global = true)]
43    pub soul: Option<PathBuf>,
44
45    /// Skills directory
46    #[arg(
47        long = "skills",
48        value_name = "DIR",
49        env = "RUSTYCLAW_SKILLS",
50        global = true
51    )]
52    pub skills_dir: Option<PathBuf>,
53
54    /// Disable secrets storage
55    #[arg(long = "no-secrets", action = ArgAction::SetTrue, global = true)]
56    pub no_secrets: bool,
57
58    /// Gateway WebSocket URL (ws://…)
59    #[arg(
60        long = "gateway",
61        value_name = "WS_URL",
62        env = "RUSTYCLAW_GATEWAY",
63        global = true
64    )]
65    pub gateway: Option<String>,
66}
67
68impl CommonArgs {
69    /// Resolve the effective settings directory, honouring `--profile`.
70    pub fn effective_settings_dir(&self) -> Option<PathBuf> {
71        if let Some(dir) = &self.settings_dir {
72            return Some(dir.clone());
73        }
74        if let Some(profile) = &self.profile {
75            let home = dirs::home_dir().unwrap_or_else(|| PathBuf::from("."));
76            return Some(home.join(format!(".rustyclaw-{}", profile)));
77        }
78        None
79    }
80
81    pub fn config_path(&self) -> Option<PathBuf> {
82        if let Some(config) = &self.config {
83            return Some(config.clone());
84        }
85
86        if let Some(settings_dir) = self.effective_settings_dir() {
87            return Some(settings_dir.join("config.toml"));
88        }
89
90        None
91    }
92
93    pub fn apply_overrides(&self, config: &mut Config) {
94        if let Some(settings_dir) = self.effective_settings_dir() {
95            config.settings_dir = settings_dir;
96        }
97
98        if let Some(soul) = &self.soul {
99            config.soul_path = Some(soul.clone());
100        }
101
102        if let Some(skills_dir) = &self.skills_dir {
103            config.skills_dir = Some(skills_dir.clone());
104        }
105
106        if self.no_secrets {
107            config.use_secrets = false;
108        }
109
110        if let Some(gateway) = &self.gateway {
111            config.gateway_url = Some(gateway.clone());
112        }
113    }
114}