Cursor の検索はなぜ「概念」を理解するのか?コードベースインデックスの仕組みを解説
Cursorを使っていると、曖昧な指示でも意図通りのファイルを提案してくれますよね。
なぜ曖昧な指示でも意図通りのファイルを見つけられるのか、Codebase Indexing (公式サイト)について調べてみました。
セマンティック検索とgrep検索
Cursorの検索機能は、主に「セマンティック検索」と「grep検索」という2つの技術が使われています。それぞれの特徴と利点を整理してみましょう。
セマンティック検索(意味検索)
セマンティック検索とは、単語の一致だけでなく「意味」や「概念」を理解して検索する技術です。
自然言語(「認証処理はどこ?」など)から、コードの意味を汲み取って検索することができます。
例えば「送信ボタンのデザインを変えたい」と指示した場合、SubmitButton.tsxやPrimaryActionといったコンポーネントを、「送信に関連するUI要素」として理解し、見つけ出すことができます。
セマンティック検索のメリット
| メリット | 説明 |
|---|---|
| 概念的なマッチング | 変数名や関数名だけでなく、「何をしているコードか」という意図で探せる |
| 表記揺れへの対応 | "auth"と"login"のような、言葉は違うが意味が近いものを関連付けられる |
| 自然言語での検索 | 「〇〇のバグを直して」といった曖昧な指示でも、関連箇所を特定できる |
grep検索(文字列検索)
grep検索は、コードに書かれている文字列そのものをパターンとして探す技術です。
「この関数がどこで使われているか知りたい」といった、明確なターゲットがある場合に有効です。
「送信ボタンのデザインを変えたい」と指示した場合であれば、コード内のコメントやラベルに"送信"と書かれている箇所のみがヒットし、メソッド名などは検索されません。
grep検索のメリット
| メリット | 説明 |
|---|---|
| 完全一致の精度 | 探したい変数名やエラーメッセージがわかっている場合、発見できる |
| 厳密なパターンマッチ | 正規表現などを使って、特定の形式を探せる |
Cursorは「両方」を使っている
実はCursorのAgentは、これらセマンティック検索とgrepの両方を組み合わせて使用しています。
厳密なパターンマッチングにはgrepを使い、概念的な類似コードの検索にはセマンティック検索を使う。このハイブリッドなアプローチにより、曖昧な指示から具体的な修正箇所まで、ユーザーが求めている結果を返すことができます。
インデックス作成の仕組み
ここまで、Cursorがgrepとセマンティック検索の両方で検索していることを紹介しました。
しかし、これらを瞬時に行うためには、あらかじめコードを検索しやすい形に整理しておく必要があります。それがCodebase Indexing(インデックス作成)です。
インデックスとは?
そもそも「インデックス」とは、本の巻末にある「索引」のようなものです。
これを作っておくことで、Cursorは膨大なコードの中から必要な情報を瞬時に探し出すことができます。インデックスがないと、毎回すべてのファイルを1行ずつ読み込む必要があり、検索に膨大な時間がかかってしまいます。
公式ドキュメントによると、インデックス作成は以下の7つのステップで行われています。

出典: Cursor 公式ドキュメント - Semantic Search
1. ファイル同期(File Syncing)
ワークスペース内のファイルは、常に最新の状態で検索できるように同期・処理されます。
Gitの差分検知のように、ファイルの変更を監視し続ける仕組みです。コードを編集して保存すると、その変更が自動的に検知され、インデックスの更新対象としてマークされます。これにより、保存した直後から最新の状態で検索できるようになります。
2. チャンク化(Chunking)
ファイルは単に文字数で区切るのではなく、関数やクラスといった「プログラムとしての意味がまとまっている単位(チャンク)」で分割されます。
例えば、1000行あるファイルを単純に100行ずつ区切ってしまうと、途中で関数が分断されてしまい、「このコードが何をしているか」という文脈が失われてしまいます。そこでCursorは、関数やクラス、コンポーネントといった「意味のまとまり」ごとにコードを分割します。
3. 埋め込み(Embedding)
分割された各チャンクは、埋め込みモデルによって「ベクトル(多次元の数値データ)」に変換されます。
埋め込みとは、コードの意味を「多次元ベクトル」として表現する処理です。例えば、def fetch_user_data():という関数が、埋め込みモデルによって固有の数値ベクトルに変換されます。似た機能を持つdef get_user_info():も非常に近いベクトルになるため、コードの意味の違いを「ベクトル間の距離」として計算し、数学的に「意味が近い」と判定できるようになります。
4. ベクトルデータベース(Vector Database)
変換されたベクトルデータは、多次元ベクトルの類似性検索に最適化されたデータベースに保存されます。
ベクトルデータベースのインデックス技術を用いることで、大規模なプロジェクトであってもミリ秒単位で「意味的に近いコード」を高速で特定することが可能です。
5. 検索クエリの処理(Search Query)
検索時には、私たちが入力した質問(クエリ)も、コード処理時と同じ埋め込みモデルを使ってベクトルに変換されます。
「この関数のエラーを直したい」という日本語の指示を、コードの処理時と同じ埋め込みモデルを用いてベクトル化します。これにより、自然言語とコードという異なる言語同士を同じ基準で比較できるようにし、意味の比較を可能にしています。
6. 類似性検索(Similarity Search)
質問のベクトルとデータベース内のコードのベクトルを比較し、意味の距離が近い(類似している)コードを探し出します。
セマンティック検索: コサイン類似度といった数学的な手法が使われ、ベクトル空間上で「質問に最も近い位置にあるコード」を計算で求めます。
grep検索: 同時に、質問に含まれる具体的なキーワード(関数名、変数名、エラーメッセージなど)が、インデックス化されたコード内で文字列として一致するものも検索されます。
この2つの検索結果を組み合わせることで、「意味的に関連するコード」と「名前が一致するコード」の両方を見つけることができます。
7. 結果のランク付け(Results Ranking)
見つかったコードは質問との関連性が高い順に並べ替えられ、AIが回答を生成する際の参考情報(コンテキスト)として利用されます。
この段階では、単純な類似度スコアだけでなく、「最近編集されたファイルか」「プロジェクトのルートに近いか」「他のファイルから多く参照されているか」といった複数の要素を組み合わせて、最終的な優先順位を決定します。
以上のステップを経て、算出されたスコアに基づいて選ばれた上位のファイルが、コンテキストとしてAIに渡されます。これら一連の複雑な処理によって、AIはプロジェクト固有の知識を持った状態で、正確な回答を生成できるのです。
Codebase Indexingに関するFAQ
最後に、ここまで読み進める中で気になりそうな点をFAQとしてまとめました。
Q. 使用する埋め込みモデルを変更することはできる?
A. 現時点では変更できません。
Cursorは、汎用的な埋め込みモデルではなく、Cursor独自にトレーニングされた専用の埋め込みモデルを使用されています。
これにより、一般的なモデルよりもコード特有の文脈や構造を理解する精度が高められています。そのため、ユーザー側でモデルを選択したり、チューニングしたりする機能は提供されていません。
Q. ファイル数が膨大だと、インデックス作成に時間がかかったり上限に達したりする?
A. はい、ファイル数の規模によっては影響があります。
膨大なファイルをそのままベクトル化しようとすると、以下の問題が起きやすくなります。
- 初回インデックス作成に時間がかかる
- 検索ノイズが増え、回答精度が下がる
これを防ぐためには、「AIに読ませる必要がないファイル」を明示的に除外することが重要です。
具体的には.cursorignoreという設定ファイルを使用します。「容量の多いファイル」「インデックス不要のファイル」などを除外することで対策することができます。
まとめ
Cursorのコード検索機能は、セマンティック検索による意味理解と、grepによる正確な検索の組み合わせによって作られています。
- 文字列だけでなく「概念」で検索できる
- grepと組み合わせることで、厳密な一致と意味的な一致の両方に対応している
私自身、これまでは「なんとなく便利だな」と使っていましたが、今回仕組みを深掘りしたことで、なぜ意図通りのコードが見つかるのかが理解できました。
「AIがどうやってコードを探しているのか」という裏側の仕組みを理解すると、指示の出し方や使いこなしの幅も広がってくるはずです。ぜひ今回の内容を参考に、Cursorのインデックス機能を活用してみてください!
Discussion