問題:AI エージェントはまず「全部」読もうとする

Claude Code や Cursor など AI コーディングツールを使って日常的にコードを書いている開発者にとって、大きなコードベースを調査させたときのトークン消費は無視できない問題です。Read を繰り返し、grep を広く打ち、関係するかどうか分からないファイルを次々と読み込む——これは「地図なしに現地を歩き回る」状態です。

bonsai はこの問題を一段手前で解決するツールです。コードベースのシグネチャ・doc・行番号だけを抽出し、LLM が「次に何を読むか」を決めるための地図を生成します。

bonsaiの処理パイプラインとトークン削減効果の図解

仕組み:骨格だけを取り出す

bonsai の処理は一本道です。tree-sitter による AST 解析でシンボルを正確に拾い、PageRank で「他から多く参照される重要なシンボル」を上位に浮かせます。--max-tokens で予算を指定すれば、その範囲に収まるように自動的に取捨選択されます。

対応言語は Rust / Python / TypeScript / JavaScript / Go の 5 言語が tree-sitter ベースで精度高く動作します。PHP は tree-sitter の ABI 不整合(v15 vs v14)のため正規表現ベースの実装になっており、一般的なパターンはカバーしますが完全ではありません。Java / C# / Ruby 等は現時点で未対応です。

インストールと基本的な使い方

現時点での入手方法はソースからのビルドです。リポジトリをクローンしてから以下を実行します。

cargo install --path crates/cli

インストール後は bonsai コマンドをそのまま使えます。

# カレントディレクトリ全体の地図(Markdown 出力)
bonsai

# 言語指定 + トークン予算つき
bonsai src --lang rust --max-tokens 4000

# 重要箇所を先頭に寄せる(重みのシードを明示)
bonsai . --max-tokens 4000 --focus Engine --focus 'src/parser/*'

# JSON 出力(エージェント組み込み向け)
bonsai src --lang rust --format json -o map.json

bonsai.toml をリポジトリに置けば focus = [...]show_body = N を設定として固定できます。CI への組み込みにも適しています。

トークン効率の実測値

実際に計測した差は無視できません。Python 123 ファイルのコードベースで比較しました。

アプローチ 対象 推定トークン
bonsai(骨格のみ) 123 ファイルの骨格 約 7,000
Read/grep(通常) 約 40 ファイル(全文+部分) 約 30,000〜35,000

骨格 123 ファイルと全文 40 ファイルを比べて 4〜5 倍のトークン差 があります。地図があれば「どの 40 ファイルを読むか」をあらかじめ絞れるため、調査の総コストはさらに下がります。

5 工程で使い分ける調査フロー

bonsai は「一発で答えを出す」ツールではありません。調査を段階的に深めるための起点です。

工程 目的 コマンド
1. 概要把握 全体像を安く掴む bonsai . --max-tokens 4000
2. 影響範囲調査 変更対象の波及先を確認 bonsai . --dependents Engine --dep-depth 1(デフォルトは 2 ホップ)
3. 詳細調査 特定シンボルの本体を展開 bonsai . --zoom Engine
4. テスト確認 関連テストを把握 bonsai tests/ --zoom Engine --include-private
5. レビュー コード差分を確認 /code-review(別ツール)
# 工程1 → 工程2 → 工程3 の典型的な流れ
bonsai src --lang rust --max-tokens 4000
bonsai src --lang rust --dependents FileMap --dep-depth 1
bonsai src --lang rust --zoom apply_token_budget

1 段目で「何がいるか」を把握し、2 段目で「どこに影響するか」を確認し、3 段目で「中身はどうか」を見る。その後、必要なファイルだけを Read で完全に読む——この流れが基本です。

--show-body N を使えば各シンボルの本体先頭 N 行だけを付加することもでき、骨格と完全展開の中間の粒度を選べます。--zoom はデフォルトで def/ref グラフ上の 1-hop 隣接ファイルも本体展開します。パスで指定したときに展開が広がりすぎる場合は --zoom-depth 0 で展開なしにできます。

影響範囲調査:--dependents の使い方

変更前に「何が壊れる可能性があるか」を把握できます。

# BayesianRiskModel を変更したとき、直接の呼び出し元を確認
bonsai api --lang python --dependents BayesianRiskModel --dep-depth 1

# 全推移閉包(dep-depth 0 = 無制限)
bonsai api --lang python --dependents BayesianRiskModel --dep-depth 0

--dep-depth のデフォルトは 2 ホップ(seed の直接の呼び出し元とその呼び出し元)です。広い範囲が必要なときは省略し、まず絞りたいときは --dep-depth 1 から試すのが実用的です。

ただし、注意点があります。FileMap のような中核型に --dependents をかけると 29 ファイル中 24 ファイルがヒットするケースがありました。ほぼ全ファイルが依存する型には ref グラフが機能しません。対策は、中核型より「具体的な関数」を seed にすること(apply_token_budget → 3 ファイルに絞れた)です。

構築サイトを探したいときは grep "ClassName {" src -r と組み合わせるのが確実です。bonsai は「型が使われているファイル群」は特定できますが、「どの行で構築しているか」は grep の方が直接的です。

aider repo-map との違い:決定性

同種のツールとして aider repo-map があります。aider repo-map は会話の中で言及された識別子を重み付けに使うため、会話の文脈によって出力が変わります。

bonsai は会話非依存・決定的です。同じコードベース・同じコマンドは常に同じ地図を返します。コードが変わらなければ地図も変わらないため、チームでの共有や CI への組み込みに向いています。重みのシードは --focus <pattern> で明示します。

ツール 重み付けの根拠
repomix / code2prompt なし(全文連結)
ctags なし(位置インデックスのみ)
aider repo-map 会話で言及した識別子
bonsai 静的解析のみ・決定的。シードは --focus で明示

限界:地図は目的地ではない

bonsai の地図には意図的に含まれないものがあります。

引数の型・デフォルト値の詳細、条件分岐・リトライ・エラーハンドリングのロジック、具体的なプロバイダ設定の切り替え条件——これらは骨格から読み取れません。Edit を書くための正確な行内容は最終的に Read が必要です。

--include-private なしでは private 関数が --zoom のパターンマッチ対象外になります。#[test] 付き関数はデフォルトでも骨格に出ますが、他の private シンボルを対象にしたいときは明示的に --include-private を付けてください。

「骨格を読めば実装を理解できる」という期待は誤りです。bonsai は「どこを読むか」を決める前段のコストを下げるツールであり、Read の代替ではありません。

まとめ

bonsai が提供するコアバリューは 2 つです。

トークン効率化——全文読み込みと比べて 4〜5 倍のトークンを削減できる実測値があります。123 ファイルの骨格が 7,000 トークンで収まるため、「全部読む」前に「何を読むか」を安く決められます。

決定性——会話に依存しない静的解析です。同じコードベース・同じコマンドは常に同じ地図を返します。コードが変わらなければ地図も変わらず、チーム共有・CI 組み込みに向きます。

この 2 つが組み合わさることで、AI エージェントが大規模コードベースを扱うときの「最初の数千トークン」をどこに使うかという問いへの実践的な答えになっています。骨格は地図であり、地図は目的地ではない。bonsai はその「地図」を低コストで、かつ毎回同じ精度で提供するツールです。