From e8b4bb0eddd1f54925821b4f7ffbee9dda3f905f Mon Sep 17 00:00:00 2001 From: Ed Zynda Date: Thu, 15 May 2025 16:53:47 +0300 Subject: [PATCH] allow configuring shell (#157) --- README.md | 22 ++++++++++++++++++++++ internal/config/config.go | 15 +++++++++++++++ internal/llm/tools/shell/shell.go | 27 ++++++++++++++++++++++++--- 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e4cf0bd8ef5672e814185fd1393d803a9ecee353..fe0b4c26acd65000058cdcaf5271f73b51a5c457 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,24 @@ You can configure OpenCode using environment variables: | `AZURE_OPENAI_ENDPOINT` | For Azure OpenAI models | | `AZURE_OPENAI_API_KEY` | For Azure OpenAI models (optional when using Entra ID) | | `AZURE_OPENAI_API_VERSION` | For Azure OpenAI models | +| `SHELL` | Default shell to use (if not specified in config) | + +### Shell Configuration + +OpenCode allows you to configure the shell used by the bash tool. By default, it uses the shell specified in the `SHELL` environment variable, or falls back to `/bin/bash` if not set. + +You can override this in your configuration file: + +```json +{ + "shell": { + "path": "/bin/zsh", + "args": ["-l"] + } +} +``` + +This is useful if you want to use a different shell than your default system shell, or if you need to pass specific arguments to the shell. ### Configuration File Structure @@ -136,6 +154,10 @@ You can configure OpenCode using environment variables: "maxTokens": 80 } }, + "shell": { + "path": "/bin/bash", + "args": ["-l"] + }, "mcpServers": { "example": { "type": "stdio", diff --git a/internal/config/config.go b/internal/config/config.go index 32a26899287440f54213d9bec2f871155f8ebd99..1fd219e50cd25fe1a13243f11ff33604dfd01110 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -73,6 +73,12 @@ type TUIConfig struct { Theme string `json:"theme,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"` AutoCompact bool `json:"autoCompact,omitempty"` } @@ -217,6 +224,14 @@ func setDefaults(debug bool) { viper.SetDefault("tui.theme", "opencode") viper.SetDefault("autoCompact", true) + // Set default shell from environment or fallback to /bin/bash + shellPath := os.Getenv("SHELL") + if shellPath == "" { + shellPath = "/bin/bash" + } + viper.SetDefault("shell.path", shellPath) + viper.SetDefault("shell.args", []string{"-l"}) + if debug { viper.SetDefault("debug", true) viper.Set("log.level", "debug") diff --git a/internal/llm/tools/shell/shell.go b/internal/llm/tools/shell/shell.go index 5731faec345d84c9d6773c914feac976a7045ca8..7d3b87e4b2f3145a7e7a157a0c31e83232048ccd 100644 --- a/internal/llm/tools/shell/shell.go +++ b/internal/llm/tools/shell/shell.go @@ -11,6 +11,8 @@ import ( "sync" "syscall" "time" + + "github.com/opencode-ai/opencode/internal/config" ) type PersistentShell struct { @@ -57,12 +59,31 @@ func GetPersistentShell(workingDir string) *PersistentShell { } func newPersistentShell(cwd string) *PersistentShell { - shellPath := os.Getenv("SHELL") + // Get shell configuration from config + cfg := config.Get() + + // Default to environment variable if config is not set or nil + var shellPath string + var shellArgs []string + + if cfg != nil { + shellPath = cfg.Shell.Path + shellArgs = cfg.Shell.Args + } + if shellPath == "" { - shellPath = "/bin/bash" + shellPath = os.Getenv("SHELL") + if shellPath == "" { + shellPath = "/bin/bash" + } + } + + // Default shell args + if len(shellArgs) == 0 { + shellArgs = []string{"-l"} } - cmd := exec.Command(shellPath, "-l") + cmd := exec.Command(shellPath, shellArgs...) cmd.Dir = cwd stdinPipe, err := cmd.StdinPipe()