Browse Source

feat: Make shell configurable via config file (#23)

Ed Zynda 9 months ago
parent
commit
4a444e9c9b
3 changed files with 60 additions and 4 deletions
  1. 33 0
      README.md
  2. 7 0
      internal/config/config.go
  3. 20 4
      internal/llm/tools/shell/shell.go

+ 33 - 0
README.md

@@ -136,6 +136,10 @@ You can configure OpenCode using environment variables:
       "command": "gopls"
     }
   },
+  "shell": {
+    "path": "/bin/zsh",
+    "args": ["-l"]
+  },
   "debug": false,
   "debugLSP": false
 }
@@ -411,6 +415,35 @@ You can define any of the following color keys in your `customTheme`:
 
 You don't need to define all colors. Any undefined colors will fall back to the default "opencode" theme colors.
 
+### Shell Configuration
+
+OpenCode allows you to configure the shell used by the `bash` tool. By default, it uses:
+1. The shell specified in the config file (if provided)
+2. The shell from the `$SHELL` environment variable (if available)
+3. Falls back to `/bin/bash` if neither of the above is available
+
+To configure a custom shell, add a `shell` section to your `.opencode.json` configuration file:
+
+```json
+{
+  "shell": {
+    "path": "/bin/zsh",
+    "args": ["-l"]
+  }
+}
+```
+
+You can specify any shell executable and custom arguments:
+
+```json
+{
+  "shell": {
+    "path": "/usr/bin/fish",
+    "args": []
+  }
+}
+```
+
 ## Architecture
 
 OpenCode is built with a modular architecture:

+ 7 - 0
internal/config/config.go

@@ -73,6 +73,12 @@ type TUIConfig struct {
 	CustomTheme map[string]any `json:"customTheme,omitempty"`
 }
 
+// ShellConfig defines the configuration for the shell used by the bash tool.
+type ShellConfig struct {
+	Path string   `json:"path,omitempty"`
+	Args []string `json:"args,omitempty"`
+}
+
 // Config is the main configuration structure for the application.
 type Config struct {
 	Data         Data                              `json:"data"`
@@ -85,6 +91,7 @@ type Config struct {
 	DebugLSP     bool                              `json:"debugLSP,omitempty"`
 	ContextPaths []string                          `json:"contextPaths,omitempty"`
 	TUI          TUIConfig                         `json:"tui"`
+	Shell        ShellConfig                       `json:"shell,omitempty"`
 }
 
 // Application constants

+ 20 - 4
internal/llm/tools/shell/shell.go

@@ -12,6 +12,7 @@ import (
 	"syscall"
 	"time"
 
+	"github.com/sst/opencode/internal/config"
 	"github.com/sst/opencode/internal/status"
 )
 
@@ -59,12 +60,27 @@ func GetPersistentShell(workingDir string) *PersistentShell {
 }
 
 func newPersistentShell(cwd string) *PersistentShell {
-	shellPath := os.Getenv("SHELL")
-	if shellPath == "" {
-		shellPath = "/bin/bash"
+	cfg := config.Get()
+	
+	// Use shell from config if specified
+	shellPath := ""
+	shellArgs := []string{"-l"}
+	
+	if cfg != nil && cfg.Shell.Path != "" {
+		shellPath = cfg.Shell.Path
+		if len(cfg.Shell.Args) > 0 {
+			shellArgs = cfg.Shell.Args
+		}
+	} else {
+		// Fall back to environment variable
+		shellPath = os.Getenv("SHELL")
+		if shellPath == "" {
+			// Default to bash if neither config nor environment variable is set
+			shellPath = "/bin/bash"
+		}
 	}
 
-	cmd := exec.Command(shellPath, "-l")
+	cmd := exec.Command(shellPath, shellArgs...)
 	cmd.Dir = cwd
 
 	stdinPipe, err := cmd.StdinPipe()