Claude Code に Glob で TSX ファイルを探してもらったら 0 件で返ってきたのに、念のためターミナルで find . -name '*.tsx' を打つと数百件出てくる。最初にこの挙動に出会ったとき、私は自分の目を疑いました。ファイルは確実に存在していて、パターンも正しく見えるのに、Claude Code だけが「ない」と言ってきます。
Claude Code を日々の開発に組み込んでから、この「ファイルが見えない」現象には何度も遭遇してきました。個人開発でいくつものリポジトリを並行して触っていると、モノレポやビルド成果物が混在したプロジェクトに切り替えた瞬間に再発します。原因はほとんどの場合、.gitignore の扱いか、隠しファイル(ドット始まり)の扱い、もしくはパターン記法のごく細かい違いのいずれかに収まります。実際にハマったケースを下敷きに、症状から原因を切り分けて、確実にファイルを見つけ出す手順を整理します。
「ファイルがあるのに Glob が0件を返す」最頻ケース
私の経験上、Glob が0件を返すケースの7〜8割は .gitignore で除外されているファイルを探そうとしたときに起きます。Claude Code の Glob ツールは内部で ripgrep ベースの実装を使っており、デフォルトで .gitignore のルールを尊重します。つまり、node_modules/、dist/、.next/、build/ のように Git で無視されているフォルダ配下は、最初から探索対象に入りません。
以下のような場面で起きやすいです。
node_modules/内の特定パッケージのソースを参照したいdist/やbuild/の中身を Glob で見ようとしている.next/や.turbo/のキャッシュを覗きたい- プロジェクト直下の
.env.localのような隠しファイル .github/workflows/配下のワークフロー定義
最後の .github/ はやや厄介で、.gitignore ではなく「ドット始まりのフォルダ」が原因です。隠しファイル・隠しフォルダは Glob のデフォルト挙動では除外されます。これは Grep でも同様で、.vscode/ や .husky/ のようなツール用フォルダも見えなくなります。
切り分け方
ターミナルで以下を打って、find で見つかるかどうかを確認します。
# パターンに一致するファイルが本当に存在するか確認
find . -type f -name '*.tsx' | head -20
# node_modules を除外して再確認
find . -type f -name '*.tsx' -not -path '*/node_modules/*' | head -20find で出てくるのに Claude Code の Glob で出てこないなら、ほぼ確実に .gitignore か隠しファイルが原因です。
解決策
最も確実なのは、Claude Code に対して「Bash 経由で rg --hidden --no-ignore を実行して」と明示的に依頼することです。私はこの一文を作業開始時の依頼文に含めるようにしています。
# .gitignore を無視して全ファイルを対象に検索
rg --hidden --no-ignore --files | grep -E '\.(tsx?|jsx?)$'
# 特定パターンを .gitignore 無視で検索
rg --hidden --no-ignore -l 'useEffect' src/Glob ツール自体に .gitignore を無視するオプションは現状ありません。意図的に「無視されているファイルも探したい」とき、私は最初から Bash で rg を呼ぶようにしています。
Grep が期待した行をヒットしない理由
Grep ツールも内部は ripgrep です。書き方の癖でつまずきやすい点が3つあります。
1. リテラルの中括弧をエスケープしていない
Go の interface{} や TypeScript の空オブジェクト型を検索したい場合、{ } は ripgrep のメタ文字として扱われます。
# 失敗例: 意図しないマッチを返す
rg 'interface{}' .
# 成功例: エスケープする
rg 'interface\{\}' .私は2025年の終わり頃、Go プロジェクトで chan struct{} を探していて30分溶かしました。Bash の grep であれば不要なエスケープが ripgrep では必要、という細かい挙動の差にハマったケースです。
2. multiline オプションを忘れている
Claude Code の Grep ツールはデフォルトで1行内のマッチしか取りません。struct { から数行下のフィールドにまたがる検索は、multiline: true を明示的に指定しない限り0件になります。「複数行にまたがる構造を探したい」と気づいた時点で、ツールの引数に multiline: true を入れるよう Claude にお願いします。
3. パスフィルタの罠
type: 'js' は .js のみで、.jsx や .ts は含みません。glob: '*.{ts,tsx}' のように波括弧での展開を使うのが安全です。
# JavaScript と TypeScript の両方を含めたい場合
rg 'pattern' --glob '*.{js,jsx,ts,tsx}'
# type フィルタは単一拡張子グループのみ
rg 'pattern' --type ts # .ts のみで .tsx は別扱いClaude Code の Edit ツールで old_string が見つからないケース も似たようなパターン記法の落とし穴に起因することが多く、考え方の引き出しは共通します。
パターン記法の小さな罠
Glob のパターンで間違えやすい組み合わせを並べておきます。
**/*.tsx— どの深さでも.tsxを取る。これは正しい書き方です**/*.{ts,tsx}— 波括弧展開も動きますsrc/**—src配下の全部を取りますが、フォルダ自体も含む点に注意src/**/*— ファイルだけを取りたいときはこちら!**/test/**— 否定パターンですが、Claude Code のGlobでは現時点で否定パターンの直接サポートはないため、Bash経由で扱うのが確実です
私は1度、**/*.tsx のつもりで *.tsx と書いてしまい、プロジェクトルート直下の .tsx ファイルしか取れずに「あれ、コンポーネントが1個もない」と慌てました。**/ の有無は探索の深さに直結します。
ワークスペース範囲外のファイルを見つけるには
Claude Code はデフォルトで、現在のセッションが起動された作業ディレクトリ配下しか探しません。親ディレクトリや、別プロジェクトのコードを参照したい場合、以下のいずれかが必要です。
/add-dir <path>で追加ディレクトリを許可するReadツールに絶対パスを直接渡すBashでfind ~/another-project -name '*.ts'のように外部から探索する
私は複数のリポジトリを横断するリファクタリングをするとき、最初に /add-dir で2〜3個のリポジトリを追加してから作業を始めます。これをやらずに「あのリポジトリの実装を参考にして」と頼むと、Glob も Grep も0件を返してきて時間を浪費します。
Read と Glob の非対称な挙動
Read ツールは絶対パスであれば、/add-dir で許可していないパスでも基本的に読めます。一方で Glob/Grep は許可されたディレクトリ内でしか検索できません。「読めるが探せない」というアシンメトリーがあるため、横断検索が必要なときは /add-dir を先に行うのが原則です。
Claude Code の Read ツールが2,000行で黙って切られる問題の対処 では Read 側の落とし穴を別の角度から扱っているので、合わせて参照すると挙動の全体像がつかめます。
それでも見つからないときの最終手段
ここまでの切り分けで原因が判明しないときは、Claude Code 側ではなくファイルシステム側の問題を疑います。私は次の順序で確認しています。
# 1. パスのケースを確認(macOS は大文字小文字を区別しないことが多い)
ls -la src/Components 2>&1
ls -la src/components 2>&1
# 2. 切れたシンボリックリンクを洗い出す
find . -type l ! -exec test -e {} \; -print
# 3. ファイル名の不可視文字(NBSP、ゼロ幅スペース)を確認
ls src/ | cat -A
# 4. ファイルの実体が存在するか
stat src/components/Button.tsxシンボリックリンクが切れている場合、Glob は無言でスキップします。私は monorepo を組み直したときに、pnpm install で再生成されるはずのリンクが残骸として残ってハマったことがあります。find -type l で破綻したリンクが見つかれば、いったん削除してから pnpm install を再実行すると解消することが多いです。
私の頭の中の切り分け順
検索結果が空で返ってきたとき、私は次の順序を頭の中で回します。30秒で済むので、Claude に同じ依頼を何度も繰り返すよりずっと早く解決できます。
まず、探そうとしているパスが .gitignore の対象かを確認します。「これビルド出力だから多分そう」と思った時点で、Bash から rg --hidden --no-ignore に切り替えます。次に、.github/ や .vscode/ のような隠しフォルダ配下かを見ます。3つ目に、パターン自体に ripgrep が特殊文字として扱う記号が含まれていないかを点検します。4つ目に、対象ファイルがワークスペース境界の外にいないかを考えます。この4つすべてが「該当しない」となって初めて、ファイルシステム側の原因を疑います。
私が経験した行き詰まりはほぼ全部、最初の4つのどれかに収まりました。シンボリックリンク切れや不可視文字といったファイルシステム側の問題は、確かに存在しますが頻度ははるかに低いです。
「見えないファイル」を減らすための予防策
私が普段心がけているのは、Claude Code に作業を依頼する最初の段階で、以下の3点を伝えておくことです。
- 「
.gitignoreで無視されているファイルも対象にしたい場合は、rg --hidden --no-ignoreをBashで呼んでください」 - 「ホームディレクトリ配下のリポジトリを参照したいときは、先に
/add-dirを提案してください」 - 「
Globで0件が返ったら、すぐに諦めずにBashのfindでも確認してみてください」
この一文を最初の依頼文に含めるだけで、「ファイルが見えない」が原因の手戻りはほぼなくなりました。AI が裏で find を呼ぶことを期待するより、こちらが明示的にツール選択の指針を渡したほうが、結果的に作業時間が短くなる、というのがここ1年の体感です。
Claude Code の Bash ツールでコマンドが想定通り動かないとき でも触れていますが、Bash を選ぶ判断と専用ツールを選ぶ判断は別物として整理しておくと、デバッグの初動が速くなります。
次に「ファイルが0件で返ってきた」と感じたら、まずは Bash で rg --hidden --no-ignore --files | grep <パターン> を試してみてください。私自身まだ落とし穴を毎月のように発見していますが、共に学んでいけたら嬉しいです。