Let the Bash tool run commands under bash, not the user's login shell (zsh)
Problem
My login shell is zsh, and the Bash tool runs commands under zsh. But the tool is called "Bash" and Claude (plus most snippets it writes) assumes bash semantics, so commands routinely break on bash-vs-zsh differences:
- an unmatched glob is FATAL in zsh (
zsh: no matches found) and aborts the whole command, instead of empty-expanding as in bash — this silently false-negatives file-existence checks - unquoted
$vardoes not word-split in zsh - bash associative arrays (
declare -A,${!m[@]}) are unsupported
These fail intermittently and are hard to prevent with prompt/CLAUDE.md rules alone.
What I found
There is no setting to control the shell the Bash tool uses. defaultShell only affects interactive ! commands, not agent tool execution. Env vars only cover timeouts/output limits (BASH_DEFAULT_TIMEOUT_MS, etc.), not shell selection.
Requested
A first-class way to make the Bash tool use bash regardless of the login shell, e.g. one of:
- a settings.json key like
bashShell/toolShell(path to the shell binary), or - an env var (e.g.
CLAUDE_BASH_SHELL=/bin/bash), or - an option to run every Bash-tool command via
bash -cautomatically.
Ideally it still inherits the interactive shell's PATH/env (sourced from .zshrc), so tools installed via the login shell keep working — i.e. a bash child inside the existing environment, not a full shell swap.
Also: please document explicitly whether Bash-tool commands run in $SHELL or always in /bin/bash — the tools reference is ambiguous on this.
Workaround today
Prefixing non-trivial commands with bash -c '...' works and inherits PATH, but it relies on Claude remembering to do it every time.