◉CLAUDE LABEN
●2.1.296 — サブエージェントごとに autoCompactWindow を指定でき、ワークフロー用のモデルも環境変数で固定できます●AGENTS — Managed Agents の動的ワークフローがベータに。大量の文書を扱う実行を agent が自分で組めます(10/09)●SONNET 4.5 — Claude API での提供終了は 11/30、残り49日。移行先は Sonnet 5.5●Q&A — バグ報告だけ渡すとテストの中だけ直る、という検証が共有されています。頼み方と範囲の決め方が論点です●HAIKU 5.5 — Haiku 4.5 向けコードは budget_tokens が 400 エラーになる点に注意●NEW — つまづき集を毎回全文読ませるのをやめ、番号で一節だけ読む●2.1.296 — サブエージェントごとに autoCompactWindow を指定でき、ワークフロー用のモデルも環境変数で固定できます●AGENTS — Managed Agents の動的ワークフローがベータに。大量の文書を扱う実行を agent が自分で組めます(10/09)●SONNET 4.5 — Claude API での提供終了は 11/30、残り49日。移行先は Sonnet 5.5●Q&A — バグ報告だけ渡すとテストの中だけ直る、という検証が共有されています。頼み方と範囲の決め方が論点です●HAIKU 5.5 — Haiku 4.5 向けコードは budget_tokens が 400 エラーになる点に注意●NEW — つまづき集を毎回全文読ませるのをやめ、番号で一節だけ読む
記事一覧/Claude Code
⟐ Claude Code/2026-08-28中級

検証スクリプトの出力を、そのまま hook から返してはいけません

hook に足した検査は正しく動いていたのに、会話のほうが先に容量を使い果たしていました。833ファイルで58バイトの検査と42KBの検査を実測で並べ、出力が会話に届く経路と、予算を機械的に守らせるラッパーの書き方をまとめます。

Claude Code261hooks20自動化87コンテキスト設計3品質ゲート7

✦ プレミアム記事

検査は、最後まで正しく動いていました。壊れていたのは会話のほうでした。

編集のたびに静的検査を走らせる hook を足した日のことです。個人開発で複数のリポジトリを行き来していると、検査は手で思い出して走らせるより、編集に紐づけて自動で挟むほうが確実に効きます。そう考えて入れたものでした。検査そのものは意図どおりに動き、違反も正しく拾っていました。ところが数十回の編集を挟んだあたりから、応答が目に見えて鈍くなり、やがて長いプロンプトを受け付けなくなりました。

原因を探して、私はしばらく検査スクリプトの中身を見ておりました。無駄な処理はないか、遅い正規表現はないか。けれど問題は処理時間ではありませんでした。検査が返していた文字列が、そのまま毎回の会話に積み上がっていたのです。

hook のタイムアウトについてはhook が command timed out で止まるときの切り分けで扱いました。今回はそれとは別の軸、つまり「時間ではなく量」の話になります。

走査した数ではなく、返した数が文脈になります

まず、自分の手元で実際に測った数字を置きます。同じリポジトリ(MDX 833ファイル)に対して、性格の違う検査をそれぞれ1回ずつ走らせ、標準出力のバイト数と行数を記録しました。

処理走査対象出力バイト行数概算トークン
フロントマター整合検査(合格)833ファイル58 B1約26
逐語重複スキャン(合格)833ファイル109 B1約50
リダイレクト整合検査(合格)リポジトリ全体126 B1約57
単一ファイル検査(違反あり)2ファイル893 B18約406
全件列挙型の grep833ファイル42,280 B398約19,218

※ トークン換算は日本語混在のテキストを 1トークン ≈ 2.2バイトとして概算したものです。実際の値はモデルとトークナイザによって変わります。

ここで目を引くのは、上から3つと下の1つの落差です。同じ833ファイルを走査していながら、返す量は58バイトと42,280バイト、およそ728倍の開きがあります。走査した対象の規模は、出力量をまったく決めていません。決めているのは、書いた人がどう返すことにしたか、それだけです。

私はこの表を作るまで、無意識に「重い検査ほど出力も重い」と思い込んでおりました。実際には逆のことが起きます。よく設計された全件検査は合格時に1行しか返さず、雑に書いた grep -rn は一致した行を全部並べます。後者のほうがはるかに軽い処理なのに、会話に対する負荷は3桁大きいのです。

その出力は、そもそも会話へ届いていますか

ここで一度、前提を確かめ直します。私は長いあいだ「hook が出力すれば、それはすべて会話に入る」と思い込んでおりました。公式のhooks リファレンスを読み直して、その理解が粗かったことに気づいたのは、この記事の初稿を書き終えたあとでした。

実際には、経路によって扱いが違います。

返し方Claude に届くか補足
exit 0 の stdout(多くのイベント)届きませんデバッグログに書かれるだけで、トランスクリプトには出ません
exit 0 の stdout(SessionStart / UserPromptSubmit / UserPromptExpansion / PostModelSwitch)届きます素のテキストがそのまま文脈に加わります
exit 0 の stderr届きませんデバッグログのみ。自分で有効化しない限り読めません
exit 2 の stderr(PostToolUse など)届きますツールは実行済みのまま、内容が Claude に渡ります
hookSpecificOutput.additionalContext届きますsystem reminder として会話に差し込まれます

そして、届く経路には上限があります。additionalContext・systemMessage・素の stdout はいずれも 10,000文字で打ち切られ、超えた分はファイルに保存されてプレビューとパスに置き換わる、と明記されています。私が最初の版で「cat を一度書き間違えれば 5.7MB が会話に流れ込む」と書いたのは、正確ではありませんでした。一度の暴発では、そこまで到達しません。

では危険がないのかというと、そうではないのです。効いてくるのは一度の量ではなく、届く経路を毎回細く使い続けることのほうでした。 編集のたびに走る hook が 400バイトを返せば、300回の編集で12万バイト。一度の上限には一度も触れないまま、会話の容量は着実に削られていきます。私が踏んだのは、まさにこちらでした。

もう一つ、終了コードの扱いも見落としやすいところです。ポリシーを守らせたいときに使うのは exit 2 で、stdout に妥当な JSON がない exit 1 は非ブロッキングエラーとして扱われ、処理はそのまま先へ進みます。Unix の慣習で 1 を返していると、検査は違反を見つけているのに何も止まらない、という状態になります。

出力量と終了コードは独立した軸で、組み合わせは4通りあります。

出力が短い出力が長い
exit 0合格した検査。既定にすべき形要注意。合格しているのに、届く経路なら文脈を消費します
exit 2原因を1行で言い切れる失敗。理想的予算内なら妥当。超えるなら要約して逃がします

見落とされやすいのは右上、つまり**「成功しているのに長い」**の枠です。ここは失敗していないので誰も調べません。エラーも出ません。それでいて、静かにコンテキストを削っていきます。私自身、応答が鈍くなった原因を探して失敗ログばかり見ていた時間がありました。犯人は一度も失敗していなかったのです。

✦

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
✦833ファイルを走査しても58バイトで済む検査と42,280バイト返す検査の差が分かり、hook に足す前に出力量を見積もれるようになります
✦exit 0 の stdout・exit 2 の stderr・additionalContext のうち、どれが実際に Claude へ届くのかを区別できるようになります
✦head -c による文字化けと exit 1 の非ブロッキング扱いを避けた、予算を守るラッパーを書けるようになります
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Claude Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥2,480 の永久アクセス
メンバーシップを見る →

関連記事

⟐ Claude Code2026-09-02
モデル切り替えの記録と歯止めを、フック2本で作る
PreModelSwitch と PostModelSwitch を使い、無人実行中のモデル切り替えを記録するフックと、約束していない切り替えだけを止めるフックをゼロから作ります。実測値つきの手順です。
⟐ Claude Code2026-10-05
「コミットは私がします」と書いたのに git log に一行増えていた朝、指示を強めるのをやめました
Claude Code に「コミットしないで」と頼んだのにコミットされたとき、まず git reset --soft で戻し、permissions.deny と PreToolUse hook の二層で物理的に止める手順です。deny ルールが素通しする git -c の形と、hook の試し方を書き残します。
⟐ Claude Code2026-09-01
heredoc のクォートを1つ落とすと、ログに書いた金額や日付が別物になります
未クォートの heredoc は本文の変数とバックティックを実行します。実測した4通りの書き換わり方、3種類のクォート記法の比較、プレースホルダと sed で値を安全に埋める手順、既存スクリプトを棚卸しする検出コードまでをまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます