Auto-update breaks grep/find in the Bash tool for already-running sessions (silent fallback to a stale CLI)

Status Open
Reported on v2.1.241
Maintainer reply None cached
Activity 1 comment · opened Aug 25, 2026

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's
grep/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.241 only
  • CLAUDE_CODE_EXECPATH in the running session: .../claude-code/2.1.237/claude.app/Contents/MacOS/claudepath does not exist
  • Fallback binary ~/.local/bin/claude: 2.1.19

Reproduction

  1. Have a standalone CLI installed at ~/.local/bin/claude that is older than the embedded

ugrep/bfs dispatch (here: 2.1.19).

  1. Start a Claude Code session (here: 2.1.237).
  2. Let the app auto-update while the session is running (2.1.237 → 2.1.241). The 2.1.237 directory

is removed.

  1. In the still-running session, run any grep or find through 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:

  1. The primary path goes stale. CLAUDE_CODE_EXECPATH is captured at session start. Auto-update

deletes that version directory, so [[ -x $_cc_bin ]] becomes false for the rest of the session.

  1. 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:

  1. Don't delete the running version's directory until no session references it, or update

CLAUDE_CODE_EXECPATH for live sessions on update.

  1. 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.

  1. 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.

  1. Re-resolve _cc_bin at 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_EXECPATH resolves to the installed version, or
  • Update the standalone CLI: ~/.local/bin/claude update (or reinstall it), or
  • Prefix with command: command grep ... / command find ...

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗