Auto-update breaks grep/find in the Bash tool for already-running sessions (silent fallback to a stale CLI)
Summary
When Claude Code auto-updates, it deletes the previous version's directory while existing sessions
are still running. Those sessions keep a now-dangling CLAUDE_CODE_EXECPATH. The shell snapshot'sgrep/find wrappers fail their [[ -x $_cc_bin ]] check, silently fall back to a standalone~/.local/bin/claude install, and — if that install is older than the embedded ugrep/bfs
multi-call dispatch — every grep and find invocation in the Bash tool breaks.
The failure is worse than a crash: grep writes error: unknown option '-G' to stderr and exits
non-zero, which in a pipeline reads as "no matches found" rather than "the search never ran."
Silent false negatives from a search tool are dangerous — an agent (or a human) concludes a string
is absent when the search simply failed.
Environment
- macOS (Darwin 25.2.0), zsh
- Claude Code desktop app
- Installed on disk:
2.1.241only CLAUDE_CODE_EXECPATHin the running session:.../claude-code/2.1.237/claude.app/Contents/MacOS/claude→ path does not exist- Fallback binary
~/.local/bin/claude: 2.1.19
Reproduction
- Have a standalone CLI installed at
~/.local/bin/claudethat is older than the embedded
ugrep/bfs dispatch (here: 2.1.19).
- Start a Claude Code session (here: 2.1.237).
- Let the app auto-update while the session is running (2.1.237 → 2.1.241). The 2.1.237 directory
is removed.
- In the still-running session, run any
greporfindthrough the Bash tool.
Observed
$ grep machinemaths t.txt
error: unknown option '-G'
$ grep -n machinemaths t.txt
error: unknown option '-G'
$ grep -c machinemaths t.txt
error: unknown option '-G'
$ grep -rn --include="*.txt" machinemaths .
error: unknown option '-G'
$ find . -name "t.txt"
error: unknown option '-S'
$ command grep -c machinemaths t.txt # bypasses the wrapper
1
Every wrapped invocation fails regardless of flags. command grep works, confirming the system
binary is fine and the wrapper is at fault.
Expected
grep/find continue working, or fail loudly and unambiguously rather than in a way that
resembles an empty result set.
Root cause
~/.claude/shell-snapshots/snapshot-zsh-*.sh contains:
# Shadow find/grep with embedded bfs/ugrep
function find {
local _cc_bin="${CLAUDE_CODE_EXECPATH:-}"
[[ -x $_cc_bin ]] || _cc_bin=/Users/<user>/.local/bin/claude
...
ARGV0=bfs "$_cc_bin" -S dfs -regextype findutils-default ${1+"$@"}
}
function grep {
...
local _cc_bin="${CLAUDE_CODE_EXECPATH:-}"
[[ -x $_cc_bin ]] || _cc_bin=/Users/<user>/.local/bin/claude
...
ARGV0=ugrep "$_cc_bin" -G --ignore-files --hidden -I --exclude-dir=.git ... ${1+"$@"}
}
Two compounding problems:
- The primary path goes stale.
CLAUDE_CODE_EXECPATHis captured at session start. Auto-update
deletes that version directory, so [[ -x $_cc_bin ]] becomes false for the rest of the session.
- The fallback is not version-checked. It unconditionally uses
~/.local/bin/claude. If that
binary predates the ARGV0=ugrep / ARGV0=bfs multi-call dispatch, it parses the wrapper's own
-G / -S dfs flags as CLI options and errors. The -G and -S in the error messages are the
wrapper's flags, not the user's — which makes the error especially confusing to diagnose.
A related symptom: some invocations printed 2.1.19 (Claude Code) — the stale binary emitting its
version banner in place of search results.
Suggested fixes
Any one of these would break the chain; the first two seem most robust:
- Don't delete the running version's directory until no session references it, or update
CLAUDE_CODE_EXECPATH for live sessions on update.
- Version-check the fallback. Before using
~/.local/bin/claude, confirm it supports the
multi-call dispatch; if not, fall through to command grep / command find.
- Fail safe, not silent. If the dispatch fails, fall back to the system binary rather than
surfacing an error that mimics an empty result. A search tool that appears to return "nothing
found" when it did not run is the highest-consequence failure mode here.
- Re-resolve
_cc_binat call time rather than trusting a session-start capture.
Impact
Any workflow relying on grep/find inside the Bash tool silently loses search capability
mid-session, with results that look like legitimate empty output. For agent-driven work that uses
absence-of-match as evidence, this can produce confidently wrong conclusions.
Workaround
- Restart the session so
CLAUDE_CODE_EXECPATHresolves to the installed version, or - Update the standalone CLI:
~/.local/bin/claude update(or reinstall it), or - Prefix with
command:command grep .../command find ...
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗