claude-code - 💡(How to fix) Fix Bash tool: shell snapshot is generated by a login shell, stripping inherited PATH on Windows + Git Bash

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Root Cause

None of them lose the venv's Scripts/ from PATH, because none of them invoke login shells for "run a command on behalf of the user." Claude Code's Bash tool is the outlier among tools, not Git Bash among shells. /etc/profile's PATH-reset is doing what login shells are documented to do; the design decision under Claude Code's control is whether to invoke the snapshot generator in login mode at all.

Fix Action

Fix

Spawn the snapshot generator (and the per-call Bash tool subshell that sources the snapshot) as an interactive non-login shell rather than a login shell.

  • Loads ~/.bashrc / ~/.zshrc — so user aliases, functions, and asdf/nvm/pyenv/direnv init lines still work (the behavior macOS users currently rely on).
  • Skips /etc/profile, ~/.bash_profile, ~/.zprofile, /etc/zprofile — so Git Bash's PATH-reset doesn't fire, and macOS's path_helper doesn't redundantly re-derive PATH that was already inherited.
  • Resolves all PATH-mutating activators in one change: venv, nvm, conda, asdf/mise, rvm/rbenv, direnv, pyenv.

The interactive matters: a non-interactive shell skips .bashrc (per the standard case $- in *i*) ;; *) return;; esac guard most distros ship), which is the proximate cause of the WSL-flavored variant (#36285).

Code Example

export PATH='/c/Users/<USER>/bin:/mingw64/bin:/usr/local/bin:/usr/bin:/bin:/mingw64/bin:/usr/bin:/c/Users/<USER>/bin:[...]'
RAW_BUFFERClick to expand / collapse

TL;DR

On Windows + Git Bash, Claude Code's shell snapshot generator runs in login mode. Git Bash's /etc/profile rewrites PATH from scratch on login, so the snapshot captures a PATH where the parent shell's activator prepends — Python venv Scripts/, nvm bin/, conda Scripts/, asdf shims, direnv exports — have already been stripped. Every subsequent Bash tool call sources that snapshot and inherits the broken PATH. Environment variables that /etc/profile doesn't touch (VIRTUAL_ENV, NVM_BIN, CONDA_PREFIX, …) survive, producing a half-activated state that no real activator ever produces.

Reproduction

  1. Windows + Git Bash + Python venv (or nvm / conda / asdf / direnv — any PATH-mutating activator).
  2. Activate in your terminal: source .venv/Scripts/activate. Confirm which just resolves to the venv.
  3. Launch claude from the same terminal.
  4. In a Bash tool call:
    • echo $VIRTUAL_ENV → returns the venv path (correctly inherited)
    • which just → "not found", despite .venv/Scripts/just.exe existing on disk
    • echo $PATH → no .venv/Scripts/, plus duplicate entries (the /etc/profile signature)

Evidence

~/.claude/shell-snapshots/snapshot-bash-<id>.sh, final line:

export PATH='/c/Users/<USER>/bin:/mingw64/bin:/usr/local/bin:/usr/bin:/bin:/mingw64/bin:/usr/bin:/c/Users/<USER>/bin:[...]'

The duplication of /mingw64/bin, /usr/bin, and ~/bin in the first eight entries is the diagnostic. Git Bash's /etc/profile unconditionally prepends /usr/local/bin:/usr/bin:/bin:/mingw64/bin. The inherited PATH from the parent already contained /mingw64/bin and ~/bin, so they appear twice. That duplication only occurs if the snapshot generator was invoked as a login shell.

(The snapshot itself is well-formed — PATH is fully expanded, no ${PATH} literal, no escaped braces. The generator's output serialization is correct. The bug is in what shell mode the generator was invoked in.)

Why this is not a Git Bash bug

Every other tool that spawns subshells on the same Git Bash inherits PATH cleanly:

  • VS Code's integrated terminal
  • bash -c '...' invoked from any parent Git Bash session
  • Windows Terminal split panes
  • IntelliJ / PyCharm run configurations
  • Plain sh in a Git Bash session

None of them lose the venv's Scripts/ from PATH, because none of them invoke login shells for "run a command on behalf of the user." Claude Code's Bash tool is the outlier among tools, not Git Bash among shells. /etc/profile's PATH-reset is doing what login shells are documented to do; the design decision under Claude Code's control is whether to invoke the snapshot generator in login mode at all.

Fix

Spawn the snapshot generator (and the per-call Bash tool subshell that sources the snapshot) as an interactive non-login shell rather than a login shell.

  • Loads ~/.bashrc / ~/.zshrc — so user aliases, functions, and asdf/nvm/pyenv/direnv init lines still work (the behavior macOS users currently rely on).
  • Skips /etc/profile, ~/.bash_profile, ~/.zprofile, /etc/zprofile — so Git Bash's PATH-reset doesn't fire, and macOS's path_helper doesn't redundantly re-derive PATH that was already inherited.
  • Resolves all PATH-mutating activators in one change: venv, nvm, conda, asdf/mise, rvm/rbenv, direnv, pyenv.

The interactive matters: a non-interactive shell skips .bashrc (per the standard case $- in *i*) ;; *) return;; esac guard most distros ship), which is the proximate cause of the WSL-flavored variant (#36285).

Related issues

  • #15128 — same symptom on Windows + Git Bash; closed Not Planned, locked.
  • #36285 — same generator, different serialization bug, with a venv on WSL; closed Not Planned.
  • #52521 — observation that the Bash tool spawns the user's login shell (raised on macOS, where the behavior is incidentally useful).
  • #50181 — sibling snapshot serialization bug (single-quoted ${PATH}); fixed.

References

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING