Desktop app shell snapshot writes process.env.PATH instead of resolved shell PATH

Resolved 💬 3 comments Opened Apr 5, 2026 by m-shibusawa0121 Closed Apr 8, 2026

Summary

The desktop app's shell snapshot generation writes export PATH=... using the JavaScript process's PATH (minimal macOS GUI app PATH: /usr/bin:/bin:/usr/sbin:/sbin) instead of the PATH resolved inside the zsh process after sourcing dotfiles (.zshenv, .zshrc, etc.).

This causes tools installed via Homebrew (/opt/homebrew/bin) and /usr/local/bin to be unavailable in Bash tool executions.

Environment

  • macOS (Apple Silicon)
  • Claude Code Desktop App v2.1.87
  • Shell: zsh

Steps to Reproduce

  1. Install tools via Homebrew (e.g., node, gh, npm)
  2. Add /opt/homebrew/bin to PATH in ~/.zshenv:

``bash
export PATH="/usr/local/bin:/opt/homebrew/bin:$PATH"
``

  1. Launch Claude Code desktop app (not terminal)
  2. Run which node via Bash tool → command not found

Root Cause

In the snapshot generation code (gW7 / G31 functions), the shell script template includes:

echo "export PATH=${W7([H || ""])}" >> "$SNAPSHOT_FILE"

This evaluates H (a JavaScript variable from process.env.PATH) at template build time, not the PATH that the zsh process resolves after sourcing .zshenv / .zshrc.

The snapshot generation runs zsh -c -l <script>, which does correctly source .zshenv and resolve the full PATH inside zsh. However, that resolved PATH is never captured — the snapshot file gets the JavaScript-side value instead.

Expected Behavior

The snapshot should capture the PATH as resolved inside the zsh process after all dotfiles are sourced, not the parent JavaScript process's PATH.

Current Workaround

Using a SessionStart hook in settings.json to patch the snapshot file after generation:

{
  "hooks": {
    "SessionStart": [{
      "hooks": [{
        "type": "command",
        "command": "sleep 1; SNAP=$(ls -t ~/.claude/shell-snapshots/snapshot-zsh-*.sh 2>/dev/null | head -1); if [ -n \"$SNAP\" ] && grep -q 'export PATH=/usr/bin' \"$SNAP\" && ! grep -q '/opt/homebrew/bin' \"$SNAP\"; then sed -i '' 's|export PATH=/usr/bin|export PATH=/usr/local/bin\\\\:/opt/homebrew/bin\\\\:/usr/bin|' \"$SNAP\"; fi",
        "timeout": 10
      }]
    }]
  }
}

Additional Notes

  • settings.json's env.PATH setting is also ineffective because the snapshot's export PATH=... overrides it when sourced.
  • The terminal version of Claude Code inherits the correct PATH from the parent shell, so this issue is specific to the desktop app.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗