Exported grep/find shell wrappers reference $ZSH_VERSION unguarded → fails under set -u

Resolved 💬 5 comments Opened May 8, 2026 by heymumford Closed Jul 13, 2026

Summary

Claude Code exports bash function wrappers for grep and find (visible via declare -F) that reference $ZSH_VERSION without a ${ZSH_VERSION-} default-empty guard. When the function is invoked from a bash subshell running under set -u (or set -euo pipefail), the unbound variable trips a non-fatal error message:

sh: line 6: ZSH_VERSION: unbound variable

The exit code is preserved (the wrappers fall through to the real binaries), so it's cosmetic — but it pollutes any just/make/CI recipe that runs strict-mode bash, which is most non-trivial automation.

Repro

On macOS with Claude Code installed and an interactive bash session inheriting the wrappers:

$ declare -f grep | head -10
grep ()
{
    local _cc_bin="${CLAUDE_CODE_EXECPATH:-}";
    [[ -x $_cc_bin ]] || _cc_bin=/Users/$USER/.local/bin/claude;
    if [[ ! -x $_cc_bin ]]; then
        command grep "$@";
        return;
    fi;
    if [[ -n $ZSH_VERSION ]]; then
                ^^^^^^^^^^^
                # ← unguarded; trips set -u
        ARGV0=ugrep "$_cc_bin" -G ...

Repro under strict mode:

$ bash -c 'set -euo pipefail; grep --version > /dev/null'
sh: line 6: ZSH_VERSION: unbound variable

find has the identical pattern.

Expected

Wrappers should guard $ZSH_VERSION references with ${ZSH_VERSION-} so they expand to empty when unset:

- if [[ -n $ZSH_VERSION ]]; then
+ if [[ -n ${ZSH_VERSION-} ]]; then

This is the canonical bash idiom for shell-detection probes (also recommended by ShellCheck SC2154 mitigation).

Workaround

Repos can defend by unset -f grep find 2>/dev/null || true at the top of any strict-mode shell scope. We've applied this in scripts/install-hooks pre-push and a just recipe in our automation-factory codebase. Not durable — every new strict-mode entry point needs the same incantation.

Environment

  • Claude Code installed via ~/.local/bin/claude
  • macOS (Darwin), bash 5.x via Homebrew
  • Surfaced from a just recipe pipeline running under set -euo pipefail

Suggested fix

Two-character change per wrapper. The same correction applies to any other Claude Code-injected wrapper that probes $ZSH_VERSION or $BASH_VERSION for shell detection.

View original on GitHub ↗

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