[BUG] argv[0]-based find/grep/rg dispatch fails in amd64 containers on Apple Silicon

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

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Related to #84639 — same shim, same injected -G, different cause. That issue's proposed fix
would cover this one too.

The find/grep/rg shell functions route through the embedded bfs/ugrep/ripgrep by
identifying themselves via argv[0]:

( exec -a ugrep "$_cc_bin" -G --ignore-files --hidden -I --exclude-dir=.git ... "$@" )

Inside an amd64 container on Apple Silicon, a caller-chosen argv[0] never reaches the
process — the Rosetta 2 binfmt_misc registration lacks the P (preserve-argv[0]) flag, so the
kernel discards it at interpreter hand-off. The arguments then hit the ordinary CLI option parser:

! grep -n foo somefile      → error: unknown option '-G'
! find . -name '*.md'       → error: unknown option '-S'

(! = run in Claude Code's own shell. In the user's plain terminal the same commands work, because
that shell does not source the snapshot — which is part of what makes this confusing to diagnose.)

Grep/Glob are absent from the tool list at the same time, which is intended — the v2.1.117
changelog replaces them with "embedded bfs and ugrep available through the Bash tool". That
premise fails here, so every default search path is dead at once; nothing works until the agent
is told to use /usr/bin/grep.

envp is not rewritten by the kernel, so the ARGV0 environment-variable channel — which the
binary already accepts, and which the shim's own msys/cygwin branch already uses — still works.

Native platforms are unaffected: on macOS the shim's zsh branch works end-to-end.

What Should Happen?

grep and find inside Claude Code's shell should reach the embedded ugrep/bfs and return
results, as they do on a native host:

! grep -n 'pattern' somefile   → matching lines   (currently: error: unknown option '-G')
! find . -name '*.md'          → matching paths   (currently: error: unknown option '-S')

grep --version is the quickest way to see whether dispatch fired — it prints ugrep 7.5.0 ... on
a native host and 2.1.224 (Claude Code) here — but that is the diagnostic, not the goal. The goal
is that searches work.

Two independent asks:

  1. **The shim should reach the embedded binaries whether or not a caller-chosen argv[0]

survives.** #84639 proposes verifying dispatch (exec -a ugrep "$_cc_bin" -G --version) and
falling back to command grep otherwise — that covers this case and causes nobody has hit yet.
A narrower alternative that keeps the embedded tools working is in Additional Information.

  1. If the shim cannot reach the embedded binaries, Grep/Glob should not be removed. Not a

request to undo v2.1.117 — the changelog conditions that swap on the binaries being available
through the Bash tool, and here they are not. This can ship without touching the shim.

Also worth noting: claude doctor reports Search: OK (bundled) in this state. Having that check
actually invoke one of the binaries would make this class of failure a one-line diagnostic.

Error Messages/Logs

All of these are run inside Claude Code's own shell (`!` prefix). The same commands succeed in a
plain terminal, which does not source the snapshot.


! grep -n 'pattern' somefile
error: unknown option '-G'

! find . -name '*.md'
error: unknown option '-S'

! grep --version
2.1.224 (Claude Code)          # expected: ugrep 7.5.0 ...


`-G` and `-S` are injected by the shim, not typed by the user.

Steps to Reproduce

Requires an Apple Silicon Mac running an amd64 container (ours: Rancher Desktop, VZ +
Rosetta 2).

1. Does this affect you? (30 s, no Claude Code needed)

docker run --rm -it --platform linux/amd64 rockylinux:9 bash
dnf install -y nodejs
echo 'console.log(process.argv0)' > a.js
( exec -a aaa node a.js )
  • prints /usr/bin/node → affected, continue
  • prints aaanot affected; nothing below will reproduce

That probe is the authoritative check — it measures the precondition directly. For context on why,
inspect your emulation handler on the VM that runs your containers (inside the container that
directory exists but is empty):

cat /proc/sys/fs/binfmt_misc/*

Ours reads interpreter /mnt/lima-rosetta/rosetta / flags: OCF — no P (preserve-argv[0]). Per
the kernel docs that is what discards the caller's argv[0], so we'd expect a handler registered
with P not to hit this; we have not verified that, since we have no P-flagged handler to test
against. Use the probe, not the flags, to decide whether you are affected.

The same command with --platform linux/arm64 on the same machine prints aaa.

2. The bug, in two commands. Install Claude Code in that container:

CC=$(readlink -f "$(command -v claude)")

( exec -a ugrep "$CC" --version )   # 2.1.224 (Claude Code)      <-- argv[0] channel: dead
ARGV0=ugrep "$CC" --version         # ugrep 7.5.0 ...            <-- env-var channel: works

The binary accepts both identity channels; only the argv[0] one is dead here.

3. The symptom. Start Claude Code without --allowedTools Grep,Glob (with that flag the
shim is not installed and the bug does not appear):

! type -t grep     # function
! grep --version   # 2.1.224 (Claude Code)   <-- expected: ugrep 7.5.0 ...
! grep -n foo somefile
                   # error: unknown option '-G'

Grep/Glob are absent from the tool list in that session, so there is no fallback.

Claude Model

Opus

Is this a regression?

No, this never worked

Last Working Version

_No response_

Claude Code Version

2.1.224 (Claude Code)

Platform

Anthropic API

Operating System

Other Linux

Terminal/Shell

VS Code integrated terminal

Additional Information

_No response_

View original on GitHub ↗

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