codex-cli-sdk 0.0.1

Rust SDK for the OpenAI Codex CLI
Documentation
//! Approval callbacks — intercept and approve/deny agent actions.
//!
//! Demonstrates both exec approval (`ApprovalPolicy::OnRequest`) and the
//! four possible decisions: `Approved`, `ApprovedForSession`, `Denied`, `Abort`.
//!
//! ```bash
//! cargo run --example 04_approval
//! ```

use codex_cli_sdk::config::ApprovalPolicy;
use codex_cli_sdk::permissions::{ApprovalCallback, ApprovalContext, ApprovalDecision};
use codex_cli_sdk::{Codex, CodexConfig, ThreadOptions};
use std::sync::Arc;

#[tokio::main]
async fn main() -> codex_cli_sdk::Result<()> {
    let codex = Codex::new(CodexConfig::default())?;

    let options = ThreadOptions::builder()
        .approval(ApprovalPolicy::OnRequest)
        .build();

    // Approve read-only commands; approve writes for the session; deny everything else
    let callback: ApprovalCallback = Arc::new(|ctx: ApprovalContext| {
        Box::pin(async move {
            let cmd = &ctx.request.command;
            println!("\n[approval] {cmd}");

            if cmd.starts_with("cat ")
                || cmd.starts_with("ls ")
                || cmd.starts_with("find ")
                || cmd.starts_with("grep ")
            {
                println!("  -> Approved (read-only)");
                ApprovalDecision::Approved.into()
            } else if cmd.starts_with("cargo ") || cmd.starts_with("rustfmt ") {
                println!("  -> Approved for session (build tool)");
                ApprovalDecision::ApprovedForSession.into()
            } else if cmd.starts_with("rm ") || cmd.starts_with("sudo ") {
                println!("  -> Denied (destructive)");
                ApprovalDecision::Denied.into()
            } else {
                println!("  -> Approved");
                ApprovalDecision::Approved.into()
            }
        })
    });

    let mut thread = codex.start_thread(options).with_approval_callback(callback);

    let turn = thread
        .run(
            "Set up a new Rust project called my-app",
            Default::default(),
        )
        .await?;

    println!("\nResponse:\n{}", turn.final_response);

    Ok(())
}