CLAUDE.mdAGENTS.mdcopilot-instructions.md が膨らんできて、削りたいが怖くて削れない人向けです。 削ってよい行を、勘ではなく CI の終了コードで判定する方法を書きます。手元のリポジトリで9通り実測したので、その手順と結果をそのまま載せます。

以下、規則違反を検出して CI を落とす自動検査(lint、ビルド時の検査、生成物の検査など、種類は問いません)を 「ゲート」 と呼びます。この記事の話は結局のところ、文書に書いた規則と、ゲートが見ている規則の、重なりを測るというだけのことです。

もう1つ先に読み方を。この記事の RED/GREEN は、いつもの「ビルドが通った/落ちた」ではありません。 わざと違反を仕込んだ状態で CI を回すので、向きが裏返ります。

いつもの CI この記事
RED まずい ゲートが仕事をした
GREEN よい 誰も見ていない

TDD で、実装を書く前にテストを一度 RED にして「このテストはちゃんと落ちる」と確かめるのと同じ向きです。赤くならないテストが無意味なのと同様に、破っても GREEN のままの規則は、機械には存在していません。(コードの世界では mutation testing——わざと壊したコードにテストを当てて、ちゃんと落ちるか確かめる手法——と呼ばれているものを、命令文書に当てているだけです。)

たとえるなら、CLAUDE.md の一行は「ドアを閉めること」という張り紙で、ゲートは開けっぱなしを検知する警報装置です。この記事でやるのは、張り紙を剥がしてみて様子を見ることではありません

  1. 張り紙(文書の規則)を1つ選ぶ。まだ剥がさない
  2. 張り紙が禁じていることを、コードのほうでわざとやってみる(確かめたら元に戻します)
  3. 警報(CI)が鳴れば RED。機械が見張っているので、張り紙は剥がせる
  4. 鳴らなければ GREEN。見張りは張り紙しかないので、剥がせない。先に警報装置を作る

順序が肝心です。先に張り紙を剥がしても警報の配線は何も変わらないので、鳴るかどうかの確かめにはなりません。剥がすのは、鳴ると確かめたあとです。

まとめ

  1. 判定はこれだけです。「その規則をわざと破ったとき、CI は気づくか」。 気づく(RED)なら機械が同じことを言っているので、文書の行は消せます(ただし、その規則を破る頻度が低いときに限ります。理由は後半に)。
  2. 気づかない(GREEN)は「文書に残す」ではありません。「ゲートの積み残し」です。 まずゲートを書けないか考え、書けないものだけを文書に残します。 手元では GREEN 4件のうち3件を実際に書けたので、CLAUDE.md から削除しました。最終的に 9件中8件が文書から消え、残ったのは1件です。
  3. 削れる行の割合は、文書の質ではなくゲートの本数で決まります。 8割削りたければ、先に8割を捕まえる機械が要ります。順序は逆にできません。

なぜこれを測ったか

「Claude Code のプロンプトの 80% を削った」と題した Claude Code 作者の動画が公開されました(YouTube、2026-08-07 取得)。ページの HTML には "uploadDate":"2026-07-27T10:00:30-07:00"itemprop="duration" content="PT35M52S" とあります。同ページの説明文によれば、出演は Boris Cherny と Diana Hu、収録は Startup School 2026 です。

同じ説明文のチャプター一覧で、削る工程と作り直す工程が別々に立っています。

  • 03:21 — Why Claude Code Deleted 80% of Its System Prompt
  • 07:20 — How to Rebuild Your System Prompt
  • 21:57 — The Two-Week Claude Code Prompt

「80%」が何を分母に何を削った数値かは、このページの HTML には書かれていません。 HTML 中の 80% は 21 箇所ありますが、内訳はタイトルとチャプター見出しの2種類だけで、削減の対象・時期・方法を述べた記述はありません(説明文は外部のトランスクリプトを案内していますが、そちらは取得していません)。この数値は以下で根拠に使いません。 使うのは「削除が独立した工程として立っている」という、見出しの並びだけです。

判定の手順

ここは実測前の見立てです。命令ファイルは足す方向にしか育ちません。足す側には「うまくいかなかった」という明確なきっかけがあるのに、削る側にはきっかけが無いからです。うまくいっている間は、その行が効いているのか単に無害なだけなのか区別がつきません。

だとすると、削除は外から工程として与えるしかない。そしてその工程は、こう書けるはずです。

文書の規則を1つ選ぶ 例: SVG に空行を入れない その規則を破る変更を コードに仕込む CI を回す わざと壊した状態で回す RED ゲートが検出 GREEN 誰も検出しない 文書から消せる ゲートを書けるなら 作って文書から消す 書けないものだけ 文書に残す

測った先を先に説明しておきます。AI エージェント活用パターンのカタログを作っている VitePress のリポジトリで、日本語ページと英語ページを1対1で持つ対訳サイトです。ページの体裁には規約があり——必須の見出しが決まっている、英語の原文を引くときは引用元の一覧ファイルに逐語を控えておく、など——それを 8 本の lint が検査しています。以下の実測に出てくる規則は、すべてこのサイトの規約です。

都合のいいことに、このリポジトリの CLAUDE.md は、すでにこの二分を主張していました。冒頭に「機械ゲートが捕まえる規則はここに書かず索引から引く」とあり、「ゲートが無い規則(踏んでも build は緑のまま)」という節が別に立っています。つまり文書が自分で分割線を引いている。その線が正しいかを測れます。

試した結果

npm run docs:build(lint 8本 → VitePress build → 生成された HTML の検査)が1回 4 秒だったので、9通り回しました。回すスクリプトはこれだけです(パスは自分のリポジトリの任意のページに読み替えてください)。

P=docs/patterns/read-and-discard-isolation.md   # 違反を仕込む対象ページ

r(){ git checkout -- . >/dev/null 2>&1; rm -rf docs/notes; }   # 復元
t(){ local id=$1; r; eval "$2"
     npm run docs:build >/tmp/p-$id.log 2>&1 \
       && echo "$id GREEN" || echo "$id RED"
     r; }

t A1-forbidden-term "printf '\n設定は .chatmode.md に書く。\n' >> $P"
t B1-svg-blank-line "perl -i -pe 'print \"\n\" if \$.==38' $P"
# …以下同様に、1試行につき違反1件

$.==38 は、この図のインデントされた子要素の途中にあたる行番号です(後述)。

結果です。規則の種類の列を付けたのは、そのまま読むと手元のサイト固有の話に見えるからです。この9件は5つのクラスの実例にすぎず、自分の CLAUDE.md の行をこのクラスに写像できます。 中央の列は違反を仕込んだ状態でのビルドで、RED がゲートの成功、GREEN がすり抜けです。

規則の種類 破った規則(手元での具体) 違反を仕込んだ build 文書の行は
語彙 使ってはいけない語(古い API 名)を書く RED 消せる
構造 ページに必須の見出しを1つ消す RED 消せる
リンク 存在しないページへリンクする RED 消せる
引用 原文を控えた一覧に無い英文を、引用として本文に書く RED 消せる
翻訳 英文の引用に訳を添えない RED 消せる
構造 図(インライン SVG)の中に空行を入れる GREEN ゲートを書いて消した
リンク 英語ページのリンクから /en/ を落とし、日本語ページを指させる GREEN ゲートを書いて消した
翻訳 日本語ページだけ本文を書き換え、英語ページを放置する GREEN 文書に残す
公開範囲 公開しないつもりのディレクトリを docs/ 直下に作る GREEN ゲートを書いて消した

RED の5件はどれを捕まえたのがどの検査かも記録しています(lint-forbidden-terms / lint-page-template / VitePress のデッドリンク検査 / lint-brief-citations / lint-quote-translations)。どの検査が落ちたかまで見ないと、1試行は終わっていません(理由は後述します)。

CLAUDE.md の「ゲートが無い規則」節(全12項目)に載っていたのは、GREEN の4件だけでした。 残り8項目は今回試していません(git のコミットの書き方やレビューの作法など、ビルドでは破れないものが混じっています)。

試した9件 RED 5件 機械が捕まえる → 文書から消せる GREEN 4件 誰も何も言わない → 残す CLAUDE.md「ゲートが無い規則」節 4件とも、ここに載っていた RED の5件は同節に1件も載っていない = 文書は自分の分割線を正しく把握していた

GREEN の2件は、黙って壊れることまで確認しました

「落ちない」だけでは見落としの可能性があるので、実害が出るところまで見ました。

破った規則 何が起きるか 誰が気づくか
docs/ に新トップレベル 非公開のはずのページが leak.html として実際に描画される 誰も気づかない
SVG に空行 図が壊れ、<pre> が出てマークアップが読者に生で見える 読者だけが気づく
$ mkdir -p docs/notes && printf '# 漏れたページ\n' > docs/notes/leak.md
$ npm run docs:build && ls docs/.vitepress/dist/notes/
leak.html
[build-output] 検査した出力ファイル: 188(正常時は 185)

出力を検査するゲートは通っています。ファイル数を数えてはいるものの、増えたこと自体は咎めません。

$ npm run docs:build && grep -o '<pre[^>]*>' docs/.vitepress/dist/patterns/read-and-discard-isolation.html
<pre>

正常時のこのページに <pre> は出ません。Markdown の HTML ブロックが空行で終端し、続く4スペースインデント行がコードブロックとして解釈された結果です。ビルドは GREEN のままです。

ただし空行を入れる位置で結果が変わりました。 開始タグ <svg …> の直後に空行を入れた場合は、実描画に影響がありませんでした(&lt; の出現数は正常時と同じ 0)。壊れたのは、インデントされた子要素の間に入れたときだけです。文書の書き方(「SVG ブロック内に空行を入れない」)は安全側に倒していて、実際の破壊条件はもう少し狭い、ということになります。

GREEN の4件は、そのまま「書くべきゲート」の一覧になります

ここが本題です。GREEN は「文書に残してよい」という判定ではありません。 この粒度の規則——「SVG に空行を入れるな」「/en/ を落とすな」——は、人間の注意力に預けるには具体的すぎます。具体的だということは、「どんなときも成り立つべき条件」の形に書き直せるということでもあります。

実際、4件のうち3件はその形に書き直せました。書いたので、以下は見立てではなく実測です。

すり抜けた規則 ゲートにした条件 破ったときの結果
SVG に空行 出力 HTML に &lt;rect &lt;text &lt;path 等が現れない RED(日英2ページとも)
/en/ 欠落 docs/en/** の内部リンクは、すべて /en/ で始まる RED(9件検出)
docs/ に新トップレベル docs/ 直下のディレクトリ集合が、宣言した集合と完全一致する RED
日英乖離 内容が同値であることは機械で判定できない。片方だけが変わったコミットを警告する、程度の近似が上限 書けなかった

書いてみて分かったことが2つあります。

SVG の検査だけは <pre>/<code> を除去してはいけませんでした。 既存の「生の **」検査はコードブロックの誤検出を避けるために除去しているので、つい同じ形で書きたくなります。しかし崩れた図はまさにその <pre> の中に落ちるので、除去すると証拠ごと消えて素通りします。同じリポジトリの似た検査でも、除去してよいかは中身で決まりました。

「増えたこと自体」は、出力を見るゲートでは原理的に捕まりません。 出力側の検査が言えるのは「禁止リストに載っているものが出ていない」ところまでで、未知のディレクトリは「公開してよいもの」と同じ顔をしているからです。結局「docs/ 直下のディレクトリ集合が、宣言した集合と一致する」という形——どんなときも成り立つべき条件(不変条件)——でしか書けませんでした。

つまり手元の結果は「5件消せて4件残す」ではありませんでした。8件消せて、文書に残すのが本来の仕事なのは日英乖離の1件だけです。実際に CLAUDE.md から3件の記述を消しました(2件は項目ごと、1件は項目内の該当部分のみ)。

ゲートは、書いただけでは存在しません。 3本とも、経路ごとにわざと破って RED になることと、壊していない状態では GREEN のままであること(陽性対照)を実測しました。どのゲートが落ちたかもログで確認しています — これをやらないと、別の lint が落ちているのを自分のゲートの手柄だと思い込みます(この記事の実験でも、最初の2試行がそれでした)。

最初の2試行は的を外していました

再現するときのために書いておきます。9件のうち2件は、1回目の結果を捨てました。

  • 引用の規則を破るのに、検査の対象外だったファイルを狙っていました。GREEN になったので lint 本体を読むと、そのファイルは除外リストに明示的に載っていました(lint-brief-citations.mjs:56)。ゲートが無いのではなく、私が的を外していただけです。
  • 「日英乖離」を試すのに h2 見出しを書き換えたら RED でした。捕まえたのは定型 lint で、乖離の検出ではありません。地の文だけを変え直したら GREEN になりました。

どちらも GREEN/RED だけ見ていたら逆の結論を書いていました。どの lint が落ちたのかをログで確かめるまで、1試行は終わっていません。

消してよい前提条件は、2つあります

ここまで「RED なら消せる」と書いてきましたが、条件が1つ足りません。ゲートがあることに加えて、その規則を破る頻度が低いことが要ります。

文書の一行とゲートは、コストを払うタイミングが違います。

文書に書いた一行 ゲート
いつ払うか 毎セッション・毎リクエスト(常にコンテキストに載る) 破ったときだけ
効く相手 その文書を読んだエージェント 人の直接編集も、別のエージェントも、全員
すり抜け ある 無い(通れば規則を満たしている)

ゲートだけにすると、書いてから指摘されて直すという往復が増えます。文書に書いておけば、たいていは最初から正しく出てきます。この往復コストは実在します。

文書に規則を書く 依頼 生成 (規則を読む) CI GREEN 規則の行は、破らない回も含めて毎リクエスト読まれる ゲートだけにする 依頼 生成 CI RED 直す CI GREEN ここが増える分の往復 ただし、規則を破ったときだけ発生する

ただし文書の側も無料ではなく、破る頻度に関係なく毎回コンテキストを消費します。上の図の上段は、破らなかった回にも同じだけ払っています。したがって破る頻度が低い規則ほど、ゲート側が安くなります。

今回消した3件(SVG の空行 / /en/ の欠落 / 新トップレベル)は、どれも数十セッションに一度あるかという頻度でした。ここは明確にゲート側です。逆に、毎ページ必ず触るような規則——文体、使ってはいけない語——は、ゲートがあっても文書から消しません。 消すと往復が毎回発生します。この場合はゲートと文書の両方を持ちます。二者択一ではありません。

なお往復コストの実額は、見た目より小さいと思います。CI は着地前にどのみち一度回すので、追加で発生するのはビルド1回分ではなく「エラーを読んで1箇所直す」分です。今回作った3本はいずれも違反箇所のパスと行を出すので、直しは機械的でした。

この記事の執筆中にも、1件ゲート化しました

この方法は CLAUDE.md 固有の話ではないので、別リポジトリの実例をひとつ。この記事を公開しているブログ自体で、執筆中に踏みました。CommonMark は ** のすぐ内側が「」などの約物で、すぐ外側がふつうの文字だと、強調と解釈しません。素の ** が本文に露出し、対になれなかった ** が別の ** と誤ペアを組んで、無関係な部分が太字になります。ビルドは GREEN のまま、気づくのは読者だけ——先の分類で言えば、SVG の空行と同じクラスです。

「かぎ括弧に接して太字を書かない」は、人間の注意力に預けるには具体的すぎる規則です。そこで「出力 HTML の可視テキスト(コード表記を除く)に素の ** が現れない」という不変条件に書き直し、デプロイ前の検査として足しました。旧記事に残っていた既知の露出23ページは許容リストに宣言し、実態との完全一致を要求します。ここでも書いてみて分かったことがありました。検出の正規表現をわざと壊して検証したところ、違反の見逃しとしてではなく、「既知の23ページがクリーンに見える」という不一致としてゲートが落ちたのです。宣言済みリストが、検出器自身のカナリアを兼ねていました。

そしてこの規則は、どの命令文書にも書かずに済んでいます。書くとしたら CLAUDE.md か、Copilot を使うなら copilot-instructions.md か、両方か——ゲートにすると、この選択自体が消えます。 文書は読んだエージェントにしか効きませんが、ゲートは人の直接編集も含めて全員に効きます(先の比較表の「効く相手」の行)。命令文書を複数持つリポジトリほど、ゲート側が有利になる理由です。

手順としてのまとめ

自分の CLAUDE.md に対してやることは4つです。

  1. 規則を1つ選ぶ
  2. それを破ったコミットを作って CI を回す(文書の行を消すのではありません。ここを間違えると、lint の走査対象に文書が入っていない限り必ず GREEN になります)
  3. RED で、かつその規則を破る頻度が低いなら、その行は消す。 頻度が高いなら、ゲートと文書の両方を持つ
  4. GREEN なら、「どんなときも成り立つべき条件」の形に書き直せないか考える。書けたらゲートにして、3 に戻る。 文書に残るのは、機械で書けなかったものと、頻度が高いものだけです

削除を可能にしたのは決意ではなく、同じことを言う機械が別にあるという状態でした。裏を返すと、削れない行が多いリポジトリは、文書が悪いのではなくゲートが足りていないのだと考えています。そして文書に規則を書き足したくなったときは、たいてい書くべき場所はそこではありません。