Skip to main content
OpenCode executes shell commands through its bash tool. You can customize which shell is used and how it’s configured.

Default behavior

By default, OpenCode uses the shell specified in your SHELL environment variable. If SHELL is not set, it falls back to /bin/bash.
# OpenCode will use your default shell
echo $SHELL
# /bin/zsh (or /bin/bash, etc.)

Configuration options

Setting the shell path

You can override the default shell in your OpenCode configuration:
.opencode.json
{
  "shell": {
    "path": "/bin/zsh"
  }
}

Passing shell arguments

Shell arguments allow you to control how the shell is initialized:
.opencode.json
{
  "shell": {
    "path": "/bin/zsh",
    "args": ["-l"]
  }
}
The default argument is ["-l"], which starts the shell as a login shell, loading your profile files.

Common configurations

Bash

Loads .bash_profile and .bashrc:
.opencode.json
{
  "shell": {
    "path": "/bin/bash",
    "args": ["-l"]
  }
}

Zsh

Fish

.opencode.json
{
  "shell": {
    "path": "/usr/bin/fish",
    "args": ["-l"]
  }
}

Custom shell

You can use any shell that supports the -c option for command execution:
.opencode.json
{
  "shell": {
    "path": "/usr/local/bin/custom-shell",
    "args": ["--custom-arg"]
  }
}

Shell argument reference

Starts the shell as a login shell, loading profile files.Bash: Loads /etc/profile, ~/.bash_profile, ~/.bash_login, and ~/.profileZsh: Loads /etc/zprofile, ~/.zprofile, /etc/zshrc, and ~/.zshrcUse when: You need your full shell environment, including PATH modifications, aliases, and environment variables.
Starts the shell in interactive mode.Bash: Loads ~/.bashrcZsh: Loads ~/.zshrcUse when: You want interactive features but don’t need full profile loading.
Starts a non-interactive, non-login shell.Use when: You want minimal overhead and don’t need your custom environment.
Executes a specific command (automatically used by OpenCode).
Don’t include -c in your args configuration. OpenCode automatically adds it when executing commands.

Use cases

Loading custom environment variables

If your development environment requires specific environment variables, use a login shell:
.opencode.json
{
  "shell": {
    "path": "/bin/bash",
    "args": ["-l"]
  }
}
Then in your ~/.bash_profile or ~/.zprofile:
~/.bash_profile
export NODE_PATH="/usr/local/lib/node_modules"
export GOPATH="$HOME/go"
export PATH="$PATH:$GOPATH/bin"

Using version managers

If you use version managers like nvm, rbenv, or pyenv, you typically need a login shell:
.opencode.json
{
  "shell": {
    "path": "/bin/zsh",
    "args": ["-l"]
  }
}
~/.zprofile
# Load nvm
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"

# Load rbenv
export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"

Minimal overhead

For faster command execution without environment customization:
.opencode.json
{
  "shell": {
    "path": "/bin/bash",
    "args": []
  }
}

CI/CD environments

In containerized or CI environments, you might want to ensure consistent behavior:
.opencode.json
{
  "shell": {
    "path": "/bin/sh",
    "args": []
  }
}

Troubleshooting

Symptoms: Tools like npm, python, or custom scripts are not foundSolution: Use a login shell to load your PATH:
.opencode.json
{
  "shell": {
    "path": "/bin/bash",
    "args": ["-l"]
  }
}
Verify your PATH is set correctly:
~/.bash_profile
export PATH="$HOME/.local/bin:$PATH"
Symptoms: Shell aliases defined in your profile don’t workCause: Aliases are typically only available in interactive shellsSolution: Use functions instead of aliases, or use an interactive shell:
.opencode.json
{
  "shell": {
    "path": "/bin/bash",
    "args": ["-i"]
  }
}
Better approach - convert aliases to functions:
~/.bashrc
# Instead of: alias gs="git status"
# Use:
gs() { git status "$@"; }
Symptoms: Commands take a long time to startCause: Your shell profile may be loading slowly (plugins, external tools, etc.)Solution: Profile your shell startup:
# For bash
time bash -l -c 'echo loaded'

# For zsh
time zsh -l -c 'echo loaded'
Optimize your profile files by:
  • Lazy-loading plugins and tools
  • Removing unnecessary initialization
  • Using a faster shell configuration
Symptoms: Environment variables you set in your profile aren’t availableSolution: Ensure you’re using a login shell and the variables are exported:
~/.bash_profile
# Use export to make variables available to child processes
export MY_VAR="value"
Symptoms: Shell can’t execute commands or scriptsSolution:
  • Verify the shell path is correct and executable:
ls -l /bin/bash
# Should show: -rwxr-xr-x
  • Ensure scripts have execute permissions:
chmod +x /path/to/script.sh

Advanced configuration

Per-project shell configuration

You can use a local .opencode.json in your project directory to override the global shell configuration:
./.opencode.json
{
  "shell": {
    "path": "/bin/bash",
    "args": ["-l"]
  }
}
This is useful when different projects require different shell environments.

Setting the SHELL environment variable

Alternatively, you can set the SHELL environment variable when launching OpenCode:
SHELL=/bin/zsh opencode

Testing your shell configuration

To test that your shell configuration works correctly:
1

Check shell path

Verify the shell executable exists:
which bash  # or zsh, fish, etc.
2

Test command execution

Test that commands run correctly:
/bin/bash -l -c 'echo $PATH'
3

Verify environment loading

Check that your environment is loaded:
/bin/bash -l -c 'env | grep MY_CUSTOM_VAR'

Best practices

Use login shells

Start with -l to ensure your full environment is loaded.

Keep profiles fast

Optimize shell startup time by lazy-loading tools and plugins.

Export variables

Always use export for variables that need to be available to child processes.

Test configurations

Test shell configurations before using them with OpenCode.

Build docs developers (and LLMs) love