Skip to main content

vtcode_core/cli/
tool_policy_commands.rs

1//! CLI commands for managing tool policies
2
3use crate::tool_policy::{ToolPolicy, ToolPolicyManager};
4use crate::tools::ToolRegistry;
5use crate::utils::colors::style;
6use anyhow::Result;
7use clap::Subcommand;
8
9/// Tool policy management commands
10#[derive(Debug, Clone, Subcommand)]
11pub enum ToolPolicyCommands {
12    /// Show current tool policy status
13    Status,
14    /// Allow a specific tool
15    Allow {
16        /// Tool name to allow
17        tool: String,
18    },
19    /// Deny a specific tool
20    Deny {
21        /// Tool name to deny
22        tool: String,
23    },
24    /// Set a tool to prompt for confirmation
25    Prompt {
26        /// Tool name to set to prompt
27        tool: String,
28    },
29    /// Allow all tools
30    AllowAll,
31    /// Deny all tools
32    DenyAll,
33    /// Reset all tools to prompt
34    ResetAll,
35}
36
37/// Handle tool policy commands
38pub async fn handle_tool_policy_command(command: ToolPolicyCommands) -> Result<()> {
39    let mut policy_manager = ToolPolicyManager::new().await?;
40
41    match command {
42        ToolPolicyCommands::Status => {
43            policy_manager.print_status();
44        }
45        ToolPolicyCommands::Allow { tool } => {
46            let normalized_tool = normalize_cli_tool_name(&tool).await;
47            policy_manager
48                .set_policy(&normalized_tool, ToolPolicy::Allow)
49                .await?;
50            println!(
51                "{}",
52                style(format!(
53                    "✓ Tool '{}' is now allowed",
54                    display_tool_name(&tool, &normalized_tool)
55                ))
56                .green()
57            );
58        }
59        ToolPolicyCommands::Deny { tool } => {
60            let normalized_tool = normalize_cli_tool_name(&tool).await;
61            policy_manager
62                .set_policy(&normalized_tool, ToolPolicy::Deny)
63                .await?;
64            println!(
65                "{}",
66                style(format!(
67                    "✗ Tool '{}' is now denied",
68                    display_tool_name(&tool, &normalized_tool)
69                ))
70                .red()
71            );
72        }
73        ToolPolicyCommands::Prompt { tool } => {
74            let normalized_tool = normalize_cli_tool_name(&tool).await;
75            policy_manager
76                .set_policy(&normalized_tool, ToolPolicy::Prompt)
77                .await?;
78            println!(
79                "{}",
80                style(format!(
81                    "? Tool '{}' will now prompt for confirmation",
82                    display_tool_name(&tool, &normalized_tool)
83                ))
84                .cyan()
85            );
86        }
87        ToolPolicyCommands::AllowAll => {
88            policy_manager.allow_all_tools().await?;
89            println!("{}", style("✓ All tools are now allowed").green());
90        }
91        ToolPolicyCommands::DenyAll => {
92            policy_manager.deny_all_tools().await?;
93            println!("{}", style("✗ All tools are now denied").red());
94        }
95        ToolPolicyCommands::ResetAll => {
96            policy_manager.reset_all_to_prompt().await?;
97            println!(
98                "{}",
99                style("? All tools reset to prompt for confirmation").cyan()
100            );
101        }
102    }
103
104    Ok(())
105}
106
107async fn normalize_cli_tool_name(tool: &str) -> String {
108    let Ok(workspace_root) = std::env::current_dir() else {
109        return tool.to_string();
110    };
111
112    let registry = ToolRegistry::new(workspace_root).await;
113    registry
114        .resolve_public_tool_name_sync(tool)
115        .unwrap_or_else(|_| tool.to_string())
116}
117
118fn display_tool_name(requested_tool: &str, normalized_tool: &str) -> String {
119    if requested_tool == normalized_tool {
120        requested_tool.to_string()
121    } else {
122        format!("{requested_tool} -> {normalized_tool}")
123    }
124}
125
126/// Print tool policy help
127pub fn print_tool_policy_help() {
128    println!("{}", style("Tool Policy Management").cyan().bold());
129    println!();
130    println!("Tool policies control which tools the agent can use:");
131    println!();
132    println!(
133        "  {} - Tool executes automatically without prompting",
134        style("allow").green()
135    );
136    println!(
137        "  {} - Tool prompts for user confirmation each time",
138        style("prompt").cyan()
139    );
140    println!(
141        "  {} - Tool is never allowed to execute",
142        style("deny").red()
143    );
144    println!();
145    println!("Policies are stored in ~/.vtcode/tool-policy.json");
146    println!("Once you approve or deny a tool, your choice is remembered for future runs.");
147    println!();
148    println!("Examples:");
149    println!("  vtcode tool-policy status           # Show current policies");
150    println!("  vtcode tool-policy allow read_file  # Allow read_file tool");
151    println!("  vtcode tool-policy deny rm          # Deny rm tool");
152    println!("  vtcode tool-policy reset-all        # Reset all to prompt");
153}