Skip to content
ソフトウェア自動開発のメモ帳

ソフトウェア開発 repo の RAG は grep が現状の最適解である

Claude Code を使い始めて、ふとこう思った人もいるはずだ

「これ grep するより、ベクトル検索に対応した方がいいのでは?」——ところが claude を覗くと、コードベースのインデックスも embedding も無く、検索に使うのは Glob・Grep・Read だけ。それでも関数の参照はちゃんと返ってくる。2024 年頃の RAG パイプライン全盛期から、コード repo の検索は grep 系のツールに揺り戻している。ソフトウェア開発 repo のコード検索に限れば、ベクトル DB を構築するより agent に grep 系のツールを渡したほうが現状の最適解だ。理由と限界を整理する。

CLI エージェントは、ベクトル DB から grep 系に揺り戻した

Anthropic の Claude Code は初期バージョンではローカルベクトル DB を使った RAG を試したが、現在は採用していない。代わりに使われているのは Glob(ファイル名検索)、Grep(テキスト検索)、Read(ファイル読み取り)という古典的なツール群を、LLM が自律的に組み合わせて検索する方式だ。Zenn と Qiita の解説記事12では、これを「Agentic RAG」あるいは「Agentic Search」と呼んで紹介している。

OpenAI の Codex CLI、SST の Opencode も、ベースのコード検索は同じ路線だ。grep 系のツールを agent に渡し、agent 側が多段で読みに行く。

「ベクトル DB を作らずにファイル検索ツールを渡すだけ」——このやり方が、主要 CLI エージェントの標準になっている。これが現状の到達点だ。

なぜ grep 系で十分なのか

ベクトル検索が威力を発揮するのは、「テキストの意味的類似度」が唯一の手がかりであるような場面だ。サポートチケットを過去事例とマッチさせる、長文の契約書から似た条項を探す、といったケース。データに構造がなく、人間が手作業で索引も貼っていないとき、embedding は強力になる。

コード repo はそうではない。 すでに、十分すぎるほど構造化されている。

人間がコードを読むときは、ファイル名でディレクトリを辿り、grep で参照を追い、コミット履歴を見る。LLM agent も同じことができる。人間のコード検索は元から「embedding なし」で回っている——それを真似ているだけだ。

Zenn の Knowledge Sense 記事2は、これをコスト面でも整理している。ベクトル検索には事前のインデックス作成と、コード変更のたびの継続的なインデックス更新コストがかかる。Glob/Grep は初期コストがゼロで、ファイルが変わった瞬間に最新の結果が返る。コードが秒単位で書き換わる開発環境とは、ベクトル DB の設計が根本的に噛み合わない、というのが彼らの分析だ。

論文の側でも同じ構図が観測された:Direct Corpus Interaction

2026 年 5 月上旬、arXiv に Beyond Semantic Similarity: Rethinking Retrieval for Agentic Search via Direct Corpus Interaction という論文が出て、HuggingFace Daily Papers にも 5 月 8 日付で投稿され、その日のトップに上がった。

著者らはこう主張している。従来の検索システムは、corpus へのアクセスを「固定された類似度インターフェイス」で圧縮しすぎている、と。一発の top-k 検索で結果を返したら、そこで切り捨てた証拠は後段の推論がどんなに強くなっても拾い直せない。

そこで彼らが試したのは、embedding モデルもベクトルインデックスも検索 API も使わず、agent に grep / ファイル read / shell コマンド / 軽量スクリプトといった汎用 terminal ツールだけを渡して、生 corpus を直接探らせる方式だ。論文ではこの方式を「Direct Corpus Interaction (DCI)」と呼んでいる。

論文の報告によれば、この素朴なセットアップが、情報検索ベンチマークの BRIGHT・BEIR の複数データセットで、sparse(キーワード検索系)・dense(ベクトル検索系)・rerank(再並び替え系) の強力な baseline を「substantially outperforms」したという(具体的な数値は本文 PDF を参照)。複雑な多段推論を要する QA タスクでも、従来の意味検索を一切使わずに高精度に到達したと著者らは報告している。

著者らの主張を要約すると、こうなる(直訳ではない筆者要約):

言語エージェントが強くなるほど、検索の品質は推論能力だけでなく、モデルが corpus と対話するインターフェイスの解像度にも依存する。

ここで一つ重要な留保がある。DCI 論文の対象は一般コーパスでの agent 駆動の検索(ウェブ検索や QA データセットに近い設定)であって、ソフトウェアリポジトリのコード検索を直接ベンチマークしたわけではない。だから「論文が grep 系を最適と証明した」とまでは言えない。言えるのは、「embedding で前処理してから top-k で返す」という固定インターフェイスより、agent に terminal ツールを多段で叩かせるほうが検索は強くなる、という同じ構図が、IR ベンチでも独立に観測された、という点だ。

それでも、これは Claude Code や Codex CLI を毎日使っている側にとっては「そういえば自分は最初からそれをやっていた」という、地味だが意味のある合流地点になる。

何を agent に渡すかは好みで決めればいい

「grep 系」と書いてきたが、agent に渡せる検索ツールは grep 系を中心としつつ、構文単位やシンボル単位の選択肢もある。

私自身は普段、ripgrep を入れておいて agent からはそれを呼ばせている。Rust 製で十分に速くて、.gitignore を勝手に認識して node_modules/ を除外してくれる、というのが選んだ理由——とはいえ、これは個人的な好みだ。git grep で十分という人もいれば、構造的クエリのために ast-grep を使う人もいる。「grep 系を agent に渡す」という構図さえ守れば、具体的なツールは差し替え可能だ。

なお、Claude Code 系の CLI エージェントは最近のバージョンで grep 系の高速実装を内蔵している。CLI を素で使うだけならホストに何かを別途入れなくても済むのだが、Bash ツールから rgast-grep を直接呼べる状態にしておくと、agent が独自の組み合わせ(パイプ、git log との連結など)を試せて、結果的に手数が増える、というのが経験則だ。

実際に agent が打つコマンドは、たとえばこういう形になる。

# 関数 processPayment の定義を探す (ripgrep)
rg -n 'function processPayment|processPayment\s*=' --type ts

# 「Result<...> を返り値型に明示した function 宣言」を構造的に探す (ast-grep)
ast-grep --pattern 'function $NAME($$$): Result<$$$> { $$$ }' --lang ts

# 直近 7 日のコミットで触られた認証ファイル (git + rg のパイプ)
git log --since='7 days ago' --name-only --pretty=format: | rg 'auth' | sort -u

人間がやることと同じだ。違うのは、LLM が自然言語の要求をこういう複数のクエリに翻訳し、結果を読んで次のクエリを組み立てる、という多段ループが回ること。DCI 論文が「interface の解像度」と呼んでいるのは厳密にはより広い概念だが、多段で grep を打ち直せる、という挙動はその具体例の一つだ。

grep 系で足りなくなる場面

正直に書いておく。「現状の最適解」とは書いたが、「すべての場面で十分」ではない。境界を明確にしておく。

大規模 monorepo(数百万ファイル / 数十 GB)

grep 系のツールは速いが、それでも 1 クエリで秒オーダーになる規模の repo は存在する。Google の monorepo、Meta の Buck repo、Microsoft の Windows repo クラス。この規模では、事前にコードシンボルインデックス(LSP の workspace index、Sourcegraph の zoekt など)を貼っておく価値が出てくる。

DCI 論文自身も、コーパスを 20 万ドキュメント / 40 万ドキュメントへ拡大したときに、ツール呼び出し回数とレイテンシが膨らみ、精度も低下したと報告している。生 corpus を直接叩く戦略は、サイズが大きくなると素直にスケールしない。個人開発から中規模 OSS、エンタープライズの単一サービス repo までは grep 系で困らないが、それを超えると別の仕組みが要る。境界はこのあたりだ。

コード以外の長文ドキュメント(PDF、契約書、論文)

これらは構造化されていない。ファイル名に意味情報が乗っておらず、ディレクトリ階層も検索の手がかりにならない。意味的に近い段落を見つけたい用途では、ベクトル検索や NotebookLM 的な「文書を丸ごとコンテキストに載せる」アプローチに分がある。コード repo 用と文書 RAG 用は分けて考えるべきだ。

抽象的なクエリ(「認証ロジックの全体像」「リトライ方針」)

processPayment の定義」のような具体的なクエリは grep 系の独擅場だが、「このシステムの認証フローを説明して」「リトライポリシーはどう実装されている?」のような字面の手がかりがない抽象クエリは、単一の正規表現では拾えない。

このタイプには二つの対処がある。一つは「LLM がクエリを多角的に書き換えて多段で検索する」(まさに DCI 論文が示した方式) — 例えば「リトライ」を retry|backoff|exponential|attempts のように展開して並列に当てに行く。もう一つは、意味的アンカーを探すための補助としてベクトル検索や AST 検索を加えること。どちらが効くかはケース次第で、grep だけで突破する agent もあれば、最初のアンカー発見だけ embedding に任せて、そこから grep で参照を追う構成もある。「ベクトル DB が完全に不要」ではなく、「メインの検索を grep 系に置き、必要な場面でだけ補助として加える」のが現実的だ。

これら 3 つに該当しない、典型的なソフトウェア開発の現場(コード repo を主に扱う、ファイル数は数千〜数十万、変更が毎日起きる)では、grep 系 + agent で足りる。

それでも、自分は何も運用していない

私が普段触っているコードベースは、複数の repo に分散していて合計ファイル数は数万、毎日 git pull 程度の更新頻度。Claude Code を中心とした agent ベースの開発をしている。上で挙げた 3 つの境界には触れない、典型的な部類だ。

コード検索用のベクトル DB は一つも構築していない。embedding 計算もしていない。Claude Code がデフォルトで持っている Glob / Grep / Read を agent に任せている。実用上、困ったことがない。

事前のインデックス作成も、CI でのインデックス更新も、ファイル削除時の整合性管理も、すべて不要だ。git pull した瞬間に最新のコードが検索対象になる。何も運用していない、というのが運用コストとして最強だ。

長文ドキュメントの検索が必要な場面では、docs/ 配下を構造化して .md で保存し、ファイル名と見出し階層で agent が辿れるようにしている。それも一種の Direct Corpus Interaction だ。

まとめ:RAG を作る前に、まず grep で困るか試せ

ベクトル DB を組む前にやるべきことが一つある。agent に rgcat を渡して、それで困るかどうか試すことだ

多くの場合、困らない。コード repo は元から構造化されており、agent はそれを使いこなせる。Claude Code、Codex CLI、Opencode はすでにそうしている。IR 研究コミュニティでも、これと近い構図がベンチマークで示された(DCI 論文)。日本語のテック界隈でも、Zenn・Qiita で複数のエンジニアが同じ結論に到達している。

grep 系が現状の最適解になっている理由は、特別だからではない、平凡で速くて運用ゼロだからだ。意味があるのは、「革命的でないツールで十分だった」と気付くまでの数年の遠回りのほうだ。

ベクトル DB を組むのは、grep 系で具体的に困ってからでいい。境界は上に書いた 3 つ:大規模 monorepo、長文非構造化ドキュメント、抽象的意味検索。それ以外は、grep 系 + agent で済む。

参考リンク

Footnotes

  1. Claude Codeはなぜベクトル検索を捨てたのか — Embeddingの仕組みから理解する – Qiita

  2. Claude Codeがベクトル検索を採用しなくなった理由 – Zenn 2