claudetool: minor auto-install cleanup

Follow-up to 495c1fa247565e21b36bcb847c6cd3f08e0e196f
diff --git a/claudetool/bash.go b/claudetool/bash.go
index 43659b8..39914c6 100644
--- a/claudetool/bash.go
+++ b/claudetool/bash.go
@@ -363,19 +363,6 @@
 	return nil
 }
 
-// commandExists checks if a command exists using exec.LookPath
-func commandExists(command string) bool {
-	// If it's an absolute or relative path, check if the file exists
-	if strings.Contains(command, "/") {
-		_, err := os.Stat(command)
-		return err == nil
-	}
-
-	// Otherwise, use exec.LookPath to find it in PATH
-	_, err := exec.LookPath(command)
-	return err == nil
-}
-
 // Command safety check cache to avoid repeated LLM calls
 var (
 	autoInstallMu           sync.Mutex
diff --git a/claudetool/bashkit/parsing.go b/claudetool/bashkit/parsing.go
index 2b17ae3..df37ab8 100644
--- a/claudetool/bashkit/parsing.go
+++ b/claudetool/bashkit/parsing.go
@@ -4,6 +4,7 @@
 	"fmt"
 	"strings"
 
+	"mvdan.cc/sh/v3/interp"
 	"mvdan.cc/sh/v3/syntax"
 )
 
@@ -52,7 +53,7 @@
 			// commands with slashes are user-specified executables/scripts
 			return true
 		}
-		if isBuiltin(cmdName) {
+		if interp.IsBuiltin(cmdName) {
 			return true
 		}
 		if !seen[cmdName] {
@@ -64,19 +65,3 @@
 
 	return commands, nil
 }
-
-// isBuiltin checks if a command is a shell built-in using the same logic as mvdan.cc/sh/v3/interp
-// This is copied from mvdan.cc/sh/v3/interp.isBuiltin since it's not exported
-// See https://github.com/mvdan/sh/issues/1164
-func isBuiltin(name string) bool {
-	switch name {
-	case "true", ":", "false", "exit", "set", "shift", "unset",
-		"echo", "printf", "break", "continue", "pwd", "cd",
-		"wait", "builtin", "trap", "type", "source", ".", "command",
-		"dirs", "pushd", "popd", "umask", "alias", "unalias",
-		"fg", "bg", "getopts", "eval", "test", "[", "exec",
-		"return", "read", "mapfile", "readarray", "shopt":
-		return true
-	}
-	return false
-}
diff --git a/claudetool/bashkit/parsing_test.go b/claudetool/bashkit/parsing_test.go
index 9a2b831..40e1bb0 100644
--- a/claudetool/bashkit/parsing_test.go
+++ b/claudetool/bashkit/parsing_test.go
@@ -80,32 +80,6 @@
 	}
 }
 
-func TestIsBuiltin(t *testing.T) {
-	tests := []struct {
-		name     string
-		command  string
-		expected bool
-	}{
-		{"echo is builtin", "echo", true},
-		{"cd is builtin", "cd", true},
-		{"test is builtin", "test", true},
-		{"[ is builtin", "[", true},
-		{"ls is not builtin", "ls", false},
-		{"curl is not builtin", "curl", false},
-		{"python3 is not builtin", "python3", false},
-		{"nonexistent is not builtin", "nonexistent", false},
-	}
-
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			result := isBuiltin(tt.command)
-			if result != tt.expected {
-				t.Errorf("IsBuiltin(%q) = %v, want %v", tt.command, result, tt.expected)
-			}
-		})
-	}
-}
-
 func TestExtractCommandsErrorHandling(t *testing.T) {
 	// Test with syntactically invalid bash
 	invalidBash := "if [ incomplete"