Pin Bash tool shell to zsh so the prompt matches reality#13
Merged
Conversation
Our login shell is fish, but Claude Code's Bash tool only runs bash or zsh and silently falls back to /bin/zsh. The system prompt's "Shell:" line reports raw $SHELL (fish), so Claude is told fish while commands actually run in zsh, then misattributes zsh behavior (\! history expansion, quoting) to a shell that never ran the command. Set SHELL=/bin/zsh in base.jsonc so the prompt reports zsh, matching the shell already in use. Execution is unchanged; this only corrects what Claude is told. Adds ADR 0037 with the full reverse-engineering. Refs: anthropics/claude-code#68349 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…-zsh # Conflicts: # doc/adr/README.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Our login shell is fish, but Claude Code's Bash tool can't run fish. It only runs bash or zsh, and when
$SHELLis neither it silently falls back to/bin/zsh. The catch: the system prompt'sShell:line just echoes raw$SHELL, so Claude gets told "fish" while every command actually runs in zsh. Then it blames fish for zsh behavior it never caused (the classic being!history expansion, which fish doesn't even do).Setting
SHELL=/bin/zshinbase.jsoncmakes that prompt line tell the truth. Execution doesn't change, it was already zsh. This just stops Claude from being lied to.ADR 0037 has the full reverse-engineering: both the prompt builder and the Bash tool's shell resolver read
process.env.SHELLand do opposite things with it. Upstream tracks the same gap in anthropics/claude-code#68349.Verify
On the next fresh session (the
envblock applies at session init, not mid-session), the environment block'sShell:line readszshinstead of/opt/homebrew/bin/fish.