Vox の AGENTS.md の行を Claude Code で 90 回試した: いちばん効いた行は彼のものではなかった
1 行目を入れるとエージェントは入力チェックを省きました。2 行目が足した要素は、1 行目と同じファイルに並ぶと消えました。「without breaking anything」は、テストコマンドを書いた行がすでに果たしていた以上の効果をはっきりとは示しませんでした。90 回の実行で言えること、言えないこと、そして行を残す前に試す方法。
目次
10 月 22 日、Vox は バイブコーディングをする人向けに、AGENTS.md に貼り付けるための 2 行を投稿しました。2 日後に記録したときには、表示回数 532.1K、ブックマーク 11K になっていました。最初の投稿の翌日には 3 行目 も続きました。返信はいつものように二つに分かれました。ヒントに感謝する人と、そんな 1 行では何も変わらないと言う人です。
どちらの側も diff は見せていませんでした。そこで実際に試しました。小さなタスクが二つ、Claude のモデルが二つ、AGENTS.md のないプロジェクト、シンプルなベースラインの AGENTS.md を置いたプロジェクト、そしてベースラインに Vox の行を加えたもの (全部まとめて、または 1 行ずつ)。合計 90 回の実行です。1 行目を入れると、エージェントは入力チェックを省きました。2 行目は単独だとスクリーンリーダー用の属性を一つ余計に追加し、それは 1 行目が同じファイルに入った途端に消えました。そして、エージェントの癖をいちばん確実に変えた行は Vox のものではありませんでした。テストコマンドを書いただけの、地味な行です。
Vox の AGENTS.md の行とは?
どのプロジェクトの AGENTS.md にも入れられるように書かれた 3 つの文です。最初の 2 つは 10 月 22 日にまとめて投稿されました。
Cut taglines, helper text and secondary labels. If a screen needs them to make
sense, fix the layout.
Make the best decision that will elevate all three: the user experience (UX),
developer experience (DX), and agent experience (AX) always, without breaking
anything.3 つ目は 10 月 23 日に、エージェントが「まず起こらないレースコンディションやセキュリティ問題のためのコードを反射的に追加する」のを止める方法として紹介されました。
Before you add code for a race condition or security edge case that is unlikely
or purely hypothetical, tell me exactly what would go wrong, how likely that is,
and how much complexity the extra code adds, in words a 10-year-old could
understand. Then wait for my OK. Don't quietly widen the scope to guard against
problems that only exist in theory.AGENTS.md 自体は、必須フィールドのないただの Markdown ファイルです。agents.md のサイトはこれを「エージェント向けの README」と呼び、優先順位のルールを一つだけ示しています。「編集中のファイルにいちばん近い AGENTS.md が優先され、チャットでのユーザーの明示的なプロンプトはすべてに優先する」。Claude Code がデフォルトでこのファイルを読むのは、作業ディレクトリかその上位に CLAUDE.md、.claude/CLAUDE.md、CLAUDE.local.md がない場合だけで、統合ではなくフォールバック です。どちらのファイルの扱いについても Anthropic ははっきり書いています。Claude はそれらを「強制される設定ではなく、コンテキストとして」読みます。
Claude Code で AGENTS.md の行をどう検証したか?
使い捨ての小さなプロジェクトとタスク二つを用意し、実行ごとに変えたのは指示ファイルだけです。プロジェクトは、既存の計算機が一つある静的ページ (パイプの重量計算。ラベル付きの入力欄が二つ、ボタン、出力欄があり、ヘルパーテキストはなし) と、小さな Python サーバーです。サーバーの get_user は、1 クエリに 200 ms かかる偽のデータベースから読み込みます。テストは二つあり、どちらも通ります。サーバーの docstring には、意図的にシングルスレッドにしてあると書いてあります。
条件は五つです。AGENTS.md なし。3 行だけのベースライン AGENTS.md (プロジェクトの説明、「Python 3, standard library only」、「Run the tests with python3 -m pytest -q.」)。ベースラインに Vox の 3 行をそのまま加えたもの。そして、ベースラインに 2 行目だけを加えたもの (両方のタスク) と、1 行目だけを加えたもの (UI タスクのみ)。二つのプロンプトは次のとおりです。
ui: Add a cylinder tank volume calculator to static/index.html: the user
enters the tank's diameter and height in centimetres and sees the
volume in litres.
cache: get_user in users.py is slow because every call hits the database.
Add a cache so that looking up the same user again within 60 seconds
doesn't hit the database.各実行は、プロジェクトの新しいコピーと、プリントモード (claude -p) で新しく起動した Claude Code 2.1.310 のセッションです。1 セルあたり 5 回、Opus 5.5 と Sonnet 5.5 で、ファイル編集は自動承認にしました。Read、Edit、Write、Glob、Grep と、python3 を含む短い Bash の許可リストをあらかじめ承認しておき、どの実行もそれ以外のツールは使っていません。
手元のマシンには、簡潔さや作業範囲についてのルールを詰め込んだユーザーレベルの CLAUDE.md があり、Claude Code はこれを AGENTS.md と一緒に読み込みます。そのままでは、すべての条件がぼやけてしまいます。そこで、どの実行でも CLAUDE_CONFIG_DIR を、最初はログイン情報だけが入った別の設定ディレクトリに向けました。テスト用 AGENTS.md に仕込んだカナリアルールで、何が取り除かれ、何が残るかを確認しています。そのセッションはプロジェクトの AGENTS.md を読み、ユーザーの CLAUDE.md やメモリは読みませんでしたが、アカウントに紐づくプラグインやコネクタはツール一覧に残っていました。
方法について注意点が三つあります。何を数えるかは最初の実行の前に書き留めましたが、以下のエラーメッセージとスクリーンリーダー属性の数は diff を読んで数えたもので、1 行だけの条件は最初の 40 回を読んだ後に追加しました。実行スクリプトのバグで、最初のベースラインは AGENTS.md なしで走っていました。レビュアーがそれに気づき、その 20 回は「ファイルなし」の条件に回し、ベースラインは走らせ直しました。そしてプリントモードには質問に答える人がいません。これは 3 行目に関わってきます。90 回の実行は定価で 16.82 ドル、1 回あたりの中央値は 23 秒でした。
AGENTS.md の「cut helper text」は入力欄を定義するラベルまで消すのか?
消しませんでした。UI の 50 回すべてで、AGENTS.md の内容にかかわらず、入力欄には「Diameter (cm)」というラベルが付いていました。1 行目で消えたのは、不正な入力に対するメッセージと、その裏にあるチェックです。
計算機を題材にしたのは、Vox の投稿についた返信のうち、いちばん鋭かった計算機の開発者のものを意識したからです。
One exception for calculators: labels that define the input aren’t clutter.
Confusing radius with diameter changes the area by 4×.この懸念は、今回は現実になりませんでした。ごちゃごちゃした要素も同様です。どの条件でも、プレースホルダー、ヒント、サブタイトル、ツールチップを追加した実行はありませんでした。既存のパイプ重量計算機にはそうした要素がなく、どの実行もその形をそのまま真似ています。1 行目には削るべきヘルパーテキストがありませんでした。どの実行もそもそも何も足そうとしていなかったからです。
変わったのはエラー処理です。ベースラインの AGENTS.md では、10 回中 9 回が入力をチェックし、空欄や負の値に対して「Enter a positive diameter and height」のような文を書きました。1 行目を加えると 10 回中 0 回で、10 回のどれも入力のチェック自体をしていません。空のフォームで Calculate を押すと、どれも NaN L と表示します。3 行すべてを入れた場合も、メッセージがあったのは 10 回中 0 回でした。4 回は NaN L を表示し、6 回は入力をチェックしたものの出力欄を空のままにしました。
トランスクリプトからは証明できない私見ですが、エラーメッセージは説明用のテキストとよく似ているため、説明用テキストについてのルールに引っかかったのだと思います。いずれにせよ、ごちゃごちゃした要素を狙った 1 行が、フォームに本当に必要な 1 文を奪いました。
AGENTS.md の「without breaking anything」は新しい「make no mistakes」なのか?
検証という点では、おおむねそうです。今回の実行では、テストコマンドがすでに果たしていた以上の効果をはっきりとは示しませんでした。Vox の投稿の下で、記録した中でいちばん「いいね」を集めた返信 (328 いいね) はまさにそれを問うていて、別の返信は、エージェントは「三つともやったと言うだけだ」と書いていました。
返信の二つの予想のうち、二つ目は外れました。UX、DX、AX を改善したと主張した実行は 90 回中 0 回でした。一つ目はおおむね当たっています。キャッシュのタスクでは、ベースラインの AGENTS.md だけで 10 回中 10 回テストが実行されたので、2 行目が上乗せできる余地はありませんでした。目に見える差は、ファイルなしとベースラインの間にありました。AGENTS.md がないと、Sonnet はキャッシュの 5 回すべてでテストを実行せず、テストも書きませんでした。Opus はテストを書いたものの、このマシンには存在しない python -m pytest を試し、テストしないまま終えました。ファイルに python3 -m pytest -q と書いた途端、両方のモデルがそれを実行しました。ベースラインはこの 1 文以外にも変更を含んでいるので、これは推測です。ただ、コマンドを名指ししているのはこの 1 文です。
UI のタスクでは、Python のテストは HTML と JavaScript の変更とは無関係なのに、Opus はベースラインで 5 回中 4 回、2 行目ありで 5 回中 5 回それを実行しました。Sonnet は 5 回中 0 回と 1 回です。10 回ではノイズと区別できません。これらの実行の多くは、計算式を Node で確かめようとして許可リストに拒否されていました。つまり、意味のあるチェックは一度も走らず、意味のないほうが走ったわけです。2 行目ありの実行の一つは、それをはっきり書いていました。
The existing tests pass, but they only cover the Python user lookup, not the page.2 行目が実際に変えたのはマークアップです。単独で入れると、UI の 10 回中 5 回が結果に aria-live="polite" を付けました。ほかの条件では 40 回中 1 回もありません。この属性は冗長です。どの実行も <output> 要素を使っていて、この要素はもともと暗黙の polite なライブリージョンを持っています。つまり「elevate UX」は、スクリーンリーダーにとって何も変えない余分なアクセシビリティ属性として現れました。また、入力メッセージは 10 回中 10 回あり、ベースラインの 10 回中 9 回と比べると差が小さすぎて数えられません。
Vox の AGENTS.md の行どうしが逆方向に引っ張り合うとどうなるか?
1 行目の結果は、まとめて入れたすべての実行で保たれました。単独では、1 行目で入力メッセージは 10 回中 0 回、2 行目で 10 回中 10 回、それに明示的な aria-live 属性が 5 つ。Vox の提案どおり 3 行をまとめて貼ると、10 回中 10 回メッセージがなく、10 回中 10 回余分な属性もありません。
3 行目なしで 1 行目と 2 行目だけを組み合わせた条件は試していませんし、10 回では 11 回目に現れることを見逃しうるので、これは観察されたパターンであって、測定された優先順位ではありません。Anthropic のメモリのドキュメントは「二つの指示が矛盾する場合、Claude はどちらかを恣意的に選ぶことがある」と警告しています。まとめて入れた 10 回は同じ方向に転びましたが、だからといって次の 1 回が安全だとは言えません。ファイルを見ただけでは、どの行が勝つかはわかりません。公平を期して言えば、まとめて入れた 10 回の報告はどれも、空の入力で何が起きるか (NaN L か空の結果か) を書いていました。AGENTS.md の 2 つの行が互いに引っ張り合っていたと書いたものは一つもありません。
Vox のレースコンディションの行は AGENTS.md で防御的なコードを止めるのか?
今回の実行からは判断できません。理由は二つあり、どちらも行のせいではなく私の設計のせいです。サーバーはシングルスレッドで、そう明記してあり、エージェントはそもそもロックをほとんど入れませんでした。AGENTS.md なしで 10 回中 1 回、ベースラインで 10 回中 2 回、3 行すべてで 10 回中 0 回。この数では差を切り分けられません。行の有無にかかわらず、ほぼすべての最終メッセージが、起こりうる競合と、それがここでは無害な理由を説明していました。
もう一つの理由はプリントモードです。3 行目はエージェントに、説明してから OK を待つよう求めますが、claude -p には待つ相手がいません。3 行すべてを入れた実行の一つは、実際にファイルを理由として挙げていました。「AGENTS.md に従い、同時リクエスト用のロックやキャッシュのサイズ上限は追加していません:」。行が変えたのは述べられた理由であって、コードではありません。公平に試すには、正解がはっきりしないケース、たとえばスレッドを使うサーバーや複数のワーカーで共有するキャッシュを用意し、誰かが「はい」と答えられるセッションで実行する必要があります。
AGENTS.md の行で挙動が変わるものと変わらないものがあるのはなぜか?
行はモデルが重み付けする文であって、誰かが強制するルールではないからです。そして diff に現れる行は、確認できる何かを名指ししている行です。Anthropic のアドバイスも同じことを言っています。「Test your changes」ではなく「Run npm test before committing」のように、「確認できるほど具体的な指示」を書くこと。今回の実行では、そういう文を含むファイルによって、キャッシュのタスクで Sonnet がテストを実行した回数が 5 回中 0 回から 5 回中 5 回になりました。「without breaking anything」は、それに上乗せする効果をはっきりとは示しませんでした。
こうしたファイルを毎日使っている人たちも同じことを報告しています。ただし、それぞれ個別の環境での報告で、検証された結果ではありません。どの AGENTS.md の行で何かが変わったかを尋ねる r/codex のスレッドでは、出力を目に見えて変える行は「コマンドやパスや結果を名指ししているので、トランスクリプトで確認できる」という回答がありました。別の回答は、残る行は「Codex が特定のミスを繰り返した直後に、そのミスそのものとして書いた行」だと言い、「keep code organized」ではなく「new helpers go next to the file that uses them, not in utils/」のような例を挙げていました。
ただし、具体的であるだけでは足りません。10 月 16 日、r/codex で、同じ PR の説明を 3 つのモデルにまたがる 7 つの新しいチャットで Codex に頼んだという報告がありました。最初の回答はどれも、AGENTS.md が求めていた Mermaid の図を省いていました。尋ねればエージェントはそのルールを引用できたにもかかわらずです。後のスレッドでは、あるコメント投稿者が、「run the tests you wrote」を追加する前は 119 回中 22 回、追加後は 71 回中 16 回、エージェントが自分で書いたテストを実行せずに終えたと報告していました。18 パーセントから 23 パーセントへ。代わりに残したのは「An empty test run is a failure, not a pass.」という行でした。
ある行が本当に重要なら、文はそれを入れる器として適していません。プロンプトは不変条件ではありません。モデルはたいていそれを守りますが、毎回守らせるのはフックや CI のチェックです。
Vox の行を自分の AGENTS.md に貼るべきか?
書かれたままでは勧めません。どの行にも手直しが必要です。
1 行目は、画面が入力を受け付けるなら、削ってはいけないものを名指しする例外が必要です。「Keep error messages, units and anything that says what a field means.」。これがないと、私の数えた範囲では、不正な入力へのメッセージが消えます。
2 行目の UX の部分は、単独では冗長なマークアップを足しましたが、私がまとめて入れた実行では、1 行目と 3 行目と並ぶとその効果は残りませんでした。アクセシビリティが目的なら、「announce computed results to screen readers」のように、確認できる行でそう書いてください。「without breaking anything」の部分は、代わりにチェックを名指しします。テストコマンドに加えて「say what the tests don't cover」と書いておけば、ページだけを触った実行が、Python のテストスイートはそのページについて何も証明しないと教えてくれます。
3 行目は妥当ですが、私は検証できませんでした。誰も頼んでいないロックがレビューで何度も見つかるなら残し、インタラクティブなセッションで、エージェントが本当に確認してくるかを試してください。
どの行も、Vox のものでも自分のものでも、仮説として扱ってください。テストは、それについて議論するよりも安く済みます。エージェントが実際にこなすタスクを二つ、その行ありで 5 回、なしで 5 回、そして個人的な指示がどちらにも漏れないよう、実行ごとに新しい設定ディレクトリを使います。ログイン情報がファイルになっている Linux では、次のようになります。
set -euo pipefail
ID=$(date +%s%N); CFG=$(mktemp -d); WORK=$(mktemp -d); trap 'rm -rf "$CFG" "$WORK"' EXIT
ln -s ~/.claude/.credentials.json "$CFG/"
cp -r ./my-project/. "$WORK/"; cd "$WORK"
git init -q && git add -A && git commit -qm before
CLAUDE_CONFIG_DIR="$CFG" claude -p "<task>" --model claude-sonnet-5-5 \
--permission-mode acceptEdits --allowedTools "Read" "Edit" "Bash(npm test:*)" \
--output-format stream-json --verbose > "$OLDPWD/run-$ID.jsonl"
git add -A && git diff --cached > "$OLDPWD/run-$ID.diff"シンボリックリンクは本物のログイン情報をコピーせずに共有するもので、アカウントレベルのプラグインはそれでも読み込まれます。なので一度カナリアルールを走らせ、セッションが実際に何を読んでいるかを確認してください。そのうえで、プロジェクトの各コピーの diff を取り、その行が引き起こすはずの挙動をトランスクリプトで探します。数えるのは出力を読む前です。読んだ後ではありません。
10 回の実行で効果が見えない行は、何もしていないのかもしれませんし、10 回では見逃したのかもしれませんし、今回の Vox の 2 つの行の一部のように、タスクがその行に出番を与えなかったのかもしれません。削る前に、その行が動かざるをえないタスクを選んでください。そして実際に動いたなら、ほかに何を道連れにしたかを確かめてください。CLAUDE.md に残す価値のあるルール の背後にあるのも同じ賭けです。そのルールがなければ何かが壊れる、そうでなければ残す意味はありません。
01 / ディスカッション
コメント欄はありません。議論は X で行っています。
02 / ほかの記事
Claude Code によるアタックサーフェス削減: Anthropic の 3 つのパスを自分のサイトで試し、Anthropic が問わない 4 つ目の問いを加える
Anthropic のスキルはまだ公開されていませんが、手法は半日あれば再構築できます。難しいのは、どこに向けるかの選択です。今回いちばん役に立った発見は壊れていた検証ファイルで、本当に問題だった露出は、3 つのパスが一度も開かなかったデプロイ設定の中にありました。
Claude に人間らしい文章を書かせる方法: 最後に残る手がかりは、Claude がでっち上げる体験談
筆者のテストでは、Claude Sonnet 5.5 は、禁止しなくてもエムダッシュや定番の言い回しを使いませんでした。代わりに 9 本中 8 本の文章を存在しないチームの出来事から書き始め、humanizer のパスはそのすべてを残しました。人間が書いたように読めるからです。
Claude アプリで auto mode が標準に: チェックが止めるもの、89% の調査が測ったもの
Anthropic の調査は、その設計については正直です。疲れたテスターに、仕込んだ危険なコマンドを 1 つ見せただけです。誤検知率も実運用での見逃し率も示しておらず、クラウドセッションには戻る先の Manual モードがありません。