claude-code - 💡(How to fix) Fix Monitor tool doesn't source the shell snapshot like Bash does; PATH-dependent tools (jq, sleep, etc.) fail in Monitor commands on macOS/Nix

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…

Error Message

The Bash tool's invocation source-loads ~/.claude/shell-snapshots/snapshot-zsh-<id>.sh, which replays the user's interactive zsh state (PATH, functions, aliases, exports). The Monitor tool's invocation does not. Verified by inspecting ps -o command= -p $$ from a Bash-tool subshell (shows the snapshot source) vs the stderr error format from Monitor ((eval):<n>: command not found: <tool>, the zsh--c-without-init form).

Root Cause

Root cause

Fix Action

Fix / Workaround

Workaround

Code Example

zsh -c "source ~/.claude/shell-snapshots/snapshot-zsh-<id>.sh 2>/dev/null || true && setopt NO_EXTENDED_GLOB NO_BARE_GLOB_QUAL 2>/dev/null || true && eval '<user-cmd>'"

---

zsh -c '<user-cmd>'

---

source ~/.claude/shell-snapshots/snapshot-zsh-<id>.sh 2>/dev/null || true && setopt NO_EXTENDED_GLOB NO_BARE_GLOB_QUAL 2>/dev/null || true &&

---

/run/current-system/sw/bin/bash /path/to/script.sh
RAW_BUFFERClick to expand / collapse

Summary

The Monitor tool's command: field runs subprocesses without sourcing the Claude Code shell-snapshot file (~/.claude/shell-snapshots/snapshot-zsh-<id>.sh), but the Bash tool does. As a result, Monitor commands see a near-empty PATH and can't find common tools (jq, sleep, grep, etc.) on systems where those tools live in a profile dir (Nix profile, Homebrew, asdf-vm, mise, pyenv, etc.) rather than /usr/bin. The Monitor tool description claims "the script runs in the same shell environment as Bash," which is empirically false on macOS Darwin.

Reproduction (macOS Sequoia 15.x, nix-darwin user)

System info:

  • Platform: darwin (macOS 15.x via Darwin 24.6.0)
  • User shell: /run/current-system/sw/bin/fish (interactive)
  • macOS default shell for spawned subprocesses: zsh
  • Profile dir for jq/etc.: /etc/profiles/per-user/$USER/bin/ (Nix)

Bash tool invocation (works):

zsh -c "source ~/.claude/shell-snapshots/snapshot-zsh-<id>.sh 2>/dev/null || true && setopt NO_EXTENDED_GLOB NO_BARE_GLOB_QUAL 2>/dev/null || true && eval '<user-cmd>'"

→ PATH includes /etc/profiles/per-user/$USER/bin, /run/current-system/sw/bin, etc. jq, sleep, grep all resolve.

Monitor tool invocation (broken):

zsh -c '<user-cmd>'

→ PATH is the bare Claude Code parent-process PATH (no snapshot source). On this system, jq, sleep, grep all command not found.

Concrete failure mode in my session: a long-running Monitor script that polled gh pr checks ... | jq -r ... in a while true; ...; sleep 60; done loop. With jq missing, the pipe produced no output (silent). With sleep missing, the loop spun at full CPU. Result: each watcher produced ~750 MB of [stderr] (eval):17: command not found: jq\n(eval):39: command not found: sleep\n over ~12 hours before I noticed. (Four watchers ≈ 3 GB of garbage stderr.)

Expected: Monitor's command: runs in the same shell environment as Bash (per docs).

Actual: Monitor's command: runs in a stripped-down env without the user's profile PATH.

Root cause

The Bash tool's invocation source-loads ~/.claude/shell-snapshots/snapshot-zsh-<id>.sh, which replays the user's interactive zsh state (PATH, functions, aliases, exports). The Monitor tool's invocation does not. Verified by inspecting ps -o command= -p $$ from a Bash-tool subshell (shows the snapshot source) vs the stderr error format from Monitor ((eval):<n>: command not found: <tool>, the zsh--c-without-init form).

Suggested fix

Reuse the same wrapper for Monitor's command: as Bash uses. Specifically, prepend:

source ~/.claude/shell-snapshots/snapshot-zsh-<id>.sh 2>/dev/null || true && setopt NO_EXTENDED_GLOB NO_BARE_GLOB_QUAL 2>/dev/null || true &&

…then eval the user-supplied command:. One-line change, fulfills the existing docs claim.

Impact

Anyone running Claude Code on macOS where their dev tools live in a non-system path. nix-darwin is the most-affected because everything (jq, gh, bash builds, modern coreutils, etc.) lives under /etc/profiles/per-user/$USER/bin/ or /run/current-system/sw/bin/. Homebrew users with /opt/homebrew/bin/ packages hit the same issue but less severely (macOS ships /usr/bin/jq as a fallback in recent versions, so failures look different). asdf/mise/pyenv users are also vulnerable for any language tool a Monitor script depends on.

Workaround

Until fixed upstream, use absolute-path bash from Monitor's command: field:

/run/current-system/sw/bin/bash /path/to/script.sh

…and put the actual watcher logic inside script.sh with a #!/usr/bin/env bash shebang. bash itself sources /etc/profile on Darwin, which gets you back to a working Nix PATH. This works but is verbose for what should be a single-string Monitor command.

Severity: Medium. Silently produces non-functional Monitor scripts. The failure mode (CPU-spinning watcher with stderr-to-task-output flood) consumes disk and CPU before the user notices.

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