無料AIコーディングのおすすめ選びより先に、何が渡っているかを測る
目次
無料のAIコーディングツールで返ってきた提案が的外れだったとき、私はモデルの実力を疑ってきた。だが今回測って分かったのは、同じリポジトリ・同じツールでも、指定するモデル名を変えただけでAIに渡る範囲が6ファイルにも43ファイルにもなるということだった。ここを確かめずに乗り換えを繰り返すと、比べているのはツールの実力ではなく、たまたま文脈に載ったファイルの引きになる。
aider には --show-repo-map がある。モデルにリクエストを投げず、リポジトリの要約(repo map)を組み立てて表示して終わるだけのオプションだ。APIキーも課金も要らないので、無料のまま入力側を覗ける。
APIキー無しで入力側は覗ける。ただし git 管理下に限る
最初に --no-git を付けて動かしたら、map が1行も出なかった。
$ python3 probe_aider.py
[cmd] aider --show-repo-map --no-git --map-tokens 1024 --model gpt-4o --yes --no-check-update
...
Aider v0.86.2
Main model: gpt-4o with diff edit format
Weak model: gpt-4o-mini
Git repo: none
Repo-map: disabled
...
# exit=0 (19359 ms)
Repo-map: disabled と出ている。aider の repo map は git リポジトリを前提にしていて、--no-git で起動すると組み立て自体が行われない。「無料ツールを入れて、まず手元のフォルダで試す」という始め方をすると、repo map の恩恵をゼロにしたままツールを評価することになる。
そこで検証用のリポジトリを作ろうとして、今度は git init に止められた。この環境では作業ディレクトリ配下に .git/config を書けず、Operation not permitted で exit=128 になる。テンプレートを空にして再実行しても同じだった。リポジトリができていないことに気づかず次へ進むと、こうなる。
$ git -C /tmp/claude-501/maprepo add -A
fatal: not a git repository (or any of the parent directories): .git
# exit=128 (182 ms)
検証用リポジトリは /tmp 配下に作り直した。以降の測定はすべてそこで回している。実行環境は macOS 26.6.1、aider 0.86.2、計測スクリプトは python3 3.14.7 で動かした。
予算を指定して測る——50ファイル中13しか載らない設定がある
測る対象を自分で作った。関数名とクラス名を一意にした合成リポジトリで、あとから「map に何個載ったか」を数えられるようにしてある。
$ python3 gen_repo.py 50 8 /tmp/claude-501/maprepo
generated_files=50 functions=400 classes=50 methods=100 source_lines=1900
# exit=0 (232 ms)
50ファイル・400関数・50クラス。git init と git add -A で追跡下に置き、--map-tokens 1024 を明示して repo map を出す。数えているのは、出力に現れた f_00_0 形式の関数名と mod_00.py 形式のファイル名のユニーク数だ。
$ python3 measure_map.py /tmp/claude-501/maprepo 1024 --dump
defined: files=50 functions=400 classes=50
[cmd] aider --show-repo-map --map-tokens 1024 --model gpt-4o --yes --no-check-update --no-show-model-warnings --env-file env.txt
budget=1024 exit=0 elapsed= 22.1s out_chars= 4878 out_lines= 306 funcs_in_map=101/400 classes_in_map=13/50 files_in_map=13/50
...
src/mod_37.py:
⋮
│def f_37_3(value, factor=2):
⋮
│def f_37_4(value, factor=2):
⋮
│def f_37_5(value, factor=2):
...
# exit=0 (22179 ms)
400関数のうち101、50ファイルのうち13。map の中身は上の引用のとおりで、関数のシグネチャだけが並び、本体は ⋮ に畳まれている。読ませているのは実装ではなく目次だと考えると分かりやすい。
--env-file を付けているのは、aider が git ルートを遡って .env を探しにいくからだ。検証と関係ないファイルを読ませたくなかったので、リポジトリ内の空ファイルを指している。
予算を変えて同じリポジトリを測ると、こうなる。
$ python3 measure_map.py /tmp/claude-501/maprepo 256,1024,4096,16384,65536
defined: files=50 functions=400 classes=50
[cmd] aider --show-repo-map --map-tokens 256 --model gpt-4o --yes --no-check-update --no-show-model-warnings --env-file env.txt
budget=256 exit=0 elapsed= 20.0s out_chars= 1590 out_lines= 89 funcs_in_map=25/400 classes_in_map=4/50 files_in_map=4/50
[cmd] aider --show-repo-map --map-tokens 1024 --model gpt-4o --yes --no-check-update --no-show-model-warnings --env-file env.txt
budget=1024 exit=0 elapsed= 16.7s out_chars= 4806 out_lines= 304 funcs_in_map=101/400 classes_in_map=13/50 files_in_map=13/50
[cmd] aider --show-repo-map --map-tokens 4096 --model gpt-4o --yes --no-check-update --no-show-model-warnings --env-file env.txt
budget=4096 exit=0 elapsed= 11.7s out_chars= 14161 out_lines= 930 funcs_in_map=320/400 classes_in_map=40/50 files_in_map=40/50
[cmd] aider --show-repo-map --map-tokens 16384 --model gpt-4o --yes --no-check-update --no-show-model-warnings --env-file env.txt
budget=16384 exit=0 elapsed= 7.2s out_chars= 17692 out_lines=1164 funcs_in_map=400/400 classes_in_map=50/50 files_in_map=50/50
[cmd] aider --show-repo-map --map-tokens 65536 --model gpt-4o --yes --no-check-update --no-show-model-warnings --env-file env.txt
budget=65536 exit=0 elapsed= 5.4s out_chars= 17692 out_lines=1164 funcs_in_map=400/400 classes_in_map=50/50 files_in_map=50/50
# exit=0 (61061 ms)
16384 で400関数すべてが載り、65536 まで上げても出力は 17692 文字のまま1文字も増えなかった。予算は上限であって要求量ではない。逆に 256 まで絞ると4ファイル・25関数まで落ちる。このリポジトリは 1900行しかないので、実務のリポジトリならもっと早く頭打ちになるはずだ。そこは測っていない。
git add していないファイルは1文字も渡らない
新しく5ファイル作って、git add しないまま測った。
$ python3 gen_repo.py 55 8 /tmp/claude-501/maprepo
generated_files=55 functions=440 classes=55 methods=110 source_lines=2090
# exit=0 (63 ms)
$ git -C /tmp/claude-501/maprepo status --porcelain
...
?? .gitignore
?? src/mod_50.py
?? src/mod_51.py
?? src/mod_52.py
?? src/mod_53.py
?? src/mod_54.py
# exit=0 (34 ms)
$ python3 measure_map.py /tmp/claude-501/maprepo 16384
defined: files=55 functions=440 classes=55
[cmd] aider --show-repo-map --map-tokens 16384 --model gpt-4o --yes --no-check-update --no-show-model-warnings --env-file env.txt
budget=16384 exit=0 elapsed= 4.0s out_chars= 17692 out_lines=1164 funcs_in_map=400/440 classes_in_map=50/55 files_in_map=50/55
# exit=0 (4058 ms)
分母は55ファイル・440関数に増えているのに、載ったのは50ファイル・400関数のままだ。出力の文字数は 17692 で、5ファイルを置く前とまったく同じだった。未追跡の5ファイルは、repo map に1文字も出ていない。
git add した直後に測り直すと変わる。
$ python3 measure_map.py /tmp/claude-501/maprepo 16384,1024
defined: files=55 functions=440 classes=55
[cmd] aider --show-repo-map --map-tokens 16384 --model gpt-4o --yes --no-check-update --no-show-model-warnings --env-file env.txt
budget=16384 exit=0 elapsed= 4.4s out_chars= 19419 out_lines=1281 funcs_in_map=440/440 classes_in_map=55/55 files_in_map=55/55
[cmd] aider --show-repo-map --map-tokens 1024 --model gpt-4o --yes --no-check-update --no-show-model-warnings --env-file env.txt
budget=1024 exit=0 elapsed= 3.3s out_chars= 5021 out_lines= 319 funcs_in_map=105/440 classes_in_map=14/55 files_in_map=14/55
# exit=0 (7736 ms)
55ファイル・440関数、文字数は 19419 に増えた。コミットはしていない。ステージに載せただけで map に入る。新しく作ったファイルを起点にAIへ相談する場面は多いが、その新規ファイル自身は追跡外なので、repo map からは抜け落ちる。
既定値はドキュメントの1024ではなく、モデルで変わった
ここまでは --map-tokens を明示してきた。公式ドキュメントは既定値を1024と説明している(Repository map)。ならばフラグを外せば1024と同じ結果になるはずだ、と考えて確かめた。
$ python3 default_map.py /tmp/claude-501/maprepo
defined: files=55 functions=440 classes=55
[cmd] aider --show-repo-map --model gpt-4o --yes --no-check-update --no-show-model-warnings --env-file env.txt
no-budget-flag exit=0 elapsed= 15.3s out_chars= 15032 out_lines= 990 funcs_in_map=339/440 classes_in_map=43/55 files_in_map=43/55
Repo-map: using 4096 tokens, auto refresh
# exit=0 (15499 ms)
Repo-map: using 4096 tokens と出た。1024ではない。43ファイル・339関数が載っている。
モデル名を変えるとさらに動く。gpt-4o-mini でも 4096 のままで、載った数も43ファイル・339関数で変わらなかった。ところが Claude の Haiku を指定すると別の値になる。
$ python3 default_map.py /tmp/claude-501/maprepo claude-3-5-haiku-20241022
defined: files=55 functions=440 classes=55
[cmd] aider --show-repo-map --model claude-3-5-haiku-20241022 --yes --no-check-update --no-show-model-warnings --env-file env.txt
no-budget-flag model=claude-3-5-haiku-20241022 exit=0 elapsed= 9.9s out_chars= 2235 out_lines= 132 funcs_in_map=40/440 classes_in_map=6/55 files_in_map=6/55
Repo-map: using 1024 tokens, auto refresh
# exit=0 (10115 ms)
同じリポジトリ、同じコマンド、違うのはモデル名だけで、6ファイル・40関数まで落ちた。--map-tokens を指定しない限り、渡る量はモデル設定に引きずられる。無料枠の都合で軽いモデルに切り替えたとき、落ちるのは推論性能だけではない。渡している文脈も一緒に落ちる。
この3モデルはどれも --show-repo-map で呼んだだけで、APIキーは設定していない。モデル名は「どの設定を読むか」を決めているだけで、推論は走っていない。
時間が下がっていく理由を、私は読み違えた
スイープの表で、同じリポジトリなのに所要時間が 20.0秒から 5.4秒まで下がっていくのが気になった。aider はタグのキャッシュをリポジトリ直下に作るので、それが効いたのだと考えた。
確かめたら外れた。キャッシュを消してから、同じ条件で3回続けて測った。
$ rm -rf /tmp/claude-501/maprepo/.aider.tags.cache.v4
# exit=0 (14 ms)
$ python3 measure_map.py /tmp/claude-501/maprepo 16384,16384,16384
defined: files=50 functions=400 classes=50
[cmd] aider --show-repo-map --map-tokens 16384 --model gpt-4o --yes --no-check-update --no-show-model-warnings --env-file env.txt
budget=16384 exit=0 elapsed= 5.6s out_chars= 17692 out_lines=1164 funcs_in_map=400/400 classes_in_map=50/50 files_in_map=50/50
[cmd] aider --show-repo-map --map-tokens 16384 --model gpt-4o --yes --no-check-update --no-show-model-warnings --env-file env.txt
budget=16384 exit=0 elapsed= 4.6s out_chars= 17692 out_lines=1164 funcs_in_map=400/400 classes_in_map=50/50 files_in_map=50/50
[cmd] aider --show-repo-map --map-tokens 16384 --model gpt-4o --yes --no-check-update --no-show-model-warnings --env-file env.txt
budget=16384 exit=0 elapsed= 5.3s out_chars= 17692 out_lines=1164 funcs_in_map=400/400 classes_in_map=50/50 files_in_map=50/50
# exit=0 (15569 ms)
キャッシュを消した直後の1回目が 5.6秒だった。タグの再構築が 20.0秒の正体なら、ここは 20.0秒側に戻るはずだった。戻らなかったので仮説を捨てた。では何が 20.0秒を作っていたのかは特定していない。プロセスの起動まわりを疑ってはいるが、切り分けていないので断定しない。
測り方としての教訓は別にある。時間が下がる列を見て理由を思いついたら、その理由を消してもう一度測ること。思いつきのまま書いていたら「タグキャッシュが効いて速くなる」という誤った記述になっていた。既定値の件も同じで、ドキュメントを引いて済ませていたら 4096 には気づかなかった。
課金前に自分で確かめられること・できないこと
無料の範囲で確かめられるのは、出力の質ではなく入力の中身だ。--show-repo-map はモデルを呼ばないので、APIキーが無くても、課金枠が尽きていても動く。自分のリポジトリで「何ファイル中何ファイルが載るか」を数えるところまでは、今日そのままできる。
手順はこうなる。git 管理下のリポジトリのルートで、私が回したのと同じ形のコマンドを実行する。
aider --show-repo-map --model gpt-4o --yes --no-check-update --no-show-model-warnings --env-file env.txt
--env-file は .env を遡って読ませないための指定なので、自分の .env を読ませて構わないなら外してよい。出力の先頭に Repo-map: using N tokens が出る。その N が、今のモデル設定での予算だ。そのあとに続くファイル名のなかに、これから触る予定のファイルがあるかを見る。
無いなら、そのファイルは repo map 経由では渡っていない。ただし、チャットに明示的に追加したファイルは repo map とは別の経路で渡る。そちらは今回測っていないので、「AIがまったく知らない」とまでは言えない。言えるのは「要約の側には載っていない」までだ。
ここが分かると、比較の順序が変わる。既定のまま使っていて回答が浅いと感じたなら、疑うべき候補が3つ増える。モデル設定に紐づいた予算、追跡から漏れているファイル、そして予算を明示していないこと自体だ。どれも無料で確かめられて、確かめてから乗り換えても遅くない。AIコーディングでどれがおすすめかを決めるのは、そのあとでいい。
できないことも並べておく。
- 実トークン数は測っていない。 私が数えたのは出力の文字数と識別子の個数であって、モデルに入るトークン数ではない
- 合成リポジトリには依存関係が無い。 aider は重要度でファイルを選ぶので、相互参照のある実リポジトリでは選ばれる顔ぶれが変わる。ここは測っていない
- チャットへ明示追加する経路は測っていない。 全ログが
--show-repo-map単体の実行で、実際に推論を走らせていない - この測り方は aider に固有だ。 補完型のツールや、文脈の作り方を公開していないツールには、同じ覗き方が無い
向かないのは、ツールを1つに決めたい読者だ。この記事はランキングを出さない。出せるのは「あなたのリポジトリで測る手順」までで、そこから先の答えはリポジトリごと、モデルごとに違う。
無料という言葉が保証するのは費用がゼロであることだけで、渡している文脈が足りていることまでは保証しない。私はここを混同していて、出力が悪いと感じたときにモデルを替える側へ先に手を伸ばしていた。替える前に数えれば、替えずに済む場合がある。数えるのに要るのは、コマンド1行と数分だけだ。
関連書籍
