@@ -4,6 +4,7 @@ import (
44 "context"
55 "encoding/json"
66 "fmt"
7+ "runtime"
78 "strings"
89 "time"
910
@@ -45,27 +46,58 @@ var bannedCommands = []string{
4546 "http-prompt", "chrome", "firefox", "safari",
4647}
4748
48−var safeReadOnlyCommands = []string{
49− "ls", "echo", "pwd", "date", "cal", "uptime", "whoami", "id", "groups", "env", "printenv", "set", "unset", "which", "type", "whereis",
50− "whatis", "uname", "hostname", "df", "du", "free", "top", "ps", "kill", "killall", "nice", "nohup", "time", "timeout",
51−
52− "git status", "git log", "git diff", "git show", "git branch", "git tag", "git remote", "git ls-files", "git ls-remote",
53− "git rev-parse", "git config --get", "git config --list", "git describe", "git blame", "git grep", "git shortlog",
49+// getSafeReadOnlyCommands returns platform-appropriate safe commands
50+func getSafeReadOnlyCommands() []string {
51+ // Base commands that work on all platforms
52+ baseCommands := []string{
53+ // Cross-platform commands
54+ "echo", "hostname", "whoami",
55+
56+ // Git commands (cross-platform)
57+ "git status", "git log", "git diff", "git show", "git branch", "git tag", "git remote", "git ls-files", "git ls-remote",
58+ "git rev-parse", "git config --get", "git config --list", "git describe", "git blame", "git grep", "git shortlog",
59+
60+ // Go commands (cross-platform)
61+ "go version", "go help", "go list", "go env", "go doc", "go vet", "go fmt", "go mod", "go test", "go build", "go run", "go install", "go clean",
62+ }
5463
55− "go version", "go help", "go list", "go env", "go doc", "go vet", "go fmt", "go mod", "go test", "go build", "go run", "go install", "go clean",
64+ if runtime.GOOS == "windows" {
65+ // Windows-specific commands
66+ windowsCommands := []string{
67+ "dir", "type", "where", "ver", "systeminfo", "tasklist", "ipconfig", "ping", "nslookup",
68+ "Get-Process", "Get-Location", "Get-ChildItem", "Get-Content", "Get-Date", "Get-Host", "Get-ComputerInfo",
69+ }
70+ return append(baseCommands, windowsCommands...)
71+ } else {
72+ // Unix/Linux commands (including WSL, since WSL reports as Linux)
73+ unixCommands := []string{
74+ "ls", "pwd", "date", "cal", "uptime", "id", "groups", "env", "printenv", "set", "unset", "which", "type", "whereis",
75+ "whatis", "uname", "df", "du", "free", "top", "ps", "kill", "killall", "nice", "nohup", "time", "timeout",
76+ }
77+ return append(baseCommands, unixCommands...)
78+ }
5679}
5780
5881func bashDescription() string {
5982 bannedCommandsStr := strings.Join(bannedCommands, ", ")
6083 return fmt.Sprintf(`Executes a given bash command in a persistent shell session with optional timeout, ensuring proper handling and security measures.
6184
62−IMPORTANT FOR WINDOWS USERS:
63−- This tool uses a POSIX shell emulator (mvdan.cc/sh/v3) that works cross-platform, including Windows
64−- On Windows, this provides bash-like functionality without requiring WSL or Git Bash
65−- Use forward slashes (/) in paths - they work on all platforms and are converted automatically
66−- Windows-specific commands (like 'dir', 'type', 'copy') are not available - use Unix equivalents ('ls', 'cat', 'cp')
67−- Environment variables use Unix syntax: $VAR instead of %%VAR%%
68−- File paths are automatically converted between Windows and Unix formats as needed
85+CROSS-PLATFORM SHELL SUPPORT:
86+- Unix/Linux/macOS: Uses native bash/sh shell
87+- Windows: Intelligent shell selection:
88+ * Windows commands (dir, type, copy, etc.) use cmd.exe
89+ * PowerShell commands (Get-, Set-, etc.) use PowerShell
90+ * Unix-style commands (ls, cat, etc.) use POSIX emulation
91+- WSL: Automatically treated as Linux (which is correct)
92+- Automatic detection: Chooses the best shell based on command and platform
93+- Persistent state: Working directory and environment variables persist between commands
94+
95+WINDOWS-SPECIFIC FEATURES:
96+- Native Windows commands: dir, type, copy, move, del, md, rd, cls, where, tasklist, etc.
97+- PowerShell support: Get-Process, Set-Location, and other PowerShell cmdlets
98+- Windows path handling: Supports both forward slashes (/) and backslashes (\)
99+- Drive letters: Properly handles C:\, D:\, etc.
100+- Environment variables: Supports both Unix ($VAR) and Windows (%%VAR%%) syntax
69101
70102Before executing the command, please follow these steps:
71103
@@ -262,6 +294,8 @@ func (b *bashTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error)
262294 isSafeReadOnly := false
263295 cmdLower := strings.ToLower(params.Command)
264296
297+ // Get platform-appropriate safe commands
298+ safeReadOnlyCommands := getSafeReadOnlyCommands()
265299 for _, safe := range safeReadOnlyCommands {
266300 if strings.HasPrefix(cmdLower, strings.ToLower(safe)) {
267301 if len(cmdLower) == len(safe) || cmdLower[len(safe)] == ' ' || cmdLower[len(safe)] == '-' {
@@ -361,4 +395,4 @@ func countLines(s string) int {
361395 return 0
362396 }
363397 return len(strings.Split(s, "\n"))
364−}
398+}