Skip to main content

codex_wrapper/command/
raw.rs

1use crate::Codex;
2use crate::command::CodexCommand;
3use crate::error::Result;
4use crate::exec::{self, CommandOutput};
5
6/// Run an arbitrary codex subcommand with raw arguments.
7///
8/// Use this when the higher-level command builders do not cover the subcommand
9/// or flags you need. The first argument passed to [`RawCommand::new`] becomes
10/// the subcommand name; additional arguments are appended with
11/// [`arg`](RawCommand::arg) or [`args`](RawCommand::args).
12///
13/// # Example
14///
15/// ```no_run
16/// use codex_wrapper::{Codex, CodexCommand, RawCommand};
17///
18/// # async fn example() -> codex_wrapper::Result<()> {
19/// let codex = Codex::builder().build()?;
20/// let output = RawCommand::new("mcp")
21///     .args(["list", "--json"])
22///     .execute(&codex)
23///     .await?;
24/// println!("{}", output.stdout);
25/// # Ok(())
26/// # }
27/// ```
28#[derive(Debug, Clone)]
29pub struct RawCommand {
30    command_args: Vec<String>,
31}
32
33impl RawCommand {
34    /// Create a new raw command with the given subcommand name.
35    #[must_use]
36    pub fn new(subcommand: impl Into<String>) -> Self {
37        Self {
38            command_args: vec![subcommand.into()],
39        }
40    }
41
42    /// Append a single argument.
43    #[must_use]
44    pub fn arg(mut self, arg: impl Into<String>) -> Self {
45        self.command_args.push(arg.into());
46        self
47    }
48
49    /// Append multiple arguments.
50    #[must_use]
51    pub fn args(mut self, args: impl IntoIterator<Item = impl Into<String>>) -> Self {
52        self.command_args.extend(args.into_iter().map(Into::into));
53        self
54    }
55}
56
57impl CodexCommand for RawCommand {
58    type Output = CommandOutput;
59
60    fn args(&self) -> Vec<String> {
61        self.command_args.clone()
62    }
63
64    async fn execute(&self, codex: &Codex) -> Result<CommandOutput> {
65        exec::run_codex(codex, self.args()).await
66    }
67}
68
69#[cfg(test)]
70mod tests {
71    use super::*;
72    use crate::command::CodexCommand;
73
74    #[test]
75    fn raw_command_args() {
76        let cmd = RawCommand::new("mcp").args(["list", "--json"]);
77        assert_eq!(CodexCommand::args(&cmd), vec!["mcp", "list", "--json"]);
78    }
79}