claude_rust_tools/infrastructure/
enter_worktree_tool.rs1use claude_rust_errors::{AppError, AppResult};
2use claude_rust_types::{PermissionLevel, Tool};
3use serde_json::{Value, json};
4use tokio::process::Command;
5
6pub struct EnterWorktreeTool;
7
8impl EnterWorktreeTool {
9 pub fn new() -> Self {
10 Self
11 }
12}
13
14#[async_trait::async_trait]
15impl Tool for EnterWorktreeTool {
16 fn name(&self) -> &str {
17 "enter_worktree"
18 }
19
20 fn description(&self) -> &str {
21 "Create a git worktree for the specified branch."
22 }
23
24 fn input_schema(&self) -> Value {
25 json!({
26 "type": "object",
27 "properties": {
28 "branch": {
29 "type": "string",
30 "description": "Branch name to create the worktree for"
31 },
32 "path": {
33 "type": "string",
34 "description": "Path for the worktree directory (defaults to ../branch-name)"
35 }
36 },
37 "required": ["branch"]
38 })
39 }
40
41 fn permission_level(&self) -> PermissionLevel {
42 PermissionLevel::Dangerous
43 }
44
45 fn is_destructive(&self, _input: &Value) -> bool { true }
46
47 async fn execute(&self, input: Value) -> AppResult<String> {
48 let branch = input
49 .get("branch")
50 .and_then(|v| v.as_str())
51 .ok_or_else(|| AppError::Tool("missing 'branch' field".into()))?;
52
53 let default_path = format!("../{branch}");
54 let path = input
55 .get("path")
56 .and_then(|v| v.as_str())
57 .unwrap_or(&default_path);
58
59 tracing::info!(branch, path, "creating worktree");
60
61 let output = Command::new("git")
63 .args(["worktree", "add", path, "-b", branch])
64 .output()
65 .await
66 .map_err(|e| AppError::Tool(format!("failed to run git: {e}")))?;
67
68 if output.status.success() {
69 return Ok(format!("Created worktree at '{path}' on new branch '{branch}'."));
70 }
71
72 let output = Command::new("git")
74 .args(["worktree", "add", path, branch])
75 .output()
76 .await
77 .map_err(|e| AppError::Tool(format!("failed to run git: {e}")))?;
78
79 if output.status.success() {
80 Ok(format!("Created worktree at '{path}' on existing branch '{branch}'."))
81 } else {
82 let stderr = String::from_utf8_lossy(&output.stderr);
83 Err(AppError::Tool(format!("git worktree add failed: {stderr}")))
84 }
85 }
86}