こんにちは、タイミーのバックエンド/Webフロント基盤チーム マネージャーの新谷(@euglena1215)です。
先日開催された RubyKaigi 2026 に参加してきました。その中で特に気になったのが、Shopify の Alexandre Terrasa さんによる「Blazing-fast Code Indexing for Smarter Ruby Tools」という発表です。
この発表では rubydex という Rust 製の Ruby Code Indexer が紹介されていました。RubyLSP や Tapioca に統合することで最大10倍の高速化と2倍のメモリ削減を実現したという内容でした。また、Ruby ツールのための統一的なコードインデックス基盤としてのビジョンも示されていました。Shopify の Ruby DX チームが9名関わっているということで、Shopify への rubydex への本気度が伺えます。
発表の中では、Experimental ながら MCP サーバー(rubydex-mcp)も提供されていることが紹介されていました。Claude Code などの AI アシスタントからセマンティックにコードベースを検索できるようになっています。
AI Coding Agent にコードベースを調査させると、Grep → Read → また Grep…というループが延々と続き、トークンがみるみる消費されていきます。rubydex-mcp を使えば、クラス定義やリファレンス、継承ツリーといった構造的な情報を、1回の MCP ツール呼び出しで取得できます。そのため、このループを大幅に削減できそうです。
実際にどの程度効果があるのか、タイミーのバックエンドリポジトリで定量的に検証してみました。
rubydex とは
rubydex は Shopify が開発した Ruby Code Indexer です。
Rust 製の Indexer がコードベースを解析し、MCP(Model Context Protocol)サーバーとして以下のツールを提供します。
| ツール | 機能 |
|---|---|
search_declarations |
名前によるファジー検索(クラス、モジュール、メソッド、定数) |
get_declaration |
完全修飾名による定義情報の取得(ドキュメント、祖先チェーン、メンバー) |
find_constant_references |
定数の参照箇所をコードベース全体から検索 |
get_descendants |
クラス/モジュールの継承ツリーを取得 |
get_file_declarations |
ファイル内の構造一覧 |
codebase_stats |
コードベース全体の統計情報 |
通常、AI Coding Agent がコードベースを調査する際は grep や find でファイルを探し、Read で中身を読み、また grep で次のファイルを探し…というループを繰り返します。rubydex を使うと、このループの多くが1回の MCP ツール呼び出しで完結できる可能性があります。
検証方法
概要
claude -p(Claude Code の非インタラクティブモード)を使い、rubydex あり/なし の2条件で同じプロンプトを実行し、トークン消費量と回答品質を比較しました。
検証環境
- ツール:Claude Code CLI (
claude -p) - モデル:claude-sonnet-4-6
- rubydex_mcp バージョン:0.1.0
- 対象リポジトリ:タイミーのバックエンド(モジュラーモノリス、70パッケージ)
条件の制御
外部要因を排除するため、以下の共通オプションを使用しました。
claude -p "<prompt>" \\ --output-format json \\ # トークン使用量を含む JSON 出力 --model sonnet \\ # モデル固定 --bare \\ # hooks, CLAUDE.md 等を無効化 --strict-mcp-config \\ # .mcp.json を無視し引数の MCP 設定のみ使用 --mcp-config <config> \\ # 条件別の MCP 設定 --tools "Read,Bash,Edit" \\ --no-session-persistence
--bare で CLAUDE.md の自動読み込み等の副作用を排除し、--strict-mcp-config により MCP サーバーの有効/無効を制御しています。これにより、2条件間の差は rubydex の有無のみになります。
プロンプト
rubydex のツール群が効果を発揮しそうな質問を5種類用意しました。
| ID | プロンプト |
|---|---|
class_hierarchy |
XXXモデルのクラス継承チェーンと、includeしているモジュールの一覧を教えてください。それぞれのモジュールがどのファイルで定義されているかも含めてください。 |
find_references |
YYYモデルがコードベース全体でどこから参照されているか調査してください。参照元をコントローラ、モデル、サービス等のカテゴリ別に分類して一覧にしてください。 |
descendants |
ApplicationRecordを継承しているクラスの一覧を取得し、packs/ディレクトリ配下のパッケージごとに何個のモデルが存在するか集計してください。上位10パッケージを表示してください。 |
method_investigation |
XXXモデルに定義されているpublicインスタンスメソッドのうち、名前に'status'を含むものをすべてリストアップしてください。各メソッドの定義場所(ファイルパスと行番号)と、そのメソッドが何をしているかの簡単な説明を付けてください。 |
codebase_overview |
このRailsプロジェクトのpacks/ディレクトリ配下のパッケージ構成を調査してください。各パッケージに含まれるモデル数、主要なクラス名を一覧にし、パッケージ間の依存関係で特に密結合なものがあれば指摘してください。 |
各条件 × 各プロンプトで5回ずつ、合計50回実行しました。LLM の出力は非決定的なので、複数回実行して平均を取ることでばらつきの影響を軽減しています。
結果
トークン消費量
| プロンプト | rubydex なし(平均トークン) | rubydex あり(平均トークン) | 変化率 |
|---|---|---|---|
| class_hierarchy | 144,076 | 85,958 | -40.3% |
| codebase_overview | 1,187,722 | 664,761 | -44.0% |
| descendants | 46,501 | 165,795 | +256.5% |
| find_references | 770,404 | 332,369 | -56.9% |
| method_investigation | 986,840 | 636,411 | -35.5% |
5つ中4つのプロンプトで 35〜57% のトークン削減 を達成しました 🎉
コスト・速度
| プロンプト | コスト変化 | 実行時間変化 | ターン数変化 |
|---|---|---|---|
| class_hierarchy | -16.7% | -48.6% | -35.4% |
| codebase_overview | -34.3% | -19.6% | -13.7% |
| descendants | +294.6% | +261.0% | +62.7% |
| find_references | -33.5% | -19.0% | -11.9% |
| method_investigation | -30.7% | -50.1% | -38.1% |
ターン数(エージェントのツール呼び出し回数)の削減がトークン削減の主因です。rubydex のセマンティック検索が Grep → Read の繰り返しを置き換えることで、エージェントループが短縮されています。
回答品質(LLM-as-a-Judge)
トークンが減っても回答品質が下がっては意味がありません。別の Claude セッションを立ち上げ両条件の回答を渡し、正確性・網羅性・有用性の3観点で5点満点のスコアリングを行いました。
| プロンプト | rubydex なし(平均) | rubydex あり(平均) | 差分 |
|---|---|---|---|
| class_hierarchy | 4.33 | 4.00 | -0.33 |
| codebase_overview | 4.33 | 4.00 | -0.33 |
| descendants | 3.00 | 4.67 | +1.67 |
| find_references | 4.00 | 4.00 | 0.00 |
| method_investigation | 3.33 | 4.33 | +1.00 |
| 平均 | 3.80 | 4.20 | +0.40 |
回答品質はむしろ改善しています 👏 Judge のコメントから見えた傾向を簡単にまとめます。
rubydex ありで改善した点(正確性)
- rubydex なしの場合、grep の結果をもとに関連しそうなクラスやメソッドを補足情報として列挙する傾向があった。目視では誤情報は確認できなかったが、裏取りが不十分な状態で情報を出しているため信頼性の判断がしにくい(
method_investigationなど) - rubydex ありではインデックスに基づいた情報を返すため、出力の根拠が明確になっている
rubydex なしが勝った点(網羅性・有用性)
- grep ベースの調査は探索範囲が広いため、rubydex が返さないカテゴリ(Policy、Mailer 等)の参照元も拾えていた(
find_references) - rubydex なしの回答はファイルのフルパスや構造図を含むなど、開発者がすぐに使える形に整理されている傾向があった(
class_hierarchy,codebase_overview)
総じて、rubydex ありは正確性で優位、rubydex なしは網羅性で優位という傾向が見られました。また、いくつかのプロンプトの回答を目視でも確認しましたが、rubydex ありで明らかにおかしな内容を回答しているケースは見られませんでした。
descendants が悪化したケース
唯一、descendants プロンプトではトークンが +256.5% と大幅に悪化しました。
このプロンプトは「ApplicationRecord の子孫クラスをパッケージ別に集計する」という内容です。rubydex の get_descendants ツールは全子孫を忠実に返します。(我々の環境では346クラス)一方、rubydex なしの場合は grep -r "< ApplicationRecord" のような検索で主要なものだけを拾うため、結果的にトークンが少なく済んでいました。
つまり、大量の結果を返すような網羅的な検索では、rubydex がかえってトークンを増やすケースがあります。ただし、品質面では rubydex ありの方が +1.67pt と最も大きく改善しており、正確性とのトレードオフと言えます。
まとめ
5つ中4つのプロンプトで 35〜57% のトークン削減 と 17〜34% のコスト削減 を達成しつつ、回答品質は LLM-as-a-Judge の評価で同等以上(5点満点で 3.80 → 4.20)でした。特に「クラスの参照元を探す」「メソッドの定義場所を調べる」といった構造的な検索タスクで効果が顕著です。
一方、全件取得のような網羅的検索ではトークンが増えるケースもあり、万能ではありません。rubydex が提供するツールの特性を理解した上で導入すると、より効果的に活用できそうです。
また、現状 rubydex-mcp を利用するには Rust ツールチェーン(cargo)が必要で、ソースからのビルドが求められます。開発環境の依存が増えることになるため、チーム全員が使える形に整備するかどうかはもう少し見極めたいところです。とはいえ、トークン35〜57%削減という効果は十分に大きく、rubydex-mcp への期待はとても高まる結果となりました。
検証の制約
今回の検証にはいくつかの制約があります。結果を解釈する際の参考にしてください。
--bareモードでの検証: CLAUDE.md 等が無効化されているため、通常利用時とはベースのトークン消費量が異なります- キャッシュの影響: 実行順序や間隔によってキャッシュヒット率が変わるため、コスト比較は参考値です
- 回答品質の評価: LLM-as-a-Judge による自動評価のみで、正解データとの突合は行っていません
- プロンプトの偏り: rubydex が得意そうなタスクを選んでいるため、実際の利用での改善幅はこれより小さくなる可能性があります