Skip to main content

claude_wrapper/command/
auto_mode.rs

1//! `claude auto-mode` subcommands: inspect the auto-mode classifier
2//! configuration.
3//!
4//! The CLI exposes three children under `auto-mode`:
5//!
6//! - [`AutoModeConfigCommand`] -- `auto-mode config`, the effective
7//!   merged config as JSON.
8//! - [`AutoModeDefaultsCommand`] -- `auto-mode defaults`, the default
9//!   rules as JSON.
10//! - [`AutoModeCritiqueCommand`] -- `auto-mode critique`, AI feedback
11//!   on your custom auto-mode rules.
12
13#[cfg(feature = "async")]
14use crate::Claude;
15use crate::command::ClaudeCommand;
16#[cfg(feature = "async")]
17use crate::error::Result;
18#[cfg(feature = "async")]
19use crate::exec;
20use crate::exec::CommandOutput;
21
22/// Print the effective auto-mode config as JSON.
23///
24/// Emits your settings where set and defaults otherwise, merged.
25///
26/// # Example
27///
28/// ```no_run
29/// # #[cfg(feature = "async")] {
30/// use claude_wrapper::{AutoModeConfigCommand, Claude, ClaudeCommand};
31///
32/// # async fn example() -> claude_wrapper::Result<()> {
33/// let claude = Claude::builder().build()?;
34/// let output = AutoModeConfigCommand::new().execute(&claude).await?;
35/// println!("{}", output.stdout);
36/// # Ok(()) }
37/// # }
38/// ```
39#[derive(Debug, Clone, Default)]
40pub struct AutoModeConfigCommand;
41
42impl AutoModeConfigCommand {
43    #[must_use]
44    pub fn new() -> Self {
45        Self
46    }
47}
48
49impl ClaudeCommand for AutoModeConfigCommand {
50    type Output = CommandOutput;
51
52    fn args(&self) -> Vec<String> {
53        vec!["auto-mode".to_string(), "config".to_string()]
54    }
55
56    #[cfg(feature = "async")]
57    async fn execute(&self, claude: &Claude) -> Result<CommandOutput> {
58        exec::run_claude(claude, self.args()).await
59    }
60}
61
62/// Print the default auto-mode environment, allow, and deny rules as
63/// JSON. Useful as a reference when writing custom rules.
64#[derive(Debug, Clone, Default)]
65pub struct AutoModeDefaultsCommand;
66
67impl AutoModeDefaultsCommand {
68    #[must_use]
69    pub fn new() -> Self {
70        Self
71    }
72}
73
74impl ClaudeCommand for AutoModeDefaultsCommand {
75    type Output = CommandOutput;
76
77    fn args(&self) -> Vec<String> {
78        vec!["auto-mode".to_string(), "defaults".to_string()]
79    }
80
81    #[cfg(feature = "async")]
82    async fn execute(&self, claude: &Claude) -> Result<CommandOutput> {
83        exec::run_claude(claude, self.args()).await
84    }
85}
86
87/// Get AI feedback on your custom auto-mode rules.
88///
89/// Takes an optional model override; without one the CLI picks its
90/// default. Output is free-form text.
91///
92/// # Example
93///
94/// ```no_run
95/// # #[cfg(feature = "async")] {
96/// use claude_wrapper::{AutoModeCritiqueCommand, Claude, ClaudeCommand};
97///
98/// # async fn example() -> claude_wrapper::Result<()> {
99/// let claude = Claude::builder().build()?;
100/// let output = AutoModeCritiqueCommand::new()
101///     .model("opus")
102///     .execute(&claude)
103///     .await?;
104/// println!("{}", output.stdout);
105/// # Ok(()) }
106/// # }
107/// ```
108#[derive(Debug, Clone, Default)]
109pub struct AutoModeCritiqueCommand {
110    model: Option<String>,
111}
112
113impl AutoModeCritiqueCommand {
114    #[must_use]
115    pub fn new() -> Self {
116        Self::default()
117    }
118
119    /// Override the model used for the critique.
120    #[must_use]
121    pub fn model(mut self, model: impl Into<String>) -> Self {
122        self.model = Some(model.into());
123        self
124    }
125}
126
127impl ClaudeCommand for AutoModeCritiqueCommand {
128    type Output = CommandOutput;
129
130    fn args(&self) -> Vec<String> {
131        let mut args = vec!["auto-mode".to_string(), "critique".to_string()];
132        if let Some(ref model) = self.model {
133            args.push("--model".to_string());
134            args.push(model.clone());
135        }
136        args
137    }
138
139    #[cfg(feature = "async")]
140    async fn execute(&self, claude: &Claude) -> Result<CommandOutput> {
141        exec::run_claude(claude, self.args()).await
142    }
143}
144
145#[cfg(test)]
146mod tests {
147    use super::*;
148
149    #[test]
150    fn config_command_args() {
151        let cmd = AutoModeConfigCommand::new();
152        assert_eq!(
153            ClaudeCommand::args(&cmd),
154            vec!["auto-mode".to_string(), "config".to_string()]
155        );
156    }
157
158    #[test]
159    fn defaults_command_args() {
160        let cmd = AutoModeDefaultsCommand::new();
161        assert_eq!(
162            ClaudeCommand::args(&cmd),
163            vec!["auto-mode".to_string(), "defaults".to_string()]
164        );
165    }
166
167    #[test]
168    fn critique_command_defaults_omit_model() {
169        let cmd = AutoModeCritiqueCommand::new();
170        let args = ClaudeCommand::args(&cmd);
171        assert_eq!(args, vec!["auto-mode".to_string(), "critique".to_string()]);
172    }
173
174    #[test]
175    fn critique_command_with_model() {
176        let cmd = AutoModeCritiqueCommand::new().model("opus");
177        let args = ClaudeCommand::args(&cmd);
178        assert_eq!(
179            args,
180            vec![
181                "auto-mode".to_string(),
182                "critique".to_string(),
183                "--model".to_string(),
184                "opus".to_string(),
185            ]
186        );
187    }
188}