Skip to main content

claude_code_rs/types/
permissions.rs

1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3use std::future::Future;
4use std::pin::Pin;
5use std::sync::Arc;
6
7/// Permission mode for tool usage.
8#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
9#[serde(rename_all = "lowercase")]
10#[non_exhaustive]
11pub enum PermissionMode {
12    /// Default permissions - prompt user for dangerous tools.
13    Default,
14    /// Accept all tool uses without prompting.
15    AcceptAll,
16    /// Deny all tool uses.
17    DenyAll,
18    /// Use allowed-tools list from CLI config.
19    AllowedTools,
20}
21
22impl Default for PermissionMode {
23    fn default() -> Self {
24        Self::Default
25    }
26}
27
28/// Result from a permission check callback.
29#[derive(Debug, Clone, Serialize, Deserialize)]
30pub struct PermissionResult {
31    /// Whether the tool use is allowed.
32    pub allowed: bool,
33    /// Optional reason for denial.
34    #[serde(default, skip_serializing_if = "Option::is_none")]
35    pub reason: Option<String>,
36}
37
38impl PermissionResult {
39    #[must_use]
40    pub fn allow() -> Self {
41        Self {
42            allowed: true,
43            reason: None,
44        }
45    }
46
47    #[must_use]
48    pub fn deny(reason: impl Into<String>) -> Self {
49        Self {
50            allowed: false,
51            reason: Some(reason.into()),
52        }
53    }
54}
55
56/// Input provided to the can_use_tool callback.
57#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct CanUseToolInput {
59    pub tool_name: String,
60    pub input: Value,
61}
62
63/// Async callback for permission checks.
64pub type CanUseToolCallback = Arc<
65    dyn Fn(CanUseToolInput) -> Pin<Box<dyn Future<Output = PermissionResult> + Send>>
66        + Send
67        + Sync,
68>;
69
70/// Helper to create a CanUseToolCallback from a closure.
71pub fn permission_callback<F, Fut>(f: F) -> CanUseToolCallback
72where
73    F: Fn(CanUseToolInput) -> Fut + Send + Sync + 'static,
74    Fut: Future<Output = PermissionResult> + Send + 'static,
75{
76    Arc::new(move |input| Box::pin(f(input)))
77}